libcouchbase 0.3.3 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (167) hide show
  1. checksums.yaml +4 -4
  2. data/ext/libcouchbase/CMakeLists.txt +6 -8
  3. data/ext/libcouchbase/README.markdown +2 -2
  4. data/ext/libcouchbase/RELEASE_NOTES.markdown +229 -2
  5. data/ext/libcouchbase/cmake/Modules/ConfigureDtrace.cmake +11 -0
  6. data/ext/libcouchbase/cmake/Modules/GenerateConfigDotH.cmake +18 -0
  7. data/ext/libcouchbase/cmake/Modules/GetLibcouchbaseFlags.cmake +3 -2
  8. data/ext/libcouchbase/cmake/Modules/GetVersionInfo.cmake +3 -3
  9. data/ext/libcouchbase/cmake/config-cmake.h.in +4 -0
  10. data/ext/libcouchbase/cmake/defs.mk.in +0 -2
  11. data/ext/libcouchbase/cmake/source_files.cmake +21 -5
  12. data/ext/libcouchbase/contrib/cJSON/cJSON.c +1 -1
  13. data/ext/libcouchbase/contrib/cbsasl/src/client.c +2 -0
  14. data/ext/libcouchbase/example/users/README +48 -0
  15. data/ext/libcouchbase/example/users/users.c +147 -0
  16. data/ext/libcouchbase/include/libcouchbase/auth.h +175 -31
  17. data/ext/libcouchbase/include/libcouchbase/cntl.h +82 -1
  18. data/ext/libcouchbase/include/libcouchbase/couchbase.h +45 -3
  19. data/ext/libcouchbase/include/libcouchbase/error.h +19 -1
  20. data/ext/libcouchbase/include/libcouchbase/iops.h +3 -0
  21. data/ext/libcouchbase/include/libcouchbase/n1ql.h +31 -1
  22. data/ext/libcouchbase/include/libcouchbase/plugins/io/bsdio-inl.c +4 -1
  23. data/ext/libcouchbase/include/libcouchbase/subdoc.h +36 -2
  24. data/ext/libcouchbase/include/libcouchbase/views.h +7 -1
  25. data/ext/libcouchbase/include/libcouchbase/visibility.h +1 -0
  26. data/ext/libcouchbase/include/memcached/protocol_binary.h +24 -1146
  27. data/ext/libcouchbase/packaging/parse-git-describe.pl +1 -1
  28. data/ext/libcouchbase/plugins/io/libev/libev_io_opts.h +3 -2
  29. data/ext/libcouchbase/src/README.md +0 -2
  30. data/ext/libcouchbase/src/auth-priv.h +23 -4
  31. data/ext/libcouchbase/src/auth.cc +51 -43
  32. data/ext/libcouchbase/src/bootstrap.cc +244 -0
  33. data/ext/libcouchbase/src/bootstrap.h +58 -38
  34. data/ext/libcouchbase/src/bucketconfig/bc_cccp.cc +120 -158
  35. data/ext/libcouchbase/src/bucketconfig/bc_file.cc +281 -0
  36. data/ext/libcouchbase/src/bucketconfig/bc_http.cc +526 -0
  37. data/ext/libcouchbase/src/bucketconfig/bc_http.h +50 -25
  38. data/ext/libcouchbase/src/bucketconfig/bc_static.cc +150 -0
  39. data/ext/libcouchbase/src/bucketconfig/clconfig.h +410 -386
  40. data/ext/libcouchbase/src/bucketconfig/confmon.cc +393 -0
  41. data/ext/libcouchbase/src/cbft.cc +22 -27
  42. data/ext/libcouchbase/src/cntl.cc +56 -22
  43. data/ext/libcouchbase/src/connspec.cc +47 -6
  44. data/ext/libcouchbase/src/connspec.h +27 -0
  45. data/ext/libcouchbase/src/dns-srv.cc +147 -0
  46. data/ext/libcouchbase/src/dump.cc +3 -3
  47. data/ext/libcouchbase/src/errmap.cc +173 -0
  48. data/ext/libcouchbase/src/errmap.h +198 -0
  49. data/ext/libcouchbase/src/getconfig.cc +7 -33
  50. data/ext/libcouchbase/src/handler.cc +118 -7
  51. data/ext/libcouchbase/src/hostlist.cc +0 -36
  52. data/ext/libcouchbase/src/hostlist.h +44 -62
  53. data/ext/libcouchbase/src/http/http-priv.h +125 -112
  54. data/ext/libcouchbase/src/http/http.cc +27 -35
  55. data/ext/libcouchbase/src/http/http.h +1 -34
  56. data/ext/libcouchbase/src/http/http_io.cc +28 -36
  57. data/ext/libcouchbase/src/instance.cc +131 -34
  58. data/ext/libcouchbase/src/internal.h +58 -26
  59. data/ext/libcouchbase/src/jsparse/parser.cc +136 -210
  60. data/ext/libcouchbase/src/jsparse/parser.h +84 -98
  61. data/ext/libcouchbase/src/lcbht/lcbht.cc +177 -0
  62. data/ext/libcouchbase/src/lcbht/lcbht.h +174 -163
  63. data/ext/libcouchbase/src/lcbio/connect.cc +569 -0
  64. data/ext/libcouchbase/src/lcbio/connect.h +16 -7
  65. data/ext/libcouchbase/src/lcbio/ctx.c +1 -1
  66. data/ext/libcouchbase/src/lcbio/iotable.h +101 -16
  67. data/ext/libcouchbase/src/lcbio/{ioutils.c → ioutils.cc} +30 -51
  68. data/ext/libcouchbase/src/lcbio/ioutils.h +29 -90
  69. data/ext/libcouchbase/src/lcbio/manager.cc +543 -0
  70. data/ext/libcouchbase/src/lcbio/manager.h +133 -96
  71. data/ext/libcouchbase/src/lcbio/protoctx.c +2 -2
  72. data/ext/libcouchbase/src/lcbio/timer-cxx.h +87 -0
  73. data/ext/libcouchbase/src/mc/mcreq.c +11 -2
  74. data/ext/libcouchbase/src/mc/mcreq.h +9 -2
  75. data/ext/libcouchbase/src/mcserver/mcserver.cc +175 -43
  76. data/ext/libcouchbase/src/mcserver/mcserver.h +9 -13
  77. data/ext/libcouchbase/src/mcserver/negotiate.cc +181 -62
  78. data/ext/libcouchbase/src/mcserver/negotiate.h +1 -3
  79. data/ext/libcouchbase/src/mctx-helper.h +51 -0
  80. data/ext/libcouchbase/src/n1ql/ixmgmt.cc +1 -2
  81. data/ext/libcouchbase/src/n1ql/n1ql.cc +74 -42
  82. data/ext/libcouchbase/src/netbuf/netbuf.c +4 -4
  83. data/ext/libcouchbase/src/newconfig.cc +6 -6
  84. data/ext/libcouchbase/src/nodeinfo.cc +2 -2
  85. data/ext/libcouchbase/src/operations/{cbflush.c → cbflush.cc} +7 -15
  86. data/ext/libcouchbase/src/operations/{counter.c → counter.cc} +0 -0
  87. data/ext/libcouchbase/src/operations/durability.cc +6 -26
  88. data/ext/libcouchbase/src/operations/durability_internal.h +6 -3
  89. data/ext/libcouchbase/src/operations/{get.c → get.cc} +24 -26
  90. data/ext/libcouchbase/src/operations/{observe.c → observe.cc} +68 -93
  91. data/ext/libcouchbase/src/operations/{pktfwd.c → pktfwd.cc} +0 -0
  92. data/ext/libcouchbase/src/operations/{remove.c → remove.cc} +0 -0
  93. data/ext/libcouchbase/src/operations/stats.cc +3 -8
  94. data/ext/libcouchbase/src/operations/{store.c → store.cc} +27 -32
  95. data/ext/libcouchbase/src/operations/subdoc.cc +129 -42
  96. data/ext/libcouchbase/src/operations/{touch.c → touch.cc} +0 -0
  97. data/ext/libcouchbase/src/packetutils.h +30 -2
  98. data/ext/libcouchbase/src/probes.d +1 -1
  99. data/ext/libcouchbase/src/rdb/rope.c +1 -1
  100. data/ext/libcouchbase/src/{retrychk.c → retrychk.cc} +2 -3
  101. data/ext/libcouchbase/src/retryq.cc +52 -14
  102. data/ext/libcouchbase/src/retryq.h +3 -3
  103. data/ext/libcouchbase/src/settings.c +5 -0
  104. data/ext/libcouchbase/src/settings.h +11 -0
  105. data/ext/libcouchbase/src/ssl/ssl_c.c +1 -0
  106. data/ext/libcouchbase/src/ssl/ssl_common.c +2 -0
  107. data/ext/libcouchbase/src/ssl/ssl_e.c +0 -1
  108. data/ext/libcouchbase/src/strcodecs/strcodecs.h +1 -1
  109. data/ext/libcouchbase/src/trace.h +4 -4
  110. data/ext/libcouchbase/src/vbucket/vbucket.c +6 -10
  111. data/ext/libcouchbase/src/views/{docreq.c → docreq.cc} +48 -54
  112. data/ext/libcouchbase/src/views/docreq.h +24 -30
  113. data/ext/libcouchbase/src/views/viewreq.cc +318 -0
  114. data/ext/libcouchbase/src/views/viewreq.h +43 -13
  115. data/ext/libcouchbase/tests/basic/t_connstr.cc +88 -50
  116. data/ext/libcouchbase/tests/basic/t_creds.cc +47 -5
  117. data/ext/libcouchbase/tests/basic/t_host.cc +67 -75
  118. data/ext/libcouchbase/tests/basic/t_jsparse.cc +27 -82
  119. data/ext/libcouchbase/tests/basic/t_misc.cc +1 -1
  120. data/ext/libcouchbase/tests/basic/t_n1qlstrings.cc +0 -1
  121. data/ext/libcouchbase/tests/htparse/t_basic.cc +58 -78
  122. data/ext/libcouchbase/tests/ioserver/connection.cc +1 -1
  123. data/ext/libcouchbase/tests/ioserver/ioserver.cc +19 -6
  124. data/ext/libcouchbase/tests/iotests/mock-environment.cc +28 -2
  125. data/ext/libcouchbase/tests/iotests/mock-environment.h +51 -1
  126. data/ext/libcouchbase/tests/iotests/t_behavior.cc +1 -7
  127. data/ext/libcouchbase/tests/iotests/t_confmon.cc +97 -115
  128. data/ext/libcouchbase/tests/iotests/t_durability.cc +0 -1
  129. data/ext/libcouchbase/tests/iotests/t_eerrs.cc +119 -0
  130. data/ext/libcouchbase/tests/iotests/t_errmap.cc +178 -0
  131. data/ext/libcouchbase/tests/iotests/t_misc.cc +3 -3
  132. data/ext/libcouchbase/tests/iotests/t_netfail.cc +1 -1
  133. data/ext/libcouchbase/tests/iotests/t_obseqno.cc +0 -1
  134. data/ext/libcouchbase/tests/iotests/t_subdoc.cc +18 -11
  135. data/ext/libcouchbase/tests/mc/t_alloc.cc +9 -9
  136. data/ext/libcouchbase/tests/socktests/socktest.cc +7 -10
  137. data/ext/libcouchbase/tests/socktests/socktest.h +2 -3
  138. data/ext/libcouchbase/tests/socktests/t_basic.cc +6 -6
  139. data/ext/libcouchbase/tests/socktests/t_manager.cc +5 -6
  140. data/ext/libcouchbase/tests/socktests/t_ssl.cc +1 -1
  141. data/ext/libcouchbase/tests/vbucket/confdata/ketama_expected.json +2562 -0
  142. data/ext/libcouchbase/tests/vbucket/confdata/memd_ketama_config.json +31 -0
  143. data/ext/libcouchbase/tests/vbucket/t_config.cc +35 -5
  144. data/ext/libcouchbase/tools/CMakeLists.txt +2 -2
  145. data/ext/libcouchbase/tools/cbc-handlers.h +128 -0
  146. data/ext/libcouchbase/tools/cbc-n1qlback.cc +64 -10
  147. data/ext/libcouchbase/tools/cbc-pillowfight.cc +2 -2
  148. data/ext/libcouchbase/tools/cbc.cc +143 -10
  149. data/ext/libcouchbase/tools/docgen/loc.h +1 -1
  150. data/lib/libcouchbase/connection.rb +4 -3
  151. data/lib/libcouchbase/version.rb +1 -1
  152. metadata +37 -28
  153. data/ext/libcouchbase/include/memcached/vbucket.h +0 -42
  154. data/ext/libcouchbase/src/bootstrap.c +0 -269
  155. data/ext/libcouchbase/src/bucketconfig/bc_file.c +0 -347
  156. data/ext/libcouchbase/src/bucketconfig/bc_http.c +0 -630
  157. data/ext/libcouchbase/src/bucketconfig/bc_mcraw.c +0 -150
  158. data/ext/libcouchbase/src/bucketconfig/confmon.c +0 -474
  159. data/ext/libcouchbase/src/lcbht/lcbht.c +0 -282
  160. data/ext/libcouchbase/src/lcbio/connect.c +0 -557
  161. data/ext/libcouchbase/src/lcbio/manager.c +0 -584
  162. data/ext/libcouchbase/src/packetutils.c +0 -37
  163. data/ext/libcouchbase/src/simplestring.c +0 -211
  164. data/ext/libcouchbase/src/simplestring.h +0 -228
  165. data/ext/libcouchbase/src/ssobuf.h +0 -82
  166. data/ext/libcouchbase/src/views/viewreq.c +0 -358
  167. data/ext/libcouchbase/tests/basic/t_string.cc +0 -112
