couchbase 3.2.2 → 3.2.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (129) hide show
  1. package/binding.gyp +5 -0
  2. package/deps/lcb/CMakeLists.txt +1 -1
  3. package/deps/lcb/CONTRIBUTING.md +1 -1
  4. package/deps/lcb/README.markdown +2 -2
  5. package/deps/lcb/RELEASE_NOTES.markdown +84 -17
  6. package/deps/lcb/cmake/Modules/GetVersionInfo.cmake +1 -1
  7. package/deps/lcb/contrib/cbsasl/src/scram-sha/scram_utils.cc +22 -26
  8. package/deps/lcb/contrib/lcb-jsoncpp/lcb-jsoncpp.cpp +20 -6
  9. package/deps/lcb/doc/Doxyfile +1 -1
  10. package/deps/lcb/example/minimal/query.c +9 -7
  11. package/deps/lcb/gyp_config/common/libcouchbase/configuration.h +3 -3
  12. package/deps/lcb/gyp_config/linux/arm64/config.h +243 -0
  13. package/deps/lcb/include/libcouchbase/couchbase.h +55 -1
  14. package/deps/lcb/include/libcouchbase/error.h +6 -1
  15. package/deps/lcb/include/libcouchbase/ixmgmt.h +15 -10
  16. package/deps/lcb/include/libcouchbase/tracing.h +2 -2
  17. package/deps/lcb/include/memcached/protocol_binary.h +21 -0
  18. package/deps/lcb/libcouchbase.gyp +353 -349
  19. package/deps/lcb/packaging/deb/control +1 -1
  20. package/deps/lcb/src/analytics/analytics_handle.cc +7 -5
  21. package/deps/lcb/src/analytics/analytics_handle.hh +28 -0
  22. package/deps/lcb/src/capi/cmd_counter.hh +18 -0
  23. package/deps/lcb/src/capi/cmd_exists.hh +18 -0
  24. package/deps/lcb/src/capi/cmd_get.hh +17 -0
  25. package/deps/lcb/src/capi/cmd_get_replica.hh +20 -1
  26. package/deps/lcb/src/capi/cmd_query.cc +13 -0
  27. package/deps/lcb/src/capi/cmd_query.hh +22 -14
  28. package/deps/lcb/src/capi/cmd_remove.hh +18 -0
  29. package/deps/lcb/src/capi/cmd_search.hh +6 -0
  30. package/deps/lcb/src/capi/cmd_store.hh +28 -21
  31. package/deps/lcb/src/capi/cmd_subdoc.hh +30 -0
  32. package/deps/lcb/src/capi/cmd_touch.hh +18 -0
  33. package/deps/lcb/src/capi/cmd_unlock.hh +18 -0
  34. package/deps/lcb/src/capi/cmd_view.hh +6 -0
  35. package/deps/lcb/src/capi/collection_qualifier.hh +6 -8
  36. package/deps/lcb/src/cntl.cc +42 -8
  37. package/deps/lcb/src/dns-srv.cc +5 -3
  38. package/deps/lcb/src/errmap.cc +5 -9
  39. package/deps/lcb/src/errmap.h +7 -3
  40. package/deps/lcb/src/handler.cc +24 -18
  41. package/deps/lcb/src/internal.h +2 -1
  42. package/deps/lcb/src/lcbio/ctx.cc +4 -2
  43. package/deps/lcb/src/mcserver/mcserver.cc +8 -5
  44. package/deps/lcb/src/mcserver/negotiate.cc +42 -17
  45. package/deps/lcb/src/n1ql/ixmgmt.cc +1 -2
  46. package/deps/lcb/src/n1ql/n1ql.cc +5 -1
  47. package/deps/lcb/src/n1ql/query_handle.cc +80 -44
  48. package/deps/lcb/src/n1ql/query_handle.hh +41 -3
  49. package/deps/lcb/src/operations/counter.cc +13 -1
  50. package/deps/lcb/src/operations/exists.cc +14 -2
  51. package/deps/lcb/src/operations/get.cc +14 -2
  52. package/deps/lcb/src/operations/get_replica.cc +18 -6
  53. package/deps/lcb/src/operations/observe.cc +1 -1
  54. package/deps/lcb/src/operations/remove.cc +13 -1
  55. package/deps/lcb/src/operations/store.cc +13 -1
  56. package/deps/lcb/src/operations/subdoc.cc +13 -2
  57. package/deps/lcb/src/operations/touch.cc +14 -2
  58. package/deps/lcb/src/operations/unlock.cc +14 -2
  59. package/deps/lcb/src/search/search_handle.cc +26 -8
  60. package/deps/lcb/src/search/search_handle.hh +29 -0
  61. package/deps/lcb/src/ssl/ssl_common.c +7 -8
  62. package/deps/lcb/src/tracing/span.cc +43 -10
  63. package/deps/lcb/src/tracing/tracing-internal.h +105 -93
  64. package/deps/lcb/src/utilities.cc +21 -0
  65. package/deps/lcb/src/utilities.h +3 -0
  66. package/deps/lcb/src/views/view_handle.cc +13 -5
  67. package/deps/lcb/src/views/view_handle.hh +29 -0
  68. package/deps/lcb/tests/CMakeLists.txt +21 -0
  69. package/deps/lcb/tests/basic/t_ctlcodes.cc +24 -3
  70. package/deps/lcb/tests/basic/t_jsparse.cc +8 -0
  71. package/deps/lcb/tests/iotests/mock-environment.cc +25 -1
  72. package/deps/lcb/tests/iotests/mock-environment.h +49 -1
  73. package/deps/lcb/tests/iotests/mock-unit-test.cc +96 -5
  74. package/deps/lcb/tests/iotests/mock-unit-test.h +32 -0
  75. package/deps/lcb/tests/iotests/serverparams.h +7 -2
  76. package/deps/lcb/tests/iotests/t_collections.cc +1 -1
  77. package/deps/lcb/tests/iotests/t_confmon.cc +4 -2
  78. package/deps/lcb/tests/iotests/t_get.cc +14 -4
  79. package/deps/lcb/tests/iotests/t_n1ql.cc +17 -1
  80. package/deps/lcb/tests/iotests/t_ratelimit.cc +729 -0
  81. package/deps/lcb/tests/iotests/t_views.cc +1 -0
  82. package/deps/lcb/tests/iotests/testutil.cc +342 -0
  83. package/deps/lcb/tests/iotests/testutil.h +164 -0
  84. package/deps/lcb/tests/mocksupport/procutil.c +32 -28
  85. package/deps/lcb/tests/mocksupport/server.c +0 -1
  86. package/deps/lcb/tools/cbc.cc +7 -0
  87. package/dist/analyticsexecutor.js +2 -2
  88. package/dist/analyticsindexmanager.js +512 -524
  89. package/dist/binarycollection.d.ts +17 -0
  90. package/dist/binding.d.ts +2 -0
  91. package/dist/binding.js +1 -1
  92. package/dist/bindingutilities.js +9 -1
  93. package/dist/bucketmanager.d.ts +32 -23
  94. package/dist/bucketmanager.js +197 -189
  95. package/dist/cluster.js +37 -36
  96. package/dist/collection.js +17 -23
  97. package/dist/collectionmanager.js +181 -200
  98. package/dist/connection.js +6 -3
  99. package/dist/connspec.js +5 -1
  100. package/dist/couchbase.js +7 -14
  101. package/dist/datastructures.js +239 -310
  102. package/dist/diagnosticsexecutor.js +70 -85
  103. package/dist/errors.d.ts +18 -0
  104. package/dist/errors.js +26 -2
  105. package/dist/eventingfunctionmanager.js +267 -294
  106. package/dist/httpexecutor.js +31 -38
  107. package/dist/logging.js +1 -1
  108. package/dist/queryexecutor.js +3 -3
  109. package/dist/queryindexmanager.js +236 -263
  110. package/dist/scope.js +8 -2
  111. package/dist/searchexecutor.js +3 -0
  112. package/dist/searchindexmanager.js +240 -271
  113. package/dist/searchquery.d.ts +17 -0
  114. package/dist/searchquery.js +22 -1
  115. package/dist/searchtypes.d.ts +7 -2
  116. package/dist/searchtypes.js +2 -2
  117. package/dist/usermanager.js +250 -263
  118. package/dist/utilities.d.ts +3 -2
  119. package/dist/utilities.js +16 -4
  120. package/dist/viewexecutor.js +1 -1
  121. package/dist/viewindexmanager.js +131 -150
  122. package/package.json +1 -1
  123. package/src/connection.cpp +2 -0
  124. package/src/constants.cpp +2 -0
  125. package/src/instance.cpp +8 -1
  126. package/src/instance.h +1 -0
  127. package/src/uv-plugin-all.cpp +1 -0
  128. package/dist/cas.d.ts +0 -0
  129. package/dist/cas.js +0 -1
