couchbase 3.2.0 → 3.2.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (175) hide show
  1. package/README.md +24 -18
  2. package/binding.gyp +88 -85
  3. package/deps/lcb/CMakeLists.txt +1 -1
  4. package/deps/lcb/CONTRIBUTING.md +1 -1
  5. package/deps/lcb/README.markdown +2 -2
  6. package/deps/lcb/RELEASE_NOTES.markdown +99 -14
  7. package/deps/lcb/cmake/Modules/GetVersionInfo.cmake +1 -1
  8. package/deps/lcb/contrib/cbsasl/src/scram-sha/scram_utils.cc +22 -26
  9. package/deps/lcb/contrib/lcb-jsoncpp/lcb-jsoncpp.cpp +20 -7
  10. package/deps/lcb/doc/Doxyfile +1 -1
  11. package/deps/lcb/example/CMakeLists.txt +4 -4
  12. package/deps/lcb/example/libuvdirect/main.c +39 -12
  13. package/deps/lcb/example/minimal/durability.cc +149 -0
  14. package/deps/lcb/example/minimal/query.c +11 -9
  15. package/deps/lcb/gyp_config/common/libcouchbase/configuration.h +3 -3
  16. package/deps/lcb/gyp_config/linux/arm64/config.h +243 -0
  17. package/deps/lcb/include/libcouchbase/couchbase.h +80 -5
  18. package/deps/lcb/include/libcouchbase/error.h +2 -0
  19. package/deps/lcb/include/libcouchbase/ixmgmt.h +15 -10
  20. package/deps/lcb/include/libcouchbase/tracing.h +2 -2
  21. package/deps/lcb/include/memcached/protocol_binary.h +21 -0
  22. package/deps/lcb/libcouchbase.gyp +347 -349
  23. package/deps/lcb/packaging/deb/control +1 -1
  24. package/deps/lcb/src/analytics/analytics_handle.cc +13 -5
  25. package/deps/lcb/src/analytics/analytics_handle.hh +29 -0
  26. package/deps/lcb/src/bootstrap.cc +6 -3
  27. package/deps/lcb/src/capi/cmd_analytics.cc +12 -1
  28. package/deps/lcb/src/capi/cmd_analytics.hh +30 -0
  29. package/deps/lcb/src/capi/cmd_counter.hh +23 -0
  30. package/deps/lcb/src/capi/cmd_exists.hh +24 -1
  31. package/deps/lcb/src/capi/cmd_get.hh +22 -0
  32. package/deps/lcb/src/capi/cmd_get_replica.hh +23 -0
  33. package/deps/lcb/src/capi/cmd_http.hh +7 -0
  34. package/deps/lcb/src/capi/cmd_query.cc +11 -1
  35. package/deps/lcb/src/capi/cmd_query.hh +31 -0
  36. package/deps/lcb/src/capi/cmd_remove.hh +23 -0
  37. package/deps/lcb/src/capi/cmd_search.cc +6 -0
  38. package/deps/lcb/src/capi/cmd_search.hh +23 -0
  39. package/deps/lcb/src/capi/cmd_store.hh +33 -21
  40. package/deps/lcb/src/capi/cmd_subdoc.hh +35 -0
  41. package/deps/lcb/src/capi/cmd_touch.hh +23 -0
  42. package/deps/lcb/src/capi/cmd_unlock.hh +23 -0
  43. package/deps/lcb/src/capi/cmd_view.hh +6 -0
  44. package/deps/lcb/src/capi/collection_qualifier.hh +2 -2
  45. package/deps/lcb/src/cntl.cc +45 -11
  46. package/deps/lcb/src/crypto.cc +2 -2
  47. package/deps/lcb/src/dns-srv.cc +5 -3
  48. package/deps/lcb/src/errmap.cc +5 -9
  49. package/deps/lcb/src/errmap.h +7 -3
  50. package/deps/lcb/src/handler.cc +24 -18
  51. package/deps/lcb/src/hostlist.h +2 -2
  52. package/deps/lcb/src/http/http-priv.h +2 -2
  53. package/deps/lcb/src/http/http.cc +5 -2
  54. package/deps/lcb/src/instance.cc +20 -11
  55. package/deps/lcb/src/internal.h +9 -0
  56. package/deps/lcb/src/lcbio/connect.cc +14 -2
  57. package/deps/lcb/src/lcbio/connect.h +2 -2
  58. package/deps/lcb/src/lcbio/ctx.cc +4 -2
  59. package/deps/lcb/src/lcbio/ioutils.cc +9 -10
  60. package/deps/lcb/src/lcbio/manager.cc +1 -1
  61. package/deps/lcb/src/mcserver/mcserver.cc +9 -6
  62. package/deps/lcb/src/mcserver/negotiate.cc +39 -17
  63. package/deps/lcb/src/n1ql/ixmgmt.cc +1 -2
  64. package/deps/lcb/src/n1ql/query_handle.cc +41 -19
  65. package/deps/lcb/src/n1ql/query_handle.hh +28 -1
  66. package/deps/lcb/src/operations/counter.cc +18 -5
  67. package/deps/lcb/src/operations/exists.cc +25 -4
  68. package/deps/lcb/src/operations/get.cc +39 -19
  69. package/deps/lcb/src/operations/get_replica.cc +28 -8
  70. package/deps/lcb/src/operations/observe.cc +1 -1
  71. package/deps/lcb/src/operations/ping.cc +8 -8
  72. package/deps/lcb/src/operations/pktfwd.cc +2 -1
  73. package/deps/lcb/src/operations/remove.cc +39 -22
  74. package/deps/lcb/src/operations/store.cc +18 -5
  75. package/deps/lcb/src/operations/subdoc.cc +18 -6
  76. package/deps/lcb/src/operations/touch.cc +34 -16
  77. package/deps/lcb/src/operations/unlock.cc +24 -5
  78. package/deps/lcb/src/packetutils.h +3 -2
  79. package/deps/lcb/src/retryq.cc +24 -5
  80. package/deps/lcb/src/search/search.cc +1 -0
  81. package/deps/lcb/src/search/search_handle.cc +30 -8
  82. package/deps/lcb/src/search/search_handle.hh +29 -0
  83. package/deps/lcb/src/settings.cc +1 -1
  84. package/deps/lcb/src/ssl/ssl_common.c +6 -7
  85. package/deps/lcb/src/tracing/span.cc +47 -14
  86. package/deps/lcb/src/tracing/tracer.cc +11 -2
  87. package/deps/lcb/src/tracing/tracing-internal.h +105 -93
  88. package/deps/lcb/src/utilities.cc +43 -0
  89. package/deps/lcb/src/utilities.h +53 -0
  90. package/deps/lcb/src/vbucket/vbucket.c +34 -33
  91. package/deps/lcb/src/views/view_handle.cc +13 -5
  92. package/deps/lcb/src/views/view_handle.hh +29 -0
  93. package/deps/lcb/tests/CMakeLists.txt +21 -0
  94. package/deps/lcb/tests/basic/t_ctlcodes.cc +24 -3
  95. package/deps/lcb/tests/basic/t_jsparse.cc +8 -0
  96. package/deps/lcb/tests/basic/t_n1qlstrings.cc +73 -0
  97. package/deps/lcb/tests/iotests/mock-environment.cc +30 -1
  98. package/deps/lcb/tests/iotests/mock-environment.h +49 -0
  99. package/deps/lcb/tests/iotests/mock-unit-test.cc +104 -6
  100. package/deps/lcb/tests/iotests/mock-unit-test.h +34 -0
  101. package/deps/lcb/tests/iotests/t_collections.cc +1 -1
  102. package/deps/lcb/tests/iotests/t_confmon.cc +4 -2
  103. package/deps/lcb/tests/iotests/t_get.cc +109 -7
  104. package/deps/lcb/tests/iotests/t_http.cc +9 -4
  105. package/deps/lcb/tests/iotests/t_lock.cc +18 -0
  106. package/deps/lcb/tests/iotests/t_mutate.cc +157 -63
  107. package/deps/lcb/tests/iotests/t_n1ql.cc +330 -33
  108. package/deps/lcb/tests/iotests/t_views.cc +1 -0
  109. package/deps/lcb/tests/iotests/testutil.cc +168 -0
  110. package/deps/lcb/tests/iotests/testutil.h +116 -0
  111. package/deps/lcb/tests/mocksupport/procutil.c +32 -28
  112. package/deps/lcb/tests/mocksupport/server.c +0 -1
  113. package/deps/lcb/tests/mocksupport/timeout.c +2 -2
  114. package/deps/lcb/tools/cbc.cc +7 -0
  115. package/dist/analyticsindexmanager.js +512 -524
  116. package/dist/binding.d.ts +3 -0
  117. package/dist/bindingutilities.js +4 -0
  118. package/dist/bucket.js +1 -1
  119. package/dist/bucketmanager.d.ts +31 -1
  120. package/dist/bucketmanager.js +194 -186
  121. package/dist/cluster.d.ts +7 -0
  122. package/dist/cluster.js +48 -38
  123. package/dist/collection.js +11 -17
  124. package/dist/collectionmanager.js +181 -197
  125. package/dist/connection.d.ts +3 -1
  126. package/dist/connection.js +27 -16
  127. package/dist/couchbase.d.ts +1 -0
  128. package/dist/couchbase.js +3 -13
  129. package/dist/datastructures.js +239 -310
  130. package/dist/diagnosticsexecutor.js +70 -85
  131. package/dist/errors.d.ts +70 -0
  132. package/dist/errors.js +96 -2
  133. package/dist/eventingfunctionmanager.d.ts +804 -0
  134. package/dist/eventingfunctionmanager.js +993 -0
  135. package/dist/httpexecutor.d.ts +2 -1
  136. package/dist/httpexecutor.js +30 -37
  137. package/dist/queryindexmanager.js +240 -266
  138. package/dist/scope.js +10 -4
  139. package/dist/sdspecs.d.ts +1 -1
  140. package/dist/searchexecutor.js +3 -0
  141. package/dist/searchindexmanager.js +240 -271
  142. package/dist/searchquery.d.ts +17 -0
  143. package/dist/searchquery.js +22 -1
  144. package/dist/searchtypes.d.ts +7 -2
  145. package/dist/searchtypes.js +2 -2
  146. package/dist/usermanager.js +251 -264
  147. package/dist/utilities.d.ts +2 -0
  148. package/dist/utilities.js +7 -2
  149. package/dist/viewexecutor.js +1 -1
  150. package/dist/viewindexmanager.js +131 -150
  151. package/package.json +1 -1
  152. package/src/addondata.cpp +58 -0
  153. package/src/addondata.h +40 -0
  154. package/src/binding.cpp +3 -1
  155. package/src/cas.h +2 -2
  156. package/src/connection.cpp +25 -178
  157. package/src/connection.h +8 -65
  158. package/src/connection_ops.cpp +57 -34
  159. package/src/constants.cpp +3 -0
  160. package/src/instance.cpp +235 -0
  161. package/src/instance.h +102 -0
  162. package/src/{connection_callbacks.cpp → instance_callbacks.cpp} +34 -34
  163. package/src/logger.cpp +11 -1
  164. package/src/logger.h +3 -0
  165. package/src/metrics.cpp +10 -0
  166. package/src/metrics.h +3 -0
  167. package/src/mutationtoken.h +2 -2
  168. package/src/opbuilder.h +13 -15
  169. package/src/respreader.cpp +1 -0
  170. package/src/respreader.h +6 -4
  171. package/src/tracespan.h +11 -11
  172. package/src/tracing.cpp +11 -0
  173. package/src/tracing.h +3 -0
  174. package/src/valueparser.h +5 -0
  175. package/deps/lcb/example/observe/durability.c +0 -110
