couchbase 4.2.3 → 4.2.5-dev.1

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 (205) hide show
  1. package/CMakeLists.txt +136 -11
  2. package/deps/couchbase-cxx-client/CMakeLists.txt +54 -4
  3. package/deps/couchbase-cxx-client/README.md +1 -0
  4. package/deps/couchbase-cxx-client/bin/create-search-index +164 -0
  5. package/deps/couchbase-cxx-client/bin/init-cluster +55 -10
  6. package/deps/couchbase-cxx-client/bin/run-unit-tests +62 -6
  7. package/deps/couchbase-cxx-client/bin/travel-sample-index-v6.json +184 -0
  8. package/deps/couchbase-cxx-client/bin/travel-sample-index.json +188 -0
  9. package/deps/couchbase-cxx-client/cmake/Documentation.cmake +0 -1
  10. package/deps/couchbase-cxx-client/cmake/OpenSSL.cmake +98 -3
  11. package/deps/couchbase-cxx-client/cmake/Testing.cmake +8 -0
  12. package/deps/couchbase-cxx-client/cmake/build_config.hxx.in +3 -0
  13. package/deps/couchbase-cxx-client/core/bucket.cxx +183 -152
  14. package/deps/couchbase-cxx-client/core/bucket.hxx +17 -4
  15. package/deps/couchbase-cxx-client/core/cluster.hxx +18 -1
  16. package/deps/couchbase-cxx-client/core/cluster_options.hxx +1 -0
  17. package/deps/couchbase-cxx-client/core/error_context/key_value.cxx +2 -1
  18. package/deps/couchbase-cxx-client/core/error_context/key_value.hxx +10 -12
  19. package/deps/couchbase-cxx-client/core/error_context/search.hxx +1 -1
  20. package/deps/couchbase-cxx-client/core/impl/analytics.cxx +1 -0
  21. package/deps/couchbase-cxx-client/core/impl/boolean_field_query.cxx +40 -0
  22. package/deps/couchbase-cxx-client/core/impl/boolean_query.cxx +62 -0
  23. package/deps/couchbase-cxx-client/core/impl/cluster.cxx +1 -0
  24. package/deps/couchbase-cxx-client/core/impl/conjunction_query.cxx +51 -0
  25. package/deps/couchbase-cxx-client/core/impl/date_range.cxx +89 -0
  26. package/deps/couchbase-cxx-client/core/impl/date_range_facet.cxx +54 -0
  27. package/deps/couchbase-cxx-client/core/impl/date_range_facet_result.cxx +64 -0
  28. package/deps/couchbase-cxx-client/core/impl/date_range_query.cxx +125 -0
  29. package/deps/couchbase-cxx-client/core/impl/disjunction_query.cxx +51 -0
  30. package/deps/couchbase-cxx-client/core/impl/encoded_search_facet.hxx +29 -0
  31. package/deps/couchbase-cxx-client/core/impl/encoded_search_query.hxx +29 -0
  32. package/deps/couchbase-cxx-client/core/impl/encoded_search_sort.hxx +29 -0
  33. package/deps/couchbase-cxx-client/core/impl/geo_bounding_box_query.cxx +46 -0
  34. package/deps/couchbase-cxx-client/core/impl/geo_distance_query.cxx +43 -0
  35. package/deps/couchbase-cxx-client/core/impl/geo_polygon_query.cxx +46 -0
  36. package/deps/couchbase-cxx-client/core/impl/internal_date_range_facet_result.cxx +80 -0
  37. package/deps/couchbase-cxx-client/core/impl/internal_date_range_facet_result.hxx +48 -0
  38. package/deps/couchbase-cxx-client/core/impl/internal_numeric_range_facet_result.cxx +80 -0
  39. package/deps/couchbase-cxx-client/core/impl/internal_numeric_range_facet_result.hxx +48 -0
  40. package/deps/couchbase-cxx-client/core/impl/internal_search_error_context.cxx +141 -0
  41. package/deps/couchbase-cxx-client/core/impl/internal_search_error_context.hxx +61 -0
  42. package/deps/couchbase-cxx-client/core/impl/internal_search_meta_data.cxx +60 -0
  43. package/deps/couchbase-cxx-client/core/impl/internal_search_meta_data.hxx +41 -0
  44. package/deps/couchbase-cxx-client/core/impl/internal_search_result.cxx +84 -0
  45. package/deps/couchbase-cxx-client/core/impl/internal_search_result.hxx +43 -0
  46. package/deps/couchbase-cxx-client/core/impl/internal_search_row.cxx +82 -0
  47. package/deps/couchbase-cxx-client/core/impl/internal_search_row.hxx +56 -0
  48. package/deps/couchbase-cxx-client/core/impl/internal_search_row_location.hxx +32 -0
  49. package/deps/couchbase-cxx-client/core/impl/internal_search_row_locations.cxx +137 -0
  50. package/deps/couchbase-cxx-client/core/impl/internal_search_row_locations.hxx +45 -0
  51. package/deps/couchbase-cxx-client/core/impl/internal_term_facet_result.cxx +80 -0
  52. package/deps/couchbase-cxx-client/core/impl/internal_term_facet_result.hxx +48 -0
  53. package/deps/couchbase-cxx-client/core/impl/key_value_error_context.cxx +98 -0
  54. package/deps/couchbase-cxx-client/core/impl/match_all_query.cxx +35 -0
  55. package/deps/couchbase-cxx-client/core/impl/match_none_query.cxx +35 -0
  56. package/deps/couchbase-cxx-client/core/impl/match_phrase_query.cxx +43 -0
  57. package/deps/couchbase-cxx-client/core/impl/match_query.cxx +59 -0
  58. package/deps/couchbase-cxx-client/core/impl/numeric_range.cxx +49 -0
  59. package/deps/couchbase-cxx-client/core/impl/numeric_range_facet.cxx +54 -0
  60. package/deps/couchbase-cxx-client/core/impl/numeric_range_facet_result.cxx +64 -0
  61. package/deps/couchbase-cxx-client/core/impl/numeric_range_query.cxx +56 -0
  62. package/deps/couchbase-cxx-client/core/impl/phrase_query.cxx +42 -0
  63. package/deps/couchbase-cxx-client/core/impl/prefix_query.cxx +40 -0
  64. package/deps/couchbase-cxx-client/core/impl/query_error_context.cxx +75 -0
  65. package/deps/couchbase-cxx-client/core/impl/query_string_query.cxx +37 -0
  66. package/deps/couchbase-cxx-client/core/impl/regexp_query.cxx +40 -0
  67. package/deps/couchbase-cxx-client/core/impl/search.cxx +191 -0
  68. package/deps/couchbase-cxx-client/core/impl/search_error_context.cxx +147 -0
  69. package/deps/couchbase-cxx-client/core/impl/search_meta_data.cxx +46 -0
  70. package/deps/couchbase-cxx-client/core/impl/search_result.cxx +66 -0
  71. package/deps/couchbase-cxx-client/core/impl/search_row.cxx +74 -0
  72. package/deps/couchbase-cxx-client/core/impl/search_row_location.cxx +64 -0
  73. package/deps/couchbase-cxx-client/core/impl/search_row_locations.cxx +66 -0
  74. package/deps/couchbase-cxx-client/core/impl/search_sort_field.cxx +104 -0
  75. package/deps/couchbase-cxx-client/core/impl/search_sort_id.cxx +43 -0
  76. package/deps/couchbase-cxx-client/core/impl/search_sort_score.cxx +43 -0
  77. package/deps/couchbase-cxx-client/core/impl/term_facet.cxx +36 -0
  78. package/deps/couchbase-cxx-client/core/impl/term_facet_result.cxx +64 -0
  79. package/deps/couchbase-cxx-client/core/impl/term_query.cxx +56 -0
  80. package/deps/couchbase-cxx-client/core/impl/term_range_query.cxx +57 -0
  81. package/deps/couchbase-cxx-client/core/impl/wildcard_query.cxx +40 -0
  82. package/deps/couchbase-cxx-client/core/io/mcbp_command.hxx +9 -2
  83. package/deps/couchbase-cxx-client/core/io/mcbp_session.cxx +54 -37
  84. package/deps/couchbase-cxx-client/core/io/mcbp_session.hxx +4 -3
  85. package/deps/couchbase-cxx-client/core/json_string.hxx +5 -0
  86. package/deps/couchbase-cxx-client/core/meta/version.cxx +18 -4
  87. package/deps/couchbase-cxx-client/core/mozilla_ca_bundle.hxx +39 -0
  88. package/deps/couchbase-cxx-client/core/operations/document_search.cxx +3 -1
  89. package/deps/couchbase-cxx-client/core/operations/document_search.hxx +1 -1
  90. package/deps/couchbase-cxx-client/core/protocol/client_request.hxx +11 -2
  91. package/deps/couchbase-cxx-client/core/protocol/client_response.hxx +1 -0
  92. package/deps/couchbase-cxx-client/core/utils/connection_string.cxx +59 -46
  93. package/deps/couchbase-cxx-client/core/utils/connection_string.hxx +1 -0
  94. package/deps/couchbase-cxx-client/couchbase/analytics_error_context.hxx +1 -1
  95. package/deps/couchbase-cxx-client/couchbase/boolean_field_query.hxx +77 -0
  96. package/deps/couchbase-cxx-client/couchbase/boolean_query.hxx +223 -0
  97. package/deps/couchbase-cxx-client/couchbase/cluster.hxx +39 -0
  98. package/deps/couchbase-cxx-client/couchbase/conjunction_query.hxx +88 -0
  99. package/deps/couchbase-cxx-client/couchbase/date_range.hxx +69 -0
  100. package/deps/couchbase-cxx-client/couchbase/date_range_facet.hxx +56 -0
  101. package/deps/couchbase-cxx-client/couchbase/date_range_facet_result.hxx +55 -0
  102. package/deps/couchbase-cxx-client/couchbase/date_range_query.hxx +265 -0
  103. package/deps/couchbase-cxx-client/couchbase/disjunction_query.hxx +109 -0
  104. package/deps/couchbase-cxx-client/couchbase/doc_id_query.hxx +111 -0
  105. package/deps/couchbase-cxx-client/couchbase/error_context.hxx +17 -8
  106. package/deps/couchbase-cxx-client/couchbase/fmt/analytics_scan_consistency.hxx +52 -0
  107. package/deps/couchbase-cxx-client/{core/topology/error_map_fmt.hxx → couchbase/fmt/key_value_error_map_attribute.hxx} +21 -21
  108. package/deps/couchbase-cxx-client/couchbase/fmt/search_scan_consistency.hxx +49 -0
  109. package/deps/couchbase-cxx-client/couchbase/geo_bounding_box_query.hxx +107 -0
  110. package/deps/couchbase-cxx-client/couchbase/geo_distance_query.hxx +109 -0
  111. package/deps/couchbase-cxx-client/couchbase/geo_point.hxx +32 -0
  112. package/deps/couchbase-cxx-client/couchbase/geo_polygon_query.hxx +85 -0
  113. package/deps/couchbase-cxx-client/couchbase/highlight_style.hxx +45 -0
  114. package/deps/couchbase-cxx-client/couchbase/key_value_error_context.hxx +7 -2
  115. package/deps/couchbase-cxx-client/couchbase/manager_error_context.hxx +1 -1
  116. package/deps/couchbase-cxx-client/couchbase/match_all_query.hxx +43 -0
  117. package/deps/couchbase-cxx-client/couchbase/match_none_query.hxx +43 -0
  118. package/deps/couchbase-cxx-client/couchbase/match_operator.hxx +45 -0
  119. package/deps/couchbase-cxx-client/couchbase/match_phrase_query.hxx +108 -0
  120. package/deps/couchbase-cxx-client/couchbase/match_query.hxx +163 -0
  121. package/deps/couchbase-cxx-client/couchbase/numeric_range.hxx +58 -0
  122. package/deps/couchbase-cxx-client/couchbase/numeric_range_facet.hxx +56 -0
  123. package/deps/couchbase-cxx-client/couchbase/numeric_range_facet_result.hxx +55 -0
  124. package/deps/couchbase-cxx-client/couchbase/numeric_range_query.hxx +143 -0
  125. package/deps/couchbase-cxx-client/couchbase/phrase_query.hxx +93 -0
  126. package/deps/couchbase-cxx-client/couchbase/prefix_query.hxx +82 -0
  127. package/deps/couchbase-cxx-client/couchbase/query_error_context.hxx +3 -1
  128. package/deps/couchbase-cxx-client/couchbase/query_string_query.hxx +72 -0
  129. package/deps/couchbase-cxx-client/couchbase/regexp_query.hxx +82 -0
  130. package/deps/couchbase-cxx-client/couchbase/scope.hxx +39 -0
  131. package/deps/couchbase-cxx-client/couchbase/search_date_range.hxx +68 -0
  132. package/deps/couchbase-cxx-client/couchbase/search_error_context.hxx +138 -0
  133. package/deps/couchbase-cxx-client/couchbase/search_facet.hxx +60 -0
  134. package/deps/couchbase-cxx-client/couchbase/search_facet_result.hxx +50 -0
  135. package/deps/couchbase-cxx-client/couchbase/search_meta_data.hxx +85 -0
  136. package/deps/couchbase-cxx-client/couchbase/search_metrics.hxx +127 -0
  137. package/deps/couchbase-cxx-client/couchbase/search_numeric_range.hxx +69 -0
  138. package/deps/couchbase-cxx-client/couchbase/search_options.hxx +509 -0
  139. package/deps/couchbase-cxx-client/couchbase/search_query.hxx +69 -0
  140. package/deps/couchbase-cxx-client/couchbase/search_result.hxx +77 -0
  141. package/deps/couchbase-cxx-client/couchbase/search_row.hxx +104 -0
  142. package/deps/couchbase-cxx-client/couchbase/search_row_location.hxx +55 -0
  143. package/deps/couchbase-cxx-client/couchbase/search_row_locations.hxx +86 -0
  144. package/deps/couchbase-cxx-client/couchbase/search_scan_consistency.hxx +34 -0
  145. package/deps/couchbase-cxx-client/couchbase/search_sort.hxx +58 -0
  146. package/deps/couchbase-cxx-client/couchbase/search_sort_field.hxx +117 -0
  147. package/deps/couchbase-cxx-client/couchbase/search_sort_field_missing.hxx +26 -0
  148. package/deps/couchbase-cxx-client/couchbase/search_sort_field_mode.hxx +27 -0
  149. package/deps/couchbase-cxx-client/couchbase/search_sort_field_type.hxx +28 -0
  150. package/deps/couchbase-cxx-client/couchbase/search_sort_id.hxx +60 -0
  151. package/deps/couchbase-cxx-client/couchbase/search_sort_score.hxx +60 -0
  152. package/deps/couchbase-cxx-client/couchbase/search_term_range.hxx +51 -0
  153. package/deps/couchbase-cxx-client/couchbase/security_options.hxx +3 -0
  154. package/deps/couchbase-cxx-client/couchbase/subdocument_error_context.hxx +4 -2
  155. package/deps/couchbase-cxx-client/couchbase/term_facet.hxx +48 -0
  156. package/deps/couchbase-cxx-client/couchbase/term_facet_result.hxx +55 -0
  157. package/deps/couchbase-cxx-client/couchbase/term_query.hxx +151 -0
  158. package/deps/couchbase-cxx-client/couchbase/term_range_query.hxx +142 -0
  159. package/deps/couchbase-cxx-client/couchbase/transactions/transaction_options.hxx +1 -1
  160. package/deps/couchbase-cxx-client/couchbase/transactions/transaction_query_options.hxx +2 -1
  161. package/deps/couchbase-cxx-client/couchbase/transactions/transaction_result.hxx +1 -1
  162. package/deps/couchbase-cxx-client/couchbase/transactions.hxx +3 -3
  163. package/deps/couchbase-cxx-client/couchbase/wildcard_query.hxx +83 -0
  164. package/deps/couchbase-cxx-client/docs/Doxyfile.in +1 -1
  165. package/deps/couchbase-cxx-client/docs/cbc-analytics.md +2 -2
  166. package/deps/couchbase-cxx-client/docs/cbc-get.md +3 -2
  167. package/deps/couchbase-cxx-client/docs/cbc-pillowfight.md +7 -2
  168. package/deps/couchbase-cxx-client/docs/cbc-query.md +2 -2
  169. package/deps/couchbase-cxx-client/docs/cbc.md +3 -3
  170. package/deps/couchbase-cxx-client/docs/cli.hxx +5 -5
  171. package/deps/couchbase-cxx-client/docs/mainpage.hxx +42 -5
  172. package/deps/couchbase-cxx-client/test/CMakeLists.txt +1 -0
  173. package/deps/couchbase-cxx-client/test/test_integration_analytics.cxx +28 -6
  174. package/deps/couchbase-cxx-client/test/test_integration_collections.cxx +7 -3
  175. package/deps/couchbase-cxx-client/test/test_integration_connect.cxx +7 -3
  176. package/deps/couchbase-cxx-client/test/test_integration_crud.cxx +13 -3
  177. package/deps/couchbase-cxx-client/test/test_integration_diagnostics.cxx +8 -2
  178. package/deps/couchbase-cxx-client/test/test_integration_durability.cxx +12 -7
  179. package/deps/couchbase-cxx-client/test/test_integration_examples.cxx +283 -11
  180. package/deps/couchbase-cxx-client/test/test_integration_management.cxx +140 -88
  181. package/deps/couchbase-cxx-client/test/test_integration_query.cxx +67 -9
  182. package/deps/couchbase-cxx-client/test/test_integration_range_scan.cxx +12 -12
  183. package/deps/couchbase-cxx-client/test/test_integration_read_replica.cxx +48 -11
  184. package/deps/couchbase-cxx-client/test/test_integration_search.cxx +19 -1
  185. package/deps/couchbase-cxx-client/test/test_integration_subdoc.cxx +60 -9
  186. package/deps/couchbase-cxx-client/test/test_integration_tracer.cxx +3 -0
  187. package/deps/couchbase-cxx-client/test/test_integration_transcoders.cxx +4 -0
  188. package/deps/couchbase-cxx-client/test/test_transaction_examples.cxx +100 -85
  189. package/deps/couchbase-cxx-client/test/test_unit_connection_string.cxx +29 -0
  190. package/deps/couchbase-cxx-client/test/test_unit_search.cxx +427 -0
  191. package/deps/couchbase-cxx-client/test/utils/integration_test_guard.cxx +2 -1
  192. package/deps/couchbase-cxx-client/test/utils/logger.cxx +3 -1
  193. package/deps/couchbase-cxx-client/test/utils/server_version.hxx +31 -15
  194. package/deps/couchbase-cxx-client/test/utils/test_context.cxx +8 -0
  195. package/deps/couchbase-cxx-client/tools/get.cxx +9 -8
  196. package/deps/couchbase-cxx-client/tools/pillowfight.cxx +175 -75
  197. package/deps/couchbase-cxx-client/tools/version.cxx +4 -2
  198. package/dist/binding.d.ts +1 -1
  199. package/dist/binding.js +3 -2
  200. package/package.json +96 -1
  201. package/scripts/createPlatformPackages.js +108 -0
  202. package/scripts/install.js +45 -0
  203. package/scripts/prebuilds.js +249 -0
  204. package/scripts/prune.js +124 -0
  205. 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