libcouchbase 1.2.8 → 1.3.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 (186) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +4 -4
  3. data/README.md +16 -8
  4. data/ext/libcouchbase/CMakeLists.txt +34 -32
  5. data/ext/libcouchbase/RELEASE_NOTES.markdown +277 -6
  6. data/ext/libcouchbase/cmake/Modules/ConfigureDtrace.cmake +14 -0
  7. data/ext/libcouchbase/cmake/Modules/FindCouchbaseLibevent.cmake +2 -0
  8. data/ext/libcouchbase/cmake/Modules/FindCouchbaseLibuv.cmake +2 -1
  9. data/ext/libcouchbase/cmake/Modules/GenerateConfigDotH.cmake +2 -0
  10. data/ext/libcouchbase/cmake/Modules/GetLibcouchbaseFlags.cmake +8 -1
  11. data/ext/libcouchbase/cmake/Modules/GetVersionInfo.cmake +3 -3
  12. data/ext/libcouchbase/cmake/config-cmake.h.in +14 -0
  13. data/ext/libcouchbase/cmake/configure +8 -26
  14. data/ext/libcouchbase/cmake/defs.mk.in +2 -2
  15. data/ext/libcouchbase/cmake/libcouchbase.stp.in +829 -0
  16. data/ext/libcouchbase/cmake/source_files.cmake +11 -2
  17. data/ext/libcouchbase/contrib/cbsasl/CMakeLists.txt +18 -2
  18. data/ext/libcouchbase/contrib/cbsasl/include/cbsasl/cbsasl.h +44 -2
  19. data/ext/libcouchbase/contrib/cbsasl/src/client.c +285 -73
  20. data/ext/libcouchbase/contrib/cbsasl/src/common.c +4 -0
  21. data/ext/libcouchbase/contrib/cbsasl/src/scram-sha/scram_utils.c +500 -0
  22. data/ext/libcouchbase/contrib/cbsasl/src/scram-sha/scram_utils.h +99 -0
  23. data/ext/libcouchbase/contrib/cliopts/CMakeLists.txt +1 -1
  24. data/ext/libcouchbase/contrib/cliopts/cliopts.h +14 -1
  25. data/ext/libcouchbase/contrib/snappy/CMakeLists.txt +2 -3
  26. data/ext/libcouchbase/contrib/snappy/snappy-sinksource.cc +4 -0
  27. data/ext/libcouchbase/contrib/snappy/snappy-stubs-public.h +7 -5
  28. data/ext/libcouchbase/contrib/snappy/snappy.cc +7 -2
  29. data/ext/libcouchbase/example/crypto/.gitignore +2 -0
  30. data/ext/libcouchbase/example/crypto/Makefile +13 -0
  31. data/ext/libcouchbase/example/crypto/common_provider.c +24 -0
  32. data/ext/libcouchbase/example/crypto/common_provider.h +31 -0
  33. data/ext/libcouchbase/example/crypto/openssl_symmetric_decrypt.c +139 -0
  34. data/ext/libcouchbase/example/crypto/openssl_symmetric_encrypt.c +147 -0
  35. data/ext/libcouchbase/example/crypto/openssl_symmetric_provider.c +281 -0
  36. data/ext/libcouchbase/example/crypto/openssl_symmetric_provider.h +29 -0
  37. data/ext/libcouchbase/example/tracing/.gitignore +2 -0
  38. data/ext/libcouchbase/example/tracing/Makefile +8 -0
  39. data/ext/libcouchbase/example/tracing/cJSON.c +1 -0
  40. data/ext/libcouchbase/example/tracing/cJSON.h +1 -0
  41. data/ext/libcouchbase/example/tracing/tracing.c +439 -0
  42. data/ext/libcouchbase/example/tracing/views.c +444 -0
  43. data/ext/libcouchbase/include/libcouchbase/auth.h +56 -4
  44. data/ext/libcouchbase/include/libcouchbase/cbft.h +8 -0
  45. data/ext/libcouchbase/include/libcouchbase/cntl-private.h +55 -1
  46. data/ext/libcouchbase/include/libcouchbase/cntl.h +101 -1
  47. data/ext/libcouchbase/include/libcouchbase/configuration.h.in +6 -0
  48. data/ext/libcouchbase/include/libcouchbase/couchbase.h +109 -6
  49. data/ext/libcouchbase/include/libcouchbase/crypto.h +140 -0
  50. data/ext/libcouchbase/include/libcouchbase/error.h +38 -2
  51. data/ext/libcouchbase/include/libcouchbase/kvbuf.h +6 -1
  52. data/ext/libcouchbase/include/libcouchbase/metrics.h +79 -0
  53. data/ext/libcouchbase/include/libcouchbase/n1ql.h +9 -0
  54. data/ext/libcouchbase/include/libcouchbase/tracing.h +319 -0
  55. data/ext/libcouchbase/include/libcouchbase/vbucket.h +1 -1
  56. data/ext/libcouchbase/include/libcouchbase/views.h +8 -0
  57. data/ext/libcouchbase/include/memcached/protocol_binary.h +40 -10
  58. data/ext/libcouchbase/packaging/rpm/libcouchbase.spec.in +6 -14
  59. data/ext/libcouchbase/plugins/io/libuv/plugin-internal.h +3 -0
  60. data/ext/libcouchbase/plugins/io/libuv/plugin-libuv.c +1 -0
  61. data/ext/libcouchbase/plugins/io/select/plugin-select.c +4 -1
  62. data/ext/libcouchbase/src/auth-priv.h +36 -4
  63. data/ext/libcouchbase/src/auth.cc +66 -27
  64. data/ext/libcouchbase/src/bootstrap.cc +1 -1
  65. data/ext/libcouchbase/src/bucketconfig/bc_cccp.cc +12 -7
  66. data/ext/libcouchbase/src/bucketconfig/bc_http.cc +26 -17
  67. data/ext/libcouchbase/src/bucketconfig/bc_http.h +1 -1
  68. data/ext/libcouchbase/src/bucketconfig/clconfig.h +4 -2
  69. data/ext/libcouchbase/src/bucketconfig/confmon.cc +6 -3
  70. data/ext/libcouchbase/src/cbft.cc +48 -0
  71. data/ext/libcouchbase/src/cntl.cc +138 -2
  72. data/ext/libcouchbase/src/config_static.h +17 -0
  73. data/ext/libcouchbase/src/connspec.cc +54 -6
  74. data/ext/libcouchbase/src/connspec.h +9 -1
  75. data/ext/libcouchbase/src/crypto.cc +386 -0
  76. data/ext/libcouchbase/src/ctx-log-inl.h +23 -6
  77. data/ext/libcouchbase/src/dump.cc +4 -0
  78. data/ext/libcouchbase/src/getconfig.cc +1 -2
  79. data/ext/libcouchbase/src/handler.cc +65 -27
  80. data/ext/libcouchbase/src/hostlist.cc +35 -7
  81. data/ext/libcouchbase/src/hostlist.h +7 -0
  82. data/ext/libcouchbase/src/http/http-priv.h +2 -0
  83. data/ext/libcouchbase/src/http/http.cc +77 -37
  84. data/ext/libcouchbase/src/http/http_io.cc +19 -2
  85. data/ext/libcouchbase/src/instance.cc +90 -17
  86. data/ext/libcouchbase/src/internal.h +5 -0
  87. data/ext/libcouchbase/src/lcbio/connect.cc +39 -4
  88. data/ext/libcouchbase/src/lcbio/connect.h +27 -0
  89. data/ext/libcouchbase/src/lcbio/ctx.c +49 -23
  90. data/ext/libcouchbase/src/lcbio/ioutils.cc +30 -3
  91. data/ext/libcouchbase/src/lcbio/ioutils.h +2 -0
  92. data/ext/libcouchbase/src/lcbio/manager.cc +44 -8
  93. data/ext/libcouchbase/src/lcbio/manager.h +2 -0
  94. data/ext/libcouchbase/src/lcbio/rw-inl.h +1 -0
  95. data/ext/libcouchbase/src/lcbio/ssl.h +3 -5
  96. data/ext/libcouchbase/src/logging.c +1 -1
  97. data/ext/libcouchbase/src/logging.h +2 -0
  98. data/ext/libcouchbase/src/mc/compress.cc +164 -0
  99. data/ext/libcouchbase/src/mc/compress.h +7 -12
  100. data/ext/libcouchbase/src/mc/mcreq-flush-inl.h +5 -1
  101. data/ext/libcouchbase/src/mc/mcreq.c +11 -1
  102. data/ext/libcouchbase/src/mc/mcreq.h +35 -4
  103. data/ext/libcouchbase/src/mcserver/mcserver.cc +30 -7
  104. data/ext/libcouchbase/src/mcserver/mcserver.h +7 -0
  105. data/ext/libcouchbase/src/mcserver/negotiate.cc +103 -57
  106. data/ext/libcouchbase/src/mcserver/negotiate.h +2 -2
  107. data/ext/libcouchbase/src/mctx-helper.h +11 -0
  108. data/ext/libcouchbase/src/metrics.cc +132 -0
  109. data/ext/libcouchbase/src/n1ql/ixmgmt.cc +2 -1
  110. data/ext/libcouchbase/src/n1ql/n1ql.cc +66 -0
  111. data/ext/libcouchbase/src/newconfig.cc +9 -2
  112. data/ext/libcouchbase/src/operations/counter.cc +2 -1
  113. data/ext/libcouchbase/src/operations/durability-cas.cc +11 -0
  114. data/ext/libcouchbase/src/operations/durability-seqno.cc +3 -0
  115. data/ext/libcouchbase/src/operations/durability.cc +24 -2
  116. data/ext/libcouchbase/src/operations/durability_internal.h +19 -0
  117. data/ext/libcouchbase/src/operations/get.cc +4 -2
  118. data/ext/libcouchbase/src/operations/observe-seqno.cc +1 -0
  119. data/ext/libcouchbase/src/operations/observe.cc +113 -62
  120. data/ext/libcouchbase/src/operations/ping.cc +246 -67
  121. data/ext/libcouchbase/src/operations/remove.cc +2 -1
  122. data/ext/libcouchbase/src/operations/store.cc +17 -14
  123. data/ext/libcouchbase/src/operations/touch.cc +3 -0
  124. data/ext/libcouchbase/src/packetutils.h +68 -4
  125. data/ext/libcouchbase/src/probes.d +132 -161
  126. data/ext/libcouchbase/src/rdb/bigalloc.c +1 -1
  127. data/ext/libcouchbase/src/retryq.cc +6 -2
  128. data/ext/libcouchbase/src/rnd.cc +68 -0
  129. data/ext/libcouchbase/src/rnd.h +39 -0
  130. data/ext/libcouchbase/src/settings.c +27 -0
  131. data/ext/libcouchbase/src/settings.h +67 -3
  132. data/ext/libcouchbase/src/ssl/CMakeLists.txt +0 -12
  133. data/ext/libcouchbase/src/ssl/ssl_common.c +23 -4
  134. data/ext/libcouchbase/src/strcodecs/base64.c +141 -16
  135. data/ext/libcouchbase/src/strcodecs/strcodecs.h +16 -1
  136. data/ext/libcouchbase/src/trace.h +68 -61
  137. data/ext/libcouchbase/src/tracing/span.cc +289 -0
  138. data/ext/libcouchbase/src/tracing/threshold_logging_tracer.cc +171 -0
  139. data/ext/libcouchbase/src/tracing/tracer.cc +53 -0
  140. data/ext/libcouchbase/src/tracing/tracing-internal.h +213 -0
  141. data/ext/libcouchbase/src/utilities.c +5 -0
  142. data/ext/libcouchbase/src/vbucket/CMakeLists.txt +2 -2
  143. data/ext/libcouchbase/src/vbucket/vbucket.c +50 -18
  144. data/ext/libcouchbase/src/views/docreq.cc +26 -1
  145. data/ext/libcouchbase/src/views/docreq.h +17 -0
  146. data/ext/libcouchbase/src/views/viewreq.cc +64 -1
  147. data/ext/libcouchbase/src/views/viewreq.h +21 -0
  148. data/ext/libcouchbase/tests/CMakeLists.txt +6 -6
  149. data/ext/libcouchbase/tests/basic/t_base64.cc +34 -6
  150. data/ext/libcouchbase/tests/basic/t_connstr.cc +14 -0
  151. data/ext/libcouchbase/tests/basic/t_creds.cc +10 -10
  152. data/ext/libcouchbase/tests/basic/t_host.cc +22 -2
  153. data/ext/libcouchbase/tests/basic/t_scram.cc +514 -0
  154. data/ext/libcouchbase/tests/check-all.cc +6 -2
  155. data/ext/libcouchbase/tests/iotests/mock-environment.cc +64 -0
  156. data/ext/libcouchbase/tests/iotests/mock-environment.h +27 -1
  157. data/ext/libcouchbase/tests/iotests/t_confmon.cc +2 -2
  158. data/ext/libcouchbase/tests/iotests/t_forward.cc +8 -0
  159. data/ext/libcouchbase/tests/iotests/t_netfail.cc +124 -0
  160. data/ext/libcouchbase/tests/iotests/t_smoke.cc +1 -1
  161. data/ext/libcouchbase/tests/iotests/t_snappy.cc +316 -0
  162. data/ext/libcouchbase/tests/socktests/socktest.cc +2 -2
  163. data/ext/libcouchbase/tests/socktests/t_basic.cc +6 -6
  164. data/ext/libcouchbase/tests/socktests/t_manager.cc +1 -1
  165. data/ext/libcouchbase/tests/socktests/t_ssl.cc +1 -1
  166. data/ext/libcouchbase/tools/CMakeLists.txt +1 -1
  167. data/ext/libcouchbase/tools/cbc-handlers.h +17 -0
  168. data/ext/libcouchbase/tools/cbc-n1qlback.cc +7 -4
  169. data/ext/libcouchbase/tools/cbc-pillowfight.cc +408 -100
  170. data/ext/libcouchbase/tools/cbc-proxy.cc +134 -3
  171. data/ext/libcouchbase/tools/cbc-subdoc.cc +1 -2
  172. data/ext/libcouchbase/tools/cbc.cc +113 -8
  173. data/ext/libcouchbase/tools/common/histogram.cc +1 -0
  174. data/ext/libcouchbase/tools/common/options.cc +28 -1
  175. data/ext/libcouchbase/tools/common/options.h +5 -0
  176. data/ext/libcouchbase/tools/docgen/docgen.h +36 -10
  177. data/ext/libcouchbase/tools/docgen/loc.h +5 -4
  178. data/ext/libcouchbase/tools/docgen/seqgen.h +28 -0
  179. data/lib/libcouchbase/ext/libcouchbase/enums.rb +10 -0
  180. data/lib/libcouchbase/n1ql.rb +6 -1
  181. data/lib/libcouchbase/version.rb +1 -1
  182. data/spec/connection_spec.rb +6 -6
  183. metadata +38 -5
  184. data/ext/libcouchbase/cmake/Modules/FindCouchbaseSnappy.cmake +0 -11
  185. data/ext/libcouchbase/src/mc/compress.c +0 -90
  186. data/ext/libcouchbase/tools/common/my_inttypes.h +0 -22