@@ -21,6 +21,8 @@
21
21
  #include "mc/compress.h"
22
22
  #include "trace.h"
23
23
 
24
+ #define LOGARGS(obj, lvl) (obj)->settings, "handler", LCB_LOG_##lvl, __FILE__, __LINE__
25
+
24
26
  using lcb::MemcachedResponse;
25
27
 
26
28
  template <typename T>
@@ -28,12 +30,60 @@ class ResponsePack {
28
30
  public:
29
31
  T resp;
30
32
  lcb_MUTATION_TOKEN mt;
33
+ const char *value;
34
+ lcb_SIZE nvalue;
35
+ char *err_ref;
36
+ char *err_ctx;
37
+
38
+ ~ResponsePack() {
39
+ free(err_ref);
40
+ free(err_ctx);
41
+ }
31
42
 
32
43
  static const lcb_MUTATION_TOKEN*
33
44
  get_mt(const lcb_RESPBASE *rb) {
34
45
  const ResponsePack *rp = reinterpret_cast<const ResponsePack*>(rb);
35
46
  return &rp->mt;
36
47
  }
48
+
49
+ static const char*
50
+ get_err_ctx(const lcb_RESPBASE *rb) {
51
+ const ResponsePack *rp = reinterpret_cast<const ResponsePack*>(rb);
52
+ if (rp->resp.rflags & LCB_RESP_F_ERRINFO) {
53
+ if (rp->err_ctx) {
54
+ return rp->err_ctx;
55
+ } else {
56
+ parse_enhanced_error(rp);
57
+ return rp->err_ctx;
58
+ }
59
+ }
60
+ return NULL;
61
+ }
62
+
63
+ static const char*
64
+ get_err_ref(const lcb_RESPBASE *rb) {
65
+ const ResponsePack *rp = reinterpret_cast<const ResponsePack*>(rb);
66
+ if (rp->resp.rflags & LCB_RESP_F_ERRINFO) {
67
+ if (rp->err_ref) {
68
+ return rp->err_ref;
69
+ } else {
70
+ parse_enhanced_error(rp);
71
+ return rp->err_ref;
72
+ }
73
+ }
74
+ return NULL;
75
+ }
76
+
77
+ private:
78
+
79
+ static void
80
+ parse_enhanced_error(const ResponsePack *rp) {
81
+ ResponsePack *mrp = const_cast<ResponsePack *>(rp);
82
+ lcb_error_t rc = MemcachedResponse::parse_enhanced_error(mrp->value, mrp->nvalue, &mrp->err_ref, &mrp->err_ctx);
83
+ if (rc != LCB_SUCCESS) {
84
+ mrp->resp.rflags &= ~LCB_RESP_F_ERRINFO;
85
+ }
86
+ }
37
87
  };