@@ -65,7 +65,7 @@ struct Connstart : ConnectionRequest {
65
65
  void cancel() override;
66
66
  void C_connect();
67
67
 
68
- enum State { CS_PENDING, CS_CANCELLED, CS_CONNECTED, CS_ERROR };
68
+ enum State { CS_PENDING, CS_CANCELLED, CS_CONNECTED, CS_ERROR, CS_ERROR_CANCELLED };
69
69
 
70
70
  void state_signal(State next_state, lcb_STATUS err);
71
71
  void notify_success();
@@ -145,6 +145,12 @@ void Connstart::handler()
145
145
  sock->refcount--; /* dereference because of unsuccessful attempt */
146
146
  }
147
147
  goto GT_DTOR;
148
+ } else if (state == CS_ERROR_CANCELLED) {
149
+ /* same as above, except the refcount has already been decremented */
150
+ if (sock != nullptr && sock->io->is_C() && sock->u.sd) {
151
+ sock->u.sd->lcbconn = nullptr;
152
+ }
153
+ goto GT_DTOR;
148
154
  }
149
155
 
150
156
  if (sock) {
@@ -225,7 +231,13 @@ void Connstart::cancel()
225
231
  /* already inside user-defined handler */
226
232
  return;
227
233
  }
228
- state = CS_CANCELLED;
234
+
235
+ if (state == CS_ERROR) {
236
+ state = CS_ERROR_CANCELLED;
237
+ } else {
238
+ state = CS_CANCELLED;
239
+ }
240
+
229
241
  handler();