@@ -16,12 +16,29 @@
16
16
  */
17
17
 
18
18
  /* small utility for retrieving host/port information from the CTX */
19
- static const char* get__ctx_hostinfo(const lcbio_CTX *ctx, int is_host)
19
+ static const lcb_host_t *get_ctx_host(const lcbio_CTX *ctx)
20
20
  {
21
- if (ctx == NULL || ctx->sock == NULL || ctx->sock->info == NULL) {
22
- return is_host ? "NOHOST" : "NOPORT";
21
+ static lcb_host_t host = {"NOHOST", "NOPORT", 0};
22
+ if (!ctx) {
23
+ return &host;
23
24
  }
24
- return is_host ? ctx->sock->info->ep.host : ctx->sock->info->ep.port;
25
+ if (!ctx->sock) {
26
+ return &host;
27
+ }
28
+ if (!ctx->sock->info) {
29
+ return &host;
30
+ }
31
+ return &ctx->sock->info->ep;
25
32
  }
26
- static const char *get_ctx_host(const lcbio_CTX *ctx) { return get__ctx_hostinfo(ctx, 1); }
27
- static const char *get_ctx_port(const lcbio_CTX *ctx) { return get__ctx_hostinfo(ctx, 0); }
33
+
34
+ #define CTX_LOGFMT_PRE "<" LCB_LOG_SPEC("%s%s%s:%s") "> (CTX=%p,%s"
35
+ #define CTX_LOGFMT CTX_LOGFMT_PRE ") "
36
+ #define CTX_LOGID(ctx) \
37
+ (ctx && ctx->sock && ctx->sock->settings->log_redaction) ? LCB_LOG_SD_OTAG : "", \
38
+ (get_ctx_host(ctx)->ipv6 ? "[" : ""), \
39
+ get_ctx_host(ctx)->host, \
40
+ (get_ctx_host(ctx)->ipv6 ? "]" : ""), \
41
+ get_ctx_host(ctx)->port, \
42
+ (ctx && ctx->sock && ctx->sock->settings->log_redaction) ? LCB_LOG_SD_CTAG : "", \
43
+ (void *)ctx, \
44
+ ctx ? ctx->subsys : ""
@@ -89,6 +89,10 @@ lcb_dump(lcb_t instance, FILE *fp, lcb_U32 flags)
89
89
  } else {
90
90
  fprintf(fp, "** == NOT DUMPING PACKETS. LCB_DUMP_PKTINFO not passed\n");
91
91
  }
