couchbase 3.2.0 → 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 (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