libcouchbase 1.2.8 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
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);