couchbase 4.2.11-rc.1 → 4.2.11

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 (26) hide show
  1. package/deps/couchbase-cxx-client/CMakeLists.txt +1 -0
  2. package/deps/couchbase-cxx-client/cmake/ThirdPartyDependencies.cmake +2 -0
  3. package/deps/couchbase-cxx-client/core/bucket.cxx +2 -2
  4. package/deps/couchbase-cxx-client/core/io/mcbp_session.cxx +11 -0
  5. package/deps/couchbase-cxx-client/core/io/mcbp_session.hxx +1 -0
  6. package/deps/couchbase-cxx-client/core/range_scan_load_balancer.cxx +141 -0
  7. package/deps/couchbase-cxx-client/core/range_scan_load_balancer.hxx +64 -0
  8. package/deps/couchbase-cxx-client/core/range_scan_orchestrator.cxx +224 -336
  9. package/deps/couchbase-cxx-client/core/range_scan_orchestrator.hxx +5 -6
  10. package/deps/couchbase-cxx-client/core/range_scan_orchestrator_options.hxx +6 -4
  11. package/deps/couchbase-cxx-client/core/scan_result.hxx +1 -11
  12. package/deps/couchbase-cxx-client/couchbase/bucket.hxx +2 -2
  13. package/deps/couchbase-cxx-client/couchbase/cluster.hxx +1 -1
  14. package/deps/couchbase-cxx-client/couchbase/collection.hxx +1 -0
  15. package/deps/couchbase-cxx-client/couchbase/collection_query_index_manager.hxx +1 -1
  16. package/deps/couchbase-cxx-client/couchbase/error_context.hxx +1 -0
  17. package/deps/couchbase-cxx-client/couchbase/get_links_analytics_options.hxx +2 -2
  18. package/deps/couchbase-cxx-client/couchbase/scope.hxx +1 -1
  19. package/deps/couchbase-cxx-client/couchbase/search_options.hxx +2 -2
  20. package/deps/couchbase-cxx-client/couchbase/search_result.hxx +1 -1
  21. package/deps/couchbase-cxx-client/couchbase/subdocument_error_context.hxx +1 -0
  22. package/deps/couchbase-cxx-client/couchbase/transactions/transaction_options.hxx +1 -1
  23. package/deps/couchbase-cxx-client/couchbase-sdk-cxx-black-duck-manifest.yaml +1 -0
  24. package/package.json +7 -7
  25. package/src/jstocbpp_autogen.hpp +0 -1
  26. package/deps/couchbase-cxx-client/core/scan_options.hxx +0 -44
@@ -360,6 +360,7 @@ set(couchbase_cxx_client_FILES
360
360
  core/protocol/cmd_upsert.cxx
361
361
  core/protocol/frame_info_utils.cxx
362
362
  core/protocol/status.cxx
363
+ core/range_scan_load_balancer.cxx
363
364
  core/range_scan_options.cxx
364
365
  core/range_scan_orchestrator.cxx
365
366
  core/retry_orchestrator.cxx
@@ -1,3 +1,5 @@
1
+ # NOTE: This file MUST be in sync with couchbase-sdk-cxx-black-duck-manifest.yaml
2
+
1
3
  include(cmake/CPM.cmake)
2
4
 
3
5
  # https://cmake.org/cmake/help/v3.28/policy/CMP0063.html
@@ -495,7 +495,7 @@ class bucket_impl
495
495
  std::size_t i = start;
496
496
  do {
497
497
  auto ptr = sessions_.find(i % sessions_.size());
498
- if (ptr != sessions_.end() && ptr->second.supports_gcccp()) {
498
+ if (ptr != sessions_.end() && ptr->second.is_bootstrapped() && ptr->second.supports_gcccp()) {
499
499
  session = ptr->second;
500
500
  }
501
501
  i = heartbeat_next_index_.fetch_add(1);
@@ -506,7 +506,7 @@ class bucket_impl
506
506
  req.opaque(session->next_opaque());
507
507
  session->write_and_flush(req.data());
508
508
  } else {
509
- CB_LOG_WARNING(R"({} unable to find session with GCCCP support, retry in {})", log_prefix_, heartbeat_interval_);
509
+ CB_LOG_WARNING(R"({} unable to find connected session with GCCCP support, retry in {})", log_prefix_, heartbeat_interval_);
510
510
  }
511
511
  }
512
512
 
@@ -920,6 +920,11 @@ class mcbp_session_impl
920
920
  return stopped_;
921
921
  }