38
88
 
39
89
  LIBCOUCHBASE_API
@@ -53,7 +103,7 @@ lcb_errmap_default(lcb_t instance, lcb_uint16_t in)
53
103
  case PROTOCOL_BINARY_RESPONSE_EINTERNAL:
54
104
  default:
55
105
  if (instance) {
56
- lcb_log(instance->settings, "handler", LCB_LOG_ERROR, __FILE__, __LINE__, "Got unhandled memcached error 0x%X", in);
106
+ lcb_log(LOGARGS(instance, ERROR), "Got unhandled memcached error 0x%X", in);
57
107
  } else {
58
108
  fprintf(stderr, "COUCHBASE: Unhandled memcached status=0x%x\n", in);
59
109
  }
@@ -113,6 +163,8 @@ map_error(lcb_t instance, int in)
113
163
  return LCB_UNKNOWN_COMMAND;
114
164
  case PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED:
115
165
  return LCB_NOT_SUPPORTED;
166
+ case PROTOCOL_BINARY_RESPONSE_EACCESS:
167
+ return LCB_NOT_AUTHORIZED;
116
168
  default:
117
169
  if (instance != NULL) {
118
170
  return instance->callbacks.errmap(instance, in);
@@ -174,6 +226,18 @@ void make_error(lcb_t instance, T* resp,
174
226
  }
175
227
  }