92
+ if ((flags & LCB_DUMP_METRICS) && server->metrics) {
93
+ fprintf(fp, "=== SERVER METRICS ===\n");
94
+ lcb_metrics_dumpserver(server->metrics, fp);
95
+ }
92
96
  fprintf(fp, "\n\n");
93
97
  }
94
98
  fprintf(fp, "=== END PIPELINE DUMP ===\n");
@@ -28,8 +28,7 @@ ext_callback_proxy(mc_PIPELINE *pl, mc_PACKET *req, lcb_error_t rc,
28
28
  const lcb::MemcachedResponse *res =
29
29
  reinterpret_cast<const lcb::MemcachedResponse*>(resdata);
30
30
 
31
- lcb::clconfig::cccp_update(
32
- rd->cookie, rc, res->body<const char*>(), res->bodylen(),
31
+ lcb::clconfig::cccp_update(rd->cookie, rc, res->value(), res->vallen(),
33
32
  &server->get_host());
34
33
  free(rd);
35
34
  }
@@ -149,6 +149,24 @@ map_error(lcb_t instance, int in)
149
149
  return LCB_SUBDOC_PATH_EEXISTS;
150
150
  case PROTOCOL_BINARY_RESPONSE_SUBDOC_MULTI_PATH_FAILURE:
151
151
  return LCB_SUBDOC_MULTI_FAILURE;
152
+ case PROTOCOL_BINARY_RESPONSE_SUBDOC_INVALID_COMBO:
153
+ return LCB_SUBDOC_INVALID_COMBO;
154
+ case PROTOCOL_BINARY_RESPONSE_SUBDOC_SUCCESS_DELETED:
155
+ return LCB_SUBDOC_SUCCESS_DELETED;
156
+ case PROTOCOL_BINARY_RESPONSE_SUBDOC_XATTR_INVALID_FLAG_COMBO:
157
+ return LCB_SUBDOC_XATTR_INVALID_FLAG_COMBO;
158
+ case PROTOCOL_BINARY_RESPONSE_SUBDOC_XATTR_INVALID_KEY_COMBO:
159
+ return LCB_SUBDOC_XATTR_INVALID_KEY_COMBO;
160
+ case PROTOCOL_BINARY_RESPONSE_SUBDOC_XATTR_UNKNOWN_MACRO:
161
+ return LCB_SUBDOC_XATTR_UNKNOWN_MACRO;
162
+ case PROTOCOL_BINARY_RESPONSE_SUBDOC_XATTR_UNKNOWN_VATTR:
163
+ return LCB_SUBDOC_XATTR_UNKNOWN_VATTR;
164
+ case PROTOCOL_BINARY_RESPONSE_SUBDOC_XATTR_CANT_MODIFY_VATTR:
165
+ return LCB_SUBDOC_XATTR_CANT_MODIFY_VATTR;
166
+ case PROTOCOL_BINARY_RESPONSE_SUBDOC_MULTI_PATH_FAILURE_DELETED:
167
+ return LCB_SUBDOC_MULTI_PATH_FAILURE_DELETED;
168
+ case PROTOCOL_BINARY_RESPONSE_SUBDOC_INVALID_XATTR_ORDER:
169
+ return LCB_SUBDOC_INVALID_XATTR_ORDER;
152
170
  case PROTOCOL_BINARY_RESPONSE_EINVAL:
153
171
  return LCB_EINVAL_MCD;
154
172
  case PROTOCOL_BINARY_RESPONSE_NOT_STORED:
@@ -165,6 +183,8 @@ map_error(lcb_t instance, int in)
165
183
  return LCB_NOT_SUPPORTED;
166
184
  case PROTOCOL_BINARY_RESPONSE_EACCESS:
167
185
  return LCB_NOT_AUTHORIZED;
186
+ case PROTOCOL_BINARY_RESPONSE_UNKNOWN_COLLECTION:
187
+ return LCB_EINVAL;
168
188
  default:
169
189
  if (instance != NULL) {
170
190
  return instance->callbacks.errmap(instance, in);
@@ -271,7 +291,7 @@ handle_mutation_token(lcb_t instance, const MemcachedResponse *mc_resp,
271
291
  }
272
292
  }
273
293
 
274
- sbuf = mc_resp->body<const char*>();
294
+ sbuf = mc_resp->ext();
275
295
  vbid = mcreq_get_vbucket(req);
276
296
  stok->vbid_ = vbid;
277
297
  memcpy(&stok->uuid_, sbuf, 8);
@@ -362,19 +382,20 @@ H_get(mc_PIPELINE *pipeline, mc_PACKET *request, MemcachedResponse* response,
362
382
  resp.rflags |= LCB_RESP_F_FINAL;
363
383
 
364
384
  if (resp.rc == LCB_SUCCESS) {
365
- const protocol_binary_response_get *get =
366
- reinterpret_cast<const protocol_binary_response_get*>(
367
- response->ephemeral_start());
368
385
  resp.datatype = response->datatype();
369
- resp.itmflags = ntohl(get->message.body.flags);
370
386
  resp.value = response->value();
371
387
  resp.nvalue = response->vallen();
372
388
  resp.bufh = response->bufseg();
389
+ if (response->extlen() == sizeof(uint32_t)) {
390
+ memcpy(&resp.itmflags, response->ext(), sizeof(uint32_t));
391
+ resp.itmflags = ntohl(resp.itmflags);
392
+ }
373
393
  }
374
394
 
375
395
  void *freeptr = NULL;
376
396
  maybe_decompress(o, response, &resp, &freeptr);
377
- TRACE_GET_END(response, &resp);
397
+ LCBTRACE_KV_FINISH(pipeline, request, response);
398
+ TRACE_GET_END(o, request, response, &resp);
378
399
  invoke_callback(request, o, &resp, LCB_CALLBACK_GET);
379
400
  free(freeptr);
380
401
  }
@@ -393,14 +414,14 @@ H_getreplica(mc_PIPELINE *pipeline, mc_PACKET *request,
393
414
  handle_error_info(response, &w);
394
415
 
395
416
  if (resp.rc == LCB_SUCCESS) {
396
- const protocol_binary_response_get *get =
397
- reinterpret_cast<const protocol_binary_response_get*>(
398
- response->ephemeral_start());
399
- resp.itmflags = ntohl(get->message.body.flags);
400
417
  resp.datatype = response->datatype();
401
418
  resp.value = response->value();
402
419
  resp.nvalue = response->vallen();
403
420
  resp.bufh = response->bufseg();
421
+ if (response->extlen() == sizeof(uint32_t)) {
422
+ memcpy(&resp.itmflags, response->ext(), sizeof(uint32_t));
423
+ resp.itmflags = ntohl(resp.itmflags);
424
+ }
404
425
  }
405
426
 
406
427
  maybe_decompress(instance, response, &resp, &freeptr);
@@ -533,6 +554,7 @@ sdmutate_next(const MemcachedResponse *response, lcb_SDENTRY *ent, size_t *iter)
533
554
  ent->nvalue = 0;
534
555
  }
535
556
 
557
+ (void)buf_end;
536
558
  return 1;
537
559
  #undef ADVANCE_BUF
538
560
  }
