couchbase 3.2.3 → 3.2.4

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 (100) hide show
  1. package/deps/lcb/CMakeLists.txt +1 -1
  2. package/deps/lcb/CONTRIBUTING.md +1 -1
  3. package/deps/lcb/README.markdown +2 -2
  4. package/deps/lcb/RELEASE_NOTES.markdown +72 -17
  5. package/deps/lcb/cmake/Modules/GetVersionInfo.cmake +1 -1
  6. package/deps/lcb/contrib/cbsasl/src/scram-sha/scram_utils.cc +22 -26
  7. package/deps/lcb/contrib/lcb-jsoncpp/lcb-jsoncpp.cpp +20 -6
  8. package/deps/lcb/doc/Doxyfile +1 -1
  9. package/deps/lcb/example/minimal/query.c +9 -7
  10. package/deps/lcb/gyp_config/common/libcouchbase/configuration.h +3 -3
  11. package/deps/lcb/include/libcouchbase/couchbase.h +3 -1
  12. package/deps/lcb/include/libcouchbase/error.h +2 -0
  13. package/deps/lcb/include/libcouchbase/ixmgmt.h +15 -10
  14. package/deps/lcb/include/libcouchbase/tracing.h +2 -2
  15. package/deps/lcb/include/memcached/protocol_binary.h +21 -0
  16. package/deps/lcb/libcouchbase.gyp +347 -349
  17. package/deps/lcb/packaging/deb/control +1 -1
  18. package/deps/lcb/src/analytics/analytics_handle.cc +7 -5
  19. package/deps/lcb/src/analytics/analytics_handle.hh +28 -0
  20. package/deps/lcb/src/capi/cmd_counter.hh +6 -0
  21. package/deps/lcb/src/capi/cmd_exists.hh +6 -0
  22. package/deps/lcb/src/capi/cmd_get.hh +5 -0
  23. package/deps/lcb/src/capi/cmd_get_replica.hh +6 -0
  24. package/deps/lcb/src/capi/cmd_remove.hh +6 -0
  25. package/deps/lcb/src/capi/cmd_search.hh +6 -0
  26. package/deps/lcb/src/capi/cmd_store.hh +16 -21
  27. package/deps/lcb/src/capi/cmd_subdoc.hh +18 -0
  28. package/deps/lcb/src/capi/cmd_touch.hh +6 -0
  29. package/deps/lcb/src/capi/cmd_unlock.hh +6 -0
  30. package/deps/lcb/src/capi/cmd_view.hh +6 -0
  31. package/deps/lcb/src/capi/collection_qualifier.hh +2 -2
  32. package/deps/lcb/src/cntl.cc +42 -8
  33. package/deps/lcb/src/dns-srv.cc +5 -3
  34. package/deps/lcb/src/errmap.cc +5 -9
  35. package/deps/lcb/src/errmap.h +7 -3
  36. package/deps/lcb/src/handler.cc +24 -18
  37. package/deps/lcb/src/lcbio/ctx.cc +4 -2
  38. package/deps/lcb/src/mcserver/mcserver.cc +8 -5
  39. package/deps/lcb/src/mcserver/negotiate.cc +39 -17
  40. package/deps/lcb/src/n1ql/ixmgmt.cc +1 -2
  41. package/deps/lcb/src/n1ql/query_handle.cc +27 -16
  42. package/deps/lcb/src/n1ql/query_handle.hh +27 -1
  43. package/deps/lcb/src/operations/counter.cc +1 -1
  44. package/deps/lcb/src/operations/exists.cc +2 -2
  45. package/deps/lcb/src/operations/get.cc +2 -2
  46. package/deps/lcb/src/operations/observe.cc +1 -1
  47. package/deps/lcb/src/operations/remove.cc +1 -1
  48. package/deps/lcb/src/operations/store.cc +1 -1
  49. package/deps/lcb/src/operations/subdoc.cc +1 -2
  50. package/deps/lcb/src/operations/touch.cc +2 -2
  51. package/deps/lcb/src/operations/unlock.cc +2 -2
  52. package/deps/lcb/src/search/search_handle.cc +27 -8
  53. package/deps/lcb/src/search/search_handle.hh +29 -0
  54. package/deps/lcb/src/ssl/ssl_common.c +6 -7
  55. package/deps/lcb/src/tracing/span.cc +43 -10
  56. package/deps/lcb/src/tracing/tracing-internal.h +105 -93
  57. package/deps/lcb/src/views/view_handle.cc +13 -5
  58. package/deps/lcb/src/views/view_handle.hh +29 -0
  59. package/deps/lcb/tests/CMakeLists.txt +21 -0
  60. package/deps/lcb/tests/basic/t_ctlcodes.cc +24 -3
  61. package/deps/lcb/tests/basic/t_jsparse.cc +8 -0
  62. package/deps/lcb/tests/iotests/mock-environment.cc +15 -0
  63. package/deps/lcb/tests/iotests/mock-environment.h +47 -0
  64. package/deps/lcb/tests/iotests/mock-unit-test.cc +96 -5
  65. package/deps/lcb/tests/iotests/mock-unit-test.h +32 -0
  66. package/deps/lcb/tests/iotests/t_collections.cc +1 -1
  67. package/deps/lcb/tests/iotests/t_confmon.cc +4 -2
  68. package/deps/lcb/tests/iotests/t_get.cc +14 -4
  69. package/deps/lcb/tests/iotests/t_n1ql.cc +17 -1
  70. package/deps/lcb/tests/iotests/t_views.cc +1 -0
  71. package/deps/lcb/tests/iotests/testutil.cc +168 -0
  72. package/deps/lcb/tests/iotests/testutil.h +111 -0
  73. package/deps/lcb/tests/mocksupport/procutil.c +32 -28
  74. package/deps/lcb/tests/mocksupport/server.c +0 -1
  75. package/deps/lcb/tools/cbc.cc +7 -0
  76. package/dist/analyticsindexmanager.js +3 -3
  77. package/dist/binding.d.ts +2 -0
  78. package/dist/bindingutilities.js +4 -0
  79. package/dist/bucketmanager.d.ts +31 -1
  80. package/dist/bucketmanager.js +28 -2
  81. package/dist/collection.js +2 -2
  82. package/dist/collectionmanager.js +2 -2
  83. package/dist/connection.js +3 -0
  84. package/dist/errors.d.ts +18 -0
  85. package/dist/errors.js +26 -2
  86. package/dist/eventingfunctionmanager.js +6 -6
  87. package/dist/queryindexmanager.js +3 -3
  88. package/dist/searchexecutor.js +3 -0
  89. package/dist/searchindexmanager.js +1 -1
  90. package/dist/searchquery.d.ts +17 -0
  91. package/dist/searchquery.js +22 -1
  92. package/dist/searchtypes.d.ts +7 -2
  93. package/dist/searchtypes.js +2 -2
  94. package/dist/usermanager.js +1 -1
  95. package/dist/viewindexmanager.js +1 -1
  96. package/package.json +1 -1
  97. package/src/connection.cpp +2 -0
  98. package/src/constants.cpp +2 -0
  99. package/src/instance.cpp +8 -1
  100. package/src/instance.h +1 -0