230
242
  }
231
243
 
@@ -75,8 +75,8 @@ typedef struct {
75
75
  struct sockaddr_storage sa_remote;
76
76
  struct sockaddr_storage sa_local;
77
77
  lcb_host_t ep_remote;
78
- lcb_host_t ep_local2;
79
- char ep_local[NI_MAXHOST + NI_MAXSERV + 2];
78
+ lcb_host_t ep_local;
79
+ char ep_local_host_and_port[NI_MAXHOST + 1 + NI_MAXSERV + 1];
80
80
  } lcbio_CONNINFO;
81
81
 
82
82
  struct lcb_IOMETRICS_st;
@@ -136,8 +136,10 @@ void lcbio_ctx_close_ex(lcbio_CTX *ctx, lcbio_CTXCLOSE_cb cb, void *arg, lcbio_C
136
136
  }
137
137
 
138
138
  oldrc = ctx->sock->refcount;
139
- lcb_log(LOGARGS(ctx, DEBUG), CTX_LOGFMT "Destroying context. Pending Writes=%d, Entered=%s, Socket Refcount=%d",
140
- CTX_LOGID(ctx), (int)ctx->npending, (int)ctx->entered ? "true" : "false", oldrc);
139
+
140
+ lcb_log(LOGARGS(ctx, DEBUG),
141
+ CTX_LOGFMT "Destroying context for SOCK=%016" PRIx64 ". Pending Writes=%d, Entered=%s, Socket Refcount=%d",
142
+ CTX_LOGID(ctx), ctx->sock->id, (int)ctx->npending, (int)ctx->entered ? "true" : "false", oldrc);
141
143
 