@@ -21,6 +21,7 @@
21
21
  #include <lcbio/iotable.h>
22
22
  #include <mcserver/negotiate.h>
23
23
  #include <lcbio/ssl.h>
24
+ #include "n1ql/query_utils.hh"
24
25
 
25
26
  #define LOGARGS(instance, lvl) instance->settings, "cntl", LCB_LOG_##lvl, __FILE__, __LINE__
26
27
 
@@ -238,7 +239,35 @@ HANDLER(select_bucket_handler){RETURN_GET_SET(int, LCBT_SETTING(instance, select
238
239
 
239
240
  HANDLER(log_redaction_handler){RETURN_GET_SET(int, LCBT_SETTING(instance, log_redaction))}
240
241
 
241
- HANDLER(enable_tracing_handler){RETURN_GET_SET(int, LCBT_SETTING(instance, use_tracing))}
242
+ HANDLER(enable_tracing_handler)
243
+ {
244
+ if (mode == LCB_CNTL_GET) {
245
+ RETURN_GET_ONLY(int, instance->settings->use_tracing)
246
+ } else if (mode == LCB_CNTL_SET) {
247
+ if (arg == nullptr) {
248
+ return LCB_ERR_INVALID_ARGUMENT;
249
+ }
250
+ int enabled = *(static_cast<int *>(arg));
251
+ if (enabled) {
252
+ if (instance->settings->use_tracing) {
253
+ /* do nothing */
254
+ return LCB_SUCCESS;
255
+ }
256
+ instance->settings->tracer = lcbtrace_new(instance, LCBTRACE_F_THRESHOLD);
257
+ instance->settings->use_tracing = true;
258
+ return LCB_SUCCESS;
259
+ } else {
260
+ if (instance->settings->use_tracing) {
261
+ lcbtrace_destroy(instance->settings->tracer);
262
+ instance->settings->tracer = nullptr;
263
+ instance->settings->use_tracing = false;
264
+ }
265
+ return LCB_SUCCESS;
266
+ }
267
+ } else {
268
+ return LCB_ERR_CONTROL_UNSUPPORTED_MODE;
269
+ }
270
+ }
242
271
 
243
272
  HANDLER(enable_errmap_handler){RETURN_GET_SET(int, LCBT_SETTING(instance, use_errmap))}
244
273
 
@@ -858,14 +887,19 @@ typedef struct {
858
887
 
859
888
  static lcb_STATUS convert_timevalue(const char *arg, u_STRCONVERT *u)
860
889
  {
861
- double dtmp;
862
- char *end = nullptr;
863
- errno = 0;
864
- dtmp = std::strtod(arg, &end);
865
- if (errno == ERANGE || end == arg) {
866
- return LCB_ERR_CONTROL_INVALID_ARGUMENT;
890
+ try {
891
+ auto tmo_ns = lcb_parse_golang_duration(arg);
892
+ u->u32 = static_cast<std::uint32_t>(std::chrono::duration_cast<std::chrono::microseconds>(tmo_ns).count());
893
+ } catch (const lcb_duration_parse_error &) {
894
+ double dtmp;
895
+ char *end = nullptr;
896
+ errno = 0;
897
+ dtmp = std::strtod(arg, &end);
898
+ if (errno == ERANGE || end == arg) {
899
+ return LCB_ERR_CONTROL_INVALID_ARGUMENT;
900
+ }
901
+ u->u32 = static_cast<std::uint32_t>(dtmp * (double)1000000);
867
902
  }
868
- u->u32 = static_cast<std::uint32_t>(dtmp * (double)1000000);
869
903
  return LCB_SUCCESS;
870
904
  }
871
905
 
@@ -105,9 +105,11 @@ lcb_STATUS lcb::dnssrv_query(const char *addr, Hostlist &hs)
105
105
  }
106
106
 
107
107
  for (cur = root; cur; cur = cur->pNext) {
108
- // Use the ASCII version of the DNS lookup structure
109
- const DNS_SRV_DATAA *srv = &cur->Data.SRV;
110
- hs.add(srv->pNameTarget, srv->wPort);
108
+ if(cur->wType == DNS_TYPE_SRV) {
109
+ // Use the ASCII version of the DNS lookup structure
110
+ const DNS_SRV_DATAA *srv = &cur->Data.SRV;
111
+ hs.add(srv->pNameTarget, srv->wPort);
112
+ }
111
113
  }
112
114
  DnsRecordListFree(root, DnsFreeRecordList);
113
115
  return LCB_SUCCESS;
@@ -131,8 +131,7 @@ ErrorMap::ParseStatus ErrorMap::parse(const char *s, size_t n, std::string &errm
131
131
  return PARSE_ERROR;
132
132
  }
133
133
 
134
- Json::Value::const_iterator ii = errsJson.begin();
135
- for (; ii != errsJson.end(); ++ii) {
134
+ for (Json::Value::const_iterator ii = errsJson.begin(); ii != errsJson.end(); ++ii) {
136
135
  // Key is the version in hex
137
136
  unsigned ec = 0;
138
137
  if (sscanf(ii.key().asCString(), "%x", &ec) != 1) {
@@ -155,14 +154,11 @@ ErrorMap::ParseStatus ErrorMap::parse(const char *s, size_t n, std::string &errm
155
154
  return PARSE_ERROR;
156
155
  }
157
156
 
158
- Json::Value::const_iterator jj = attrs.begin();
159
- for (; jj != attrs.end(); ++jj) {
160
- ErrorAttribute attr = getAttribute(jj->asString());
161
- if (attr == INVALID_ATTRIBUTE) {
162
- errmsg = "unknown attribute received";
163
- return UNKNOWN_VERSION;
157
+ for (const auto &jj : attrs) {
158
+ ErrorAttribute attr = getAttribute(jj.asString());
159
+ if (attr != INVALID_ATTRIBUTE) {
160
+ error.attributes.insert(attr);
164
161
  }
165
- error.attributes.insert(attr);
166
162
  }
167
163
  if (error.hasAttribute(AUTO_RETRY)) {
168
164
  const Json::Value &retryJson = errorJson["retry"];
@@ -124,7 +124,11 @@ enum ErrorAttribute {
124
124
  * This attribute means that the error is related to operating on \
125
125
  * a soft-deleted document. \
126
126
  */ \
127
- X(ITEM_DELETED, "item-deleted")
127
+ X(ITEM_DELETED, "item-deleted") \
128
+ /** \
129
+ * The error is related to rate limitation for the client (version 2) \
130
+ */ \
131
+ X(ITEM_RATE_LIMIT, "rate-limit")
128
132
 
129
133
  #define X(c, s) c,
130
134
  LCB_XERRMAP_ATTRIBUTES(X)
@@ -221,7 +225,7 @@ struct Error {
221
225
  uint16_t code;
222
226
  std::string shortname;
223
227
  std::string description;
224
- std::set< ErrorAttribute > attributes;
228
+ std::set<ErrorAttribute> attributes;
225
229
  SpecWrapper retry;
226
230
 
227
231
  Error() : code(-1) {}
@@ -280,7 +284,7 @@ class ErrorMap
280
284
  private:
281
285
  static const uint32_t MAX_VERSION;
282
286
  ErrorMap(const ErrorMap &);
283
- typedef std::map< uint16_t, Error > MapType;
287
+ typedef std::map<uint16_t, Error> MapType;
284
288
  MapType errors;
285
289
  uint32_t revision{0};
286
290
  uint32_t version{0};
@@ -157,6 +157,13 @@ lcb_STATUS lcb_map_error(lcb_INSTANCE *instance, int in)
157
157
  return LCB_ERR_DURABILITY_AMBIGUOUS;
158
158
  case PROTOCOL_BINARY_RESPONSE_LOCKED:
159
159
  return LCB_ERR_DOCUMENT_LOCKED;
160
+ case PROTOCOL_BINARY_RATE_LIMITED_NETWORK_INGRESS:
161
+ case PROTOCOL_BINARY_RATE_LIMITED_NETWORK_EGRESS:
162
+ case PROTOCOL_BINARY_RATE_LIMITED_MAX_CONNECTIONS:
163
+ case PROTOCOL_BINARY_RATE_LIMITED_MAX_COMMANDS:
164
+ return LCB_ERR_RATE_LIMITED;
165
+ case PROTOCOL_BINARY_SCOPE_SIZE_LIMIT_EXCEEDED:
166
+ return LCB_ERR_QUOTA_LIMITED;
160
167
  default:
161
168
  if (instance != nullptr) {
162
169
  return instance->callbacks.errmap(instance, in);
@@ -269,20 +276,19 @@ void init_resp(lcb_INSTANCE *instance, mc_PIPELINE *pipeline, const MemcachedRes
269
276
  resp->ctx.key.assign(key, key_len);
270
277
  }
271
278
 
272
- auto *server = static_cast<lcb::Server *>(pipeline);
279
+ const auto *server = static_cast<lcb::Server *>(pipeline);
273
280
  const lcb_host_t *remote = server->curhost;
274
281
  if (remote) {
275
- std::stringstream ss;
282
+ resp->ctx.endpoint.reserve(sizeof(remote->host) + sizeof(remote->port) + 3);
276
283
  if (remote->ipv6) {
277
- ss << '[';
284
+ resp->ctx.endpoint.append("[");
278
285
  }
279
- ss << remote->host;
286
+ resp->ctx.endpoint.append(remote->host);
280
287
  if (remote->ipv6) {
281
- ss << ']';
288
+ resp->ctx.endpoint.append("]");
282
289
  }
283
- ss << ':';
284
- ss << remote->port;
285
- resp->ctx.endpoint = ss.str();
290
+ resp->ctx.endpoint.append(":");
291
+ resp->ctx.endpoint.append(remote->port);
286
292
  }
287
293
  }
288
294
 
@@ -421,7 +427,7 @@ static void H_get(mc_PIPELINE *pipeline, mc_PACKET *request, MemcachedResponse *
421
427
 
422
428
  void *freeptr = nullptr;
423
429
  maybe_decompress(o, response, &resp, &freeptr);
424
- LCBTRACE_KV_FINISH(pipeline, request, resp, response->duration());
430
+ lcb::trace::finish_kv_span(pipeline, request, response);
425
431
  TRACE_GET_END(o, request, response, &resp);
426
432
  record_kv_op_latency("get", o, request);
427
433
  if (request->flags & MCREQ_F_REQEXT) {
@@ -455,7 +461,7 @@ static void H_exists(mc_PIPELINE *pipeline, mc_PACKET *request, MemcachedRespons
455
461
  resp.seqno = lcb_ntohll(resp.seqno);
456
462
  }
457
463
  }
458
- LCBTRACE_KV_FINISH(pipeline, request, resp, response->duration());
464
+ lcb::trace::finish_kv_span(pipeline, request, response);
459
465
  TRACE_EXISTS_END(root, request, response, &resp);
460
466
  record_kv_op_latency("exists", root, request);
461
467
  invoke_callback(request, root, &resp, LCB_CALLBACK_EXISTS);
@@ -555,7 +561,7 @@ static void H_subdoc(mc_PIPELINE *pipeline, mc_PACKET *request, MemcachedRespons
555
561
  handle_error_info(response, resp);
556
562
  }
557
563
  }
558
- LCBTRACE_KV_FINISH(pipeline, request, resp, response->duration());
564
+ lcb::trace::finish_kv_span(pipeline, request, response);
559
565
 
560
566
  if (cbtype == LCB_CALLBACK_SDLOOKUP) {
561
567
  record_kv_op_latency("lookup_in", o, request);
@@ -689,7 +695,7 @@ static void H_delete(mc_PIPELINE *pipeline, mc_PACKET *packet, MemcachedResponse
689
695
  init_resp(root, pipeline, response, packet, immerr, &resp);
690
696
  handle_error_info(response, resp);
691
697
  handle_mutation_token(root, response, packet, &resp.mt);
692
- LCBTRACE_KV_FINISH(pipeline, packet, resp, response->duration());
698
+ lcb::trace::finish_kv_span(pipeline, packet, response);
693
699
  TRACE_REMOVE_END(root, packet, response, &resp);
694
700
  record_kv_op_latency("remove", root, packet);
695
701
  invoke_callback(packet, root, &resp, LCB_CALLBACK_REMOVE);
@@ -797,7 +803,7 @@ static void H_observe_seqno(mc_PIPELINE *pipeline, mc_PACKET *request, Memcached
797
803
  /* Get the server for this command. Note that since this is a successful
798
804
  * operation, the server is never a dummy */
799
805
  }
800
- LCBTRACE_KV_FINISH(pipeline, request, resp, response->duration());
806
+ lcb::trace::finish_kv_span(pipeline, request, response);
801
807
  invoke_callback(request, root, &resp, LCB_CALLBACK_OBSEQNO);
802
808
  }
803
809
 
@@ -829,7 +835,7 @@ static void H_store(mc_PIPELINE *pipeline, mc_PACKET *request, MemcachedResponse
829
835
  resp.rflags |= LCB_RESP_F_EXTDATA | LCB_RESP_F_FINAL;
830
836
  handle_mutation_token(root, response, request, &resp.mt);
831
837
  TRACE_STORE_END(root, request, response, &resp);
832
- LCBTRACE_KV_FINISH(pipeline, request, resp, response->duration());
838
+ lcb::trace::finish_kv_span(pipeline, request, response);
833
839
  record_kv_op_latency_store(root, request, &resp);
834
840
  if (request->flags & MCREQ_F_REQEXT) {
835
841
  request->u_rdata.exdata->procs->handler(pipeline, request, LCB_CALLBACK_STORE, immerr, &resp);
@@ -854,7 +860,7 @@ static void H_arithmetic(mc_PIPELINE *pipeline, mc_PACKET *request, MemcachedRes
854
860
  }
855
861
  resp.rflags |= LCB_RESP_F_FINAL;
856
862
  resp.ctx.cas = response->cas();
857
- LCBTRACE_KV_FINISH(pipeline, request, resp, response->duration());
863
+ lcb::trace::finish_kv_span(pipeline, request, response);
858
864
  TRACE_ARITHMETIC_END(root, request, response, &resp);
859
865
  record_kv_op_latency("arithmetic", root, request);
860
866
  invoke_callback(request, root, &resp, LCB_CALLBACK_COUNTER);
@@ -941,7 +947,7 @@ static void H_noop(mc_PIPELINE *pipeline, mc_PACKET *request, MemcachedResponse
941
947
  {
942
948
  lcb_INSTANCE *root = get_instance(pipeline);
943
949
  lcb_RESPNOOP resp{};
944
- mc_REQDATAEX *exdata = request->u_rdata.exdata;
950
+ const mc_REQDATAEX *exdata = request->u_rdata.exdata;
945
951
 
946
952
  make_error(root, &resp, response, immerr, request);
947
953
 
@@ -955,7 +961,7 @@ static void H_touch(mc_PIPELINE *pipeline, mc_PACKET *request, MemcachedResponse
955
961
  init_resp(root, pipeline, response, request, immerr, &resp);
956
962
  handle_error_info(response, resp);
957
963
  resp.rflags |= LCB_RESP_F_FINAL;
958
- LCBTRACE_KV_FINISH(pipeline, request, resp, response->duration());
964
+ lcb::trace::finish_kv_span(pipeline, request, response);
959
965
  TRACE_TOUCH_END(root, request, response, &resp);
960
966
  record_kv_op_latency("touch", root, request);
961
967
  invoke_callback(request, root, &resp, LCB_CALLBACK_TOUCH);
@@ -968,7 +974,7 @@ static void H_unlock(mc_PIPELINE *pipeline, mc_PACKET *request, MemcachedRespons
968
974
  init_resp(root, pipeline, response, request, immerr, &resp);
969
975
  handle_error_info(response, resp);
970
976
  resp.rflags |= LCB_RESP_F_FINAL;
971
- LCBTRACE_KV_FINISH(pipeline, request, resp, response->duration());
977
+ lcb::trace::finish_kv_span(pipeline, request, response);
972
978
  TRACE_UNLOCK_END(root, request, response, &resp);
973
979
  record_kv_op_latency("unlock", root, request);
974
980
  invoke_callback(request, root, &resp, LCB_CALLBACK_UNLOCK);
@@ -259,7 +259,8 @@ lcb_STATUS lcb_initialize_socket_subsystem(void);
259
259
  lcb_STATUS lcb_reinit(lcb_INSTANCE *obj, const char *connstr);
260
260
 
261
261
  lcb_RETRY_ACTION lcb_kv_should_retry(const lcb_settings *settings, const mc_PACKET *pkt, lcb_STATUS err);
262
- lcb_RETRY_ACTION lcb_query_should_retry(const lcb_settings *settings, lcb_QUERY_HANDLE *query, lcb_STATUS err);
262
+ lcb_RETRY_ACTION lcb_query_should_retry(const lcb_settings *settings, lcb_QUERY_HANDLE *query, lcb_STATUS err,
263
+ int retry_attribute);
263
264
 
264
265
  lcb_RESPCALLBACK lcb_find_callback(lcb_INSTANCE *instance, lcb_CALLBACK_TYPE cbtype);
265
266
 
@@ -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 */
@@ -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
  }
@@ -816,7 +819,7 @@ void Server::purge_single(mc_PACKET *pkt, lcb_STATUS err)
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 {
@@ -658,24 +660,46 @@ GT_NEXT_PACKET:
658
660
  status);
659
661
  set_error(LCB_ERR_PROTOCOL_ERROR, "GET_ERRMAP response unexpected", &resp);
660
662
  }
663
+ if (settings->keypath) {
664
+ completed = !maybe_select_bucket();
665
+ }
661
666
  // Note, there is no explicit state transition here. LIST_MECHS is
662
667
  // pipelined after this request.
663
668
  break;
664
669
  }
665
670
 
666
671
  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);
672
+ switch (status) {
673
+ case PROTOCOL_BINARY_RESPONSE_SUCCESS:
674
+ completed = true;
675
+ info->selected = true;
676
+ break;
677
+
678
+ case PROTOCOL_BINARY_RESPONSE_EACCESS:
679
+ set_error(LCB_ERR_BUCKET_NOT_FOUND,
680
+ "Provided credentials not allowed for bucket or bucket does not exist", &resp);
681
+ break;
682
+
683
+ case PROTOCOL_BINARY_RESPONSE_KEY_ENOENT:
684
+ set_error(LCB_ERR_BUCKET_NOT_FOUND, "Key/Value service is not configured for given node", &resp);
685
+ break;
686
+
687
+ case PROTOCOL_BINARY_RATE_LIMITED_MAX_COMMANDS:
688
+ case PROTOCOL_BINARY_RATE_LIMITED_MAX_CONNECTIONS:
689
+ case PROTOCOL_BINARY_RATE_LIMITED_NETWORK_EGRESS:
690
+ case PROTOCOL_BINARY_RATE_LIMITED_NETWORK_INGRESS:
691
+ set_error(LCB_ERR_RATE_LIMITED, "The tenant has reached rate limit", &resp);
692
+ break;
693
+
694
+ case PROTOCOL_BINARY_SCOPE_SIZE_LIMIT_EXCEEDED:
695
+ set_error(LCB_ERR_QUOTA_LIMITED, "The tenant has reached quota limit", &resp);
696
+ break;
697
+
698
+ default:
699
+ lcb_log(LOGARGS(this, ERROR), LOGFMT "Unexpected status 0x%x received for SELECT_BUCKET",
700
+ LOGID(this), status);
701
+ set_error(LCB_ERR_PROTOCOL_ERROR, "Other auth error", &resp);
702
+ break;
679
703
  }
680
704
  break;
681
705
  }
@@ -744,6 +768,7 @@ void SessionRequestImpl::start(lcbio_SOCKET *sock)
744
768
  send_hello();
745
769
  if (settings->use_errmap) {
746
770
  request_errmap();
771
+ expecting_error_map = true;
747
772
  } else {
748
773
  lcb_log(LOGARGS(this, TRACE), LOGFMT "GET_ERRORMAP disabled", LOGID(this));
749
774
  }
@@ -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
@@ -52,10 +52,14 @@ static lcb_RETRY_REASON query_code_to_reason(lcb_STATUS err)
52
52
  }
53
53
  }
54
54
 
55
- lcb_RETRY_ACTION lcb_query_should_retry(const lcb_settings *settings, lcb_QUERY_HANDLE *query, lcb_STATUS err)
55
+ lcb_RETRY_ACTION lcb_query_should_retry(const lcb_settings *settings, lcb_QUERY_HANDLE *query, lcb_STATUS err,
56
+ int retry_attribute)
56
57
  {
57
58
  lcb_RETRY_ACTION retry_action{};
58
59
  lcb_RETRY_REASON retry_reason = query_code_to_reason(err);
60
+ if (retry_attribute) {
61
+ retry_reason = LCB_RETRY_REASON_QUERY_ERROR_RETRYABLE;
62
+ }
59
63
  if (err == LCB_ERR_TIMEOUT) {
60
64
  /* We can't exceed a timeout for ETIMEDOUT */
61
65
  retry_action.should_retry = 0;