couchbase 4.2.3 → 4.2.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (199) hide show
  1. package/deps/couchbase-cxx-client/CMakeLists.txt +54 -4
  2. package/deps/couchbase-cxx-client/README.md +1 -0
  3. package/deps/couchbase-cxx-client/bin/create-search-index +164 -0
  4. package/deps/couchbase-cxx-client/bin/init-cluster +55 -10
  5. package/deps/couchbase-cxx-client/bin/run-unit-tests +62 -6
  6. package/deps/couchbase-cxx-client/bin/travel-sample-index-v6.json +184 -0
  7. package/deps/couchbase-cxx-client/bin/travel-sample-index.json +188 -0
  8. package/deps/couchbase-cxx-client/cmake/Documentation.cmake +0 -1
  9. package/deps/couchbase-cxx-client/cmake/OpenSSL.cmake +98 -3
  10. package/deps/couchbase-cxx-client/cmake/Testing.cmake +8 -0
  11. package/deps/couchbase-cxx-client/cmake/build_config.hxx.in +3 -0
  12. package/deps/couchbase-cxx-client/core/bucket.cxx +183 -152
  13. package/deps/couchbase-cxx-client/core/bucket.hxx +17 -4
  14. package/deps/couchbase-cxx-client/core/cluster.hxx +18 -1
  15. package/deps/couchbase-cxx-client/core/cluster_options.hxx +1 -0
  16. package/deps/couchbase-cxx-client/core/error_context/key_value.cxx +2 -1
  17. package/deps/couchbase-cxx-client/core/error_context/key_value.hxx +10 -12
  18. package/deps/couchbase-cxx-client/core/error_context/search.hxx +1 -1
  19. package/deps/couchbase-cxx-client/core/impl/analytics.cxx +1 -0
  20. package/deps/couchbase-cxx-client/core/impl/boolean_field_query.cxx +40 -0
  21. package/deps/couchbase-cxx-client/core/impl/boolean_query.cxx +62 -0
  22. package/deps/couchbase-cxx-client/core/impl/cluster.cxx +1 -0
  23. package/deps/couchbase-cxx-client/core/impl/conjunction_query.cxx +51 -0
  24. package/deps/couchbase-cxx-client/core/impl/date_range.cxx +89 -0
  25. package/deps/couchbase-cxx-client/core/impl/date_range_facet.cxx +54 -0
  26. package/deps/couchbase-cxx-client/core/impl/date_range_facet_result.cxx +64 -0
  27. package/deps/couchbase-cxx-client/core/impl/date_range_query.cxx +125 -0
  28. package/deps/couchbase-cxx-client/core/impl/disjunction_query.cxx +51 -0
  29. package/deps/couchbase-cxx-client/core/impl/encoded_search_facet.hxx +29 -0
  30. package/deps/couchbase-cxx-client/core/impl/encoded_search_query.hxx +29 -0
  31. package/deps/couchbase-cxx-client/core/impl/encoded_search_sort.hxx +29 -0
  32. package/deps/couchbase-cxx-client/core/impl/geo_bounding_box_query.cxx +46 -0
  33. package/deps/couchbase-cxx-client/core/impl/geo_distance_query.cxx +43 -0
  34. package/deps/couchbase-cxx-client/core/impl/geo_polygon_query.cxx +46 -0
  35. package/deps/couchbase-cxx-client/core/impl/internal_date_range_facet_result.cxx +80 -0
  36. package/deps/couchbase-cxx-client/core/impl/internal_date_range_facet_result.hxx +48 -0
  37. package/deps/couchbase-cxx-client/core/impl/internal_numeric_range_facet_result.cxx +80 -0
  38. package/deps/couchbase-cxx-client/core/impl/internal_numeric_range_facet_result.hxx +48 -0
  39. package/deps/couchbase-cxx-client/core/impl/internal_search_error_context.cxx +141 -0
  40. package/deps/couchbase-cxx-client/core/impl/internal_search_error_context.hxx +61 -0
  41. package/deps/couchbase-cxx-client/core/impl/internal_search_meta_data.cxx +60 -0
  42. package/deps/couchbase-cxx-client/core/impl/internal_search_meta_data.hxx +41 -0
  43. package/deps/couchbase-cxx-client/core/impl/internal_search_result.cxx +84 -0
  44. package/deps/couchbase-cxx-client/core/impl/internal_search_result.hxx +43 -0
  45. package/deps/couchbase-cxx-client/core/impl/internal_search_row.cxx +82 -0
  46. package/deps/couchbase-cxx-client/core/impl/internal_search_row.hxx +56 -0
  47. package/deps/couchbase-cxx-client/core/impl/internal_search_row_location.hxx +32 -0
  48. package/deps/couchbase-cxx-client/core/impl/internal_search_row_locations.cxx +137 -0
  49. package/deps/couchbase-cxx-client/core/impl/internal_search_row_locations.hxx +45 -0
  50. package/deps/couchbase-cxx-client/core/impl/internal_term_facet_result.cxx +80 -0
  51. package/deps/couchbase-cxx-client/core/impl/internal_term_facet_result.hxx +48 -0
  52. package/deps/couchbase-cxx-client/core/impl/key_value_error_context.cxx +98 -0
  53. package/deps/couchbase-cxx-client/core/impl/match_all_query.cxx +35 -0
  54. package/deps/couchbase-cxx-client/core/impl/match_none_query.cxx +35 -0
  55. package/deps/couchbase-cxx-client/core/impl/match_phrase_query.cxx +43 -0
  56. package/deps/couchbase-cxx-client/core/impl/match_query.cxx +59 -0
  57. package/deps/couchbase-cxx-client/core/impl/numeric_range.cxx +49 -0
  58. package/deps/couchbase-cxx-client/core/impl/numeric_range_facet.cxx +54 -0
  59. package/deps/couchbase-cxx-client/core/impl/numeric_range_facet_result.cxx +64 -0
  60. package/deps/couchbase-cxx-client/core/impl/numeric_range_query.cxx +56 -0
  61. package/deps/couchbase-cxx-client/core/impl/phrase_query.cxx +42 -0
  62. package/deps/couchbase-cxx-client/core/impl/prefix_query.cxx +40 -0
  63. package/deps/couchbase-cxx-client/core/impl/query_error_context.cxx +75 -0
  64. package/deps/couchbase-cxx-client/core/impl/query_string_query.cxx +37 -0
  65. package/deps/couchbase-cxx-client/core/impl/regexp_query.cxx +40 -0
  66. package/deps/couchbase-cxx-client/core/impl/search.cxx +191 -0
  67. package/deps/couchbase-cxx-client/core/impl/search_error_context.cxx +147 -0
  68. package/deps/couchbase-cxx-client/core/impl/search_meta_data.cxx +46 -0
  69. package/deps/couchbase-cxx-client/core/impl/search_result.cxx +66 -0
  70. package/deps/couchbase-cxx-client/core/impl/search_row.cxx +74 -0
  71. package/deps/couchbase-cxx-client/core/impl/search_row_location.cxx +64 -0
  72. package/deps/couchbase-cxx-client/core/impl/search_row_locations.cxx +66 -0
  73. package/deps/couchbase-cxx-client/core/impl/search_sort_field.cxx +104 -0
  74. package/deps/couchbase-cxx-client/core/impl/search_sort_id.cxx +43 -0
  75. package/deps/couchbase-cxx-client/core/impl/search_sort_score.cxx +43 -0
  76. package/deps/couchbase-cxx-client/core/impl/term_facet.cxx +36 -0
  77. package/deps/couchbase-cxx-client/core/impl/term_facet_result.cxx +64 -0
  78. package/deps/couchbase-cxx-client/core/impl/term_query.cxx +56 -0
  79. package/deps/couchbase-cxx-client/core/impl/term_range_query.cxx +57 -0
  80. package/deps/couchbase-cxx-client/core/impl/wildcard_query.cxx +40 -0
  81. package/deps/couchbase-cxx-client/core/io/mcbp_command.hxx +9 -2
  82. package/deps/couchbase-cxx-client/core/io/mcbp_session.cxx +54 -37
  83. package/deps/couchbase-cxx-client/core/io/mcbp_session.hxx +4 -3
  84. package/deps/couchbase-cxx-client/core/json_string.hxx +5 -0
  85. package/deps/couchbase-cxx-client/core/meta/version.cxx +18 -4
  86. package/deps/couchbase-cxx-client/core/mozilla_ca_bundle.hxx +39 -0
  87. package/deps/couchbase-cxx-client/core/operations/document_search.cxx +3 -1
  88. package/deps/couchbase-cxx-client/core/operations/document_search.hxx +1 -1
  89. package/deps/couchbase-cxx-client/core/protocol/client_request.hxx +11 -2
  90. package/deps/couchbase-cxx-client/core/protocol/client_response.hxx +1 -0
  91. package/deps/couchbase-cxx-client/core/utils/connection_string.cxx +59 -46
  92. package/deps/couchbase-cxx-client/core/utils/connection_string.hxx +1 -0
  93. package/deps/couchbase-cxx-client/couchbase/analytics_error_context.hxx +1 -1
  94. package/deps/couchbase-cxx-client/couchbase/boolean_field_query.hxx +77 -0
  95. package/deps/couchbase-cxx-client/couchbase/boolean_query.hxx +223 -0
  96. package/deps/couchbase-cxx-client/couchbase/cluster.hxx +39 -0
  97. package/deps/couchbase-cxx-client/couchbase/conjunction_query.hxx +88 -0
  98. package/deps/couchbase-cxx-client/couchbase/date_range.hxx +69 -0
  99. package/deps/couchbase-cxx-client/couchbase/date_range_facet.hxx +56 -0
  100. package/deps/couchbase-cxx-client/couchbase/date_range_facet_result.hxx +55 -0
  101. package/deps/couchbase-cxx-client/couchbase/date_range_query.hxx +265 -0
  102. package/deps/couchbase-cxx-client/couchbase/disjunction_query.hxx +109 -0
  103. package/deps/couchbase-cxx-client/couchbase/doc_id_query.hxx +111 -0
  104. package/deps/couchbase-cxx-client/couchbase/error_context.hxx +17 -8
  105. package/deps/couchbase-cxx-client/couchbase/fmt/analytics_scan_consistency.hxx +52 -0
  106. package/deps/couchbase-cxx-client/{core/topology/error_map_fmt.hxx → couchbase/fmt/key_value_error_map_attribute.hxx} +21 -21
  107. package/deps/couchbase-cxx-client/couchbase/fmt/search_scan_consistency.hxx +49 -0
  108. package/deps/couchbase-cxx-client/couchbase/geo_bounding_box_query.hxx +107 -0
  109. package/deps/couchbase-cxx-client/couchbase/geo_distance_query.hxx +109 -0
  110. package/deps/couchbase-cxx-client/couchbase/geo_point.hxx +32 -0
  111. package/deps/couchbase-cxx-client/couchbase/geo_polygon_query.hxx +85 -0
  112. package/deps/couchbase-cxx-client/couchbase/highlight_style.hxx +45 -0
  113. package/deps/couchbase-cxx-client/couchbase/key_value_error_context.hxx +7 -2
  114. package/deps/couchbase-cxx-client/couchbase/manager_error_context.hxx +1 -1
  115. package/deps/couchbase-cxx-client/couchbase/match_all_query.hxx +43 -0
  116. package/deps/couchbase-cxx-client/couchbase/match_none_query.hxx +43 -0
  117. package/deps/couchbase-cxx-client/couchbase/match_operator.hxx +45 -0
  118. package/deps/couchbase-cxx-client/couchbase/match_phrase_query.hxx +108 -0
  119. package/deps/couchbase-cxx-client/couchbase/match_query.hxx +163 -0
  120. package/deps/couchbase-cxx-client/couchbase/numeric_range.hxx +58 -0
  121. package/deps/couchbase-cxx-client/couchbase/numeric_range_facet.hxx +56 -0
  122. package/deps/couchbase-cxx-client/couchbase/numeric_range_facet_result.hxx +55 -0
  123. package/deps/couchbase-cxx-client/couchbase/numeric_range_query.hxx +143 -0
  124. package/deps/couchbase-cxx-client/couchbase/phrase_query.hxx +93 -0
  125. package/deps/couchbase-cxx-client/couchbase/prefix_query.hxx +82 -0
  126. package/deps/couchbase-cxx-client/couchbase/query_error_context.hxx +3 -1
  127. package/deps/couchbase-cxx-client/couchbase/query_string_query.hxx +72 -0
  128. package/deps/couchbase-cxx-client/couchbase/regexp_query.hxx +82 -0
  129. package/deps/couchbase-cxx-client/couchbase/scope.hxx +39 -0
  130. package/deps/couchbase-cxx-client/couchbase/search_date_range.hxx +68 -0
  131. package/deps/couchbase-cxx-client/couchbase/search_error_context.hxx +138 -0
  132. package/deps/couchbase-cxx-client/couchbase/search_facet.hxx +60 -0
  133. package/deps/couchbase-cxx-client/couchbase/search_facet_result.hxx +50 -0
  134. package/deps/couchbase-cxx-client/couchbase/search_meta_data.hxx +85 -0
  135. package/deps/couchbase-cxx-client/couchbase/search_metrics.hxx +127 -0
  136. package/deps/couchbase-cxx-client/couchbase/search_numeric_range.hxx +69 -0
  137. package/deps/couchbase-cxx-client/couchbase/search_options.hxx +509 -0
  138. package/deps/couchbase-cxx-client/couchbase/search_query.hxx +69 -0
  139. package/deps/couchbase-cxx-client/couchbase/search_result.hxx +77 -0
  140. package/deps/couchbase-cxx-client/couchbase/search_row.hxx +104 -0
  141. package/deps/couchbase-cxx-client/couchbase/search_row_location.hxx +55 -0
  142. package/deps/couchbase-cxx-client/couchbase/search_row_locations.hxx +86 -0
  143. package/deps/couchbase-cxx-client/couchbase/search_scan_consistency.hxx +34 -0
  144. package/deps/couchbase-cxx-client/couchbase/search_sort.hxx +58 -0
  145. package/deps/couchbase-cxx-client/couchbase/search_sort_field.hxx +117 -0
  146. package/deps/couchbase-cxx-client/couchbase/search_sort_field_missing.hxx +26 -0
  147. package/deps/couchbase-cxx-client/couchbase/search_sort_field_mode.hxx +27 -0
  148. package/deps/couchbase-cxx-client/couchbase/search_sort_field_type.hxx +28 -0
  149. package/deps/couchbase-cxx-client/couchbase/search_sort_id.hxx +60 -0
  150. package/deps/couchbase-cxx-client/couchbase/search_sort_score.hxx +60 -0
  151. package/deps/couchbase-cxx-client/couchbase/search_term_range.hxx +51 -0
  152. package/deps/couchbase-cxx-client/couchbase/security_options.hxx +3 -0
  153. package/deps/couchbase-cxx-client/couchbase/subdocument_error_context.hxx +4 -2
  154. package/deps/couchbase-cxx-client/couchbase/term_facet.hxx +48 -0
  155. package/deps/couchbase-cxx-client/couchbase/term_facet_result.hxx +55 -0
  156. package/deps/couchbase-cxx-client/couchbase/term_query.hxx +151 -0
  157. package/deps/couchbase-cxx-client/couchbase/term_range_query.hxx +142 -0
  158. package/deps/couchbase-cxx-client/couchbase/transactions/transaction_options.hxx +1 -1
  159. package/deps/couchbase-cxx-client/couchbase/transactions/transaction_query_options.hxx +2 -1
  160. package/deps/couchbase-cxx-client/couchbase/transactions/transaction_result.hxx +1 -1
  161. package/deps/couchbase-cxx-client/couchbase/transactions.hxx +3 -3
  162. package/deps/couchbase-cxx-client/couchbase/wildcard_query.hxx +83 -0
  163. package/deps/couchbase-cxx-client/docs/Doxyfile.in +1 -1
  164. package/deps/couchbase-cxx-client/docs/cbc-analytics.md +2 -2
  165. package/deps/couchbase-cxx-client/docs/cbc-get.md +3 -2
  166. package/deps/couchbase-cxx-client/docs/cbc-pillowfight.md +7 -2
  167. package/deps/couchbase-cxx-client/docs/cbc-query.md +2 -2
  168. package/deps/couchbase-cxx-client/docs/cbc.md +3 -3
  169. package/deps/couchbase-cxx-client/docs/cli.hxx +5 -5
  170. package/deps/couchbase-cxx-client/docs/mainpage.hxx +42 -5
  171. package/deps/couchbase-cxx-client/test/CMakeLists.txt +1 -0
  172. package/deps/couchbase-cxx-client/test/test_integration_analytics.cxx +28 -6
  173. package/deps/couchbase-cxx-client/test/test_integration_collections.cxx +7 -3
  174. package/deps/couchbase-cxx-client/test/test_integration_connect.cxx +7 -3
  175. package/deps/couchbase-cxx-client/test/test_integration_crud.cxx +13 -3
  176. package/deps/couchbase-cxx-client/test/test_integration_diagnostics.cxx +8 -2
  177. package/deps/couchbase-cxx-client/test/test_integration_durability.cxx +12 -7
  178. package/deps/couchbase-cxx-client/test/test_integration_examples.cxx +283 -11
  179. package/deps/couchbase-cxx-client/test/test_integration_management.cxx +140 -88
  180. package/deps/couchbase-cxx-client/test/test_integration_query.cxx +67 -9
  181. package/deps/couchbase-cxx-client/test/test_integration_range_scan.cxx +12 -12
  182. package/deps/couchbase-cxx-client/test/test_integration_read_replica.cxx +48 -11
  183. package/deps/couchbase-cxx-client/test/test_integration_search.cxx +19 -1
  184. package/deps/couchbase-cxx-client/test/test_integration_subdoc.cxx +60 -9
  185. package/deps/couchbase-cxx-client/test/test_integration_tracer.cxx +3 -0
  186. package/deps/couchbase-cxx-client/test/test_integration_transcoders.cxx +4 -0
  187. package/deps/couchbase-cxx-client/test/test_transaction_examples.cxx +100 -85
  188. package/deps/couchbase-cxx-client/test/test_unit_connection_string.cxx +29 -0
  189. package/deps/couchbase-cxx-client/test/test_unit_search.cxx +427 -0
  190. package/deps/couchbase-cxx-client/test/utils/integration_test_guard.cxx +2 -1
  191. package/deps/couchbase-cxx-client/test/utils/logger.cxx +3 -1
  192. package/deps/couchbase-cxx-client/test/utils/server_version.hxx +31 -15
  193. package/deps/couchbase-cxx-client/test/utils/test_context.cxx +8 -0
  194. package/deps/couchbase-cxx-client/tools/get.cxx +9 -8
  195. package/deps/couchbase-cxx-client/tools/pillowfight.cxx +175 -75
  196. package/deps/couchbase-cxx-client/tools/version.cxx +4 -2
  197. package/dist/binding.d.ts +1 -1
  198. package/package.json +1 -1
  199. package/src/jstocbpp_autogen.hpp +3 -2