142
144
  if (cb) {
143
145
  int reusable = ctx->npending == 0 && /* no pending events */
@@ -169,25 +169,24 @@ static int saddr_to_string(struct sockaddr *saddr, int len, char *buf, lcb_size_
169
169
 
170
170
  static void lcbio_cache_local_name(lcbio_CONNINFO *sock)
171
171
  {
172
+ char addr_str[NI_MAXHOST + 1];
172
173
  switch (sock->sa_local.ss_family) {
173
174
  case AF_INET: {
174
175
  auto *addr = (struct sockaddr_in *)&sock->sa_local;
175
- inet_ntop(AF_INET, &(addr->sin_addr), sock->ep_local, sizeof(sock->ep_local));
176
- strncpy(sock->ep_local2.host, sock->ep_local, sizeof(sock->ep_local2.host));
177
- snprintf(sock->ep_local2.port, sizeof(sock->ep_local2.port), "%d", (int)ntohs(addr->sin_port));
178
- size_t len = strlen(sock->ep_local);
179
- snprintf(sock->ep_local + len, sizeof(sock->ep_local) - len, ":%d", (int)ntohs(addr->sin_port));
176
+ inet_ntop(AF_INET, &(addr->sin_addr), addr_str, sizeof(addr_str));
177
+ strncpy(sock->ep_local.host, addr_str, sizeof(sock->ep_local.host));
178
+ snprintf(sock->ep_local.port, sizeof(sock->ep_local.port), "%d", (int)ntohs(addr->sin_port));
180
179
  } break;
181
180
 
182
181
  case AF_INET6: {
183
182
  auto *addr = (struct sockaddr_in6 *)&sock->sa_local;
184
- inet_ntop(AF_INET6, &(addr->sin6_addr), sock->ep_local, sizeof(sock->ep_local));
185
- strncpy(sock->ep_local2.host, sock->ep_local, sizeof(sock->ep_local2.host));
186
- snprintf(sock->ep_local2.port, sizeof(sock->ep_local2.port), "%d", (int)ntohs(addr->sin6_port));
187
- size_t len = strlen(sock->ep_local);
188
- snprintf(sock->ep_local + len, sizeof(sock->ep_local) - len, ":%d", (int)ntohs(addr->sin6_port));
183
+ inet_ntop(AF_INET6, &(addr->sin6_addr), addr_str, sizeof(addr_str));
184
+ strncpy(sock->ep_local.host, addr_str, sizeof(sock->ep_local.host));
185
+ snprintf(sock->ep_local.port, sizeof(sock->ep_local.port), "%d", (int)ntohs(addr->sin6_port));
189
186
  } break;
190
187
  }
188
+ snprintf(sock->ep_local_host_and_port, sizeof(sock->ep_local_host_and_port), "%s:%s", sock->ep_local.host,
189
+ sock->ep_local.port);
191
190
  }
192
191
 
193
192
  void lcbio__load_socknames(lcbio_SOCKET *sock)
@@ -282,7 +282,7 @@ static void endpointToJSON(hrtime_t now, Json::Value &node, const PoolHost *host
282
282
  endpoint["id"] = id;
283
283
  endpoint["remote"] = get_hehost(host);
284
284
  if (info->sock->info) {
285
- endpoint["local"] = info->sock->info->ep_local;
285
+ endpoint["local"] = info->sock->info->ep_local_host_and_port;
286
286
  endpoint["last_activity_us"] = (Json::Value::UInt64)(now - info->sock->atime);
287
287
  }
288
288
  auto *session = lcb::SessionInfo::get(info->sock);
@@ -341,6 +341,11 @@ static bool is_fastpath_error(uint16_t rc)
341
341
  case PROTOCOL_BINARY_RESPONSE_SYNC_WRITE_IN_PROGRESS:
342
342
  case PROTOCOL_BINARY_RESPONSE_SYNC_WRITE_AMBIGUOUS:
343
343
  case PROTOCOL_BINARY_RESPONSE_LOCKED:
344
+ case PROTOCOL_BINARY_RATE_LIMITED_NETWORK_INGRESS:
345
+ case PROTOCOL_BINARY_RATE_LIMITED_NETWORK_EGRESS:
346
+ case PROTOCOL_BINARY_RATE_LIMITED_MAX_CONNECTIONS:
347
+ case PROTOCOL_BINARY_RATE_LIMITED_MAX_COMMANDS:
348
+ case PROTOCOL_BINARY_SCOPE_SIZE_LIMIT_EXCEEDED:
344
349
  return true;
345
350
  default:
346
351
  if (rc >= 0xc0 && rc <= 0xcc) {
@@ -395,10 +400,6 @@ int Server::handle_unknown_error(const mc_PACKET *request, const MemcachedRespon
395
400
  newerr = LCB_ERR_TEMPORARY_FAILURE;
396
401
  }
397
402
 
398
- if (err.hasAttribute(errmap::CONSTRAINT_FAILURE)) {
399
- newerr = LCB_ERR_CAS_MISMATCH;
400
- }
401
-
402
403
  if (err.hasAttribute(errmap::AUTH)) {
403
404
  newerr = LCB_ERR_AUTHENTICATION_FAILURE;
404
405
  }
@@ -754,6 +755,8 @@ static const char *opcode_name(uint8_t code)
754
755
  return "subdoc_get_count";
755
756
  case PROTOCOL_BINARY_CMD_GET_ERROR_MAP:
756
757
  return "get_error_map";
758
+ case PROTOCOL_BINARY_CMD_GET_META:
759
+ return "exists";
757
760
  default:
758
761
  return "unknown";
759
762
  }
@@ -811,12 +814,12 @@ void Server::purge_single(mc_PACKET *pkt, lcb_STATUS err)
811
814
  snprintf(local_id, sizeof(local_id), "%016" PRIx64 "/%016" PRIx64 "/%x", settings->iid, connctx->sock->id,
812
815
  (int)pkt->opaque);
813
816
  info["i"] = local_id;
814
- info["l"] = connctx->sock->info->ep_local;
817
+ info["l"] = connctx->sock->info->ep_local_host_and_port;
815
818
  }
816
819
  std::string msg(Json::FastWriter().write(info));
817
820
  if (msg.size() > 1) {
818
821
  lcb_log(LOGARGS(instance, WARN), "Failing command with error %s: %.*s", lcb_strerror_short(err),
819
- (int)(msg.size() - 1), msg.c_str());
822
+ (int)msg.size(), msg.c_str());
820
823
  }
821
824
  } else {
822
825
  lcb_log(LOGARGS_T(WARN), LOGFMT "Failing command (pkt=%p, opaque=%lu, opcode=0x%x) with error %s", LOGID_T(),
@@ -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
  }
@@ -372,6 +384,10 @@ lcb_RETRY_ACTION lcb_QUERY_HANDLE_::has_retriable_error(lcb_STATUS &rc)
372
384
  }