@@ -585,7 +607,8 @@ H_delete(mc_PIPELINE *pipeline, mc_PACKET *packet, MemcachedResponse *response,
585
607
  init_resp(root, response, packet, immerr, &w.resp);
586
608
  handle_error_info(response, &w);
587
609
  handle_mutation_token(root, response, packet, &w.mt);
588
- TRACE_REMOVE_END(response, &w.resp);
610
+ LCBTRACE_KV_FINISH(pipeline, packet, response);
611
+ TRACE_REMOVE_END(root, packet, response, &w.resp);
589
612
  invoke_callback(packet, root, &w.resp, LCB_CALLBACK_REMOVE);
590
613
  }
591
614
 
@@ -620,8 +643,8 @@ H_observe(mc_PIPELINE *pipeline, mc_PACKET *request, MemcachedResponse *response
620
643
  ttr = ntohl(ttr);
621
644
 
622
645
  /** Actual payload sequence of (vb, nkey, key). Repeats multiple times */
623
- ptr = response->body<const char *>();
624
- end = ptr + response->bodylen();
646
+ ptr = response->value();
647
+ end = ptr + response->vallen();
625
648
  config = pipeline->parent->config;
626
649
 
627
650
  for (pos = 0; ptr < end; pos++) {
@@ -648,14 +671,15 @@ H_observe(mc_PIPELINE *pipeline, mc_PACKET *request, MemcachedResponse *response
648
671
  resp.cas = lcb_ntohll(cas);
649
672
  resp.status = obs;
650
673
  resp.ismaster = pipeline->index == lcbvb_vbmaster(config, vb);
651
- resp.ttp = 0;
652
- resp.ttr = 0;
653
- TRACE_OBSERVE_PROGRESS(response, &resp);
674
+ resp.ttp = ttp;
675
+ resp.ttr = ttr;
676
+ TRACE_OBSERVE_PROGRESS(root, request, response, &resp);
677
+ LCBTRACE_KV_FINISH(pipeline, request, response);
654
678
  if (! (request->flags & MCREQ_F_INVOKED)) {
655
679
  rd->procs->handler(pipeline, request, resp.rc, &resp);
656
680
  }
657
681
  }
658
- TRACE_OBSERVE_END(response);
682
+ TRACE_OBSERVE_END(root, request, response);
659
683
  }
660
684
 
661
685
  static void
@@ -668,7 +692,7 @@ H_observe_seqno(mc_PIPELINE *pipeline, mc_PACKET *request,
668
692
  resp.server_index = pipeline->index;
669
693
 
670
694
  if (resp.rc == LCB_SUCCESS) {
671
- const uint8_t *data = response->body<const uint8_t*>();
695
+ const uint8_t *data = reinterpret_cast<const uint8_t *>(response->value());
672
696
  bool is_failover = *data != 0;
673
697
 
674
698
  data++;
@@ -690,6 +714,7 @@ H_observe_seqno(mc_PIPELINE *pipeline, mc_PACKET *request,
690
714
  /* Get the server for this command. Note that since this is a successful
691
715
  * operation, the server is never a dummy */
692
716
  }
717
+ LCBTRACE_KV_FINISH(pipeline, request, response);
693
718
  invoke_callback(request, root, &resp, LCB_CALLBACK_OBSEQNO);
694
719
  }
695
720
 
@@ -722,10 +747,12 @@ H_store(mc_PIPELINE *pipeline, mc_PACKET *request, MemcachedResponse *response,
722
747
  }
723
748
  w.resp.rflags |= LCB_RESP_F_EXTDATA | LCB_RESP_F_FINAL;
724
749
  handle_mutation_token(root, response, request, &w.mt);
725
- TRACE_STORE_END(response, &w.resp);
750
+ TRACE_STORE_END(root, request, response, &w.resp);
726
751
  if (request->flags & MCREQ_F_REQEXT) {
752
+ LCBTRACE_KV_COMPLETE(pipeline, request, response);
727
753
  request->u_rdata.exdata->procs->handler(pipeline, request, immerr, &w.resp);
728
754
  } else {
755
+ LCBTRACE_KV_FINISH(pipeline, request, response);
729
756
  invoke_callback(request, root, &w.resp, LCB_CALLBACK_STORE);
730
757
  }
731
758
  }
@@ -748,7 +775,8 @@ H_arithmetic(mc_PIPELINE *pipeline, mc_PACKET *request,
748
775
  }
749
776
  w.resp.rflags |= LCB_RESP_F_FINAL;
750
777
  w.resp.cas = response->cas();
751
- TRACE_ARITHMETIC_END(response, &w.resp);
778
+ LCBTRACE_KV_FINISH(pipeline, request, response);
779
+ TRACE_ARITHMETIC_END(root, request, response, &w.resp);
752
780
  invoke_callback(request, root, &w.resp, LCB_CALLBACK_COUNTER);
753
781
  }