922
922
 
923
+ [[nodiscard]] bool is_bootstrapped() const
924
+ {
925
+ return bootstrapped_;
926
+ }
927
+
923
928
  void on_stop(utils::movable_function<void()> handler)
924
929
  {
925
930
  on_stop_handler_ = std::move(handler);
@@ -1739,6 +1744,12 @@ mcbp_session::is_stopped() const
1739
1744
  return impl_->is_stopped();
1740
1745
  }
1741
1746
 
1747
+ bool
1748
+ mcbp_session::is_bootstrapped() const
1749
+ {
1750
+ return impl_->is_bootstrapped();
1751
+ }
1752
+
1742
1753
  std::uint32_t
1743
1754
  mcbp_session::next_opaque()
1744
1755
  {
@@ -97,6 +97,7 @@ class mcbp_session
97
97
  [[nodiscard]] const std::string& log_prefix() const;
98
98
  [[nodiscard]] bool cancel(std::uint32_t opaque, std::error_code ec, retry_reason reason);
99
99
  [[nodiscard]] bool is_stopped() const;
100
+ [[nodiscard]] bool is_bootstrapped() const;
100
101
  [[nodiscard]] std::uint32_t next_opaque();
101
102
  [[nodiscard]] std::optional<std::uint32_t> get_collection_uid(const std::string& collection_path);
102
103
  [[nodiscard]] mcbp_context context() const;
@@ -0,0 +1,141 @@
1
+ /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * Copyright 2024. 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 "range_scan_load_balancer.hxx"
19
+
20
+ #include <algorithm>
21
+ #include <limits>
22
+ #include <map>
23
+ #include <numeric>
24
+ #include <queue>
25
+ #include <random>
26
+ #include <vector>
27
+
28
+ namespace couchbase::core
29
+ {
30
+ range_scan_node_state::range_scan_node_state(std::queue<std::uint16_t> vbuckets)
31
+ : pending_vbuckets_{ std::move(vbuckets) }
32
+ {
33
+ }
34
+
35
+ auto
36
+ range_scan_node_state::fetch_vbucket_id() -> std::optional<std::uint16_t>
37
+ {
38
+ std::lock_guard<std::mutex> const lock{ mutex_ };
39
+ if (pending_vbuckets_.empty()) {
40
+ return {};
41
+ }
42
+ active_stream_count_++;
43
+ auto vbucket_id = pending_vbuckets_.front();
44
+ pending_vbuckets_.pop();
45
+ return vbucket_id;
46
+ }
47
+
48
+ void
49
+ range_scan_node_state::notify_stream_ended()
50
+ {
51
+ std::lock_guard<std::mutex> const lock{ mutex_ };
52
+ active_stream_count_--;
53
+ }
54
+
55
+ void
56
+ range_scan_node_state::enqueue_vbucket(std::uint16_t vbucket_id)
57
+ {
58
+ std::lock_guard<std::mutex> const lock{ mutex_ };
59
+ pending_vbuckets_.push(vbucket_id);
60
+ }
61
+
62
+ auto
63
+ range_scan_node_state::active_stream_count() -> std::uint16_t
64
+ {
65
+ std::lock_guard<std::mutex> const lock{ mutex_ };
66
+ return active_stream_count_;
67
+ }
68
+
69
+ auto
70
+ range_scan_node_state::pending_vbucket_count() -> std::size_t
71
+ {
72
+ std::lock_guard<std::mutex> const lock{ mutex_ };
73
+ return pending_vbuckets_.size();
74
+ }
75
+
76
+ range_scan_load_balancer::range_scan_load_balancer(const topology::configuration::vbucket_map& vbucket_map,
77
+ std::optional<std::uint64_t> seed)
78
+ : seed_{ seed }
79
+ {
80
+ std::map<std::int16_t, std::queue<std::uint16_t>> node_to_vbucket_map{};
81
+ for (std::uint16_t vbucket_id = 0; vbucket_id < vbucket_map.size(); vbucket_id++) {
82
+ auto node_id = vbucket_map[vbucket_id][0];
83
+ node_to_vbucket_map[node_id].push(vbucket_id);
84
+ }
85
+ for (auto [node_id, vbucket_ids] : node_to_vbucket_map) {
86
+ nodes_.emplace(node_id, std::move(vbucket_ids));
87
+ }
88
+ }
89
+
90
+ void
91
+ range_scan_load_balancer::seed(std::uint64_t seed)
92
+ {
93
+ seed_ = seed;
94
+ }
95
+
96
+ auto
97
+ range_scan_load_balancer::select_vbucket() -> std::optional<std::uint16_t>
98
+ {
99
+ std::lock_guard<std::mutex> const lock{ select_vbucket_mutex_ };
100
+
101
+ auto min_stream_count = std::numeric_limits<std::uint16_t>::max();
102
+ std::optional<std::int16_t> selected_node_id{};
103
+
104
+ std::vector<std::map<int16_t, range_scan_node_state>::iterator> iterators{ nodes_.size() };
105
+
106
+ std::iota(iterators.begin(), iterators.end(), nodes_.begin());
107
+ std::mt19937_64 gen{ std::random_device{}() };
108
+ if (seed_.has_value()) {
109
+ gen.seed(seed_.value());
110
+ }
111
+ std::shuffle(iterators.begin(), iterators.end(), gen);
112
+
113
+ for (auto it : iterators) {
114
+ auto& [node_id, node_status] = *it;
115
+ auto stream_count = node_status.active_stream_count();
116
+
117
+ if (stream_count < min_stream_count && node_status.pending_vbucket_count() > 0) {
118
+ min_stream_count = stream_count;
119
+ selected_node_id = node_id;
120
+ }
121
+ }
122
+
123
+ if (!selected_node_id) {
124
+ return {};
125
+ }
126
+
127
+ return nodes_.at(selected_node_id.value()).fetch_vbucket_id();
128
+ }
129
+
130
+ void
131
+ range_scan_load_balancer::notify_stream_ended(std::int16_t node_id)
132
+ {
133
+ nodes_.at(node_id).notify_stream_ended();
134
+ }
135
+
136
+ void
137
+ range_scan_load_balancer::enqueue_vbucket(std::int16_t node_id, std::uint16_t vbucket_id)
138
+ {
139
+ nodes_.at(node_id).enqueue_vbucket(vbucket_id);
140
+ }
141
+ } // namespace couchbase::core
@@ -0,0 +1,64 @@
1
+ /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * Copyright 2024. 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 "core/logger/logger.hxx"
19
+ #include "core/topology/configuration.hxx"
20
+
21
+ #include <mutex>
22
+ #include <queue>
23
+
24
+ namespace couchbase::core
25
+ {
26
+ class range_scan_node_state
27
+ {
28
+ public:
29
+ range_scan_node_state(std::queue<std::uint16_t> vbuckets);
30
+
31
+ auto fetch_vbucket_id() -> std::optional<std::uint16_t>;
32
+ void notify_stream_ended();
33
+ void enqueue_vbucket(std::uint16_t vbucket_id);
34
+ auto active_stream_count() -> std::uint16_t;
35
+ auto pending_vbucket_count() -> std::size_t;
36
+
37
+ private:
38
+ std::uint16_t active_stream_count_{ 0 };
39
+ std::queue<std::uint16_t> pending_vbuckets_{};
40
+ std::mutex mutex_{};
41
+ };
42
+
43
+ class range_scan_load_balancer
44
+ {
45
+ public:
46
+ range_scan_load_balancer(const topology::configuration::vbucket_map& vbucket_map, std::optional<std::uint64_t> seed = {});
47
+
48
+ void seed(std::uint64_t seed);
49
+
50
+ /**
51
+ * Returns the ID of a vbucket that corresponds to the node with the lowest number of active streams.
52
+ * Returns "std::nullopt" if there are no pending vbuckets
53
+ */
54
+ auto select_vbucket() -> std::optional<std::uint16_t>;
55
+
56
+ void notify_stream_ended(std::int16_t node_id);
57
+ void enqueue_vbucket(std::int16_t node_id, std::uint16_t vbucket_id);
58
+
59
+ private:
60
+ std::map<std::int16_t, range_scan_node_state> nodes_{};
61
+ std::mutex select_vbucket_mutex_{};
62
+ std::optional<std::uint64_t> seed_{};
63
+ };
64
+ } // namespace couchbase::core