373
385
  }
374
386
  }
387
+
388
+ if (rc == LCB_SUCCESS) {
389
+ return {0, 0};
390
+ }
375
391
  return lcb_query_should_retry(instance_->settings, this, rc);
376
392
  }
377
393
 
@@ -390,9 +406,12 @@ lcb_STATUS lcb_QUERY_HANDLE_::issue_htreq(const std::string &body)
390
406
  lcb_cmdhttp_content_type(htcmd, content_type.c_str(), content_type.size());
391
407
  lcb_cmdhttp_method(htcmd, LCB_HTTP_METHOD_POST);
392
408
  lcb_cmdhttp_streaming(htcmd, true);
393
- lcb_cmdhttp_timeout(htcmd, timeout);
409
+ lcb_cmdhttp_timeout(htcmd, timeout + LCBT_SETTING(instance_, n1ql_grace_period));
394
410
  lcb_cmdhttp_handle(htcmd, &http_request_);
395
411
  lcb_cmdhttp_host(htcmd, endpoint.data(), endpoint.size());
412
+ if (!impostor_.empty()) {
413
+ htcmd->set_header("cb-on-behalf-of", impostor_);
414
+ }
396
415
  if (use_multi_bucket_authentication_) {
397
416
  lcb_cmdhttp_skip_auth_header(htcmd, true);
398
417
  } else {
@@ -416,6 +435,10 @@ lcb_STATUS lcb_QUERY_HANDLE_::issue_htreq(const std::string &body)
416
435
  if (rc == LCB_SUCCESS) {
417
436
  http_request_->set_callback(reinterpret_cast<lcb_RESPCALLBACK>(chunk_callback));
418
437
  }
438
+ lcb_log(LOGARGS(this, TRACE),
439
+ LOGFMT "execute query: %.*s, idempotent=%s, timeout=%uus, grace_period=%uus, client_context_id=\"%s\"",
440
+ LOGID(this), (int)body.size(), body.c_str(), idempotent_ ? "true" : "false", timeout,
441
+ LCBT_SETTING(instance_, n1ql_grace_period), client_context_id_.c_str());
419
442
  return rc;
420
443
  }
421
444
 
@@ -506,17 +529,14 @@ lcb_QUERY_HANDLE_::lcb_QUERY_HANDLE_(lcb_INSTANCE *obj, void *user_cookie, const
506
529
  if (ccid.isNull()) {
507
530
  char buf[32];
508
531
  size_t nbuf = snprintf(buf, sizeof(buf), "%016" PRIx64, lcb_next_rand64());
509
- client_context_id.assign(buf, nbuf);
510
- json["client_context_id"] = client_context_id;
532
+ client_context_id_.assign(buf, nbuf);
533
+ json["client_context_id"] = client_context_id_;
511
534
  } else {
512
- client_context_id = ccid.asString();
535
+ client_context_id_ = ccid.asString();
513
536
  }
514
537
  if (json.isMember("readonly") && json["readonly"].asBool()) {
515
538
  idempotent_ = true;
516
539
  }
517
- lcb_log(LOGARGS(this, TRACE), LOGFMT "%.*s, idempotent=%s, timeout=%uus, grace_period=%uus", LOGID(this),
518
- (int)statement_.size(), statement_.c_str(), idempotent_ ? "true" : "false", timeout,
519
- LCBT_SETTING(obj, n1ql_grace_period));
520
540
  timeout_timer_.rearm(timeout + LCBT_SETTING(obj, n1ql_grace_period));
521
541
 
522
542
  // Determine if we need to add more credentials.
@@ -541,10 +561,12 @@ lcb_QUERY_HANDLE_::lcb_QUERY_HANDLE_(lcb_INSTANCE *obj, void *user_cookie, const
541
561
  curCreds["pass"] = ii->second;
542
562
  }
543
563
  }