@@ -22,7 +22,6 @@
22
22
  #include "core/mcbp/codec.hxx"
23
23
  #include "dispatcher.hxx"
24
24
  #include "impl/bootstrap_state_listener.hxx"
25
- #include "mcbp/completion_token.hxx"
26
25
  #include "mcbp/operation_queue.hxx"
27
26
  #include "mcbp/queue_request.hxx"
28
27
  #include "mcbp/queue_response.hxx"
@@ -41,28 +40,6 @@
41
40
 
42
41
  namespace couchbase::core
43
42
  {
44
- /**
45
- * copies nodes from rhs that are not in lhs to output vector
46
- */
47
- static void
48
- diff_nodes(const std::vector<topology::configuration::node>& lhs,
49
- const std::vector<topology::configuration::node>& rhs,
50
- std::vector<topology::configuration::node>& output)
51
- {
52
- for (const auto& re : rhs) {
53
- bool known = false;
54
- for (const auto& le : lhs) {
55
- if (le.hostname == re.hostname && le.services_plain.management.value_or(0) == re.services_plain.management.value_or(0)) {
56
- known = true;
57
- break;
58
- }
59
- }
60
- if (!known) {
61
- output.push_back(re);
62
- }
63
- }
64
- }
65
-
66
43
  class bucket_impl
67
44
  : public std::enable_shared_from_this<bucket_impl>
68
45
  , public config_listener
@@ -303,82 +280,111 @@ class bucket_impl
303
280
  return config_->map_key(key, node_index);
304
281
  }