754
782
 
@@ -803,9 +831,9 @@ H_version(mc_PIPELINE *pipeline, mc_PACKET *request,
803
831
 
804
832
  make_error(root, &resp, response, immerr);
805
833
 
806
- if (response->bodylen()) {
807
- resp.mcversion = response->body<const char *>();
808
- resp.nversion = response->bodylen();
834
+ if (response->vallen()) {
835
+ resp.mcversion = response->value();
836
+ resp.nversion = response->vallen();
809
837
  }
810
838
 
811
839
 
@@ -835,7 +863,8 @@ H_touch(mc_PIPELINE *pipeline, mc_PACKET *request, MemcachedResponse *response,
835
863
  init_resp(root, response, request, immerr, &resp);
836
864
  handle_error_info(response, &w);
837
865
  resp.rflags |= LCB_RESP_F_FINAL;
838
- TRACE_TOUCH_END(response, &resp);
866
+ LCBTRACE_KV_FINISH(pipeline, request, response);
867
+ TRACE_TOUCH_END(root, request, response, &resp);
839
868
  invoke_callback(request, root, &resp, LCB_CALLBACK_TOUCH);
840
869
  }
841
870
 
@@ -860,7 +889,8 @@ H_unlock(mc_PIPELINE *pipeline, mc_PACKET *request, MemcachedResponse *response,
860
889
  init_resp(root, response, request, immerr, &resp);
861
890
  handle_error_info(response, &w);
862
891
  resp.rflags |= LCB_RESP_F_FINAL;
863
- TRACE_UNLOCK_END(response, &resp);
892
+ LCBTRACE_KV_FINISH(pipeline, request, response);
893
+ TRACE_UNLOCK_END(root, request, response, &resp);
864
894
  invoke_callback(request, root, &resp, LCB_CALLBACK_UNLOCK);
865
895
  }
866
896
 
@@ -880,9 +910,17 @@ static void
880
910
  record_metrics(mc_PIPELINE *pipeline, mc_PACKET *req, MemcachedResponse *)
881
911
  {
882
912
  lcb_t instance = get_instance(pipeline);
913
+ if (
914
+ #ifdef HAVE_DTRACE
915
+ 1
916
+ #else
917
+ instance->kv_timings
918
+ #endif
919
+ ) {
920
+ MCREQ_PKT_RDATA(req)->dispatch = gethrtime();
921
+ }
883
922
  if (instance->kv_timings) {
884
- lcb_histogram_record(instance->kv_timings,
885
- gethrtime() - MCREQ_PKT_RDATA(req)->start);
923
+ lcb_histogram_record(instance->kv_timings, MCREQ_PKT_RDATA(req)->dispatch - MCREQ_PKT_RDATA(req)->start);
886
924
  }
887
925
  }
888
926
 
@@ -48,6 +48,7 @@ lcb_host_parse(lcb_host_t *host, const char *spec, int speclen, int deflport)
48
48
  char *host_s;
49
49
  char *port_s;
50
50
  char *delim;
51
+ bool ipv6 = false;
51
52
 
52
53
  /** Parse the host properly */
53
54
  if (speclen < 0) {
@@ -64,10 +65,6 @@ lcb_host_parse(lcb_host_t *host, const char *spec, int speclen, int deflport)
64
65
  zspec.push_back('\0');
65
66
  host_s = &zspec[0];
66
67
 
67
- if (*host_s == ':') {
68
- return LCB_INVALID_HOST_FORMAT;
69
- }
70
-
71
68
  if ( (delim = strstr(host_s, "://"))) {
72
69
  host_s = delim + 3;
73
70
  }
@@ -77,6 +74,24 @@ lcb_host_parse(lcb_host_t *host, const char *spec, int speclen, int deflport)
77
74
  }
78
75
 
79
76
  port_s = strstr(host_s, ":");
77
+ if (port_s != NULL && strstr(port_s + 1, ":") != NULL) {
78
+ ipv6 = true;
79
+ // treat as IPv6 address
80
+ if (host_s[0] == '[') {
81
+ host_s++;
82
+ char *hostend = strstr(host_s, "]");
83
+ if (hostend == NULL) {
84
+ return LCB_INVALID_HOST_FORMAT;
85
+ }
86
+ port_s = hostend + 1;
87
+ if (*port_s != ':' || (size_t)(port_s - host_s) >= strlen(host_s)) {
88
+ port_s = NULL;
89
+ }
90
+ *hostend = '\0';
91
+ } else {
92
+ port_s = NULL;
93
+ }
94
+ }
80
95
  if (port_s != NULL) {
81
96
  char *endp;
82
97
  long ll;
@@ -118,6 +133,13 @@ lcb_host_parse(lcb_host_t *host, const char *spec, int speclen, int deflport)
118
133
  case '-':
119
134
  case '_':
120
135
  break;
136
+ case ':':
137
+ case '[':
138
+ case ']':
139
+ if (ipv6) {
140
+ break;
141
+ }
142
+ /* fallthrough */
121
143
  default:
122
144
  return LCB_INVALID_HOST_FORMAT;
123
145
  }
@@ -129,6 +151,7 @@ lcb_host_parse(lcb_host_t *host, const char *spec, int speclen, int deflport)
129
151
  } else {
130
152
  sprintf(host->port, "%d", deflport);
131
153
  }
154
+ host->ipv6 = ipv6;
132
155
 
133
156
  return LCB_SUCCESS;
134
157
  }