@@ -185,6 +185,7 @@ class lcb::SessionRequestImpl : public SessionRequest
185
185
  SessionInfo *info;
186
186
  lcb_settings *settings;
187
187
  lcb_host_t host_{};
188
+ bool expecting_error_map{false};
188
189
  };
189
190
 
190
191
  static void handle_read(lcbio_CTX *ioctx, unsigned)
@@ -316,8 +317,9 @@ SessionRequestImpl::MechStatus SessionRequestImpl::set_chosen_mech(std::string &
316
317
  "PLAIN, but using SCRAM methods is strongly recommended over non-encrypted transports.",
317
318
  LOGID(this));
318
319
  #else
319
- lcb_log(LOGARGS(this, WARN), LOGFMT "SASL PLAIN authentication is not allowed on non-TLS connections",
320
- LOGID(this));
320
+ lcb_log(LOGARGS(this, WARN),
321
+ LOGFMT "SASL PLAIN authentication is not allowed on non-TLS connections (server supports: %s)",
322
+ LOGID(this), mechlist.c_str());
321
323
  return MECH_UNAVAILABLE;
322
324
  #endif
323
325
  }
@@ -642,15 +644,15 @@ GT_NEXT_PACKET:
642
644
  }
643
645
 
644
646
  if (settings->keypath) {
645
- completed = !maybe_select_bucket();
647
+ completed = !expecting_error_map && !maybe_select_bucket();
646
648
  }
647
649
  break;
648
650
  }
649
651
 
