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.
- package/deps/couchbase-cxx-client/CMakeLists.txt +1 -0
- package/deps/couchbase-cxx-client/cmake/ThirdPartyDependencies.cmake +2 -0
- package/deps/couchbase-cxx-client/core/bucket.cxx +2 -2
- package/deps/couchbase-cxx-client/core/io/mcbp_session.cxx +11 -0
- package/deps/couchbase-cxx-client/core/io/mcbp_session.hxx +1 -0
- package/deps/couchbase-cxx-client/core/range_scan_load_balancer.cxx +141 -0
- package/deps/couchbase-cxx-client/core/range_scan_load_balancer.hxx +64 -0
- package/deps/couchbase-cxx-client/core/range_scan_orchestrator.cxx +224 -336
- package/deps/couchbase-cxx-client/core/range_scan_orchestrator.hxx +5 -6
- package/deps/couchbase-cxx-client/core/range_scan_orchestrator_options.hxx +6 -4
- package/deps/couchbase-cxx-client/core/scan_result.hxx +1 -11
- package/deps/couchbase-cxx-client/couchbase/bucket.hxx +2 -2
- package/deps/couchbase-cxx-client/couchbase/cluster.hxx +1 -1
- package/deps/couchbase-cxx-client/couchbase/collection.hxx +1 -0
- package/deps/couchbase-cxx-client/couchbase/collection_query_index_manager.hxx +1 -1
- package/deps/couchbase-cxx-client/couchbase/error_context.hxx +1 -0
- package/deps/couchbase-cxx-client/couchbase/get_links_analytics_options.hxx +2 -2
- package/deps/couchbase-cxx-client/couchbase/scope.hxx +1 -1
- package/deps/couchbase-cxx-client/couchbase/search_options.hxx +2 -2
- package/deps/couchbase-cxx-client/couchbase/search_result.hxx +1 -1
- package/deps/couchbase-cxx-client/couchbase/subdocument_error_context.hxx +1 -0
- package/deps/couchbase-cxx-client/couchbase/transactions/transaction_options.hxx +1 -1
- package/deps/couchbase-cxx-client/couchbase-sdk-cxx-black-duck-manifest.yaml +1 -0
- package/package.json +7 -7
- package/src/jstocbpp_autogen.hpp +0 -1
- 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
|
@@ -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
|