@@ -152,7 +175,7 @@ Hostlist::exists(const lcb_host_t& host) const
152
175
  bool
153
176
  Hostlist::exists(const char *s) const
154
177
  {
155
- lcb_host_t tmp;
178
+ lcb_host_t tmp = {"", "", 0};
156
179
  if (lcb_host_parse(&tmp, s, -1, 1) != LCB_SUCCESS) {
157
180
  return false;
158
181
  }
@@ -189,7 +212,7 @@ Hostlist::add(const char *hostport, long len, int deflport)
189
212
  const char *curstart = ss.c_str();
190
213
  const char *delim;
191
214
  while ( (delim = strstr(curstart, ";"))) {
192
- lcb_host_t curhost;
215
+ lcb_host_t curhost = {"", "", 0};
193
216
  size_t curlen;
194
217
 
195
218
  if (delim == curstart) {
@@ -243,7 +266,12 @@ void Hostlist::ensure_strlist() {
243
266
  }
244
267
  for (size_t ii = 0; ii < hosts.size(); ii++) {
245
268
  const lcb_host_t& host = hosts[ii];
246
- std::string ss(host.host);
269
+ std::string ss;
270
+ if (host.ipv6) {
271
+ ss.append("[").append(host.host).append("]");
272
+ } else {
273
+ ss.append(host.host);
274
+ }
247
275
  ss.append(":").append(host.port);
248
276
  char *newstr = new char[ss.size() + 1];
249
277
  newstr[ss.size()] = '\0';
@@ -28,8 +28,15 @@
28
28
  typedef struct lcb_host_st {
29
29
  char host[NI_MAXHOST + 1];
30
30
  char port[NI_MAXSERV + 1];
31
+ int ipv6;
31
32
  } lcb_host_t;
32
33
 
34
+ #define LCB_HOST_FMT LCB_LOG_SPEC("%s%s%s:%s")
35
+ #define LCB_HOST_ARG(__settings, __host) \
36
+ ((__settings && __settings->log_redaction) ? LCB_LOG_SD_OTAG : ""), \
37
+ ((__host)->ipv6 ? "[" : ""), (__host)->host, ((__host)->ipv6 ? "]" : ""), (__host)->port, \
38
+ ((__settings && __settings->log_redaction) ? LCB_LOG_SD_CTAG : "") \
39
+
33
40
  /**
34
41
  * Structure representing a list of hosts. This has an internal iteration
35
42
  * index which is used to cycle between 'good' and 'bad' hosts.
@@ -221,6 +221,7 @@ struct Request {
221
221
  std::string url; /**<Base URL: http://host:port/path?query*/
222
222
  std::string host; /**< Host, derived from URL */
223
223
  std::string port; /**< Port, derived from URL */
224
+ bool ipv6;
224
225
 
225
226
  std::string pending_redirect; /**< New redirected URL */
226
227
 
@@ -313,6 +314,7 @@ struct Request {
313
314
  const uint32_t user_timeout;
314
315
 
315
316
  hrtime_t start; /**< Start time */
317
+ lcbio_SERVICE service;
316
318
  };
317
319
 
318
320
  } // namespace: http
@@ -20,10 +20,13 @@
20
20
  #include "http/http.h"
21
21
  #include "http/http-priv.h"
22
22
  #include "auth-priv.h"
23
+ #include "trace.h"
24
+
23
25
  using namespace lcb::http;
24
26
 
25
- #define LOGFMT "<%s:%s> "
26
- #define LOGID(req) (req)->host.c_str(), (req)->port.c_str()
27
+ #define LOGFMT "<%s%s%s:%s> "
28
+ #define LOGID(req) ((req)->ipv6 ? "[" : ""), (req)->host.c_str(), ((req)->ipv6 ? "]" : ""), (req)->port.c_str()
29
+
27
30
  #define LOGARGS(req, lvl) req->instance->settings, "http-io", LCB_LOG_##lvl, __FILE__, __LINE__
28
31
 
29
32
  static const char *method_strings[] = {
@@ -83,19 +86,35 @@ Request::finish_or_retry(lcb_error_t rc)
83
86
  finish(rc);
84
87
  return;
85
88
  }
89
+ struct http_parser_url next_info;
90
+ if (_lcb_http_parser_parse_url(nextnode, strlen(nextnode), 0, &next_info)) {
91
+ lcb_log(LOGARGS(this, WARN), LOGFMT "Not retrying. Invalid API endpoint", LOGID(this));
92
+ finish(LCB_EINVAL);
93
+ return;
94
+ }
86
95
 
87
96
  // Reassemble URL:
97
+ lcb_log(LOGARGS(this, DEBUG), LOGFMT "Retrying request on new node %s. Reason: 0x%02x (%s)", LOGID(this), nextnode,
98
+ rc, lcb_strerror(NULL, rc));
88
99
 
89
- // get offset and length of host bits
90
- size_t host_begin = url_info.field_data[UF_HOST].off;
91
- size_t hplen =
92
- url_info.field_data[UF_HOST].len +
93
- url_info.field_data[UF_PORT].len + 1; // +1 for ":"
100
+ url.replace(url_info.field_data[UF_PORT].off, url_info.field_data[UF_PORT].len,
101
+ nextnode + next_info.field_data[UF_PORT].off, next_info.field_data[UF_PORT].len);
102
+ url.replace(url_info.field_data[UF_HOST].off, url_info.field_data[UF_HOST].len,
103
+ nextnode + next_info.field_data[UF_HOST].off, next_info.field_data[UF_HOST].len);
94
104
 
95
- url.replace(host_begin, hplen, nextnode);
96
- lcb_error_t newrc = submit();
105
+ lcb_error_t newrc;
106
+ newrc = assign_url(NULL, 0, NULL, 0);
97
107
  if (newrc != LCB_SUCCESS) {
98
- lcb_log(LOGARGS(this, WARN), LOGFMT "Retry failed!", LOGID(this));
108
+ lcb_log(LOGARGS(this, ERR), LOGFMT "Failed to assign URL for retry request on next endpoint (%s): 0x%02x (%s)",
109
+ LOGID(this), nextnode, newrc, lcb_strerror(NULL, newrc));
110
+ finish(rc);
111
+ return;
112
+ }
113
+
114
+ newrc = submit();
115
+ if (newrc != LCB_SUCCESS) {
116
+ lcb_log(LOGARGS(this, WARN), LOGFMT "Failed to retry request on next endpoint (%s): 0x%02x (%s)", LOGID(this),
117
+ nextnode, newrc, lcb_strerror(NULL, newrc));
99
118
  finish(rc);
100
119
  }
101
120
  }
@@ -165,6 +184,7 @@ Request::finish(lcb_error_t error)
165
184
  return;
166
185
  }
167
186
 
187
+ TRACE_HTTP_END(this, error, parser->get_cur_response().status);
168
188
  status |= FINISHED;
169
189
 
170
190
  if (!(status & NOLCB)) {
@@ -199,7 +219,7 @@ lcb_error_t
199
219
  Request::submit()
200
220
  {
201
221
  lcb_error_t rc;
202
- lcb_host_t reqhost;
222
+ lcb_host_t reqhost = {"", "", 0};
203
223
 
204
224
  // Stop any pending socket/request
205
225
  close_io();
@@ -215,6 +235,7 @@ Request::submit()
215
235
  strncpy(reqhost.port, port.c_str(), port.size());
216
236
  reqhost.host[host.size()] = '\0';
217
237
  reqhost.port[port.size()] = '\0';
238
+ reqhost.ipv6 = ipv6;
218
239
 
219
240
  // Add the HTTP verb (e.g. "GET ") [note, the string contains a trailing space]
220
241
  add_to_preamble(method_strings[method]);
@@ -225,7 +246,8 @@ Request::submit()
225
246
  size_t path_len = url.size() - path_off;
226
247
  preamble.insert(preamble.end(),
227
248
  url_s + path_off, url_s + path_off + path_len);
228
- lcb_log(LOGARGS(this, TRACE), LOGFMT "%s %s. Body=%lu bytes", LOGID(this), method_strings[method], url.c_str(), body.size());
249
+ lcb_log(LOGARGS(this, TRACE), LOGFMT "%s %s. Body=%lu bytes", LOGID(this), method_strings[method], url.c_str(),
250
+ (unsigned long int)body.size());
229
251
 
230
252
  add_to_preamble(" HTTP/1.1\r\n");
231
253
 
@@ -258,6 +280,7 @@ Request::submit()
258
280
  }
259
281
  response_headers.clear();
260
282
  response_headers_clist.clear();
283
+ TRACE_HTTP_BEGIN(this);
261
284
  }
262
285
 
263
286
  return rc;
@@ -328,6 +351,7 @@ Request::assign_url(const char *base, size_t nbase, const char *path, size_t npa
328
351
 
329
352
  assign_from_urlfield(UF_HOST, host);
330
353
  assign_from_urlfield(UF_PORT, port);
354
+ ipv6 = host.find(':') != std::string::npos;
331
355
  return LCB_SUCCESS;
332
356
  }
333
357
 
@@ -408,23 +432,24 @@ Request::get_api_node(lcb_error_t &rc)
408
432
  return lcbvb_get_resturl(vbc, ix, svc, mode);
409
433
  }