650
652
  case PROTOCOL_BINARY_CMD_GET_ERROR_MAP: {
653
+ expecting_error_map = false;
651
654
  if (status == PROTOCOL_BINARY_RESPONSE_SUCCESS) {
652
- if (!update_errmap(resp)) {
653
- }
655
+ update_errmap(resp);
654
656
  } else if (isUnsupported(status)) {
655
657
  lcb_log(LOGARGS(this, DEBUG), LOGFMT "Server does not support GET_ERRMAP (0x%x)", LOGID(this), status);
656
658
  } else {
@@ -664,18 +666,37 @@ GT_NEXT_PACKET:
664
666
  }
665
667
 
666
668
  case PROTOCOL_BINARY_CMD_SELECT_BUCKET: {
667
- if (status == PROTOCOL_BINARY_RESPONSE_SUCCESS) {
668
- completed = true;
669
- info->selected = true;
670
- } else if (status == PROTOCOL_BINARY_RESPONSE_EACCESS) {
671
- set_error(LCB_ERR_BUCKET_NOT_FOUND,
672
- "Provided credentials not allowed for bucket or bucket does not exist", &resp);
673
- } else if (status == PROTOCOL_BINARY_RESPONSE_KEY_ENOENT) {
674
- set_error(LCB_ERR_BUCKET_NOT_FOUND, "Key/Value service is not configured for given node", &resp);
675
- } else {
676
- lcb_log(LOGARGS(this, ERROR), LOGFMT "Unexpected status 0x%x received for SELECT_BUCKET", LOGID(this),
677
- status);
678
- set_error(LCB_ERR_PROTOCOL_ERROR, "Other auth error", &resp);
669
+ switch (status) {
670
+ case PROTOCOL_BINARY_RESPONSE_SUCCESS:
671
+ completed = true;
672
+ info->selected = true;
673
+ break;
674
+
675
+ case PROTOCOL_BINARY_RESPONSE_EACCESS:
676
+ set_error(LCB_ERR_BUCKET_NOT_FOUND,
677
+ "Provided credentials not allowed for bucket or bucket does not exist", &resp);
678
+ break;
679
+
680
+ case PROTOCOL_BINARY_RESPONSE_KEY_ENOENT:
681
+ set_error(LCB_ERR_BUCKET_NOT_FOUND, "Key/Value service is not configured for given node", &resp);
682
+ break;
683
+
684
+ case PROTOCOL_BINARY_RATE_LIMITED_MAX_COMMANDS:
685
+ case PROTOCOL_BINARY_RATE_LIMITED_MAX_CONNECTIONS:
686
+ case PROTOCOL_BINARY_RATE_LIMITED_NETWORK_EGRESS:
687
+ case PROTOCOL_BINARY_RATE_LIMITED_NETWORK_INGRESS:
688
+ set_error(LCB_ERR_RATE_LIMITED, "The tenant has reached rate limit", &resp);
689
+ break;
690
+
691
+ case PROTOCOL_BINARY_SCOPE_SIZE_LIMIT_EXCEEDED:
692
+ set_error(LCB_ERR_QUOTA_LIMITED, "The tenant has reached quota limit", &resp);
693
+ break;
694
+
695
+ default:
696
+ lcb_log(LOGARGS(this, ERROR), LOGFMT "Unexpected status 0x%x received for SELECT_BUCKET",
697
+ LOGID(this), status);
698
+ set_error(LCB_ERR_PROTOCOL_ERROR, "Other auth error", &resp);
699
+ break;
679
700
  }
680
701
  break;
681
702
  }
@@ -744,6 +765,7 @@ void SessionRequestImpl::start(lcbio_SOCKET *sock)
744
765
  send_hello();
745
766
  if (settings->use_errmap) {
746
767
  request_errmap();
768
+ expecting_error_map = true;
747
769
  } else {
748
770
  lcb_log(LOGARGS(this, TRACE), LOGFMT "GET_ERRORMAP disabled", LOGID(this));
749
771
  }
@@ -201,8 +201,7 @@ lcb_STATUS dispatch_common(lcb_INSTANCE *instance, const void *cookie, lcb_N1XMG
201
201
  Json::Value root;
202
202
  root["statement"] = ss;
203
203
  string reqbuf = Json::FastWriter().write(root);
204
- return dispatch_common<T>(instance, cookie, u_callback, i_callback, reqbuf.c_str(), reqbuf.size() - 1 /*newline*/,
205
- obj);
204
+ return dispatch_common<T>(instance, cookie, u_callback, i_callback, reqbuf.c_str(), reqbuf.size(), obj);
206
205
  }
207
206
 
208
207
  // Class to back the storage for the actual lcb_IXSPEC without doing too much
@@ -99,7 +99,7 @@ bool lcb_QUERY_HANDLE_::parse_meta(const char *row, size_t row_len, lcb_STATUS &
99
99
  first_error_code = 0;
100
100
 
101
101
  Json::Value meta;
102
- if (!Json::Reader().parse(row, row + row_len, meta)) {
102
+ if (!Json::Reader(Json::Features::strictMode()).parse(row, row + row_len, meta)) {
103
103
  return false;
104
104
  }
105
105
  const Json::Value &errors = meta["errors"];
@@ -143,13 +143,15 @@ bool lcb_QUERY_HANDLE_::parse_meta(const char *row, size_t row_len, lcb_STATUS &
143
143
  rc = LCB_ERR_INTERNAL_SERVER_FAILURE;
144
144
  if (!first_error_message.empty()) {
145
145
  std::regex already_exists("Index.+already exists"); /* NOTE: case sensitive */
146
+ std::regex not_found("index.+not found");
146
147
  if (std::regex_search(first_error_message, already_exists)) {
147
148
  rc = LCB_ERR_INDEX_EXISTS;
148
- } else {
149
- std::regex not_found("index.+not found");
150
- if (std::regex_search(first_error_message, not_found)) {
151
- rc = LCB_ERR_INDEX_NOT_FOUND;
152
- }
149
+ } else if (std::regex_search(first_error_message, not_found)) {
150
+ rc = LCB_ERR_INDEX_NOT_FOUND;
151
+ } else if (first_error_message.find(
152
+ "Limit for number of indexes that can be created per scope has been reached") !=
153
+ std::string::npos) {
154
+ rc = LCB_ERR_QUOTA_LIMITED;
153
155
  }
154
156
  }
155
157
  break;
@@ -166,6 +168,14 @@ bool lcb_QUERY_HANDLE_::parse_meta(const char *row, size_t row_len, lcb_STATUS &
166
168
  case 13014:
167
169
  rc = LCB_ERR_AUTHENTICATION_FAILURE;
168
170
  break;
171
+
172
+ case 1191:
173
+ case 1192:
174
+ case 1193:
175
+ case 1194:
176
+ rc = LCB_ERR_RATE_LIMITED;
177
+ break;
178
+
169
179
  default:
170
180
  if (first_error_code >= 4000 && first_error_code < 5000) {
171
181
  rc = LCB_ERR_PLANNING_FAILURE;
@@ -195,8 +205,8 @@ void lcb_QUERY_HANDLE_::invoke_row(lcb_RESPQUERY *resp, bool is_last)
195
205
  resp->ctx.endpoint = resp->htresp->ctx.endpoint;
196
206
  resp->ctx.endpoint_len = resp->htresp->ctx.endpoint_len;
197
207
  }
198
- resp->ctx.client_context_id = client_context_id.c_str();
199
- resp->ctx.client_context_id_len = client_context_id.size();
208
+ resp->ctx.client_context_id = client_context_id_.c_str();
209
+ resp->ctx.client_context_id_len = client_context_id_.size();
200
210
  resp->ctx.statement = statement_.c_str();
201
211
  resp->ctx.statement_len = statement_.size();
202
212
 
@@ -213,9 +223,11 @@ void lcb_QUERY_HANDLE_::invoke_row(lcb_RESPQUERY *resp, bool is_last)
213
223
  resp->ctx.first_error_message_len = first_error_message.size();
214
224
  }
215
225
  resp->ctx.first_error_code = first_error_code;
216
- LCBTRACE_ADD_RETRIES(span_, retries_);
226
+ if (span_ != nullptr) {
227
+ lcb::trace::finish_http_span(span_, this);
228
+ span_ = nullptr;
229
+ }
217
230
 
218
- LCBTRACE_HTTP_FINISH(span_);
219
231
  if (http_request_ != nullptr) {
220
232
  http_request_->span = nullptr;
221
233
  }
@@ -426,7 +438,7 @@ lcb_STATUS lcb_QUERY_HANDLE_::issue_htreq(const std::string &body)
426
438
  lcb_log(LOGARGS(this, TRACE),
427
439
  LOGFMT "execute query: %.*s, idempotent=%s, timeout=%uus, grace_period=%uus, client_context_id=\"%s\"",
428
440
  LOGID(this), (int)body.size(), body.c_str(), idempotent_ ? "true" : "false", timeout,
429
- LCBT_SETTING(instance_, n1ql_grace_period), client_context_id.c_str());
441
+ LCBT_SETTING(instance_, n1ql_grace_period), client_context_id_.c_str());
430
442
  return rc;
431
443
  }
432
444
 
@@ -517,10 +529,10 @@ lcb_QUERY_HANDLE_::lcb_QUERY_HANDLE_(lcb_INSTANCE *obj, void *user_cookie, const
517
529
  if (ccid.isNull()) {
518
530
  char buf[32];
519
531
  size_t nbuf = snprintf(buf, sizeof(buf), "%016" PRIx64, lcb_next_rand64());
520
- client_context_id.assign(buf, nbuf);
521
- json["client_context_id"] = client_context_id;
532
+ client_context_id_.assign(buf, nbuf);
533
+ json["client_context_id"] = client_context_id_;
522
534
  } else {
523
- client_context_id = ccid.asString();
535
+ client_context_id_ = ccid.asString();
524
536
  }
525
537
  if (json.isMember("readonly") && json["readonly"].asBool()) {
526
538
  idempotent_ = true;
@@ -554,8 +566,7 @@ lcb_QUERY_HANDLE_::lcb_QUERY_HANDLE_(lcb_INSTANCE *obj, void *user_cookie, const
554
566
  }
555
567
  if (instance_->settings->tracer) {
556
568
  parent_span_ = cmd->parent_span();
557
- LCBTRACE_HTTP_START(instance_->settings, client_context_id.c_str(), parent_span_, LCBTRACE_TAG_SERVICE_N1QL,
558
- LCBTRACE_THRESHOLD_QUERY, span_);
569
+ span_ = lcb::trace::start_http_span_with_statement(instance_->settings, this, statement_);
559
570
  }
560
571
  }
561
572
 
@@ -246,6 +246,32 @@ struct lcb_QUERY_HANDLE_ : lcb::jsparse::Parser::Actions {
246
246
  return LCB_SUCCESS;
247
247
  }
248
248
 
249
+ static lcbtrace_THRESHOLDOPTS service()
250
+ {
251
+ return LCBTRACE_THRESHOLD_QUERY;
252
+ }
253
+
254
+ static const std::string &operation_name()
255
+ {
256
+ static std::string name = LCBTRACE_OP_QUERY;
257
+ return name;
258
+ }
259
+
260
+ lcbtrace_SPAN *parent_span() const
261
+ {
262
+ return parent_span_;
263
+ }
264
+
265
+ const std::string &client_context_id() const
266
+ {
267
+ return client_context_id_;
268
+ }
269
+
270
+ int retries() const
271
+ {
272
+ return retries_;
273
+ }
274
+
249
275
  private:
250
276
  void on_backoff();
251
277
 
@@ -269,7 +295,7 @@ struct lcb_QUERY_HANDLE_ : lcb::jsparse::Parser::Actions {
269
295
  Json::Value json;
270
296
  /** String of the original statement. Cached here to avoid jsoncpp lookups */
271
297
  std::string statement_;
272
- std::string client_context_id;
298
+ std::string client_context_id_;
273
299
  std::string first_error_message{};
274
300
  uint32_t first_error_code{};
275
301
 
@@ -237,7 +237,7 @@ static lcb_STATUS counter_schedule(lcb_INSTANCE *instance, std::shared_ptr<lcb_C
237
237
  }
238
238
  memcpy(SPAN_BUFFER(&packet->kh_span) + offset, &expiry, sizeof(expiry));
239
239
 
240
- LCBTRACE_KV_START(instance->settings, packet->opaque, cmd, LCBTRACE_OP_COUNTER, rdata->span);
240
+ rdata->span = lcb::trace::start_kv_span(instance->settings, packet, cmd);
241
241
  TRACE_ARITHMETIC_BEGIN(instance, &hdr, cmd);
242
242
  LCB_SCHED_ADD(instance, pipeline, packet);
243
243
  return LCB_SUCCESS;
@@ -153,7 +153,7 @@ static lcb_STATUS exists_schedule(lcb_INSTANCE *instance, std::shared_ptr<lcb_CM
153
153
 
154
154
  hdr.request.opcode = PROTOCOL_BINARY_CMD_GET_META;
155
155
  hdr.request.datatype = PROTOCOL_BINARY_RAW_BYTES;
156
- hdr.request.bodylen = htonl(ntohs(hdr.request.keylen));
156
+ hdr.request.bodylen = ntohl(mcreq_get_key_size(&hdr));
157
157
  hdr.request.opaque = pkt->opaque;
158
158
  hdr.request.cas = 0;
159
159
 
@@ -168,7 +168,7 @@ static lcb_STATUS exists_schedule(lcb_INSTANCE *instance, std::shared_ptr<lcb_CM
168
168
  memcpy(SPAN_BUFFER(&pkt->kh_span) + offset, framing_extras.data(), framing_extras.size());
169
169
  }
170
170
 
171
- LCBTRACE_KV_START(instance->settings, pkt->opaque, cmd, LCBTRACE_OP_EXISTS, pkt->u_rdata.reqdata.span);
171
+ pkt->u_rdata.reqdata.span = lcb::trace::start_kv_span(instance->settings, pkt, cmd);
172
172
  LCB_SCHED_ADD(instance, pipeline, pkt)
173
173
  TRACE_EXISTS_BEGIN(instance, &hdr, cmd);
174
174
  return LCB_SUCCESS;
@@ -187,7 +187,7 @@ static lcb_STATUS get_schedule(lcb_INSTANCE *instance, std::shared_ptr<lcb_CMDGE
187
187
 
188
188
  hdr.request.opcode = opcode;
189
189
  hdr.request.datatype = PROTOCOL_BINARY_RAW_BYTES;
190
- hdr.request.bodylen = htonl(extlen + ffextlen + ntohs(hdr.request.keylen));
190
+ hdr.request.bodylen = htonl(extlen + ffextlen + mcreq_get_key_size(&hdr));
191
191
  hdr.request.opaque = pkt->opaque;
192
192
  hdr.request.cas = 0;
193
193
 
@@ -209,7 +209,7 @@ static lcb_STATUS get_schedule(lcb_INSTANCE *instance, std::shared_ptr<lcb_CMDGE
209
209
  memcpy(SPAN_BUFFER(&pkt->kh_span) + offset, &expiry, sizeof(expiry));
210
210
  }
211
211
 
212
- LCBTRACE_KV_START(instance->settings, pkt->opaque, cmd, LCBTRACE_OP_GET, rdata->span);
212
+ rdata->span = lcb::trace::start_kv_span(instance->settings, pkt, cmd);
213
213
  LCB_SCHED_ADD(instance, pl, pkt)
214
214
  TRACE_GET_BEGIN(instance, &hdr, cmd);
215
215
  return LCB_SUCCESS;
@@ -129,7 +129,7 @@ static void handle_observe_callback(mc_PIPELINE *pl, mc_PACKET *pkt, lcb_CALLBAC
129
129
  opc->remaining--;
130
130
  if (opc->remaining == 0) {
131
131
  TRACE_OBSERVE_END(instance, pkt);
132
- LCBTRACE_KV_FINISH(pl, pkt, resp, 0);
132
+ lcb::trace::finish_kv_span(pl, pkt, nullptr);
133
133
  delete opc;
134
134
  }
135
135
  }
@@ -188,7 +188,7 @@ static lcb_STATUS remove_schedule(lcb_INSTANCE *instance, std::shared_ptr<lcb_CM
188
188
  if (!framing_extras.empty()) {
189
189
  memcpy(SPAN_BUFFER(&pkt->kh_span) + offset, framing_extras.data(), framing_extras.size());
190
190
  }
191
- LCBTRACE_KV_START(instance->settings, pkt->opaque, cmd, LCBTRACE_OP_REMOVE, pkt->u_rdata.reqdata.span);
191
+ pkt->u_rdata.reqdata.span = lcb::trace::start_kv_span(instance->settings, pkt, cmd);
192
192
  TRACE_REMOVE_BEGIN(instance, &hdr, cmd);
193
193
  LCB_SCHED_ADD(instance, pl, pkt)
194
194
  return LCB_SUCCESS;
@@ -485,7 +485,7 @@ static lcb_STATUS store_schedule(lcb_INSTANCE *instance, std::shared_ptr<lcb_CMD
485
485
  if (cmd->is_replace_semantics()) {
486
486
  packet->flags |= MCREQ_F_REPLACE_SEMANTICS;
487
487
  }
488
- LCBTRACE_KVSTORE_START(instance->settings, packet->opaque, cmd, cmd->operation_name(), rdata->span);
488
+ rdata->span = lcb::trace::start_kv_span_with_durability(instance->settings, packet, cmd);
489
489
  LCB_SCHED_ADD(instance, pipeline, packet)
490
490
 
491
491
  TRACE_STORE_BEGIN(instance, &hdr, cmd);
@@ -853,8 +853,7 @@ static lcb_STATUS subdoc_schedule(lcb_INSTANCE *instance, std::shared_ptr<lcb_CM
853
853
  MCREQ_PKT_RDATA(pkt)->start +
854
854
  cmd->timeout_or_default_in_nanoseconds(LCB_US2NS(LCBT_SETTING(instance, operation_timeout)));
855
855
  MCREQ_PKT_RDATA(pkt)->nsubreq = cmd->specs().specs().size();
856
- LCBTRACE_KV_START(instance->settings, pkt->opaque, cmd,
857
- ctx.is_mutate() ? LCBTRACE_OP_MUTATEIN : LCBTRACE_OP_LOOKUPIN, MCREQ_PKT_RDATA(pkt)->span);
856
+ MCREQ_PKT_RDATA(pkt)->span = lcb::trace::start_kv_span(instance->settings, pkt, cmd);
858
857
  LCB_SCHED_ADD(instance, pl, pkt)
859
858
  return LCB_SUCCESS;
860
859
  }
@@ -158,7 +158,7 @@ static lcb_STATUS touch_schedule(lcb_INSTANCE *instance, std::shared_ptr<lcb_CMD
158
158
  hdr.request.cas = 0;
159
159
  hdr.request.datatype = PROTOCOL_BINARY_RAW_BYTES;
160
160
  hdr.request.opaque = pkt->opaque;
161
- hdr.request.bodylen = htonl(hdr.request.extlen + ffextlen + ntohs(hdr.request.keylen));
161
+ hdr.request.bodylen = htonl(hdr.request.extlen + ffextlen + mcreq_get_key_size(&hdr));
162
162
 
163
163
  memcpy(SPAN_BUFFER(&pkt->kh_span), &hdr, sizeof(hdr));
164
164
  std::size_t offset = sizeof(hdr);
@@ -174,7 +174,7 @@ static lcb_STATUS touch_schedule(lcb_INSTANCE *instance, std::shared_ptr<lcb_CMD
174
174
  pkt->u_rdata.reqdata.deadline =
175
175
  pkt->u_rdata.reqdata.start +
176
176
  cmd->timeout_or_default_in_nanoseconds(LCB_US2NS(LCBT_SETTING(instance, operation_timeout)));
177
- LCBTRACE_KV_START(instance->settings, pkt->opaque, cmd, LCBTRACE_OP_TOUCH, pkt->u_rdata.reqdata.span);
177
+ pkt->u_rdata.reqdata.span = lcb::trace::start_kv_span(instance->settings, pkt, cmd);
178
178
  LCB_SCHED_ADD(instance, pl, pkt);
179
179
  TRACE_TOUCH_BEGIN(instance, &hdr, cmd);
180
180
  return LCB_SUCCESS;
@@ -157,7 +157,7 @@ static lcb_STATUS unlock_schedule(lcb_INSTANCE *instance, std::shared_ptr<lcb_CM
157
157
 
158
158
  hdr.request.opcode = PROTOCOL_BINARY_CMD_UNLOCK_KEY;
159
159
  hdr.request.datatype = PROTOCOL_BINARY_RAW_BYTES;
160
- hdr.request.bodylen = htonl((lcb_uint32_t)ntohs(hdr.request.keylen));
160
+ hdr.request.bodylen = htonl(mcreq_get_key_size(&hdr));
161
161
  hdr.request.opaque = pkt->opaque;
162
162
  hdr.request.cas = lcb_htonll(cmd->cas());
163
163
 
@@ -166,7 +166,7 @@ static lcb_STATUS unlock_schedule(lcb_INSTANCE *instance, std::shared_ptr<lcb_CM
166
166
  if (!framing_extras.empty()) {
167
167
  memcpy(SPAN_BUFFER(&pkt->kh_span) + offset, framing_extras.data(), framing_extras.size());
168
168
  }
169
- LCBTRACE_KV_START(instance->settings, pkt->opaque, cmd, LCBTRACE_OP_UNLOCK, rd->span);
169
+ rd->span = lcb::trace::start_kv_span(instance->settings, pkt, cmd);
170
170
  LCB_SCHED_ADD(instance, pl, pkt);
171
171
  TRACE_UNLOCK_BEGIN(instance, &hdr, cmd);
172
172
  return LCB_SUCCESS;
@@ -23,6 +23,8 @@
23
23
  #include "search_handle.hh"
24
24
  #include "capi/cmd_http.hh"
25
25
 
26
+ #include <regex>
27
+
26
28
  #define LOGFMT "(NR=%p) "
27
29
  #define LOGID(req) static_cast<const void *>(req)
28
30
  #define LOGARGS(req, lvl) (req)->instance_->settings, "searchh", LCB_LOG_##lvl, __FILE__, __LINE__
@@ -73,7 +75,7 @@ void lcb_SEARCH_HANDLE_::invoke_row(lcb_RESPSEARCH *resp)
73
75
  if (callback_) {
74
76
  if (resp->rflags & LCB_RESP_F_FINAL) {
75
77
  Json::Value meta;
76
- if (Json::Reader().parse(resp->row, resp->row + resp->nrow, meta)) {
78
+ if (Json::Reader(Json::Features::strictMode()).parse(resp->row, resp->row + resp->nrow, meta)) {
77
79
  const Json::Value &top_error = meta["error"];
78
80
  if (top_error.isString()) {
79
81
  resp->ctx.has_top_level_error = 1;
@@ -92,9 +94,19 @@ void lcb_SEARCH_HANDLE_::invoke_row(lcb_RESPSEARCH *resp)
92
94
  resp->ctx.error_message_len = error_message_.size();
93
95
  if (error_message_.find("QueryBleve parsing") != std::string::npos) {
94
96
  resp->ctx.rc = LCB_ERR_PARSING_FAILURE;
95
- } else if (resp->ctx.http_response_code == 400 &&
96
- error_message_.find("not_found") != std::string::npos) {
97
- resp->ctx.rc = LCB_ERR_INDEX_NOT_FOUND;
97
+ } else if (resp->ctx.http_response_code == 400) {
98
+ if (error_message_.find("not_found") != std::string::npos) {
99
+ resp->ctx.rc = LCB_ERR_INDEX_NOT_FOUND;
100
+ } else if (error_message_.find("CreateIndex, Prepare failed, err: num_fts_indexes") !=
101
+ std::string::npos) {
102
+ resp->ctx.rc = LCB_ERR_QUOTA_LIMITED;
103
+ }
104
+ } else if (resp->ctx.http_response_code == 429) {
105
+ std::regex rate_limiting_message(
106
+ "num_concurrent_requests|num_queries_per_min|ingress_mib_per_min|egress_mib_per_min");
107
+ if (std::regex_search(error_message_, rate_limiting_message)) {
108
+ resp->ctx.rc = LCB_ERR_RATE_LIMITED;
109
+ }
98
110
  }
99
111
  }
100
112
  }
@@ -116,7 +128,10 @@ void lcb_SEARCH_HANDLE_::invoke_last()
116
128
  resp.nrow = meta.iov_len;
117
129
  }
118
130
 
119
- LCBTRACE_HTTP_FINISH(span_);
131
+ if (span_ != nullptr) {
132
+ lcb::trace::finish_http_span(span_, this);
133
+ span_ = nullptr;
134
+ }
120
135
  if (http_request_ != nullptr) {
121
136
  http_request_->span = nullptr;
122
137
  }
@@ -154,8 +169,13 @@ lcb_SEARCH_HANDLE_::lcb_SEARCH_HANDLE_(lcb_INSTANCE *instance, void *cookie, con
154
169
  return;
155
170
  }
156
171
  index_name_ = j_ixname.asString();
172
+ {
173
+ char buf[32];
174
+ size_t nbuf = snprintf(buf, sizeof(buf), "%016" PRIx64, lcb_next_rand64());
175
+ client_context_id_.assign(buf, nbuf);
176
+ }
157
177
  if (instance_->settings->tracer) {
158
- span_ = cmd->parent_span();
178
+ parent_span_ = cmd->parent_span();
159
179
  }
160
180
 
161
181
  std::string url;
@@ -182,8 +202,7 @@ lcb_SEARCH_HANDLE_::lcb_SEARCH_HANDLE_(lcb_INSTANCE *instance, void *cookie, con
182
202
  std::string qbody(Json::FastWriter().write(root));
183
203
  lcb_cmdhttp_body(htcmd, qbody.c_str(), qbody.size());
184
204
 
185
- LCBTRACE_HTTP_START(instance_->settings, nullptr, span_, LCBTRACE_TAG_SERVICE_SEARCH, LCBTRACE_THRESHOLD_SEARCH,
186
- span_);
205
+ span_ = lcb::trace::start_http_span(instance_->settings, this);
187
206
  lcb_cmdhttp_parent_span(htcmd, span_);
188
207
 
189
208
  last_error_ = lcb_http(instance_, this, htcmd);
@@ -115,6 +115,32 @@ struct lcb_SEARCH_HANDLE_ : lcb::jsparse::Parser::Actions {
115
115
  }
116
116
  }
117
117
 
118
+ static lcbtrace_THRESHOLDOPTS service()
119
+ {
120
+ return LCBTRACE_THRESHOLD_SEARCH;
121
+ }
122
+
123
+ static const std::string &operation_name()
124
+ {
125
+ static std::string name = LCBTRACE_OP_SEARCH;
126
+ return name;
127
+ }
128
+
129
+ lcbtrace_SPAN *parent_span() const
130
+ {
131
+ return parent_span_;
132
+ }
133
+
134
+ const std::string &client_context_id() const
135
+ {
136
+ return client_context_id_;
137
+ }
138
+
139
+ int retries() const
140
+ {
141
+ return retries_;
142
+ }
143
+
118
144
  private:
119
145
  const lcb_RESPHTTP *http_response_{nullptr};
120
146
  lcb_HTTP_HANDLE *http_request_{nullptr};
@@ -124,9 +150,12 @@ struct lcb_SEARCH_HANDLE_ : lcb::jsparse::Parser::Actions {
124
150
  lcb_INSTANCE *instance_{nullptr};
125
151
  size_t rows_number_{0};
126
152
  lcb_STATUS last_error_{LCB_SUCCESS};
153
+ lcbtrace_SPAN *parent_span_{nullptr};
127
154
  lcbtrace_SPAN *span_{nullptr};
128
155
  std::string index_name_;
129
156
  std::string error_message_;
157
+ std::string client_context_id_{};
158
+ int retries_{0};
130
159
  };
131
160
 
132
161
  #endif // LIBCOUCHBASE_SEARCH_HANDLE_HH
@@ -219,7 +219,6 @@ int iotssl_maybe_error(lcbio_XSSL *xs, int rv)
219
219
  ******************************************************************************/
220
220
  static void log_callback(const SSL *ssl, int where, int ret)
221
221
  {
222
- const char *retstr;
223
222
  int should_log = 0;
224
223
  lcbio_SOCKET *sock = SSL_get_app_data(ssl);
225
224
  /* Ignore low-level SSL stuff */
@@ -238,9 +237,9 @@ static void log_callback(const SSL *ssl, int where, int ret)
238
237
  return;
239
238
  }
240
239
 
241
- retstr = SSL_alert_type_string(ret);
242
- lcb_log(LOGARGS(ssl, LCB_LOG_TRACE), "sock=%p: ST(0x%x). %s. R(0x%x)%s", (void *)sock, where,
243
- SSL_state_string_long(ssl), ret, retstr);
240
+ lcb_log(LOGARGS(ssl, LCB_LOG_TRACE), "<%s:%s> sock=%p: ST(0x%x). %s. R(0x%x) %s (%s)",
241
+ sock->info ? sock->info->ep_remote.host : "", sock->info ? sock->info->ep_remote.port : "", (void *)sock,
242
+ where, SSL_state_string_long(ssl), ret, SSL_alert_type_string_long(ret), SSL_alert_desc_string_long(ret));
244
243
 
245
244
  if (where == SSL_CB_HANDSHAKE_DONE) {
246
245
  lcb_log(LOGARGS(ssl, LCB_LOG_DEBUG), "sock=%p. Using SSL version %s. Cipher=%s", (void *)sock,
@@ -311,11 +310,11 @@ lcbio_pSSLCTX lcbio_ssl_new(const char *tsfile, const char *cafile, const char *
311
310
  "MD5:RC4-SHA:RC4-MD5:RC4-MD5:EDH-RSA-DES-CBC-SHA:EDH-DSS-DES-CBC-SHA:DES-CBC-SHA:DES-CBC-MD5:EXP-EDH-RSA-DES-"
312
311
  "CBC-SHA:EXP-EDH-DSS-DES-CBC-SHA:EXP-DES-CBC-SHA:EXP-RC2-CBC-MD5:EXP-RC2-CBC-MD5:EXP-RC4-MD5:EXP-RC4-MD5";
313
312
 
314
- const char* cipher_list = getenv("LCB_SSL_CIPHER_LIST");
313
+ const char *cipher_list = getenv("LCB_SSL_CIPHER_LIST");
315
314
  #ifdef HAVE_CIPHERSUITES
316
- const char* ciphersuites = getenv("LCB_SSL_CIPHERSUITES");
315
+ const char *ciphersuites = getenv("LCB_SSL_CIPHERSUITES");
317
316
  #endif
318
- const char* minimum_tls = getenv("LCB_SSL_MINIMUM_TLS");
317
+ const char *minimum_tls = getenv("LCB_SSL_MINIMUM_TLS");
319
318
 
320
319
  if (!cipher_list) {
321
320
  cipher_list = default_ssl_cipher_list;
@@ -21,6 +21,8 @@
21
21
  #include <sys/timeb.h>
22
22
  #endif
23
23
 
24
+ #include "n1ql/query_handle.hh"
25
+
24
26
  typedef enum { TAGVAL_STRING, TAGVAL_UINT64, TAGVAL_DOUBLE, TAGVAL_BOOL } tag_type;
25
27
  typedef struct tag_value {
26
28
  sllist_node slnode;
@@ -129,7 +131,7 @@ void lcbtrace_span_add_tag_bool(lcbtrace_SPAN *span, const char *name, int value
129
131
  }
130
132
 
131
133
  LCB_INTERNAL_API
132
- void lcbtrace_span_add_system_tags(lcbtrace_SPAN *span, lcb_settings *settings, lcbtrace_THRESHOLDOPTS svc)
134
+ void lcbtrace_span_add_system_tags(lcbtrace_SPAN *span, const lcb_settings *settings, lcbtrace_THRESHOLDOPTS svc)
133
135
  {
134
136
  if (!span) {
135
137
  return;
@@ -138,6 +140,7 @@ void lcbtrace_span_add_system_tags(lcbtrace_SPAN *span, lcb_settings *settings,
138
140
  span->service(svc);
139
141
  }
140
142
  span->add_tag(LCBTRACE_TAG_SYSTEM, 0, "couchbase", 0);
143
+ span->add_tag(LCBTRACE_TAG_TRANSPORT, 0, "IP.TCP", 0);
141
144
  std::string client_string(LCB_CLIENT_ID);
142
145
  if (settings->client_string) {
143
146
  client_string += " ";
@@ -158,15 +161,6 @@ lcbtrace_SPAN *lcbtrace_span_get_parent(lcbtrace_SPAN *span)
158
161
  return span->m_parent;
159
162
  }
160
163
 
161
- LCB_INTERNAL_API
162
- void lcbtrace_span_set_parent(lcbtrace_SPAN *span, lcbtrace_SPAN *parent)
163
- {
164
- if (!span) {
165
- return;
166
- }
167
- span->m_parent = parent;
168
- }
169
-
170
164
  LIBCOUCHBASE_API
171
165
  uint64_t lcbtrace_span_get_start_ts(lcbtrace_SPAN *span)
172
166
  {
@@ -412,6 +406,38 @@ LIBCOUCHBASE_API lcb_STATUS lcbtrace_span_get_is_encode(lcbtrace_SPAN *span, int
412
406
  return LCB_SUCCESS;
413
407
  }
414
408
 
409
+ namespace lcb
410
+ {
411
+ namespace trace
412
+ {
413
+ void finish_kv_span(const mc_PIPELINE *pipeline, const mc_PACKET *request_pkt,
414
+ const lcb::MemcachedResponse *response_pkt)
415
+ {
416
+ lcbtrace_SPAN *dispatch_span = MCREQ_PKT_RDATA(request_pkt)->span;
417
+ if (dispatch_span) {
418
+ if (response_pkt != nullptr) {
419
+ dispatch_span->increment_server(response_pkt->duration());
420
+ }
421
+ auto *server = static_cast<const lcb::Server *>(pipeline);
422
+ dispatch_span->find_outer_or_this()->add_tag(LCBTRACE_TAG_RETRIES, 0, (uint64_t)request_pkt->retries);
423
+ lcbtrace_span_add_tag_str_nocopy(dispatch_span, LCBTRACE_TAG_TRANSPORT, "IP.TCP");
424
+ lcbio_CTX *ctx = server->connctx;
425
+ if (ctx) {
426
+ char local_id[34] = {};
427
+ snprintf(local_id, sizeof(local_id), "%016" PRIx64 "/%016" PRIx64, (uint64_t)server->get_settings()->iid,
428
+ (uint64_t)ctx->sock->id);
429
+ lcbtrace_span_add_tag_str(dispatch_span, LCBTRACE_TAG_LOCAL_ID, local_id);
430
+ lcbtrace_span_add_host_and_port(dispatch_span, ctx->sock->info);
431
+ }
432
+ if (dispatch_span->should_finish()) {
433
+ lcbtrace_span_finish(dispatch_span, LCBTRACE_NOW);
434
+ }
435
+ }
436
+ }
437
+
438
+ } // namespace trace
439
+ } // namespace lcb
440
+
415
441
  using namespace lcb::trace;
416
442
 
417
443
  Span::Span(lcbtrace_TRACER *tracer, const char *opname, uint64_t start, lcbtrace_REF_TYPE ref, lcbtrace_SPAN *other,
@@ -601,6 +627,13 @@ void Span::add_tag(const char *name, int copy_key, const char *value, int copy_v
601
627
  }
602
628
  }
603
629
 
630
+ void Span::add_tag(const char *name, const std::string &value)
631
+ {
632
+ if (name != nullptr && !value.empty()) {
633
+ add_tag(name, 0, value.c_str(), value.size(), 1);
634
+ }
635
+ }
636
+
604
637
  void Span::add_tag(const char *name, int copy_key, const char *value, size_t value_len, int copy_value)
605
638
  {
606
639
  if (nullptr != m_extspan && nullptr != m_tracer) {