564
+ if (cmd->want_impersonation()) {
565
+ impostor_ = cmd->impostor();
566
+ }
544
567
  if (instance_->settings->tracer) {
545
568
  parent_span_ = cmd->parent_span();
546
- LCBTRACE_HTTP_START(instance_->settings, client_context_id.c_str(), parent_span_, LCBTRACE_TAG_SERVICE_N1QL,
547
- LCBTRACE_THRESHOLD_QUERY, span_);
569
+ span_ = lcb::trace::start_http_span_with_statement(instance_->settings, this, statement_);
548
570
  }
549
571
  }
550
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
 
@@ -290,6 +316,7 @@ struct lcb_QUERY_HANDLE_ : lcb::jsparse::Parser::Actions {
290
316
 
291
317
  lcb::io::Timer<lcb_QUERY_HANDLE_, &lcb_QUERY_HANDLE_::on_timeout> timeout_timer_;
292
318
  lcb::io::Timer<lcb_QUERY_HANDLE_, &lcb_QUERY_HANDLE_::on_backoff> backoff_timer_;
319
+ std::string impostor_{};
293
320
  };
294
321
 
295
322
  #endif // LIBCOUCHBASE_N1QL_QUERY_HANDLE_HH
@@ -136,6 +136,11 @@ LIBCOUCHBASE_API lcb_STATUS lcb_cmdcounter_durability(lcb_CMDCOUNTER *cmd, lcb_D
136
136
  return cmd->durability_level(level);
137
137
  }
138
138
 
139
+ LIBCOUCHBASE_API lcb_STATUS lcb_cmdcounter_on_behalf_of(lcb_CMDCOUNTER *cmd, const char *data, size_t data_len)
140
+ {
141
+ return cmd->on_behalf_of(std::string(data, data_len));
142
+ }
143
+
139
144
  static lcb_STATUS counter_validate(lcb_INSTANCE *instance, const lcb_CMDCOUNTER *cmd)