410
434
 
411
- static bool is_nonempty(const char *s) {
412
- return s != NULL && *s != '\0';
413
- }
414
-
415
435
  lcb_error_t
416
436
  Request::setup_inputs(const lcb_CMDHTTP *cmd)
417
437
  {
418
- const char *base = NULL, *username, *password;
438
+ std::string username, password;
439
+ const char *base = NULL;
419
440
  size_t nbase = 0;
420
- lcb_error_t rc;
441
+ lcb_error_t rc = LCB_SUCCESS;
421
442
 
422
443
  if (method > LCB_HTTP_METHOD_MAX) {
423
444
  return LCB_EINVAL;
424
445
  }
425
446
 
426
- username = cmd->username;
427
- password = cmd->password;
447
+ if (cmd->username) {
448
+ username = cmd->username;
449
+ }
450
+ if (cmd->password) {
451
+ password = cmd->password;
452
+ }
428
453
 
429
454
  if (reqtype == LCB_HTTP_TYPE_RAW) {
430
455
  if ((base = cmd->host) == NULL) {
@@ -434,19 +459,6 @@ Request::setup_inputs(const lcb_CMDHTTP *cmd)
434
459
  if (cmd->host) {
435
460
  return LCB_EINVAL;
436
461
  }
437
- if (cmd->cmdflags & LCB_CMDHTTP_F_NOUPASS) {
438
- username = password = NULL;
439
- } else if (username == NULL && password == NULL) {
440
- const Authenticator& auth = *LCBT_SETTING(instance, auth);
441
- if (reqtype == LCB_HTTP_TYPE_MANAGEMENT) {
442
- username = auth.username().c_str();
443
- password = auth.password().c_str();
444
- } else {
445
- username = auth.username_for(LCBT_SETTING(instance, bucket)).c_str();
446
- password = auth.password_for(LCBT_SETTING(instance, bucket)).c_str();
447
- }
448
- }
449
-
450
462
  base = get_api_node(rc);
451
463
  if (base == NULL || *base == '\0') {
452
464
  if (rc == LCB_SUCCESS) {
@@ -455,6 +467,34 @@ Request::setup_inputs(const lcb_CMDHTTP *cmd)
455
467
  return rc;
456
468
  }
457
469
  }
470
+
471
+ if ((cmd->cmdflags & LCB_CMDHTTP_F_NOUPASS) || instance->settings->keypath) {
472
+ // explicitly asked to skip Authorization header,
473
+ // or using SSL client certificate to authenticate
474
+ username.clear();
475
+ password.clear();
476
+ } else if (username.empty() && password.empty()) {
477
+ const Authenticator& auth = *LCBT_SETTING(instance, auth);
478
+ if (reqtype == LCB_HTTP_TYPE_MANAGEMENT) {
479
+ username = auth.username();
480
+ password = auth.password();
481
+ } else {
482
+ if (auth.mode() == LCBAUTH_MODE_DYNAMIC) {
483
+ struct http_parser_url info = {};
484
+ if (_lcb_http_parser_parse_url(base, strlen(base), 0, &info)) {
485
+ lcb_log(LOGARGS(this, WARN), LOGFMT "Failed to parse API endpoint", LOGID(this));
486
+ return LCB_EINTERNAL;
487
+ }
488
+ std::string hh(base + info.field_data[UF_HOST].off, info.field_data[UF_HOST].len);
489
+ std::string pp(base + info.field_data[UF_PORT].off, info.field_data[UF_PORT].len);
490
+ username = auth.username_for(hh.c_str(), pp.c_str(), LCBT_SETTING(instance, bucket));
491
+ password = auth.password_for(hh.c_str(), pp.c_str(), LCBT_SETTING(instance, bucket));
492
+ } else {
493
+ username = auth.username_for(NULL, NULL, LCBT_SETTING(instance, bucket));
494
+ password = auth.password_for(NULL, NULL, LCBT_SETTING(instance, bucket));
495
+ }
496
+ }
497
+ }
458
498
  }
459
499
 
460
500
  if (base) {
@@ -468,7 +508,7 @@ Request::setup_inputs(const lcb_CMDHTTP *cmd)
468
508
  return rc;
469
509
  }
470
510
 
471
- std::string ua("libcouchbase/" LCB_VERSION_STRING);
511
+ std::string ua(LCB_CLIENT_ID);
472
512
  if (instance->settings->client_string) {
473
513
  ua.append(" ").append(instance->settings->client_string);
474
514
  }
@@ -479,11 +519,11 @@ Request::setup_inputs(const lcb_CMDHTTP *cmd)
479
519
  }
480
520
 
481
521
  add_header("Accept", "application/json");
482
- if (is_nonempty(password) && is_nonempty(username)) {
522
+ if (!username.empty()) {
483
523
  char auth[256];
484
524
  std::string upassbuf;
485
525
  upassbuf.append(username).append(":").append(password);
486
- if (lcb_base64_encode(upassbuf.c_str(), auth, sizeof(auth)) == -1) {
526
+ if (lcb_base64_encode(upassbuf.c_str(), upassbuf.size(), auth, sizeof(auth)) == -1) {
487
527
  return LCB_EINVAL;
488
528
  }
489
529
  add_header("Authorization", std::string("Basic ") + auth);
@@ -491,7 +531,7 @@ Request::setup_inputs(const lcb_CMDHTTP *cmd)
491
531
 
492
532
  if (!body.empty()) {
493
533
  char lenbuf[64];
494
- sprintf(lenbuf, "%ld", body.size());
534
+ sprintf(lenbuf, "%lu", (unsigned long int)body.size());
495
535
  add_header("Content-Length", lenbuf);
496
536
  if (cmd->content_type) {
497
537
  add_header("Content-Type", cmd->content_type);