176
228
 
229
+ template <typename T>
230
+ void handle_error_info(const MemcachedResponse* mc_resp, ResponsePack<T>* rp)
231
+ {
232
+ if (mc_resp->status() != PROTOCOL_BINARY_RESPONSE_SUCCESS
233
+ && mc_resp->datatype() & PROTOCOL_BINARY_DATATYPE_JSON
234
+ && mc_resp->vallen() > 0) {
235
+ rp->resp.rflags |= LCB_RESP_F_ERRINFO;
236
+ rp->value = mc_resp->value();
237
+ rp->nvalue = mc_resp->vallen();
238
+ }
239
+ }
240
+
177
241
  template <typename T>
178
242
  void init_resp(lcb_t instance, const MemcachedResponse* mc_resp,
179
243
  const mc_PACKET *req, lcb_error_t immerr, T *resp) {
@@ -289,10 +353,12 @@ static void
289
353
  H_get(mc_PIPELINE *pipeline, mc_PACKET *request, MemcachedResponse* response,
290
354
  lcb_error_t immerr)
291
355
  {
292
- lcb_RESPGET resp = { 0 };
356
+ ResponsePack<lcb_RESPGET> w = {{ 0 }};
357
+ lcb_RESPGET& resp = w.resp;
293
358
 
294
359
  lcb_t o = get_instance(pipeline);
295
360
  init_resp(o, response, request, immerr, &resp);
361
+ handle_error_info(response, &w);
296
362
  resp.rflags |= LCB_RESP_F_FINAL;
297
363
 
298
364
  if (resp.rc == LCB_SUCCESS) {
@@ -317,12 +383,14 @@ static void
317
383
  H_getreplica(mc_PIPELINE *pipeline, mc_PACKET *request,
318
384
  MemcachedResponse *response, lcb_error_t immerr)
319
385
  {
320
- lcb_RESPGET resp = { 0 };
386
+ ResponsePack<lcb_RESPGET> w = {{ 0 }};
387
+ lcb_RESPGET& resp = w.resp;
321
388
  lcb_t instance = get_instance(pipeline);
322
389
  void *freeptr = NULL;
323
390
  mc_REQDATAEX *rd = request->u_rdata.exdata;
324
391
 
325
392
  init_resp(instance, response, request, immerr, &resp);
393
+ handle_error_info(response, &w);
326
394
 
327
395
  if (resp.rc == LCB_SUCCESS) {
328
396
  const protocol_binary_response_get *get =
@@ -511,6 +579,7 @@ H_delete(mc_PIPELINE *pipeline, mc_PACKET *packet, MemcachedResponse *response,
511
579
  ResponsePack<lcb_RESPREMOVE> w = { { 0 } };
512
580
  w.resp.rflags |= LCB_RESP_F_EXTDATA | LCB_RESP_F_FINAL;
513
581
  init_resp(root, response, packet, immerr, &w.resp);
582
+ handle_error_info(response, &w);
514
583
  handle_mutation_token(root, response, packet, &w.mt);
515
584
  TRACE_REMOVE_END(response, &w.resp);
516
585
  invoke_callback(packet, root, &w.resp, LCB_CALLBACK_REMOVE);
@@ -628,6 +697,7 @@ H_store(mc_PIPELINE *pipeline, mc_PACKET *request, MemcachedResponse *response,
628
697
  ResponsePack<lcb_RESPSTORE> w = { { 0 } };
629
698
  uint8_t opcode;
630
699
  init_resp(root, response, request, immerr, &w.resp);
700
+ handle_error_info(response, &w);
631
701
  if (!immerr) {
632
702
  opcode = response->opcode();
633
703
  } else {
@@ -669,6 +739,8 @@ H_arithmetic(mc_PIPELINE *pipeline, mc_PACKET *request,
669
739
  w.resp.value = lcb_ntohll(w.resp.value);
670
740
  w.resp.rflags |= LCB_RESP_F_EXTDATA;
671
741
  handle_mutation_token(root, response, request, &w.mt);
742
+ } else {
743
+ handle_error_info(response, &w);
672
744
  }
673
745
  w.resp.rflags |= LCB_RESP_F_FINAL;
674
746
  w.resp.cas = response->cas();
@@ -741,8 +813,10 @@ H_touch(mc_PIPELINE *pipeline, mc_PACKET *request, MemcachedResponse *response,
741
813
  lcb_error_t immerr)
742
814
  {
743
815
  lcb_t root = get_instance(pipeline);
744
- lcb_RESPTOUCH resp = { 0 };
816
+ ResponsePack<lcb_RESPTOUCH> w = {{ 0 }};
817
+ lcb_RESPTOUCH& resp = w.resp;
745
818
  init_resp(root, response, request, immerr, &resp);
819
+ handle_error_info(response, &w);
746
820
  resp.rflags |= LCB_RESP_F_FINAL;
747
821
  TRACE_TOUCH_END(response, &resp);
748
822
  invoke_callback(request, root, &resp, LCB_CALLBACK_TOUCH);
@@ -764,8 +838,10 @@ H_unlock(mc_PIPELINE *pipeline, mc_PACKET *request, MemcachedResponse *response,
764
838
  lcb_error_t immerr)
765
839
  {
766
840
  lcb_t root = get_instance(pipeline);
767
- lcb_RESPUNLOCK resp = { 0 };
841
+ ResponsePack<lcb_RESPUNLOCK> w = {{ 0 }};
842
+ lcb_RESPUNLOCK& resp = w.resp;
768
843
  init_resp(root, response, request, immerr, &resp);
844
+ handle_error_info(response, &w);
769
845
  resp.rflags |= LCB_RESP_F_FINAL;
770
846
  TRACE_UNLOCK_END(response, &resp);
771
847
  invoke_callback(request, root, &resp, LCB_CALLBACK_UNLOCK);
@@ -822,8 +898,6 @@ mcreq_dispatch_response(
822
898
  break;
823
899
 
824
900
  switch (res->opcode()) {
825
- case PROTOCOL_BINARY_CMD_GETQ:
826
- case PROTOCOL_BINARY_CMD_GATQ:
827
901
  case PROTOCOL_BINARY_CMD_GET:
828
902
  case PROTOCOL_BINARY_CMD_GAT:
829
903
  case PROTOCOL_BINARY_CMD_GET_LOCKED:
@@ -934,3 +1008,40 @@ lcb_resp_get_mutation_token(int cbtype, const lcb_RESPBASE *rb)
934
1008
  }
935
1009
  return ss;
936
1010
  }
1011
+
1012
+ #define ERRINFO_CALLBACKS(X) \
1013
+ X(GET) \
1014
+ X(STORE) \
1015
+ X(COUNTER) \
1016
+ X(TOUCH) \
1017
+ X(REMOVE) \
1018
+ X(UNLOCK) \
1019
+
1020
+
1021
+ LIBCOUCHBASE_API
1022
+ const char *
1023
+ lcb_resp_get_error_context(int cbtype, const lcb_RESPBASE *rb)
1024
+ {
1025
+ if ((rb->rflags & LCB_RESP_F_ERRINFO) == 0) {
1026
+ return NULL;
1027
+ }
1028
+
1029
+ #define X(NAME) if (cbtype == LCB_CALLBACK_##NAME) { return ResponsePack<lcb_RESP##NAME>::get_err_ctx(rb); }
1030
+ ERRINFO_CALLBACKS(X);
1031
+ #undef X
1032
+ return NULL;
1033
+ }
1034
+
1035
+ LIBCOUCHBASE_API
1036
+ const char *
1037
+ lcb_resp_get_error_ref(int cbtype, const lcb_RESPBASE *rb)
1038
+ {
1039
+ if ((rb->rflags & LCB_RESP_F_ERRINFO) == 0) {
1040
+ return NULL;
1041
+ }
1042
+
1043
+ #define X(NAME) if (cbtype == LCB_CALLBACK_##NAME) { return ResponsePack<lcb_RESP##NAME>::get_err_ref(rb); }
1044
+ ERRINFO_CALLBACKS(X);
1045
+ #undef X
1046
+ return NULL;
1047
+ }
@@ -16,7 +16,6 @@
16
16
  */
17
17
 
18
18
  #include "hostlist.h"
19
- #include "simplestring.h"
20
19
  #include <stdio.h>
21
20
  #include <ctype.h>
22
21
  #include <limits.h>
@@ -264,38 +263,3 @@ Hostlist::assign(const Hostlist& src)
264
263
  }
265
264
  return *this;
266
265
  }
267
-
268
- extern "C" {
269
- Hostlist* hostlist_create(void) { return new Hostlist(); }
270
- void hostlist_destroy(hostlist_t l) { delete l; }
271
- void hostlist_clear(hostlist_t l) { l->clear(); }
272
- void hostlist_reset_strlist(hostlist_t l) { l->reset_strlist(); }
273
- lcb_error_t hostlist_add_host(hostlist_t l, const lcb_host_t *h) { l->add(*h); return LCB_SUCCESS; }
274
- lcb_host_t *hostlist_shift_next(hostlist_t hl, int wrap) { return hl->next(wrap); }
275
- int hostlist_finished(hostlist_t l) { return l->ix == l->hosts.size(); }
276
- size_t hostlist_size(hostlist_t l) { return l->size(); }
277
- void hostlist_randomize(hostlist_t l) { l->randomize(); }
278
-
279
- lcb_error_t
280
- hostlist_add_string(hostlist_t hl, const char *spec, int len, int deflport) {
281
- return hl->add(spec, len, deflport);
282
- }
283
-
284
- void
285
- hostlist_assign(hostlist_t dst, const hostlist_t src) {
286
- dst->assign(*src);
287
- }
288
-
289
- const lcb_host_t*
290
- hostlist_get(const hostlist_t h, size_t ix) { return &h->hosts[ix]; }
291
-
292
- const char * const *
293
- hostlist_strents(const hostlist_t h) {
294
- h->ensure_strlist();
295
- if (h->hoststrs.size()) {
296
- return &h->hoststrs[0];
297
- } else {
298
- return NULL;
299
- }
300
- }
301
- }
@@ -45,21 +45,59 @@ struct Hostlist {
45
45
  Hostlist() : ix(0) {}
46
46
  ~Hostlist();
47
47
 
48
- void add(const lcb_host_t&);
48
+ /**
49
+ * Adds a string to the hostlist. See lcb_host_parse for details.
50
+ * Note that if the host already exists (see 'lcb_host_equals') it will
51
+ * not be added
52
+ * @param s the string to parse
53
+ * @param len the length of the string
54
+ * @param deflport If `s` does not contain an explicit port, use this
55
+ * port instead.
56
+ * @return LCB_EINVAL if the host string is not valid
57
+ */
49
58
  lcb_error_t add(const char *s, long len, int deflport);
50
59
  lcb_error_t add(const char *s, int deflport) { return add(s, -1, deflport); }
60
+ void add(const lcb_host_t&);
61
+
51
62
  bool exists(const lcb_host_t&) const;
52
63
  bool exists(const char *hostport) const;
64
+
65
+ /**
66
+ * Return the next host in the list.
67
+ * @param wrap If the internal iterator has reached its limit, this
68
+ * indicates whether it should be reset, or if it should return NULL
69
+ * @return a new host if available, or NULL if the list is empty or the
70
+ * iterator is finished.
71
+ */
53
72
  lcb_host_t *next(bool wrap);
54
73
  bool finished() const;
55
74
 
56
75
  size_t size() const { return hosts.size(); }
57
76
  bool empty() const { return hosts.empty(); }
58
77
  Hostlist& assign(const Hostlist& other);
78
+
79
+ /** Clears the hostlist */
59
80
  void clear() { hosts.clear(); reset_strlist(); ix = 0; }
81
+
82
+ /** Randomize the hostlist by shuffling the order. */
60
83
  void randomize();
84
+
85
+ /**
86
+ * String list handling functions. These are used to return the hostlist via
87
+ * the API where we return a char*[] terminated by a NULL pointer.
88
+ */
89
+
90
+ /** Ensure that the string list contains at least one entry */
61
91
  void ensure_strlist();
92
+
93
+ /** Frees the current list of strings */
62
94
  void reset_strlist();
95
+
96
+ const char * const *get_strlist() {
97
+ ensure_strlist();
98
+ return &hoststrs[0];
99
+ }
100
+
63
101
  unsigned int ix;
64
102
  const lcb_host_t& operator[](size_t ix_) const { return hosts[ix_]; }
65
103
 
@@ -68,28 +106,16 @@ struct Hostlist {
68
106
  };
69
107
  }
70
108
  typedef lcb::Hostlist* hostlist_t;
71
- #define hostlist_st lcb::Hostlist
109
+
110
+ struct hostlist_st : lcb::Hostlist {
111
+ hostlist_st() : Hostlist() {
112
+ }
113
+ };
72
114
  #endif
73
115
 
74
116
  #ifdef __cplusplus
75
117
  extern "C" {
76
118
  #endif
77
-
78
- /**
79
- * Creates a new hostlist. Returns NULL on allocation failure
80
- */
81
- hostlist_t hostlist_create(void);
82
-
83
- /**
84
- * Frees resources associated with the hostlist
85
- */
86
- void hostlist_destroy(hostlist_t hostlist);
87
-
88
- /**
89
- * Clears the hostlist
90
- */
91
- void hostlist_clear(hostlist_t hostlist);
92
-
93
119
  /**
94
120
  * Parses a string into a hostlist
95
121
  * @param host the target host to populate
@@ -121,50 +147,6 @@ lcb_host_parse(lcb_host_t *host, const char *spec, int speclen, int deflport);
121
147
  */
122
148
  int lcb_host_equals(const lcb_host_t *a, const lcb_host_t *b);
123
149
 
124
- /**
125
- * Adds a string to the hostlist. See lcb_host_parse for details.
126
- * Note that if the host already exists (see 'lcb_host_equals') it will
127
- * not be added
128
- * @return LCB_EINVAL if the host string is not value, LCB_CLIENT_ENOMEM on
129
- * allocation failure.
130
- */
131
- lcb_error_t hostlist_add_string(hostlist_t hostlist,
132
- const char *spec,
133
- int speclen,
134
- int deflport);
135
-
136
- #define hostlist_add_stringz(hostlist, spec, deflport) \
137
- hostlist_add_string(hostlist, spec, -1, deflport)
138
-
139
- lcb_error_t hostlist_add_host(hostlist_t hostlist, const lcb_host_t *host);
140
-
141
- /**
142
- * Return the next host in the list.
143
- * @param hostlist the hostlist to use
144
- * @param rollover If the internal iterator has reached its limit, this
145
- * indicates whether it should be reset, or if it should return NULL
146
- * @return a new host if available, or NULL if the list is empty or the
147
- * iterator is finished.
148
- */
149
- lcb_host_t *hostlist_shift_next(hostlist_t hostlist, int rollover);
150
-
151
- /**
152
- * Randomize the hostlist
153
- */
154
- void hostlist_randomize(hostlist_t hostlist);
155
-
156
- /**
157
- * String list handling functions. These are used to return the hostlist via
158
- * the API where we return a char*[] terminated by a NULL pointer.
159
- */
160
- void hostlist_reset_strlist(hostlist_t hostlist);
161
-
162
- /** Whether the internal iterator has finished. */
163
- int hostlist_finished(hostlist_t);
164
- size_t hostlist_size(const hostlist_t hl);
165
- void hostlist_assign(hostlist_t dst, const hostlist_t src);
166
- const lcb_host_t *hostlist_get(const hostlist_t, size_t);
167
- const char * const *hostlist_strents(const hostlist_t hl);
168
150
  #ifdef __cplusplus
169
151
  }
170
152
  #endif
@@ -21,6 +21,7 @@
21
21
  #include <libcouchbase/couchbase.h>
22
22
  #include <lcbio/lcbio.h>
23
23
  #include <lcbio/timer-ng.h>
24
+ #include <lcbio/timer-cxx.h>
24
25
  #include <lcbht/lcbht.h>
25
26
  #include "contrib/http_parser/http_parser.h"
26
27
  #include "http.h"
@@ -41,100 +42,34 @@ struct Header {
41
42
  };
42
43
 
43
44
  struct Request {
44
- enum State {
45
- /**
46
- * The request is still ongoing. Callbacks are still active.
47
- * Note that this essentially means the absence of any flags :)
48
- */
49
- ONGOING = 0,
50
-
51
- /**
52
- * This flag is set when the on_complete callback has been invoked. This
53
- * is used as a marker to prevent us from calling that callback more than
54
- * once per request
55
- */
56
- CBINVOKED = 1 << 0,
57
-
58
- /**
59
- * This flag is set by lcb_http_request_finish, and indicates that the
60
- * request is no longer active per se. This means that while the request
61
- * may still be valid in memory, it is simply waiting for any pending I/O
62
- * operations to close, so the reference count can hit zero.
63
- */
64
- FINISHED = 1 << 1,
65
-
66
- /**
67
- * Internal flag used to indicate that finish() should not not attempt
68
- * to modify any instance-level globals. This is currently used
69
- * from within lcb_destroy()
70
- */
71
- NOLCB = 1 << 2
72
- };
73
-
74
- lcb_t instance; /**< Library handle */
75
- std::string url; /**<Base URL: http://host:port/path?query*/
76
- std::string host; /**< Host, derived from URL */
77
- std::string port; /**< Port, derived from URL */
78
-
79
- std::string pending_redirect; /**< New redirected URL */
80
- bool has_pending_redirect() const { return !pending_redirect.empty(); }
81
- const std::vector<char> body; /**< Input body (for POST/PUT) */
82
-
83
- /** Request buffer (excluding body). Reassembled from inputs */
84
- std::vector<char> preamble;
85
-
86
- struct http_parser_url url_info; /**< Parser info for the URL */
87
- const lcb_http_method_t method; /**< Request method constant */
88
- const bool chunked; /**< Whether to invoke callback for each data chunk */
89
- bool paused; /**< See pause() and resume() */
90
- const void * const command_cookie; /** User context for callback */
91
- size_t refcount; /** Initialized to 1. See incref() and decref() */
92
- int redircount; /** Times this request was redirected */
93
-
94
45
  /**
95
- * Whether this request has delivered data to the user. This is relevant
96
- * in cases where a retry is requested. If any data has been passed at
97
- * all, we cannot retry the request.
46
+ * Initializes the request. This simply copies the relevant fields from the
47
+ * body and initializes instance members to their default values. The static
48
+ * ::create() method should be used instead to construct a new object
98
49
  */
99
- bool passed_data;
50
+ inline Request(lcb_t instance, const void *cookie, const lcb_CMDHTTP* cmd);
100
51
 
101
- /** Sparse map indicating which nodes the request was already sent to */
102
- std::vector<int> used_nodes;
52
+ /** Creates a new request object and verifies the input (setup_inputs()) */
53
+ static Request * create(lcb_t instance, const void *cookie,
54
+ const lcb_CMDHTTP *cmd, lcb_error_t *rc);
103
55
 
104
- /**
105
- * Last revision ID of vBucket config. If the current revision does not
106
- * match this number, the ::used_nodes field is cleared
107
- */
108
- int last_vbcrev;
56
+ /** Pause IO on this request */
57
+ void pause();
109
58
 
110
- const lcb_http_type_t reqtype; /**< HTTP API type */
111
- int status; /**< OR'd flags of ::State */
112
- std::vector<Header> request_headers; /**< List of request headers */
59
+ /** Resume previously paused IO */
60
+ void resume();
61
+
62
+ /** Cancel and finish this request, suppressing callbacks */
63
+ void cancel();
113
64
 
114
65
  /**
115
- * Response headers for callback (array of char*). Buffers are mapped to
116
- * ::response_headers
66
+ * Start all operations required to make this request. This should be
67
+ * called once all inputs have been completed. If successful, I/O operations
68
+ * will begin (this function calls start_io())
117
69
  */
118
- std::vector<const char*> response_headers_clist;
119
-
120
- /** Backing buffers for response headers */
121
- std::vector<Header> response_headers;
122
-
123
- /** Callback to invoke */
124
- lcb_RESPCALLBACK callback;
125
-
126
- // IO variables
127
- lcbio_pTABLE io;
128
- lcbio_pCTX ioctx;
129
- lcbio_pTIMER timer;
130
- lcbio_CONNREQ creq;
131
-
132
- /** HTTP Protocol parser */
133
- lcbht_pPARSER parser;
134
-
135
- /** overrides default timeout if nonzero */
136
- const uint32_t user_timeout;
70
+ lcb_error_t submit();
137
71
 
72
+ bool has_pending_redirect() const { return !pending_redirect.empty(); }
138
73
  /**
139
74
  * @return The effective timeout. This is either the user timeout or the
140
75
  * default timeout for the API type
@@ -152,13 +87,6 @@ struct Request {
152
87
  */
153
88
  bool is_ongoing() const { return status == ONGOING; }
154
89
 
155
- /**
156
- * Initializes the request. This simply copies the relevant fields from the
157
- * body and initializes instance members to their default values. The static
158
- * ::create() method should be used instead to construct a new object
159
- */
160
- inline Request(lcb_t instance, const void *cookie, const lcb_CMDHTTP* cmd);
161
-
162
90
  /**
163
91
  * Sets up inputs from the command. This should really be in the
164
92
  * constructor, however we also need a return value. The ::create()
@@ -180,10 +108,6 @@ struct Request {
180
108
  const char *get_api_node(lcb_error_t &rc);
181
109
  const char *get_api_node() { lcb_error_t dummy; return get_api_node(dummy); }
182
110
 
183
- /** Creates a new request object and verifies the input (setup_inputs()) */
184
- static Request * create(lcb_t instance, const void *cookie,
185
- const lcb_CMDHTTP *cmd, lcb_error_t *rc);
186
-
187
111
  /**
188
112
  * Sets the URL for the field
189
113
  * @param base The URL base (i.e. http://foo.com)
@@ -220,13 +144,6 @@ struct Request {
220
144
  inline void add_to_preamble(const std::string&);
221
145
  inline void add_to_preamble(const Header&);
222
146
 
223
- /**
224
- * Start all operations required to make this request. This should be
225
- * called once all inputs have been completed. If successful, I/O operations
226
- * will begin (this function calls start_io())
227
- */
228
- lcb_error_t submit();
229
-
230
147
  /**
231
148
  * Starts the IO on the current request. This really belongs in submit(),
232
149
  * but submit() handles building the request while start_io() sets up
@@ -241,7 +158,7 @@ struct Request {
241
158
 
242
159
  // Helper functions for parsing response data from network
243
160
  inline int handle_parse_chunked(const char *buf, unsigned nbuf);
244
- inline void assign_response_headers(const lcbht_RESPONSE*);
161
+ inline void assign_response_headers(const lcb::htparse::Response&);
245
162
 
246
163
  /**
247
164
  * Called when a redirect has happened. pending_redirect must not be empty.
@@ -273,14 +190,15 @@ struct Request {
273
190
  **/
274
191
  void finish_or_retry(lcb_error_t rc);
275
192
 
276
- /** Pause IO on this request */
277
- void pause();
278
-
279
- /** Resume previously paused IO */
280
- void resume();
281
-
282
- /** Cancel and finish this request, suppressing callbacks */
283
- void cancel();
193
+ /**
194
+ * Change the callback for this request. This is used to indicate that
195
+ * a custom internal callback is used, rather than the one installed via
196
+ * lcb_install_callback3
197
+ * @param callback_ The internal callback to invoke
198
+ */
199
+ void set_callback(lcb_RESPCALLBACK callback_) {
200
+ callback = callback_;
201
+ }
284
202
 
285
203
  /**
286
204
  * Let the request finish its normal course, suppressing any callbacks.
@@ -297,6 +215,101 @@ struct Request {
297
215
 
298
216
  /** Increment refcount */
299
217
  void incref() { refcount++; }
218
+
219
+ lcb_t instance; /**< Library handle */
220
+ std::string url; /**<Base URL: http://host:port/path?query*/
221
+ std::string host; /**< Host, derived from URL */
222
+ std::string port; /**< Port, derived from URL */
223
+
224
+ std::string pending_redirect; /**< New redirected URL */
225
+
226
+ const std::vector<char> body; /**< Input body (for POST/PUT) */
227
+
228
+ /** Request buffer (excluding body). Reassembled from inputs */
229
+ std::vector<char> preamble;
230
+
231
+ struct http_parser_url url_info; /**< Parser info for the URL */
232
+ const lcb_http_method_t method; /**< Request method constant */
233
+ const bool chunked; /**< Whether to invoke callback for each data chunk */
234
+ bool paused; /**< See pause() and resume() */
235
+ const void * const command_cookie; /** User context for callback */
236
+ size_t refcount; /** Initialized to 1. See incref() and decref() */
237
+ int redircount; /** Times this request was redirected */
238
+
239
+ /**
240
+ * Whether this request has delivered data to the user. This is relevant
241
+ * in cases where a retry is requested. If any data has been passed at
242
+ * all, we cannot retry the request.
243
+ */
244
+ bool passed_data;
245
+
246
+ /** Sparse map indicating which nodes the request was already sent to */
247
+ std::vector<int> used_nodes;
248
+
249
+ /**
250
+ * Last revision ID of vBucket config. If the current revision does not
251
+ * match this number, the ::used_nodes field is cleared
252
+ */
253
+ int last_vbcrev;
254
+
255
+ const lcb_http_type_t reqtype; /**< HTTP API type */
256
+
257
+
258
+ enum State {
259
+ /**
260
+ * The request is still ongoing. Callbacks are still active.
261
+ * Note that this essentially means the absence of any flags :)
262
+ */
263
+ ONGOING = 0,
264
+
265
+ /**
266
+ * This flag is set when the on_complete callback has been invoked. This
267
+ * is used as a marker to prevent us from calling that callback more than
268
+ * once per request
269
+ */
270
+ CBINVOKED = 1 << 0,
271
+
272
+ /**
273
+ * This flag is set by lcb_http_request_finish, and indicates that the
274
+ * request is no longer active per se. This means that while the request
275
+ * may still be valid in memory, it is simply waiting for any pending I/O
276
+ * operations to close, so the reference count can hit zero.
277
+ */
278
+ FINISHED = 1 << 1,
279
+
280
+ /**
281
+ * Internal flag used to indicate that finish() should not not attempt
282
+ * to modify any instance-level globals. This is currently used
283
+ * from within lcb_destroy()
284
+ */
285
+ NOLCB = 1 << 2
286
+ };
287
+ int status; /**< OR'd flags of ::State */
288
+ std::vector<Header> request_headers; /**< List of request headers */
289
+
290
+ /**
291
+ * Response headers for callback (array of char*). Buffers are mapped to
292
+ * ::response_headers
293
+ */
294
+ std::vector<const char*> response_headers_clist;
295
+
296
+ /** Backing buffers for response headers */
297
+ std::vector<lcb::htparse::MimeHeader> response_headers;
298
+
299
+ /** Callback to invoke */
300
+ lcb_RESPCALLBACK callback;
301
+
302
+ // IO variables
303
+ lcbio_pTABLE io;
304
+ lcbio_pCTX ioctx;
305
+ lcbio_pTIMER timer;
306
+ lcb::io::ConnectionRequest *creq;
307
+
308
+ /** HTTP Protocol parser */
309
+ lcb::htparse::Parser* parser;
310
+
311
+ /** overrides default timeout if nonzero */
312
+ const uint32_t user_timeout;
300
313
  };
301
314
 
302
315
  } // namespace: http