140
145
  {
141
146
  if (cmd->key().empty()) {
@@ -164,13 +169,21 @@ static lcb_STATUS counter_schedule(lcb_INSTANCE *instance, std::shared_ptr<lcb_C
164
169
 
165
170
  std::vector<std::uint8_t> framing_extras;
166
171
  if (new_durability_supported && cmd->has_durability_requirements()) {
172
+ auto durability_timeout = htons(lcb_durability_timeout(instance, cmd->timeout_in_microseconds()));
167
173
  std::uint8_t frame_id = 0x01;
168
- std::uint8_t frame_size = 0x04;
174
+ std::uint8_t frame_size = durability_timeout > 0 ? 3 : 1;
169
175
  framing_extras.emplace_back(frame_id << 4U | frame_size);
170
176
  framing_extras.emplace_back(cmd->durability_level());
171
- auto durability_timeout = htons(lcb_durability_timeout(instance, cmd->timeout_in_microseconds()));
172
- framing_extras.emplace_back(durability_timeout >> 8U);
173
- framing_extras.emplace_back(durability_timeout & 0xff);
177
+ if (durability_timeout > 0) {
178
+ framing_extras.emplace_back(durability_timeout >> 8U);
179
+ framing_extras.emplace_back(durability_timeout & 0xff);
180
+ }
181
+ }
182
+ if (cmd->want_impersonation()) {
183
+ err = lcb::flexible_framing_extras::encode_impersonate_user(cmd->impostor(), framing_extras);
184
+ if (err != LCB_SUCCESS) {
185
+ return err;
186
+ }
174
187
  }
175
188
 
176
189
  hdr.request.magic = framing_extras.empty() ? PROTOCOL_BINARY_REQ : PROTOCOL_BINARY_AREQ;
@@ -224,7 +237,7 @@ static lcb_STATUS counter_schedule(lcb_INSTANCE *instance, std::shared_ptr<lcb_C
224
237
  }
225
238
  memcpy(SPAN_BUFFER(&packet->kh_span) + offset, &expiry, sizeof(expiry));
226
239
 
227
- 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);
228
241
  TRACE_ARITHMETIC_BEGIN(instance, &hdr, cmd);
229
242
  LCB_SCHED_ADD(instance, pipeline, packet);
230
243
  return LCB_SUCCESS;
@@ -107,6 +107,11 @@ LIBCOUCHBASE_API lcb_STATUS lcb_cmdexists_key(lcb_CMDEXISTS *cmd, const char *ke
107
107
  return cmd->key(std::string(key, key_len));
108
108
  }
109
109
 
110
+ LIBCOUCHBASE_API lcb_STATUS lcb_cmdexists_on_behalf_of(lcb_CMDEXISTS *cmd, const char *data, size_t data_len)
111
+ {
112
+ return cmd->on_behalf_of(std::string(data, data_len));
113
+ }
114
+
110
115
  static lcb_STATUS exists_validate(lcb_INSTANCE *instance, const lcb_CMDEXISTS *cmd)
111
116
  {
112
117
  if (cmd->key().empty()) {
@@ -123,12 +128,24 @@ static lcb_STATUS exists_schedule(lcb_INSTANCE *instance, std::shared_ptr<lcb_CM
123
128
  {
124
129
  mc_CMDQUEUE *cq = &instance->cmdq;
125
130
 
126
- protocol_binary_request_header hdr;
131
+ protocol_binary_request_header hdr{};
127
132
  mc_PIPELINE *pipeline;
128
133
  mc_PACKET *pkt;
129
134
  lcb_STATUS err;
135
+
136
+ std::vector<std::uint8_t> framing_extras;
137
+ if (cmd->want_impersonation()) {
138
+ err = lcb::flexible_framing_extras::encode_impersonate_user(cmd->impostor(), framing_extras);
139
+ if (err != LCB_SUCCESS) {
140
+ return err;
141
+ }
142
+ }
143
+
144
+ hdr.request.magic = framing_extras.empty() ? PROTOCOL_BINARY_REQ : PROTOCOL_BINARY_AREQ;
145
+ auto ffextlen = static_cast<std::uint8_t>(framing_extras.size());
146
+
130
147
  lcb_KEYBUF keybuf{LCB_KV_COPY, {cmd->key().c_str(), cmd->key().size()}};
131
- err = mcreq_basic_packet(cq, &keybuf, cmd->collection().collection_id(), &hdr, 0, 0, &pkt, &pipeline,
148
+ err = mcreq_basic_packet(cq, &keybuf, cmd->collection().collection_id(), &hdr, 0, ffextlen, &pkt, &pipeline,
132
149
  MCREQ_BASICPACKET_F_FALLBACKOK);
133
150
  if (err != LCB_SUCCESS) {
134
151
  return err;
@@ -136,7 +153,7 @@ static lcb_STATUS exists_schedule(lcb_INSTANCE *instance, std::shared_ptr<lcb_CM
136
153
 
137
154
  hdr.request.opcode = PROTOCOL_BINARY_CMD_GET_META;
138
155
  hdr.request.datatype = PROTOCOL_BINARY_RAW_BYTES;
139
- hdr.request.bodylen = htonl(ntohs(hdr.request.keylen));
156
+ hdr.request.bodylen = ntohl(mcreq_get_key_size(&hdr));
140
157
  hdr.request.opaque = pkt->opaque;
141
158
  hdr.request.cas = 0;
142
159
 
@@ -146,8 +163,12 @@ static lcb_STATUS exists_schedule(lcb_INSTANCE *instance, std::shared_ptr<lcb_CM
146
163
  pkt->u_rdata.reqdata.start +
147
164
  cmd->timeout_or_default_in_nanoseconds(LCB_US2NS(LCBT_SETTING(instance, operation_timeout)));
148
165
  memcpy(SPAN_BUFFER(&pkt->kh_span), hdr.bytes, MCREQ_PKT_BASESIZE);
166
+ std::size_t offset = sizeof(hdr);
167
+ if (!framing_extras.empty()) {
168
+ memcpy(SPAN_BUFFER(&pkt->kh_span) + offset, framing_extras.data(), framing_extras.size());
169
+ }
149
170
 
150
- 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);
151
172
  LCB_SCHED_ADD(instance, pipeline, pkt)
152
173
  TRACE_EXISTS_BEGIN(instance, &hdr, cmd);
153
174
  return LCB_SUCCESS;
@@ -124,6 +124,11 @@ LIBCOUCHBASE_API lcb_STATUS lcb_cmdget_locktime(lcb_CMDGET *cmd, uint32_t durati
124
124
  return cmd->with_lock(duration);
125
125
  }
126
126
 
127
+ LIBCOUCHBASE_API lcb_STATUS lcb_cmdget_on_behalf_of(lcb_CMDGET *cmd, const char *data, size_t data_len)
128
+ {
129
+ return cmd->on_behalf_of(std::string(data, data_len));
130
+ }
131
+
127
132
  static lcb_STATUS get_validate(lcb_INSTANCE *instance, const lcb_CMDGET *cmd)
128
133
  {
129
134
  if (cmd->key().empty()) {
@@ -145,11 +150,20 @@ static lcb_STATUS get_schedule(lcb_INSTANCE *instance, std::shared_ptr<lcb_CMDGE
145
150
  mc_CMDQUEUE *q = &instance->cmdq;
146
151
  lcb_uint8_t extlen = 0;
147
152
  lcb_uint8_t opcode = PROTOCOL_BINARY_CMD_GET;
148
- protocol_binary_request_gat gcmd;
149
- protocol_binary_request_header *hdr = &gcmd.message.header;
153
+ protocol_binary_request_header hdr{};
150
154
  lcb_STATUS err;
151
155
 
152
- hdr->request.magic = PROTOCOL_BINARY_REQ;
156
+ std::vector<std::uint8_t> framing_extras;
157
+ if (cmd->want_impersonation()) {
158
+ err = lcb::flexible_framing_extras::encode_impersonate_user(cmd->impostor(), framing_extras);
159
+ if (err != LCB_SUCCESS) {
160
+ return err;
161
+ }
162
+ }
163
+
164
+ hdr.request.magic = framing_extras.empty() ? PROTOCOL_BINARY_REQ : PROTOCOL_BINARY_AREQ;
165
+ auto ffextlen = static_cast<std::uint8_t>(framing_extras.size());
166
+
153
167
  if (cmd->with_lock()) {
154
168
  extlen = 4;
155
169
  opcode = PROTOCOL_BINARY_CMD_GET_LOCKED;
@@ -159,7 +173,7 @@ static lcb_STATUS get_schedule(lcb_INSTANCE *instance, std::shared_ptr<lcb_CMDGE
159
173
  }
160
174
 
161
175
  lcb_KEYBUF keybuf{LCB_KV_COPY, {cmd->key().c_str(), cmd->key().size()}};
162
- err = mcreq_basic_packet(q, &keybuf, cmd->collection().collection_id(), hdr, extlen, 0, &pkt, &pl,
176
+ err = mcreq_basic_packet(q, &keybuf, cmd->collection().collection_id(), &hdr, extlen, ffextlen, &pkt, &pl,
163
177
  MCREQ_BASICPACKET_F_FALLBACKOK);
164
178
  if (err != LCB_SUCCESS) {
165
179
  return err;
@@ -171,27 +185,33 @@ static lcb_STATUS get_schedule(lcb_INSTANCE *instance, std::shared_ptr<lcb_CMDGE
171
185
  rdata->deadline =
172
186
  rdata->start + cmd->timeout_or_default_in_nanoseconds(LCB_US2NS(LCBT_SETTING(instance, operation_timeout)));
173
187
 
174
- hdr->request.opcode = opcode;
175
- hdr->request.datatype = PROTOCOL_BINARY_RAW_BYTES;
176
- hdr->request.bodylen = htonl(extlen + ntohs(hdr->request.keylen));
177
- hdr->request.opaque = pkt->opaque;
178
- hdr->request.cas = 0;
179
-
180
- if (cmd->with_lock()) {
181
- gcmd.message.body.norm.expiration = htonl(cmd->lock_time());
182
- }
183
- if (extlen) {
184
- gcmd.message.body.norm.expiration = htonl(cmd->expiry());
185
- }
188
+ hdr.request.opcode = opcode;
189
+ hdr.request.datatype = PROTOCOL_BINARY_RAW_BYTES;
190
+ hdr.request.bodylen = htonl(extlen + ffextlen + mcreq_get_key_size(&hdr));
191
+ hdr.request.opaque = pkt->opaque;
192
+ hdr.request.cas = 0;
186
193
 
187
194
  if (cmd->is_cookie_callback()) {
188
195
  pkt->flags |= MCREQ_F_PRIVCALLBACK;
189
196
  }
190
197
 
191
- memcpy(SPAN_BUFFER(&pkt->kh_span), gcmd.bytes, MCREQ_PKT_BASESIZE + extlen);
192
- LCBTRACE_KV_START(instance->settings, pkt->opaque, cmd, LCBTRACE_OP_GET, rdata->span);
198
+ memcpy(SPAN_BUFFER(&pkt->kh_span), &hdr, sizeof(hdr));
199
+ std::size_t offset = sizeof(hdr);
200
+ if (!framing_extras.empty()) {
201
+ memcpy(SPAN_BUFFER(&pkt->kh_span) + offset, framing_extras.data(), framing_extras.size());
202
+ offset += framing_extras.size();
203
+ }
204
+ if (cmd->with_lock()) {
205
+ std::uint32_t lock_expiry = htonl(cmd->lock_time());
206
+ memcpy(SPAN_BUFFER(&pkt->kh_span) + offset, &lock_expiry, sizeof(lock_expiry));
207
+ } else if (cmd->with_touch()) {
208
+ std::uint32_t expiry = htonl(cmd->expiry());
209
+ memcpy(SPAN_BUFFER(&pkt->kh_span) + offset, &expiry, sizeof(expiry));
210
+ }
211
+
212
+ rdata->span = lcb::trace::start_kv_span(instance->settings, pkt, cmd);
193
213
  LCB_SCHED_ADD(instance, pl, pkt)
194
- TRACE_GET_BEGIN(instance, hdr, cmd);
214
+ TRACE_GET_BEGIN(instance, &hdr, cmd);
195
215
  return LCB_SUCCESS;
196
216
  }
197
217