305
282
 
306
- void restart_node(std::size_t index, const std::string& hostname, const std::string& port)
283
+ void restart_sessions()
307
284
  {
308
- if (closed_) {
309
- CB_LOG_DEBUG(R"({} requested to restart session, but the bucket has been closed already. idx={}, address="{}:{}")",
310
- log_prefix_,
311
- index,
312
- hostname,
313
- port);
285
+ const std::scoped_lock lock(config_mutex_, sessions_mutex_);
286
+ if (!config_.has_value()) {
314
287
  return;
315
288
  }
316
- {
317
- std::scoped_lock lock(config_mutex_);
318
- if (!config_->has_node(origin_.options().network, service_type::key_value, origin_.options().enable_tls, hostname, port)) {
319
- CB_LOG_TRACE(
320
- R"({} requested to restart session, but the node has been ejected from current configuration already. idx={}, network={}, address="{}:{}")",
321
- log_prefix_,
322
- index,
323
- origin_.options().network,
324
- hostname,
325
- port);
326
- return;
327
- }
328
- }
329
- couchbase::core::origin origin(origin_.credentials(), hostname, port, origin_.options());
330
289
 
331
- io::mcbp_session session = origin_.options().enable_tls
332
- ? io::mcbp_session(client_id_, ctx_, tls_, origin, state_listener_, name_, known_features_)
333
- : io::mcbp_session(client_id_, ctx_, origin, state_listener_, name_, known_features_);
290
+ std::size_t kv_node_index{ 0 };
291
+ for (std::size_t index = 0; index < config_->nodes.size(); ++index) {
292
+ const auto& node = config_->nodes[index];
334
293
 
335
- std::scoped_lock lock(sessions_mutex_);
336
- if (auto ptr = sessions_.find(index); ptr == sessions_.end()) {
337
- CB_LOG_DEBUG(R"({} requested to restart session idx={}, which does not exist yet, initiate new one id="{}", address="{}:{}")",
338
- log_prefix_,
339
- index,
340
- session.id(),
341
- hostname,
342
- port);
343
- } else {
344
- const auto& old_session = ptr->second;
345
- auto old_id = old_session.id();
346
- sessions_.erase(ptr);
347
- Expects(sessions_.count(index) == 0);
348
- CB_LOG_DEBUG(R"({} restarting session idx={}, id=("{}" -> "{}"), address="{}:{}")",
294
+ const auto& hostname = node.hostname_for(origin_.options().network);
295
+ auto port = node.port_or(origin_.options().network, service_type::key_value, origin_.options().enable_tls, 0);
296
+ if (port == 0) {
297
+ continue;
298
+ }
299
+
300
+ auto ptr = std::find_if(sessions_.begin(), sessions_.end(), [&hostname, &port](const auto& session) {
301
+ return session.second.bootstrap_hostname() == hostname && session.second.bootstrap_port_number() == port;
302
+ });
303
+ if (ptr != sessions_.end()) {
304
+
305
+ if (auto found_kv_node_index = ptr->first; found_kv_node_index != kv_node_index) {
306
+ if (auto current = sessions_.find(kv_node_index); current == sessions_.end()) {
307
+ CB_LOG_WARNING(R"({} KV node index mismatch: config rev={} states that address="{}:{}" should be at idx={}, )"
308
+ R"(but it is at idx={} ("{}"). Moving session to idx={}.)",
309
+ log_prefix_,
310
+ config_->rev_str(),
311
+ hostname,
312
+ port,
313
+ kv_node_index,
314
+ found_kv_node_index,
315
+ ptr->second.id(),
316
+ kv_node_index);
317
+ sessions_.insert_or_assign(kv_node_index, std::move(ptr->second));
318
+ sessions_.erase(ptr);
319
+ } else {
320
+ CB_LOG_WARNING(
321
+ R"({} KV node index mismatch: config rev={} states that address="{}:{}" should be at idx={}, )"
322
+ R"(but it is at idx={} ("{}"). Slot with idx={} is holds session with address="{}" ("{}"), swapping them.)",
323
+ log_prefix_,
324
+ config_->rev_str(),
325
+ hostname,
326
+ port,
327
+ kv_node_index,
328
+ found_kv_node_index,
329
+ ptr->second.id(),
330
+ kv_node_index,
331
+ current->second.bootstrap_address(),
332
+ current->second.id());
333
+ std::swap(current->second, ptr->second);
334
+ }
335
+ }
336
+ ++kv_node_index;
337
+ continue;
338
+ }
339
+ couchbase::core::origin origin(origin_.credentials(), hostname, port, origin_.options());
340
+ io::mcbp_session session = origin_.options().enable_tls
341
+ ? io::mcbp_session(client_id_, ctx_, tls_, origin, state_listener_, name_, known_features_)
342
+ : io::mcbp_session(client_id_, ctx_, origin, state_listener_, name_, known_features_);
343
+ CB_LOG_DEBUG(R"({} rev={}, restart idx={}, session="{}", address="{}:{}")",
349
344
  log_prefix_,
350
- index,
351
- old_id,
345
+ config_->rev_str(),
346
+ node.index,
352
347
  session.id(),
353
348
  hostname,
354
349
  port);
350
+ session.bootstrap(
351
+ [self = shared_from_this(), session](std::error_code err, topology::configuration cfg) mutable {
352
+ if (err) {
353
+ return self->remove_session(session.id());
354
+ }
355
+ self->update_config(std::move(cfg));
356
+ session.on_configuration_update(self);
357
+ session.on_stop([id = session.id(), self]() { self->remove_session(id); });
358
+ self->drain_deferred_queue();
359
+ },
360
+ true);
361
+ sessions_.insert_or_assign(index, std::move(session));
362
+ ++kv_node_index;
355
363
  }
364
+ }
356
365
 
357
- session.bootstrap(
358
- [self = shared_from_this(), session, this_index = index, hostname, port](std::error_code ec,
359
- const topology::configuration& config) mutable {
360
- if (self->closed_) {
361
- asio::post(asio::bind_executor(
362
- self->ctx_, [session = std::move(session)]() mutable { return session.stop(retry_reason::do_not_retry); }));
363
- return;
364
- }
365
- if (ec) {
366
- CB_LOG_WARNING(R"({} failed to restart session idx={}, ec={})", session.log_prefix(), this_index, ec.message());
367
- self->restart_node(this_index, hostname, port);
368
- return;
369
- }
370
- session.on_configuration_update(self);
371
- session.on_stop([this_index, hostname, port, self](retry_reason reason) {
372
- if (reason == retry_reason::socket_closed_while_in_flight) {
373
- self->restart_node(this_index, hostname, port);
374
- }
375
- });
366
+ void remove_session(const std::string& id)
367
+ {
368
+ bool found{ false };
369
+ const std::scoped_lock lock(sessions_mutex_);
370
+ for (auto ptr = sessions_.cbegin(); ptr != sessions_.cend();) {
371
+ if (ptr->second.id() == id) {
372
+ CB_LOG_DEBUG(R"({} removed session id="{}", address="{}", bootstrap_address="{}:{}")",
373
+ log_prefix_,
374
+ ptr->second.id(),
375
+ ptr->second.remote_address(),
376
+ ptr->second.bootstrap_hostname(),
377
+ ptr->second.bootstrap_port());
378
+ ptr = sessions_.erase(ptr);
379
+ found = true;
380
+ } else {
381
+ ptr = std::next(ptr);
382
+ }
383
+ }
376
384
 
377
- self->update_config(config);
378
- self->drain_deferred_queue();
379
- },
380
- true);
381
- sessions_.insert_or_assign(index, std::move(session));
385
+ if (found) {
386
+ asio::post(asio::bind_executor(ctx_, [self = shared_from_this()]() { return self->restart_sessions(); }));
387
+ }
382
388
  }
383
389
 
384
390
  void bootstrap(utils::movable_function<void(std::error_code, topology::configuration)>&& handler)
@@ -393,15 +399,11 @@ class bucket_impl
393
399
  topology::configuration cfg) mutable {
394
400
  if (ec) {
395
401
  CB_LOG_WARNING(R"({} failed to bootstrap session ec={}, bucket="{}")", new_session.log_prefix(), ec.message(), self->name_);
402
+ self->remove_session(new_session.id());
396
403
  } else {
397
404
  const std::size_t this_index = new_session.index();
398
405
  new_session.on_configuration_update(self);
399
- new_session.on_stop([this_index, hostname = new_session.bootstrap_hostname(), port = new_session.bootstrap_port(), self](
400
- retry_reason reason) {
401
- if (reason == retry_reason::socket_closed_while_in_flight) {
402
- self->restart_node(this_index, hostname, port);
403
- }
404
- });
406
+ new_session.on_stop([id = new_session.id(), self]() { self->remove_session(id); });
405
407
 
406
408
  {
407
409
  std::scoped_lock lock(self->sessions_mutex_);
@@ -455,6 +457,9 @@ class bucket_impl
455
457
  std::scoped_lock lock(deferred_commands_mutex_);
456
458
  std::swap(deferred_commands_, commands);
457
459
  }
460
+ if (!commands.empty()) {
461
+ CB_LOG_TRACE(R"({} draining deferred operation queue, size={})", log_prefix_, commands.size());
462
+ }
458
463
  while (!commands.empty()) {
459
464
  commands.front()();
460
465
  commands.pop();
@@ -489,9 +494,33 @@ class bucket_impl
489
494
  }
490
495
  }
491
496
 
497
+ /**
498
+ * copies nodes from rhs that are not in lhs to output vector
499
+ */
500
+ void diff_nodes(const std::vector<topology::configuration::node>& lhs,
501
+ const std::vector<topology::configuration::node>& rhs,
502
+ std::vector<topology::configuration::node>& output)
503
+ {
504
+ for (const auto& re : rhs) {
505
+ bool known = false;
506
+ const auto& rhost = re.hostname_for(origin_.options().network);
507
+ const auto rport = re.port_or(origin_.options().network, service_type::key_value, origin_.options().enable_tls, 0);
508
+ for (const auto& le : lhs) {
509
+ const auto& lhost = le.hostname_for(origin_.options().network);
510
+ const auto lport = le.port_or(origin_.options().network, service_type::key_value, origin_.options().enable_tls, 0);
511
+ if (rhost == lhost && rport == lport) {
512
+ known = true;
513
+ break;
514
+ }
515
+ }
516
+ if (!known) {
517
+ output.push_back(re);
518
+ }
519
+ }
520
+ }
521
+
492
522
  void update_config(topology::configuration config) override
493
523
  {
494
- bool forced_config = false;
495
524
  std::vector<topology::configuration::node> added{};
496
525
  std::vector<topology::configuration::node> removed{};
497
526
  {
@@ -500,7 +529,6 @@ class bucket_impl
500
529
  CB_LOG_DEBUG("{} initialize configuration rev={}", log_prefix_, config.rev_str());
501
530
  } else if (config.force) {
502
531
  CB_LOG_DEBUG("{} forced to accept configuration rev={}", log_prefix_, config.rev_str());
503
- forced_config = true;
504
532
  } else if (!config.vbmap) {
505
533
  CB_LOG_DEBUG("{} will not update the configuration old={} -> new={}, because new config does not have partition map",
506
534
  log_prefix_,
@@ -533,78 +561,81 @@ class bucket_impl
533
561
  std::scoped_lock lock(sessions_mutex_);
534
562
  std::map<size_t, io::mcbp_session> new_sessions{};
535
563
 
536
- for (auto& [index, session] : sessions_) {
537
- std::size_t new_index = config.nodes.size() + 1;
538
- for (const auto& node : config.nodes) {
539
- if (session.bootstrap_hostname() == node.hostname_for(origin_.options().network) &&
540
- session.bootstrap_port() ==
541
- std::to_string(
542
- node.port_or(origin_.options().network, service_type::key_value, origin_.options().enable_tls, 0))) {
543
- new_index = node.index;
544
- break;
545
- }
546
- }
547
- if (new_index < config.nodes.size()) {
548
- CB_LOG_DEBUG(R"({} rev={}, preserve session="{}", address="{}:{}", index={}->{})",
549
- log_prefix_,
550
- config.rev_str(),
551
- session.id(),
552
- session.bootstrap_hostname(),
553
- session.bootstrap_port(),
554
- index,
555
- new_index);
556
- new_sessions.insert_or_assign(new_index, std::move(session));
557
- } else {
558
- CB_LOG_DEBUG(R"({} rev={}, drop session="{}", address="{}:{}", index={})",
559
- log_prefix_,
560
- config.rev_str(),
561
- session.id(),
562
- session.bootstrap_hostname(),
563
- session.bootstrap_port(),
564
- index);
565
- asio::post(asio::bind_executor(
566
- ctx_, [session = std::move(session)]() mutable { return session.stop(retry_reason::do_not_retry); }));
567
- }
568
- }
569
-
564
+ std::size_t next_index{ 0 };
570
565
  for (const auto& node : config.nodes) {
571
- if (new_sessions.find(node.index) != new_sessions.end()) {
572
- continue;
573
- }
574
-
575
566
  const auto& hostname = node.hostname_for(origin_.options().network);
576
567
  auto port = node.port_or(origin_.options().network, service_type::key_value, origin_.options().enable_tls, 0);
577
568
  if (port == 0) {
578
569
  continue;
579
570
  }
571
+
572
+ bool reused_session{ false };
573
+ for (auto it = sessions_.begin(); it != sessions_.end(); ++it) {
574
+ if (it->second.bootstrap_hostname() == hostname && it->second.bootstrap_port_number() == port) {
575
+ CB_LOG_DEBUG(R"({} rev={}, preserve session="{}", address="{}:{}", index={}->{})",
576
+ log_prefix_,
577
+ config.rev_str(),
578
+ it->second.id(),
579
+ it->second.bootstrap_hostname(),
580
+ it->second.bootstrap_port(),
581
+ it->first,
582
+ next_index);
583
+ new_sessions.insert_or_assign(next_index, std::move(it->second));
584
+ reused_session = true;
585
+ ++next_index;
586
+ sessions_.erase(it);
587
+ break;
588
+ }
589
+ }
590
+ if (reused_session) {
591
+ continue;
592
+ }
593
+
580
594
  couchbase::core::origin origin(origin_.credentials(), hostname, port, origin_.options());
581
595
  io::mcbp_session session = origin_.options().enable_tls
582
596
  ? io::mcbp_session(client_id_, ctx_, tls_, origin, state_listener_, name_, known_features_)
583
597
  : io::mcbp_session(client_id_, ctx_, origin, state_listener_, name_, known_features_);
584
- CB_LOG_DEBUG(
585
- R"({} rev={}, add session="{}", address="{}:{}")", log_prefix_, config.rev_str(), session.id(), hostname, port);
598
+ CB_LOG_DEBUG(R"({} rev={}, add session="{}", address="{}:{}", index={})",
599
+ log_prefix_,
600
+ config.rev_str(),
601
+ session.id(),
602
+ hostname,
603
+ port,
604
+ node.index);
586
605
  session.bootstrap(
587
- [self = shared_from_this(), session, forced_config, idx = node.index](std::error_code err,
588
- topology::configuration cfg) mutable {
589
- if (!err) {
590
- self->update_config(std::move(cfg));
591
- session.on_configuration_update(self);
592
- session.on_stop(
593
- [index = session.index(), hostname = session.bootstrap_hostname(), port = session.bootstrap_port(), self](
594
- retry_reason reason) {
595
- if (reason == retry_reason::socket_closed_while_in_flight) {
596
- self->restart_node(index, hostname, port);
597
- }
598
- });
599
- self->drain_deferred_queue();
600
- } else if (err == errc::common::unambiguous_timeout && forced_config) {
601
- self->restart_node(idx, session.bootstrap_hostname(), session.bootstrap_port());
606
+ [self = shared_from_this(), session, idx = next_index](std::error_code err, topology::configuration cfg) mutable {
607
+ if (err) {
608
+ CB_LOG_WARNING(R"({} failed to bootstrap session="{}", address="{}:{}", index={}, ec={})",
609
+ session.log_prefix(),
610
+ session.id(),
611
+ session.bootstrap_hostname(),
612
+ session.bootstrap_port(),
613
+ idx,
614
+ err.message());
615
+ return self->remove_session(session.id());
602
616
  }
617
+ self->update_config(std::move(cfg));
618
+ session.on_configuration_update(self);
619
+ session.on_stop([id = session.id(), self]() { self->remove_session(id); });
620
+ self->drain_deferred_queue();
603
621
  },
604
622
  true);
605
- new_sessions.insert_or_assign(node.index, std::move(session));
623
+ new_sessions.insert_or_assign(next_index, std::move(session));
624
+ ++next_index;
625
+ }
626
+ std::swap(sessions_, new_sessions);
627
+
628
+ for (auto it = new_sessions.begin(); it != new_sessions.end(); ++it) {
629
+ CB_LOG_DEBUG(R"({} rev={}, drop session="{}", address="{}:{}", index={})",
630
+ log_prefix_,
631
+ config.rev_str(),
632
+ it->second.id(),
633
+ it->second.bootstrap_hostname(),
634
+ it->second.bootstrap_port(),
635
+ it->first);
636
+ asio::post(asio::bind_executor(
637
+ ctx_, [session = std::move(it->second)]() mutable { return session.stop(retry_reason::do_not_retry); }));
606
638
  }
607
- sessions_ = new_sessions;
608
639
  }
609
640
  }
610
641
 
@@ -83,7 +83,7 @@ class bucket
83
83
  auto cmd = std::make_shared<operations::mcbp_command<bucket, Request>>(ctx_, shared_from_this(), request, default_timeout());
84
84
  cmd->start([cmd, handler = std::forward<Handler>(handler)](std::error_code ec, std::optional<io::mcbp_message>&& msg) mutable {
85
85
  using encoded_response_type = typename Request::encoded_response_type;
86
- std::uint16_t status_code = msg ? msg->header.status() : 0U;
86
+ std::uint16_t status_code = msg ? msg->header.status() : 0xffffU;
87
87
  auto resp = msg ? encoded_response_type(std::move(*msg)) : encoded_response_type{};
88
88
  auto ctx = make_key_value_error_context(ec, status_code, cmd, resp);
89
89
  handler(cmd->request.make_response(std::move(ctx), std::move(resp)));
@@ -107,7 +107,7 @@ class bucket
107
107
  auto [partition, server] = map_id(cmd->request.id);
108
108
  if (!server.has_value()) {
109
109
  CB_LOG_TRACE(
110
- R"({} unable to map key=\"{}\" to the node, id={}, partition={})", log_prefix(), cmd->request.id, cmd->id_, partition);
110
+ R"({} unable to map key="{}" to the node, id={}, partition={})", log_prefix(), cmd->request.id, cmd->id_, partition);
111
111
  return io::retry_orchestrator::maybe_retry(
112
112
  cmd->manager_, cmd, retry_reason::node_not_available, errc::common::request_canceled);
113
113
  }
@@ -116,19 +116,32 @@ class bucket
116
116
  }
117
117
  auto session = find_session_by_index(index);
118
118
  if (!session || !session->has_config()) {
119
- CB_LOG_TRACE(R"({} defer operation id={}, session={}, has_config={})",
119
+ CB_LOG_TRACE(R"({} defer operation id={}, key="{}", partition={}, index={}, session={}, address="{}", has_config={})",
120
120
  log_prefix(),
121
121
  cmd->id_,
122
+ cmd->request.id,
123
+ cmd->request.partition,
124
+ index,
122
125
  session.has_value(),
126
+ session.has_value() ? session->bootstrap_address() : "",
123
127
  session.has_value() && session->has_config());
124
128
  return defer_command([self = shared_from_this(), cmd]() { self->map_and_send(cmd); });
125
129
  }
126
130
  if (session->is_stopped()) {
127
131
  CB_LOG_TRACE(
128
- R"({} the session has been found, but it is stopped, retrying id={}, session={})", log_prefix(), cmd->id_, session->id());
132
+ R"({} the session has been found for idx={}, but it is stopped, retrying id={}, key="{}", partition={}, session={}, address="{}")",
133
+ log_prefix(),
134
+ index,
135
+ cmd->id_,
136
+ cmd->request.id,
137
+ cmd->request.partition,
138
+ session->id(),
139
+ session->bootstrap_address());
129
140
  return io::retry_orchestrator::maybe_retry(
130
141
  cmd->manager_, cmd, retry_reason::node_not_available, errc::common::request_canceled);
131
142
  }
143
+ cmd->last_dispatched_from_ = session->local_address();
144
+ cmd->last_dispatched_to_ = session->bootstrap_address();
132
145
  cmd->send_to(session.value());
133
146
  }
134
147
 
@@ -33,6 +33,7 @@
33
33
  #include "diagnostics.hxx"
34
34
  #include "dispatcher.hxx"
35
35
  #include "impl/dns_srv_tracker.hxx"
36
+ #include "mozilla_ca_bundle.hxx"
36
37
  #include "operations.hxx"
37
38
  #include "origin.hxx"
38
39
 
@@ -394,6 +395,21 @@ class cluster : public std::enable_shared_from_this<cluster>
394
395
  CB_LOG_WARNING("[{}]: unable to load default CAs: {}", id_, ec.message());
395
396
  // we don't consider this fatal and try to continue without it
396
397
  }
398
+
399
+ if (const auto certificates = default_ca::mozilla_ca_certs();
400
+ !origin_.options().disable_mozilla_ca_certificates && !certificates.empty()) {
401
+ CB_LOG_DEBUG("[{}]: loading {} CA certificates from Mozilla bundle. Update date: \"{}\", SHA256: \"{}\"",
402
+ id_,
403
+ certificates.size(),
404
+ default_ca::mozilla_ca_certs_date(),
405
+ default_ca::mozilla_ca_certs_sha256());
406
+ for (const auto& cert : certificates) {
407
+ tls_.add_certificate_authority(asio::const_buffer(cert.body.data(), cert.body.size()), ec);
408
+ if (ec) {
409
+ CB_LOG_WARNING("[{}]: unable to load CA \"{}\" from Mozilla bundle: {}", id_, cert.authority, ec.message());
410
+ }
411
+ }
412
+ }
397
413
  } else { // trust certificate is explicitly specified
398
414
  std::error_code ec{};
399
415
  // load only the explicit certificate
@@ -430,6 +446,7 @@ class cluster : public std::enable_shared_from_this<cluster>
430
446
  return close([ec, handler = std::forward<Handler>(handler)]() mutable { return handler(ec); });
431
447
  }
432
448
  }
449
+
433
450
  session_ = io::mcbp_session(id_, ctx_, tls_, origin_, dns_srv_tracker_);
434
451
  } else {
435
452
  session_ = io::mcbp_session(id_, ctx_, origin_, dns_srv_tracker_);
@@ -466,7 +483,7 @@ class cluster : public std::enable_shared_from_this<cluster>
466
483
  }
467
484
  self->session_manager_->set_configuration(config, self->origin_.options());
468
485
  self->session_->on_configuration_update(self->session_manager_);
469
- self->session_->on_stop([self](retry_reason) {
486
+ self->session_->on_stop([self]() {
470
487
  if (self->session_) {
471
488
  self->session_.reset();
472
489
  }
@@ -83,6 +83,7 @@ struct cluster_options {
83
83
  [[nodiscard]] std::chrono::milliseconds default_timeout_for(service_type type) const;
84
84
 
85
85
  bool dump_configuration{ false };
86
+ bool disable_mozilla_ca_certificates{ false };
86
87
  void apply_profile(std::string profile_name);
87
88
  };
88
89
 
@@ -24,7 +24,7 @@ key_value_error_context
24
24
  make_key_value_error_context(std::error_code ec, const document_id& id)
25
25
  {
26
26
  return {
27
- ec, {}, {}, 0, {}, id.key(), id.bucket(), id.scope(), id.collection(), 0, {}, {}, {}, {},
27
+ {}, ec, {}, {}, 0, {}, id.key(), id.bucket(), id.scope(), id.collection(), 0, {}, {}, {}, {},
28
28
  };
29
29
  }
30
30
 
@@ -36,6 +36,7 @@ make_subdocument_error_context(const key_value_error_context& ctx,
36
36
  bool deleted)
37
37
  {
38
38
  return {
39
+ ctx.operation_id(),
39
40
  ec,
40
41
  ctx.last_dispatched_to(),
41
42
  ctx.last_dispatched_from(),
@@ -43,23 +43,21 @@ make_key_value_error_context(std::error_code ec, std::uint16_t status_code, cons
43
43
  const auto& scope = command->request.id.scope();
44
44
  const auto& bucket = command->request.id.bucket();
45
45
  std::uint32_t opaque = (ec && response.opaque() == 0) ? command->request.opaque : response.opaque();
46
- auto status = response.status();
47
- auto retry_attempts = command->request.retries.retry_attempts();
48
- auto retry_reasons = command->request.retries.retry_reasons();
49
- std::optional<std::string> last_dispatched_from{};
50
- std::optional<std::string> last_dispatched_to{};
46
+ std::optional<key_value_status_code> status{};
51
47
  std::optional<key_value_error_map_info> error_map_info{};
52
- if (command->session_) {
53
- last_dispatched_from = command->session_->local_address();
54
- last_dispatched_to = command->session_->remote_address();
55
- if (status_code) {
48
+ if (status_code != 0xffffU) {
49
+ status = response.status();
50
+ if (command->session_ && status_code > 0) {
56
51
  error_map_info = command->session_->decode_error_code(status_code);
57
52
  }
58
53
  }
54
+ auto retry_attempts = command->request.retries.retry_attempts();
55
+ auto retry_reasons = command->request.retries.retry_reasons();
59
56
 
60
- return { ec,
61
- std::move(last_dispatched_from),
62
- std::move(last_dispatched_to),
57
+ return { command->id_,
58
+ ec,
59
+ command->last_dispatched_to_,
60
+ command->last_dispatched_from_,
63
61
  retry_attempts,
64
62
  std::move(retry_reasons),
65
63
  key,
@@ -32,7 +32,7 @@ struct search {
32
32
  std::error_code ec{};
33
33
  std::string client_context_id{};
34
34
  std::string index_name{};
35
- std::optional<std::string> query{};
35
+ std::string query{};
36
36
  std::optional<std::string> parameters{};
37
37
 
38
38
  std::string method{};
@@ -17,6 +17,7 @@
17
17
 
18
18
  #include <couchbase/cluster.hxx>
19
19
  #include <couchbase/error_codes.hxx>
20
+ #include <couchbase/scope.hxx>
20
21
 
21
22
  #include "core/cluster.hxx"
22
23
  #include "core/operations/document_analytics.hxx"
@@ -0,0 +1,40 @@
1
+ /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * Copyright 2023-Present Couchbase, Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ #include "encoded_search_query.hxx"
19
+
20
+ #include <couchbase/boolean_field_query.hxx>
21
+
22
+ namespace couchbase
23
+ {
24
+ auto
25
+ boolean_field_query::encode() const -> encoded_search_query
26
+ {
27
+ encoded_search_query built;
28
+
29
+ built.query = tao::json::empty_object;
30
+ if (boost_) {
31
+ built.query["boost"] = boost_.value();
32
+ }
33
+ built.query["bool"] = bool_;
34
+ if (field_) {
35
+ built.query["field"] = field_.value();
36
+ }
37
+
38
+ return built;
39
+ }
40
+ } // namespace couchbase