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
@@ -19,7 +19,6 @@
19
19
 
20
20
  #include "internal.h"
21
21
  #include "collections.h"
22
- #include "trace.h"
23
22
  #include "defer.h"
24
23
 
25
24
  #include "capi/cmd_get.hh"
@@ -140,6 +139,11 @@ LIBCOUCHBASE_API lcb_STATUS lcb_cmdgetreplica_key(lcb_CMDGETREPLICA *cmd, const
140
139
  return cmd->key(std::string(key, key_len));
141
140
  }
142
141
 
142
+ LIBCOUCHBASE_API lcb_STATUS lcb_cmdgetreplica_on_behalf_of(lcb_CMDGETREPLICA *cmd, const char *data, size_t data_len)
143
+ {
144
+ return cmd->on_behalf_of(std::string(data, data_len));
145
+ }
146
+
143
147
  struct RGetCookie : mc_REQDATAEX {
144
148
  RGetCookie(void *cookie, lcb_INSTANCE *instance, get_replica_mode, int vb);
145
149
  void decref()
@@ -248,7 +252,7 @@ static lcb_STATUS get_replica_validate(lcb_INSTANCE *instance, const lcb_CMDGETR
248
252
 
249
253
  mc_CMDQUEUE *cq = &instance->cmdq;
250
254
  int vbid, ixtmp;
251
- unsigned r0, r1 = 0;
255
+ unsigned r0 = 0, r1 = 0;
252
256
 
253
257
  lcb_KEYBUF keybuf{LCB_KV_COPY, {cmd->key().c_str(), cmd->key().size()}};
254
258
  mcreq_map_key(cq, &keybuf, MCREQ_PKT_BASESIZE, &vbid, &ixtmp);
@@ -299,8 +303,8 @@ static lcb_STATUS get_replica_schedule(lcb_INSTANCE *instance, std::shared_ptr<l
299
303
  */
300
304
  mc_CMDQUEUE *cq = &instance->cmdq;
301
305
  int vbid, ixtmp;
302
- protocol_binary_request_header req;
303
- unsigned r0, r1 = 0;
306
+ protocol_binary_request_header req{};
307
+ unsigned r0 = 0, r1 = 0;
304
308
 
305
309
  lcb_KEYBUF keybuf{LCB_KV_COPY, {cmd->key().c_str(), cmd->key().size()}};
306
310
  mcreq_map_key(cq, &keybuf, MCREQ_PKT_BASESIZE, &vbid, &ixtmp);
@@ -351,14 +355,24 @@ static lcb_STATUS get_replica_schedule(lcb_INSTANCE *instance, std::shared_ptr<l
351
355
  rck->deadline =
352
356
  rck->start + cmd->timeout_or_default_in_nanoseconds(LCB_US2NS(LCBT_SETTING(instance, operation_timeout)));
353
357
 
358
+ std::vector<std::uint8_t> framing_extras;
359
+ if (cmd->want_impersonation()) {
360
+ lcb_STATUS err = lcb::flexible_framing_extras::encode_impersonate_user(cmd->impostor(), framing_extras);
361
+ if (err != LCB_SUCCESS) {
362
+ return err;
363
+ }
364
+ }
365
+
354
366
  /* Initialize the packet */
355
- req.request.magic = PROTOCOL_BINARY_REQ;
367
+ req.request.magic = framing_extras.empty() ? PROTOCOL_BINARY_REQ : PROTOCOL_BINARY_AREQ;
356
368
  req.request.opcode = PROTOCOL_BINARY_CMD_GET_REPLICA;
357
369
  req.request.datatype = PROTOCOL_BINARY_RAW_BYTES;
358
370
  req.request.vbucket = htons(static_cast<std::uint16_t>(vbid));
359
371
  req.request.cas = 0;
360
372
  req.request.extlen = 0;
361
373
 
374
+ auto ffextlen = static_cast<std::uint8_t>(framing_extras.size());
375
+
362
376
  rck->r_cur = r0;
363
377
  do {
364
378
  int curix;
@@ -380,13 +394,16 @@ static lcb_STATUS get_replica_schedule(lcb_INSTANCE *instance, std::shared_ptr<l
380
394
  pkt->u_rdata.exdata = rck;
381
395
  pkt->flags |= MCREQ_F_REQEXT;
382
396
 
383
- mcreq_reserve_key(pl, pkt, sizeof(req.bytes), &keybuf, cmd->collection().collection_id());
397
+ mcreq_reserve_key(pl, pkt, sizeof(req.bytes) + ffextlen, &keybuf, cmd->collection().collection_id());
384
398
  size_t nkey = pkt->kh_span.size - MCREQ_PKT_BASESIZE + pkt->extlen;
385
399
  req.request.keylen = htons((uint16_t)nkey);
386
400
  req.request.bodylen = htonl((uint32_t)nkey);
387
401
  req.request.opaque = pkt->opaque;
388
402
  rck->remaining++;
389
403
  mcreq_write_hdr(pkt, &req);
404
+ if (!framing_extras.empty()) {
405
+ memcpy(SPAN_BUFFER(&pkt->kh_span) + sizeof(req.bytes), framing_extras.data(), framing_extras.size());
406
+ }
390
407
  mcreq_sched_add(pl, pkt);
391
408
  } while (++r0 < r1);
392
409
 
@@ -394,8 +411,8 @@ static lcb_STATUS get_replica_schedule(lcb_INSTANCE *instance, std::shared_ptr<l
394
411
  req.request.opcode = PROTOCOL_BINARY_CMD_GET;
395
412
  mc_PIPELINE *pl;
396
413
  mc_PACKET *pkt;
397
- lcb_STATUS err = mcreq_basic_packet(cq, &keybuf, cmd->collection().collection_id(), &req, 0, 0, &pkt, &pl,
398
- MCREQ_BASICPACKET_F_FALLBACKOK);
414
+ lcb_STATUS err = mcreq_basic_packet(cq, &keybuf, cmd->collection().collection_id(), &req, 0, ffextlen, &pkt,
415
+ &pl, MCREQ_BASICPACKET_F_FALLBACKOK);
399
416
  if (err != LCB_SUCCESS) {
400
417
  delete rck;
401
418
  return err;
@@ -405,6 +422,9 @@ static lcb_STATUS get_replica_schedule(lcb_INSTANCE *instance, std::shared_ptr<l
405
422
  pkt->flags |= MCREQ_F_REQEXT;
406
423
  rck->remaining++;
407
424
  mcreq_write_hdr(pkt, &req);
425
+ if (!framing_extras.empty()) {
426
+ memcpy(SPAN_BUFFER(&pkt->kh_span) + sizeof(req.bytes), framing_extras.data(), framing_extras.size());
427
+ }
408
428
  mcreq_sched_add(pl, pkt);
409
429
  }
410
430
 
@@ -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
  }
@@ -426,7 +426,7 @@ static void handle_ping(mc_PIPELINE *pipeline, mc_PACKET *req, lcb_CALLBACK_TYPE
426
426
  } else {
427
427
  hh.append(remote.host).append(":").append(remote.port);
428
428
  }
429
- svc.server = strdup(hh.c_str());
429
+ svc.server = lcb_strdup(hh.c_str());
430
430
  }
431
431
  svc.type = LCB_PING_SERVICE_KV;
432
432
  svc.latency = gethrtime() - MCREQ_PKT_RDATA(req)->start;
@@ -445,9 +445,9 @@ static void handle_ping(mc_PIPELINE *pipeline, mc_PACKET *req, lcb_CALLBACK_TYPE
445
445
  lcbio_CTX *ctx = server->connctx;
446
446
  if (ctx) {
447
447
  char id[20] = {0};
448
- svc.local = strdup(ctx->sock->info->ep_local);
448
+ svc.local = lcb_strdup(ctx->sock->info->ep_local_host_and_port);
449
449
  snprintf(id, sizeof(id), "%p", (void *)ctx->sock);
450
- svc.id = strdup(id);
450
+ svc.id = lcb_strdup(id);
451
451
  }
452
452
  svc.scope = server->get_instance()->get_bucketname();
453
453
 
@@ -477,7 +477,7 @@ static void handle_http(lcb_INSTANCE *instance, lcb_PING_SERVICE type, const lcb
477
477
  } else {
478
478
  hh = std::string(htreq->host) + ":" + std::string(htreq->port);
479
479
  }
480
- svc.server = strdup(hh.c_str());
480
+ svc.server = lcb_strdup(hh.c_str());
481
481
  svc.latency = gethrtime() - htreq->start;
482
482
  svc.rc = resp->ctx.rc;
483
483
  switch (resp->ctx.rc) {
@@ -495,8 +495,8 @@ static void handle_http(lcb_INSTANCE *instance, lcb_PING_SERVICE type, const lcb
495
495
  if (ctx) {
496
496
  char id[20] = {0};
497
497
  snprintf(id, sizeof(id), "%p", (void *)ctx->sock);
498
- svc.id = strdup(id);
499
- svc.local = strdup(ctx->sock->info->ep_local);
498
+ svc.id = lcb_strdup(id);
499
+ svc.local = lcb_strdup(ctx->sock->info->ep_local_host_and_port);
500
500
  }
501
501
  ck->responses.push_back(svc);
502
502
  }
@@ -759,7 +759,7 @@ lcb_STATUS lcb_diag(lcb_INSTANCE *instance, void *cookie, const lcb_CMDDIAG *cmd
759
759
  }
760
760
  if (ctx->sock) {
761
761
  if (ctx->sock->info) {
762
- endpoint["local"] = ctx->sock->info->ep_local;
762
+ endpoint["local"] = ctx->sock->info->ep_local_host_and_port;
763
763
  }
764
764
  endpoint["last_activity_us"] =
765
765
  (Json::Value::UInt64)(now > ctx->sock->atime ? now - ctx->sock->atime : 0);
@@ -790,7 +790,7 @@ lcb_STATUS lcb_diag(lcb_INSTANCE *instance, void *cookie, const lcb_CMDDIAG *cmd
790
790
  }
791
791
  if (ctx->sock) {
792
792
  if (ctx->sock->info) {
793
- endpoint["local"] = ctx->sock->info->ep_local;
793
+ endpoint["local"] = ctx->sock->info->ep_local_host_and_port;
794
794
  }
795
795
  endpoint["last_activity_us"] =
796
796
  (Json::Value::UInt64)(now > ctx->sock->atime ? now - ctx->sock->atime : 0);
@@ -66,7 +66,8 @@ lcb_STATUS lcb_pktfwd3(lcb_INSTANCE *instance, const void *cookie, const lcb_CMD
66
66
  /* set the cookie */
67
67
  packet->u_rdata.reqdata.cookie = cookie;
68
68
  packet->u_rdata.reqdata.start = gethrtime();
69
- packet->u_rdata.reqdata.deadline = packet->u_rdata.reqdata.start + LCB_US2NS(LCBT_SETTING(instance, operation_timeout));
69
+ packet->u_rdata.reqdata.deadline =
70
+ packet->u_rdata.reqdata.start + LCB_US2NS(LCBT_SETTING(instance, operation_timeout));
70
71
  return err;
71
72
  }
72
73
 
@@ -112,6 +112,11 @@ LIBCOUCHBASE_API lcb_STATUS lcb_cmdremove_durability(lcb_CMDREMOVE *cmd, lcb_DUR
112
112
  return cmd->durability_level(level);
113
113
  }
114
114
 
115
+ LIBCOUCHBASE_API lcb_STATUS lcb_cmdremove_on_behalf_of(lcb_CMDREMOVE *cmd, const char *data, size_t data_len)
116
+ {
117
+ return cmd->on_behalf_of(std::string(data, data_len));
118
+ }
119
+
115
120
  static lcb_STATUS remove_validate(lcb_INSTANCE *instance, const lcb_CMDREMOVE *cmd)
116
121
  {
117
122
  if (cmd->key().empty()) {
@@ -132,37 +137,45 @@ static lcb_STATUS remove_schedule(lcb_INSTANCE *instance, std::shared_ptr<lcb_CM
132
137
  mc_CMDQUEUE *cq = &instance->cmdq;
133
138
  mc_PIPELINE *pl;
134
139
  mc_PACKET *pkt;
135
- protocol_binary_request_delete req{};
136
- protocol_binary_request_header *hdr = &req.message.header;
137
140
  int new_durability_supported = LCBT_SUPPORT_SYNCREPLICATION(instance);
138
- lcb_U8 ffextlen = 0;
139
- size_t hsize;
140
141
  lcb_STATUS err;
141
142
 
142
- hdr->request.magic = PROTOCOL_BINARY_REQ;
143
+ protocol_binary_request_header hdr{};
144
+
145
+ std::vector<std::uint8_t> framing_extras;
143
146
  if (new_durability_supported && cmd->has_durability_requirements()) {
144
- hdr->request.magic = PROTOCOL_BINARY_AREQ;
145
- ffextlen = 4;
147
+ auto durability_timeout = htons(lcb_durability_timeout(instance, cmd->timeout_in_microseconds()));
148
+ std::uint8_t frame_id = 0x01;
149
+ std::uint8_t frame_size = durability_timeout > 0 ? 3 : 1;
150
+ framing_extras.emplace_back(frame_id << 4U | frame_size);
151
+ framing_extras.emplace_back(cmd->durability_level());
152
+ if (durability_timeout > 0) {
153
+ framing_extras.emplace_back(durability_timeout >> 8U);
154
+ framing_extras.emplace_back(durability_timeout & 0xff);
155
+ }
156
+ }
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
+ }
146
162
  }
147
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
+
148
167
  lcb_KEYBUF keybuf{LCB_KV_COPY, {cmd->key().c_str(), cmd->key().size()}};
149
- err = mcreq_basic_packet(cq, &keybuf, cmd->collection().collection_id(), hdr, 0, ffextlen, &pkt, &pl,
168
+ err = mcreq_basic_packet(cq, &keybuf, cmd->collection().collection_id(), &hdr, 0, ffextlen, &pkt, &pl,
150
169
  MCREQ_BASICPACKET_F_FALLBACKOK);
151
170
  if (err != LCB_SUCCESS) {
152
171
  return err;
153
172
  }
154
- hsize = hdr->request.extlen + sizeof(*hdr) + ffextlen;
155
173
 
156
- hdr->request.datatype = PROTOCOL_BINARY_RAW_BYTES;
157
- hdr->request.opcode = PROTOCOL_BINARY_CMD_DELETE;
158
- hdr->request.cas = lcb_htonll(cmd->cas());
159
- hdr->request.opaque = pkt->opaque;
160
- hdr->request.bodylen = htonl(ffextlen + hdr->request.extlen + mcreq_get_key_size(hdr));
161
- if (new_durability_supported && cmd->has_durability_requirements()) {
162
- req.message.body.alt.meta = (1u << 4u) | 3u;
163
- req.message.body.alt.level = cmd->durability_level();
164
- req.message.body.alt.timeout = htons(lcb_durability_timeout(instance, cmd->timeout_in_microseconds()));
165
- }
174
+ hdr.request.datatype = PROTOCOL_BINARY_RAW_BYTES;
175
+ hdr.request.opcode = PROTOCOL_BINARY_CMD_DELETE;
176
+ hdr.request.cas = lcb_htonll(cmd->cas());
177
+ hdr.request.opaque = pkt->opaque;
178
+ hdr.request.bodylen = htonl(ffextlen + hdr.request.extlen + mcreq_get_key_size(&hdr));
166
179
 
167
180
  pkt->flags |= MCREQ_F_REPLACE_SEMANTICS;
168
181
  pkt->u_rdata.reqdata.cookie = cmd->cookie();
@@ -170,9 +183,13 @@ static lcb_STATUS remove_schedule(lcb_INSTANCE *instance, std::shared_ptr<lcb_CM
170
183
  pkt->u_rdata.reqdata.deadline =
171
184
  pkt->u_rdata.reqdata.start +
172
185
  cmd->timeout_or_default_in_nanoseconds(LCB_US2NS(LCBT_SETTING(instance, operation_timeout)));
173
- memcpy(SPAN_BUFFER(&pkt->kh_span), hdr->bytes, hsize);
174
- LCBTRACE_KV_START(instance->settings, pkt->opaque, cmd, LCBTRACE_OP_REMOVE, pkt->u_rdata.reqdata.span);
175
- TRACE_REMOVE_BEGIN(instance, hdr, cmd);
186
+ memcpy(SPAN_BUFFER(&pkt->kh_span), &hdr, sizeof(hdr));
187
+ std::size_t offset = sizeof(hdr);
188
+ if (!framing_extras.empty()) {
189
+ memcpy(SPAN_BUFFER(&pkt->kh_span) + offset, framing_extras.data(), framing_extras.size());
190
+ }
191
+ pkt->u_rdata.reqdata.span = lcb::trace::start_kv_span(instance->settings, pkt, cmd);
192
+ TRACE_REMOVE_BEGIN(instance, &hdr, cmd);
176
193
  LCB_SCHED_ADD(instance, pl, pkt)
177
194
  return LCB_SUCCESS;
178
195
  }
@@ -229,6 +229,11 @@ LIBCOUCHBASE_API lcb_STATUS lcb_cmdstore_durability_observe(lcb_CMDSTORE *cmd, i
229
229
  return cmd->durability_poll(persist_to, replicate_to);
230
230
  }
231
231
 
232
+ LIBCOUCHBASE_API lcb_STATUS lcb_cmdstore_on_behalf_of(lcb_CMDSTORE *cmd, const char *data, size_t data_len)
233
+ {
234
+ return cmd->on_behalf_of(std::string(data, data_len));
235
+ }
236
+
232
237
  struct DurStoreCtx : mc_REQDATAEX {
233
238
  lcb_INSTANCE *instance;
234
239
  lcb_U16 persist_to;
@@ -375,19 +380,27 @@ static lcb_STATUS store_schedule(lcb_INSTANCE *instance, std::shared_ptr<lcb_CMD
375
380
 
376
381
  std::vector<std::uint8_t> framing_extras;
377
382
  if (new_durability_supported && cmd->has_sync_durability_requirements()) {
383
+ auto durability_timeout = htons(lcb_durability_timeout(instance, cmd->timeout_in_microseconds()));
378
384
  std::uint8_t frame_id = 0x01;
379
- std::uint8_t frame_size = 0x04;
385
+ std::uint8_t frame_size = durability_timeout > 0 ? 3 : 1;
380
386
  framing_extras.emplace_back(frame_id << 4U | frame_size);
381
387
  framing_extras.emplace_back(cmd->durability_level());
382
- auto durability_timeout = htons(lcb_durability_timeout(instance, cmd->timeout_in_microseconds()));
383
- framing_extras.emplace_back(durability_timeout >> 8U);
384
- framing_extras.emplace_back(durability_timeout & 0xff);
388
+ if (durability_timeout > 0) {
389
+ framing_extras.emplace_back(durability_timeout >> 8U);
390
+ framing_extras.emplace_back(durability_timeout & 0xff);
391
+ }
385
392
  }
386
393
  if (cmd->should_preserve_expiry()) {
387
394
  std::uint8_t frame_id = 0x05;
388
395
  std::uint8_t frame_size = 0x00;
389
396
  framing_extras.emplace_back(frame_id << 4U | frame_size);
390
397
  }
398
+ if (cmd->want_impersonation()) {
399
+ err = lcb::flexible_framing_extras::encode_impersonate_user(cmd->impostor(), framing_extras);
400
+ if (err != LCB_SUCCESS) {
401
+ return err;
402
+ }
403
+ }
391
404
  auto ffextlen = static_cast<std::uint8_t>(framing_extras.size());
392
405
  hdr.request.magic = (ffextlen == 0) ? PROTOCOL_BINARY_REQ : PROTOCOL_BINARY_AREQ;
393
406
  hdr.request.opcode = cmd->opcode();
@@ -472,7 +485,7 @@ static lcb_STATUS store_schedule(lcb_INSTANCE *instance, std::shared_ptr<lcb_CMD
472
485
  if (cmd->is_replace_semantics()) {
473
486
  packet->flags |= MCREQ_F_REPLACE_SEMANTICS;
474
487
  }
475
- 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);
476
489
  LCB_SCHED_ADD(instance, pipeline, packet)
477
490
 
478
491
  TRACE_STORE_BEGIN(instance, &hdr, cmd);
@@ -404,6 +404,11 @@ LIBCOUCHBASE_API lcb_STATUS lcb_cmdsubdoc_create_as_deleted(lcb_CMDSUBDOC *cmd,
404
404
  return cmd->create_as_deleted(flag);
405
405
  }
406
406
 
407
+ LIBCOUCHBASE_API lcb_STATUS lcb_cmdsubdoc_on_behalf_of(lcb_CMDSUBDOC *cmd, const char *data, size_t data_len)
408
+ {
409
+ return cmd->on_behalf_of(std::string(data, data_len));
410
+ }
411
+
407
412
  namespace SubdocCmdTraits
408
413
  {
409
414
  enum Options {
@@ -772,13 +777,15 @@ static lcb_STATUS subdoc_schedule(lcb_INSTANCE *instance, std::shared_ptr<lcb_CM
772
777
  hdr.request.opcode = PROTOCOL_BINARY_CMD_SUBDOC_MULTI_MUTATION;
773
778
 
774
779
  if (new_durability_supported && cmd->has_durability_requirements()) {
780
+ auto durability_timeout = htons(lcb_durability_timeout(instance, cmd->timeout_in_microseconds()));
775
781
  std::uint8_t frame_id = 0x01;
776
- std::uint8_t frame_size = 0x04;
782
+ std::uint8_t frame_size = durability_timeout > 0 ? 3 : 1;
777
783
  framing_extras.emplace_back(frame_id << 4U | frame_size);
778
784
  framing_extras.emplace_back(cmd->durability_level());
779
- auto durability_timeout = htons(lcb_durability_timeout(instance, cmd->timeout_in_microseconds()));
780
- framing_extras.emplace_back(durability_timeout >> 8U);
781
- framing_extras.emplace_back(durability_timeout & 0xff);
785
+ if (durability_timeout > 0) {
786
+ framing_extras.emplace_back(durability_timeout >> 8U);
787
+ framing_extras.emplace_back(durability_timeout & 0xff);
788
+ }
782
789
  }
783
790
  if (cmd->should_preserve_expiry()) {
784
791
  std::uint8_t frame_id = 0x05;
@@ -786,6 +793,12 @@ static lcb_STATUS subdoc_schedule(lcb_INSTANCE *instance, std::shared_ptr<lcb_CM
786
793
  framing_extras.emplace_back(frame_id << 4U | frame_size);
787
794
  }
788
795
  }
796
+ if (cmd->want_impersonation()) {
797
+ rc = lcb::flexible_framing_extras::encode_impersonate_user(cmd->impostor(), framing_extras);
798
+ if (rc != LCB_SUCCESS) {
799
+ return rc;
800
+ }
801
+ }
789
802
  hdr.request.magic = framing_extras.empty() ? PROTOCOL_BINARY_REQ : PROTOCOL_BINARY_AREQ;
790
803
  auto ffextlen = static_cast<std::uint8_t>(framing_extras.size());
791
804
 
@@ -840,8 +853,7 @@ static lcb_STATUS subdoc_schedule(lcb_INSTANCE *instance, std::shared_ptr<lcb_CM
840
853
  MCREQ_PKT_RDATA(pkt)->start +
841
854
  cmd->timeout_or_default_in_nanoseconds(LCB_US2NS(LCBT_SETTING(instance, operation_timeout)));
842
855
  MCREQ_PKT_RDATA(pkt)->nsubreq = cmd->specs().specs().size();
843
- LCBTRACE_KV_START(instance->settings, pkt->opaque, cmd,
844
- 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);
845
857
  LCB_SCHED_ADD(instance, pl, pkt)
846
858
  return LCB_SUCCESS;
847
859
  }
@@ -112,6 +112,11 @@ LIBCOUCHBASE_API lcb_STATUS lcb_cmdtouch_durability(lcb_CMDTOUCH * /* cmd */, lc
112
112
  return LCB_ERR_UNSUPPORTED_OPERATION;
113
113
  }
114
114
 
115
+ LIBCOUCHBASE_API lcb_STATUS lcb_cmdtouch_on_behalf_of(lcb_CMDTOUCH *cmd, const char *data, size_t data_len)
116
+ {
117
+ return cmd->on_behalf_of(std::string(data, data_len));
118
+ }
119
+
115
120
  static lcb_STATUS touch_validate(lcb_INSTANCE *instance, const lcb_CMDTOUCH *cmd)
116
121
  {
117
122
  if (cmd->key().empty()) {
@@ -126,39 +131,52 @@ static lcb_STATUS touch_validate(lcb_INSTANCE *instance, const lcb_CMDTOUCH *cmd
126
131
 
127
132
  static lcb_STATUS touch_schedule(lcb_INSTANCE *instance, std::shared_ptr<lcb_CMDTOUCH> cmd)
128
133
  {
129
- protocol_binary_request_touch tcmd;
130
- protocol_binary_request_header *hdr = &tcmd.message.header;
134
+ protocol_binary_request_header hdr{};
131
135
  mc_PIPELINE *pl;
132
136
  mc_PACKET *pkt;
133
137
  lcb_STATUS err;
134
- lcb_U8 ffextlen = 0;
135
- size_t hsize;
138
+
139
+ std::vector<std::uint8_t> framing_extras;
140
+ if (cmd->want_impersonation()) {
141
+ err = lcb::flexible_framing_extras::encode_impersonate_user(cmd->impostor(), framing_extras);
142
+ if (err != LCB_SUCCESS) {
143
+ return err;
144
+ }
145
+ }
146
+
147
+ hdr.request.magic = framing_extras.empty() ? PROTOCOL_BINARY_REQ : PROTOCOL_BINARY_AREQ;
148
+ auto ffextlen = static_cast<std::uint8_t>(framing_extras.size());
136
149
 
137
150
  lcb_KEYBUF keybuf{LCB_KV_COPY, {cmd->key().c_str(), cmd->key().size()}};
138
- err = mcreq_basic_packet(&instance->cmdq, &keybuf, cmd->collection().collection_id(), hdr, 4, ffextlen, &pkt, &pl,
151
+ err = mcreq_basic_packet(&instance->cmdq, &keybuf, cmd->collection().collection_id(), &hdr, 4, ffextlen, &pkt, &pl,
139
152
  MCREQ_BASICPACKET_F_FALLBACKOK);
140
153
  if (err != LCB_SUCCESS) {
141
154
  return err;
142
155
  }
143
- hsize = hdr->request.extlen + sizeof(*hdr) + ffextlen;
144
156
 
145
- hdr->request.magic = PROTOCOL_BINARY_REQ;
146
- hdr->request.opcode = PROTOCOL_BINARY_CMD_TOUCH;
147
- hdr->request.cas = 0;
148
- hdr->request.datatype = PROTOCOL_BINARY_RAW_BYTES;
149
- hdr->request.opaque = pkt->opaque;
150
- hdr->request.bodylen = htonl(4 + ffextlen + ntohs(hdr->request.keylen));
151
- tcmd.message.body.norm.expiration = htonl(cmd->expiry());
157
+ hdr.request.opcode = PROTOCOL_BINARY_CMD_TOUCH;
158
+ hdr.request.cas = 0;
159
+ hdr.request.datatype = PROTOCOL_BINARY_RAW_BYTES;
160
+ hdr.request.opaque = pkt->opaque;
161
+ hdr.request.bodylen = htonl(hdr.request.extlen + ffextlen + mcreq_get_key_size(&hdr));
162
+
163
+ memcpy(SPAN_BUFFER(&pkt->kh_span), &hdr, sizeof(hdr));
164
+ std::size_t offset = sizeof(hdr);
165
+ if (!framing_extras.empty()) {
166
+ memcpy(SPAN_BUFFER(&pkt->kh_span) + offset, framing_extras.data(), framing_extras.size());
167
+ offset += framing_extras.size();
168
+ }
169
+ std::uint32_t expiry = htonl(cmd->expiry());
170
+ memcpy(SPAN_BUFFER(&pkt->kh_span) + offset, &expiry, sizeof(expiry));
152
171
 
153
- memcpy(SPAN_BUFFER(&pkt->kh_span), tcmd.bytes, hsize);
154
172
  pkt->u_rdata.reqdata.cookie = cmd->cookie();
155
173
  pkt->u_rdata.reqdata.start = cmd->start_time_or_default_in_nanoseconds(gethrtime());
156
174
  pkt->u_rdata.reqdata.deadline =
157
175
  pkt->u_rdata.reqdata.start +
158
176
  cmd->timeout_or_default_in_nanoseconds(LCB_US2NS(LCBT_SETTING(instance, operation_timeout)));
159
- 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);
160
178
  LCB_SCHED_ADD(instance, pl, pkt);
161
- TRACE_TOUCH_BEGIN(instance, hdr, cmd);
179
+ TRACE_TOUCH_BEGIN(instance, &hdr, cmd);
162
180
  return LCB_SUCCESS;
163
181
  }
164
182
 
@@ -101,6 +101,11 @@ LIBCOUCHBASE_API lcb_STATUS lcb_cmdunlock_cas(lcb_CMDUNLOCK *cmd, uint64_t cas)
101
101
  return cmd->cas(cas);
102
102
  }
103
103
 
104
+ LIBCOUCHBASE_API lcb_STATUS lcb_cmdunlock_on_behalf_of(lcb_CMDUNLOCK *cmd, const char *data, size_t data_len)
105
+ {
106
+ return cmd->on_behalf_of(std::string(data, data_len));
107
+ }
108
+
104
109
  static lcb_STATUS unlock_validate(lcb_INSTANCE *instance, const lcb_CMDUNLOCK *cmd)
105
110
  {
106
111
  if (cmd->key().empty()) {
@@ -124,10 +129,21 @@ static lcb_STATUS unlock_schedule(lcb_INSTANCE *instance, std::shared_ptr<lcb_CM
124
129
  mc_PACKET *pkt;
125
130
  mc_REQDATA *rd;
126
131
  lcb_STATUS err;
127
- protocol_binary_request_header hdr;
132
+ protocol_binary_request_header hdr{};
133
+
134
+ std::vector<std::uint8_t> framing_extras;
135
+ if (cmd->want_impersonation()) {
136
+ err = lcb::flexible_framing_extras::encode_impersonate_user(cmd->impostor(), framing_extras);
137
+ if (err != LCB_SUCCESS) {
138
+ return err;
139
+ }
140
+ }
141
+
142
+ hdr.request.magic = framing_extras.empty() ? PROTOCOL_BINARY_REQ : PROTOCOL_BINARY_AREQ;
143
+ auto ffextlen = static_cast<std::uint8_t>(framing_extras.size());
128
144
 
129
145
  lcb_KEYBUF keybuf{LCB_KV_COPY, {cmd->key().c_str(), cmd->key().size()}};
130
- err = mcreq_basic_packet(cq, &keybuf, cmd->collection().collection_id(), &hdr, 0, 0, &pkt, &pl,
146
+ err = mcreq_basic_packet(cq, &keybuf, cmd->collection().collection_id(), &hdr, 0, ffextlen, &pkt, &pl,
131
147
  MCREQ_BASICPACKET_F_FALLBACKOK);
132
148
  if (err != LCB_SUCCESS) {
133
149
  return err;
@@ -139,15 +155,18 @@ static lcb_STATUS unlock_schedule(lcb_INSTANCE *instance, std::shared_ptr<lcb_CM
139
155
  rd->deadline =
140
156
  rd->start + cmd->timeout_or_default_in_nanoseconds(LCB_US2NS(LCBT_SETTING(instance, operation_timeout)));
141
157
 
142
- hdr.request.magic = PROTOCOL_BINARY_REQ;
143
158
  hdr.request.opcode = PROTOCOL_BINARY_CMD_UNLOCK_KEY;
144
159
  hdr.request.datatype = PROTOCOL_BINARY_RAW_BYTES;
145
- hdr.request.bodylen = htonl((lcb_uint32_t)ntohs(hdr.request.keylen));
160
+ hdr.request.bodylen = htonl(mcreq_get_key_size(&hdr));
146
161
  hdr.request.opaque = pkt->opaque;
147
162
  hdr.request.cas = lcb_htonll(cmd->cas());
148
163
 
149
164
  memcpy(SPAN_BUFFER(&pkt->kh_span), hdr.bytes, sizeof(hdr.bytes));
150
- LCBTRACE_KV_START(instance->settings, pkt->opaque, cmd, LCBTRACE_OP_TOUCH, rd->span);
165
+ std::size_t offset = sizeof(hdr);
166
+ if (!framing_extras.empty()) {
167
+ memcpy(SPAN_BUFFER(&pkt->kh_span) + offset, framing_extras.data(), framing_extras.size());
168
+ }
169
+ rd->span = lcb::trace::start_kv_span(instance->settings, pkt, cmd);
151
170
  LCB_SCHED_ADD(instance, pl, pkt);
152
171
  TRACE_UNLOCK_BEGIN(instance, &hdr, cmd);
153
172
  return LCB_SUCCESS;
@@ -23,6 +23,7 @@
23
23
  #include <libcouchbase/couchbase.h>
24
24
  #include <memcached/protocol_binary.h>
25
25
  #include "rdb/rope.h"
26
+ #include "utilities.h"
26
27
 
27
28
  #ifndef __cplusplus
28
29
  typedef struct packet_info_st packet_info;
@@ -315,10 +316,10 @@ class MemcachedResponse
315
316
  }
316
317
  std::string emsg;
317
318
  if (!jerr["ref"].empty()) {
318
- *err_ref = strdup(jerr["ref"].asCString());
319
+ *err_ref = lcb_strdup(jerr["ref"].asCString());
319
320
  }
320
321
  if (!jerr["context"].empty()) {
321
- *err_ctx = strdup(jerr["context"].asCString());
322
+ *err_ctx = lcb_strdup(jerr["context"].asCString());
322
323
  }
323
324
  return LCB_SUCCESS;
324
325
  }
@@ -366,14 +366,33 @@ void RetryQueue::add(mc_EXPACKET *pkt, const lcb_STATUS err, protocol_binary_res
366
366
  if (server == nullptr) {
367
367
  continue;
368
368
  }
369
+
369
370
  /* check pending queue */
370
- SLLIST_ITERFOR(&server->nbmgr.sendq.pending, &iter)
371
371
  {
372
- nb_SNDQELEM *el = SLLIST_ITEM(iter.cur, nb_SNDQELEM, slnode);
373
- if (el->parent == op->pkt) {
374
- sllist_iter_remove(&server->nbmgr.sendq.pending, &iter);
372
+ nb_SENDQ *sq = &server->nbmgr.sendq;
373
+
374
+ /* in the case of completion IO, there is a chunk of the sendq which
375
+ * has already been written to the network and cannot be cancelled,
376
+ * we need to only scan to remove packets which have NOT been sent
377
+ * yet.
378
+ */
379
+ sllist_node *ll;
380
+ if (sq->last_requested) {
381
+ ll = sq->last_requested->slnode.next;
382
+ } else {
383
+ ll = SLLIST_FIRST(&sq->pending);
384
+ }
385
+ if (ll) {
386
+ for (slist_iter_init_at(ll, &iter); !sllist_iter_end(&sq->pending, &iter);
387
+ slist_iter_incr(&sq->pending, &iter)) {
388
+ nb_SNDQELEM *el = SLLIST_ITEM(iter.cur, nb_SNDQELEM, slnode);
389
+ if (el->parent == op->pkt) {
390
+ sllist_iter_remove(&sq->pending, &iter);
391
+ }
392
+ }
375
393
  }
376
394
  }
395
+
377
396
  /* check flush queue */
378
397
  SLLIST_ITERFOR(&server->nbmgr.sendq.pdus, &iter)
379
398
  {
@@ -406,7 +425,7 @@ void RetryQueue::add(mc_EXPACKET *pkt, const lcb_STATUS err, protocol_binary_res
406
425
  uint32_t cid = mcreq_get_cid(get_instance(), &pkt->base);
407
426
  lcb_log(LOGARGS(this, DEBUG),
408
427
  "Adding PKT=%p to retry queue. retries=%u, cid=%u, opaque=%u, now=%" PRIu64 "ms, spent=%" PRIu64
409
- "us, deadline_in=%" PRIu64 "us, , status=0x%02x, rc=%s",
428
+ "us, deadline_in=%" PRIu64 "us, status=0x%02x, rc=%s",
410
429
  (void *)pkt, pkt->base.retries, cid, pkt->base.opaque, LCB_NS2MS(now), LCB_NS2US(now - op->start),
411
430
  LCB_NS2US(op->deadline - now), status, lcb_strerror_short(err));
412
431
  schedule();
@@ -43,6 +43,7 @@ static lcb_STATUS search_execute(lcb_INSTANCE *instance, std::shared_ptr<lcb_CMD
43
43
  auto *req = new lcb_SEARCH_HANDLE_(instance, cmd->cookie(), cmd.get());
44
44
  if (req->has_error()) {
45
45
  lcb_STATUS rc = req->last_error();
46
+ req->clear_callback();
46
47
  delete req;
47
48
  return rc;
48
49
  }