couchbase 3.4.3 → 3.4.4
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.
- checksums.yaml +4 -4
- data/README.md +2 -2
- data/ext/couchbase/CMakeLists.txt +15 -1
- data/ext/couchbase/core/bucket.cxx +183 -152
- data/ext/couchbase/core/bucket.hxx +17 -4
- data/ext/couchbase/core/cluster.hxx +34 -13
- data/ext/couchbase/core/cluster_options.hxx +3 -0
- data/ext/couchbase/core/crud_component.cxx +51 -22
- data/ext/couchbase/core/error_context/key_value.cxx +2 -1
- data/ext/couchbase/core/error_context/key_value.hxx +10 -12
- data/ext/couchbase/core/impl/build_deferred_query_indexes.cxx +115 -50
- data/ext/couchbase/core/impl/cluster.cxx +6 -0
- data/ext/couchbase/core/impl/create_bucket.cxx +155 -0
- data/ext/couchbase/core/impl/create_query_index.cxx +172 -59
- data/ext/couchbase/core/impl/dns_srv_tracker.cxx +2 -1
- data/ext/couchbase/core/impl/drop_bucket.cxx +66 -0
- data/ext/couchbase/core/impl/drop_query_index.cxx +138 -59
- data/ext/couchbase/core/impl/flush_bucket.cxx +66 -0
- data/ext/couchbase/core/impl/get_all_buckets.cxx +163 -0
- data/ext/couchbase/core/impl/get_all_query_indexes.cxx +67 -37
- data/ext/couchbase/core/impl/get_bucket.cxx +153 -0
- data/ext/couchbase/core/impl/internal_manager_error_context.cxx +113 -0
- data/ext/couchbase/core/impl/internal_manager_error_context.hxx +60 -0
- data/ext/couchbase/core/impl/key_value_error_category.cxx +2 -4
- data/ext/couchbase/core/impl/key_value_error_context.cxx +98 -0
- data/ext/couchbase/core/impl/lookup_in.cxx +1 -0
- data/ext/couchbase/core/impl/lookup_in_all_replicas.cxx +176 -0
- data/ext/couchbase/core/impl/lookup_in_all_replicas.hxx +80 -0
- data/ext/couchbase/core/impl/lookup_in_any_replica.cxx +167 -0
- data/ext/couchbase/core/impl/lookup_in_any_replica.hxx +75 -0
- data/ext/couchbase/core/impl/lookup_in_replica.cxx +97 -0
- data/ext/couchbase/core/impl/lookup_in_replica.hxx +67 -0
- data/ext/couchbase/core/impl/manager_error_context.cxx +100 -0
- data/ext/couchbase/core/impl/query.cxx +1 -0
- data/ext/couchbase/core/impl/query_error_context.cxx +75 -0
- data/ext/couchbase/core/impl/update_bucket.cxx +130 -0
- data/ext/couchbase/core/impl/watch_query_indexes.cxx +53 -29
- data/ext/couchbase/core/io/dns_client.cxx +111 -40
- data/ext/couchbase/core/io/dns_config.cxx +5 -4
- data/ext/couchbase/core/io/http_session.hxx +24 -1
- data/ext/couchbase/core/io/mcbp_command.hxx +9 -2
- data/ext/couchbase/core/io/mcbp_session.cxx +80 -43
- data/ext/couchbase/core/io/mcbp_session.hxx +4 -3
- data/ext/couchbase/core/logger/custom_rotating_file_sink.cxx +1 -1
- data/ext/couchbase/core/logger/logger.cxx +80 -20
- data/ext/couchbase/core/logger/logger.hxx +31 -0
- data/ext/couchbase/core/meta/features.hxx +25 -0
- data/ext/couchbase/core/operations/document_lookup_in_all_replicas.hxx +192 -0
- data/ext/couchbase/core/operations/document_lookup_in_any_replica.hxx +188 -0
- data/ext/couchbase/core/operations/document_query.cxx +11 -0
- data/ext/couchbase/core/operations/document_query.hxx +1 -0
- data/ext/couchbase/core/operations.hxx +2 -0
- data/ext/couchbase/core/origin.cxx +270 -0
- data/ext/couchbase/core/origin.hxx +2 -0
- data/ext/couchbase/core/protocol/client_response.hxx +1 -0
- data/ext/couchbase/core/protocol/cmd_hello.hxx +1 -0
- data/ext/couchbase/core/protocol/cmd_lookup_in_replica.cxx +107 -0
- data/ext/couchbase/core/protocol/cmd_lookup_in_replica.hxx +137 -0
- data/ext/couchbase/core/protocol/hello_feature.hxx +6 -0
- data/ext/couchbase/core/protocol/hello_feature_fmt.hxx +3 -0
- data/ext/couchbase/core/protocol/status.cxx +2 -2
- data/ext/couchbase/core/range_scan_options.cxx +3 -27
- data/ext/couchbase/core/range_scan_options.hxx +13 -17
- data/ext/couchbase/core/range_scan_orchestrator.cxx +388 -170
- data/ext/couchbase/core/range_scan_orchestrator.hxx +13 -2
- data/ext/couchbase/core/range_scan_orchestrator_options.hxx +5 -3
- data/ext/couchbase/core/scan_options.hxx +0 -19
- data/ext/couchbase/core/scan_result.cxx +19 -5
- data/ext/couchbase/core/scan_result.hxx +5 -2
- data/ext/couchbase/core/timeout_defaults.hxx +2 -3
- data/ext/couchbase/core/topology/capabilities.hxx +3 -0
- data/ext/couchbase/core/topology/capabilities_fmt.hxx +8 -0
- data/ext/couchbase/core/topology/collections_manifest_fmt.hxx +1 -1
- data/ext/couchbase/core/topology/configuration.hxx +15 -0
- data/ext/couchbase/core/topology/configuration_json.hxx +6 -1
- data/ext/couchbase/core/utils/connection_string.cxx +62 -47
- data/ext/couchbase/core/utils/connection_string.hxx +1 -0
- data/ext/couchbase/couchbase/analytics_error_context.hxx +1 -1
- data/ext/couchbase/couchbase/behavior_options.hxx +19 -2
- data/ext/couchbase/couchbase/bucket_manager.hxx +135 -0
- data/ext/couchbase/couchbase/build_query_index_options.hxx +0 -30
- data/ext/couchbase/couchbase/cluster.hxx +14 -0
- data/ext/couchbase/couchbase/collection.hxx +111 -0
- data/ext/couchbase/couchbase/collection_query_index_manager.hxx +7 -48
- data/ext/couchbase/couchbase/create_bucket_options.hxx +41 -0
- data/ext/couchbase/couchbase/create_primary_query_index_options.hxx +0 -29
- data/ext/couchbase/couchbase/create_query_index_options.hxx +0 -33
- data/ext/couchbase/couchbase/drop_bucket_options.hxx +41 -0
- data/ext/couchbase/couchbase/drop_primary_query_index_options.hxx +0 -30
- data/ext/couchbase/couchbase/drop_query_index_options.hxx +0 -31
- data/ext/couchbase/couchbase/error_codes.hxx +1 -2
- data/ext/couchbase/couchbase/error_context.hxx +10 -2
- data/ext/couchbase/couchbase/flush_bucket_options.hxx +41 -0
- data/ext/couchbase/{core/topology/error_map_fmt.hxx → couchbase/fmt/key_value_error_map_attribute.hxx} +21 -21
- data/ext/couchbase/couchbase/get_all_buckets_options.hxx +44 -0
- data/ext/couchbase/couchbase/get_all_query_indexes_options.hxx +0 -30
- data/ext/couchbase/couchbase/get_and_lock_options.hxx +2 -2
- data/ext/couchbase/couchbase/get_and_touch_options.hxx +2 -2
- data/ext/couchbase/couchbase/get_bucket_options.hxx +43 -0
- data/ext/couchbase/couchbase/get_options.hxx +2 -2
- data/ext/couchbase/couchbase/insert_options.hxx +3 -3
- data/ext/couchbase/couchbase/key_value_error_context.hxx +7 -2
- data/ext/couchbase/couchbase/lookup_in_all_replicas_options.hxx +109 -0
- data/ext/couchbase/couchbase/lookup_in_any_replica_options.hxx +101 -0
- data/ext/couchbase/couchbase/lookup_in_options.hxx +2 -2
- data/ext/couchbase/couchbase/lookup_in_replica_result.hxx +74 -0
- data/ext/couchbase/couchbase/lookup_in_result.hxx +26 -0
- data/ext/couchbase/couchbase/management/bucket_settings.hxx +116 -0
- data/ext/couchbase/couchbase/manager_error_context.hxx +29 -53
- data/ext/couchbase/couchbase/mutate_in_options.hxx +2 -2
- data/ext/couchbase/couchbase/query_error_context.hxx +3 -1
- data/ext/couchbase/couchbase/query_index_manager.hxx +16 -83
- data/ext/couchbase/couchbase/query_options.hxx +18 -0
- data/ext/couchbase/couchbase/remove_options.hxx +2 -2
- data/ext/couchbase/couchbase/replace_options.hxx +3 -3
- data/ext/couchbase/couchbase/security_options.hxx +15 -0
- data/ext/couchbase/couchbase/subdocument_error_context.hxx +4 -2
- data/ext/couchbase/couchbase/touch_options.hxx +2 -2
- data/ext/couchbase/couchbase/unlock_options.hxx +2 -2
- data/ext/couchbase/couchbase/update_bucket_options.hxx +41 -0
- data/ext/couchbase/couchbase/upsert_options.hxx +3 -3
- data/ext/couchbase/couchbase/watch_query_indexes_options.hxx +0 -31
- data/ext/couchbase/test/CMakeLists.txt +1 -0
- data/ext/couchbase/test/test_integration_collections.cxx +6 -0
- data/ext/couchbase/test/test_integration_crud.cxx +5 -0
- data/ext/couchbase/test/test_integration_examples.cxx +137 -1
- data/ext/couchbase/test/test_integration_management.cxx +709 -266
- data/ext/couchbase/test/test_integration_query.cxx +19 -7
- data/ext/couchbase/test/test_integration_range_scan.cxx +351 -112
- data/ext/couchbase/test/test_integration_search.cxx +10 -1
- data/ext/couchbase/test/test_integration_subdoc.cxx +655 -0
- data/ext/couchbase/test/test_transaction_public_async_api.cxx +13 -12
- data/ext/couchbase/test/test_transaction_public_blocking_api.cxx +27 -21
- data/ext/couchbase/test/test_unit_connection_string.cxx +29 -0
- data/ext/couchbase/test/test_unit_query.cxx +75 -0
- data/ext/couchbase.cxx +583 -29
- data/ext/revisions.rb +3 -3
- data/lib/couchbase/cluster.rb +1 -1
- data/lib/couchbase/collection.rb +108 -0
- data/lib/couchbase/collection_options.rb +100 -0
- data/lib/couchbase/errors.rb +5 -0
- data/lib/couchbase/key_value_scan.rb +125 -0
- data/lib/couchbase/options.rb +151 -0
- data/lib/couchbase/scope.rb +1 -1
- data/lib/couchbase/utils/time.rb +14 -1
- data/lib/couchbase/version.rb +1 -1
- metadata +41 -7
- data/ext/couchbase/core/impl/collection_query_index_manager.cxx +0 -93
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b3c1e2edfe7f74eb3f3094dd526e7dc1896f3002caca935ddeb76923b593f341
|
|
4
|
+
data.tar.gz: b5409f7083156b38aee870037ce0c5d3a14dc7ffe3aa3ac64b5862245b47e4d5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 16705649dc3954db461a7f8a63ee1168a4b191cacb0744e4e5b5b7b110788491d42fab78611b4898078a0276bbe0d9930352e24b4f95db87ab79ed6b6e8f9101
|
|
7
|
+
data.tar.gz: 157af7be99dc745ef7d95ef45490c0025f16ead6abb2f75079188405e82fcec9a64abb681695720e9080fd36b3c17883a56f84bafd06062e56c22ad9286c7ed4
|
data/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://opensource.org/licenses/Apache-2.0)
|
|
4
4
|
[](https://rubygems.org/gems/couchbase)
|
|
5
|
-
[](https://github.com/couchbase/couchbase-ruby-client/commits/
|
|
5
|
+
[](https://github.com/couchbase/couchbase-ruby-client/commits/main)
|
|
6
6
|
[](https://github.com/couchbase/couchbase-ruby-client/actions?query=workflow%3Alinters)
|
|
7
7
|
|
|
8
8
|
This repository contains the third generation of the official Couchbase SDK for Ruby (aka. SDKv3)
|
|
@@ -23,7 +23,7 @@ The library has been tested with MRI 3.0, 3.1 and 3.2. Supported platforms are L
|
|
|
23
23
|
Add this line to your application's Gemfile:
|
|
24
24
|
|
|
25
25
|
```ruby
|
|
26
|
-
gem "couchbase", "3.4.
|
|
26
|
+
gem "couchbase", "3.4.4"
|
|
27
27
|
```
|
|
28
28
|
|
|
29
29
|
And then execute:
|
|
@@ -100,6 +100,7 @@ set(couchbase_cxx_client_FILES
|
|
|
100
100
|
core/free_form_http_request.cxx
|
|
101
101
|
core/key_value_config.cxx
|
|
102
102
|
core/n1ql_query_options.cxx
|
|
103
|
+
core/origin.cxx
|
|
103
104
|
core/range_scan_options.cxx
|
|
104
105
|
core/range_scan_orchestrator.cxx
|
|
105
106
|
core/retry_orchestrator.cxx
|
|
@@ -232,6 +233,7 @@ set(couchbase_cxx_client_FILES
|
|
|
232
233
|
core/protocol/cmd_increment.cxx
|
|
233
234
|
core/protocol/cmd_insert.cxx
|
|
234
235
|
core/protocol/cmd_lookup_in.cxx
|
|
236
|
+
core/protocol/cmd_lookup_in_replica.cxx
|
|
235
237
|
core/protocol/cmd_mutate_in.cxx
|
|
236
238
|
core/protocol/cmd_noop.cxx
|
|
237
239
|
core/protocol/cmd_observe_seqno.cxx
|
|
@@ -265,10 +267,10 @@ set(couchbase_cxx_client_FILES
|
|
|
265
267
|
core/impl/boolean_query.cxx
|
|
266
268
|
core/impl/build_deferred_query_indexes.cxx
|
|
267
269
|
core/impl/cluster.cxx
|
|
268
|
-
core/impl/collection_query_index_manager.cxx
|
|
269
270
|
core/impl/common_error_category.cxx
|
|
270
271
|
core/impl/configuration_profiles_registry.cxx
|
|
271
272
|
core/impl/conjunction_query.cxx
|
|
273
|
+
core/impl/create_bucket.cxx
|
|
272
274
|
core/impl/create_query_index.cxx
|
|
273
275
|
core/impl/date_range.cxx
|
|
274
276
|
core/impl/date_range_facet.cxx
|
|
@@ -277,24 +279,29 @@ set(couchbase_cxx_client_FILES
|
|
|
277
279
|
core/impl/decrement.cxx
|
|
278
280
|
core/impl/disjunction_query.cxx
|
|
279
281
|
core/impl/dns_srv_tracker.cxx
|
|
282
|
+
core/impl/drop_bucket.cxx
|
|
280
283
|
core/impl/drop_query_index.cxx
|
|
281
284
|
core/impl/exists.cxx
|
|
282
285
|
core/impl/expiry.cxx
|
|
283
286
|
core/impl/fail_fast_retry_strategy.cxx
|
|
284
287
|
core/impl/field_level_encryption_error_category.cxx
|
|
288
|
+
core/impl/flush_bucket.cxx
|
|
285
289
|
core/impl/geo_bounding_box_query.cxx
|
|
286
290
|
core/impl/geo_distance_query.cxx
|
|
287
291
|
core/impl/geo_polygon_query.cxx
|
|
288
292
|
core/impl/get.cxx
|
|
293
|
+
core/impl/get_all_buckets.cxx
|
|
289
294
|
core/impl/get_all_query_indexes.cxx
|
|
290
295
|
core/impl/get_all_replicas.cxx
|
|
291
296
|
core/impl/get_and_lock.cxx
|
|
292
297
|
core/impl/get_and_touch.cxx
|
|
293
298
|
core/impl/get_any_replica.cxx
|
|
299
|
+
core/impl/get_bucket.cxx
|
|
294
300
|
core/impl/get_replica.cxx
|
|
295
301
|
core/impl/increment.cxx
|
|
296
302
|
core/impl/insert.cxx
|
|
297
303
|
core/impl/internal_date_range_facet_result.cxx
|
|
304
|
+
core/impl/internal_manager_error_context.cxx
|
|
298
305
|
core/impl/internal_numeric_range_facet_result.cxx
|
|
299
306
|
core/impl/internal_search_error_context.cxx
|
|
300
307
|
core/impl/internal_search_meta_data.cxx
|
|
@@ -303,8 +310,13 @@ set(couchbase_cxx_client_FILES
|
|
|
303
310
|
core/impl/internal_search_row_locations.cxx
|
|
304
311
|
core/impl/internal_term_facet_result.cxx
|
|
305
312
|
core/impl/key_value_error_category.cxx
|
|
313
|
+
core/impl/key_value_error_context.cxx
|
|
306
314
|
core/impl/lookup_in.cxx
|
|
315
|
+
core/impl/lookup_in_replica.cxx
|
|
316
|
+
core/impl/lookup_in_all_replicas.cxx
|
|
317
|
+
core/impl/lookup_in_any_replica.cxx
|
|
307
318
|
core/impl/management_error_category.cxx
|
|
319
|
+
core/impl/manager_error_context.cxx
|
|
308
320
|
core/impl/match_all_query.cxx
|
|
309
321
|
core/impl/match_none_query.cxx
|
|
310
322
|
core/impl/match_phrase_query.cxx
|
|
@@ -322,6 +334,7 @@ set(couchbase_cxx_client_FILES
|
|
|
322
334
|
core/impl/prepend.cxx
|
|
323
335
|
core/impl/query.cxx
|
|
324
336
|
core/impl/query_error_category.cxx
|
|
337
|
+
core/impl/query_error_context.cxx
|
|
325
338
|
core/impl/query_string_query.cxx
|
|
326
339
|
core/impl/regexp_query.cxx
|
|
327
340
|
core/impl/remove.cxx
|
|
@@ -366,6 +379,7 @@ set(couchbase_cxx_client_FILES
|
|
|
366
379
|
core/impl/transaction_get_result.cxx
|
|
367
380
|
core/impl/transaction_op_error_category.cxx
|
|
368
381
|
core/impl/unlock.cxx
|
|
382
|
+
core/impl/update_bucket.cxx
|
|
369
383
|
core/impl/upsert.cxx
|
|
370
384
|
core/impl/view_error_category.cxx
|
|
371
385
|
core/impl/watch_query_indexes.cxx
|
|
@@ -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
|
|
283
|
+
void restart_sessions()
|
|
307
284
|
{
|
|
308
|
-
|
|
309
|
-
|
|
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
|
-
|
|
332
|
-
|
|
333
|
-
|
|
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
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
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
|
-
|
|
351
|
-
|
|
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
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
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
|
-
|
|
378
|
-
|
|
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([
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
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(
|
|
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() :
|
|
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
|
|
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={},
|
|
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
|
|