couchbase 4.2.11-rc.1 → 4.2.11

Sign up to get free protection for your applications and to get access to all the features.
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