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
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
2
|
+
/*
|
|
3
|
+
* Copyright 2020-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 <couchbase/manager_error_context.hxx>
|
|
19
|
+
#include <utility>
|
|
20
|
+
|
|
21
|
+
#include "core/cluster.hxx"
|
|
22
|
+
#include "core/operations/management/bucket_update.hxx"
|
|
23
|
+
#include "couchbase/bucket_manager.hxx"
|
|
24
|
+
|
|
25
|
+
namespace couchbase
|
|
26
|
+
{
|
|
27
|
+
template<typename Response>
|
|
28
|
+
static manager_error_context
|
|
29
|
+
build_context(Response& resp)
|
|
30
|
+
{
|
|
31
|
+
return manager_error_context(internal_manager_error_context{ resp.ctx.ec,
|
|
32
|
+
resp.ctx.last_dispatched_to,
|
|
33
|
+
resp.ctx.last_dispatched_from,
|
|
34
|
+
resp.ctx.retry_attempts,
|
|
35
|
+
std::move(resp.ctx.retry_reasons),
|
|
36
|
+
std::move(resp.ctx.client_context_id),
|
|
37
|
+
resp.ctx.http_status,
|
|
38
|
+
std::move(resp.ctx.http_body),
|
|
39
|
+
std::move(resp.ctx.path) });
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
static core::operations::management::bucket_update_request
|
|
43
|
+
build_update_bucket_request(couchbase::core::management::cluster::bucket_settings bucket_settings,
|
|
44
|
+
const update_bucket_options::built& options)
|
|
45
|
+
{
|
|
46
|
+
core::operations::management::bucket_update_request request{ std::move(bucket_settings), {}, options.timeout };
|
|
47
|
+
return request;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
static couchbase::core::management::cluster::bucket_settings
|
|
51
|
+
map_bucket_settings(const couchbase::management::cluster::bucket_settings& bucket)
|
|
52
|
+
{
|
|
53
|
+
couchbase::core::management::cluster::bucket_settings bucket_settings{};
|
|
54
|
+
|
|
55
|
+
bucket_settings.name = bucket.name;
|
|
56
|
+
bucket_settings.ram_quota_mb = bucket.ram_quota_mb;
|
|
57
|
+
bucket_settings.max_expiry = bucket.max_expiry;
|
|
58
|
+
bucket_settings.minimum_durability_level = bucket.minimum_durability_level;
|
|
59
|
+
bucket_settings.num_replicas = bucket.num_replicas;
|
|
60
|
+
bucket_settings.replica_indexes = bucket.replica_indexes;
|
|
61
|
+
bucket_settings.flush_enabled = bucket.flush_enabled;
|
|
62
|
+
switch (bucket.conflict_resolution_type) {
|
|
63
|
+
case management::cluster::bucket_conflict_resolution::unknown:
|
|
64
|
+
bucket_settings.conflict_resolution_type = core::management::cluster::bucket_conflict_resolution::unknown;
|
|
65
|
+
break;
|
|
66
|
+
case management::cluster::bucket_conflict_resolution::timestamp:
|
|
67
|
+
bucket_settings.conflict_resolution_type = core::management::cluster::bucket_conflict_resolution::timestamp;
|
|
68
|
+
break;
|
|
69
|
+
case management::cluster::bucket_conflict_resolution::sequence_number:
|
|
70
|
+
bucket_settings.conflict_resolution_type = core::management::cluster::bucket_conflict_resolution::sequence_number;
|
|
71
|
+
break;
|
|
72
|
+
case management::cluster::bucket_conflict_resolution::custom:
|
|
73
|
+
bucket_settings.conflict_resolution_type = core::management::cluster::bucket_conflict_resolution::custom;
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
switch (bucket.eviction_policy) {
|
|
77
|
+
case management::cluster::bucket_eviction_policy::unknown:
|
|
78
|
+
bucket_settings.eviction_policy = core::management::cluster::bucket_eviction_policy::unknown;
|
|
79
|
+
break;
|
|
80
|
+
case management::cluster::bucket_eviction_policy::full:
|
|
81
|
+
bucket_settings.eviction_policy = core::management::cluster::bucket_eviction_policy::full;
|
|
82
|
+
break;
|
|
83
|
+
case management::cluster::bucket_eviction_policy::value_only:
|
|
84
|
+
bucket_settings.eviction_policy = core::management::cluster::bucket_eviction_policy::value_only;
|
|
85
|
+
break;
|
|
86
|
+
case management::cluster::bucket_eviction_policy::no_eviction:
|
|
87
|
+
bucket_settings.eviction_policy = core::management::cluster::bucket_eviction_policy::no_eviction;
|
|
88
|
+
break;
|
|
89
|
+
case management::cluster::bucket_eviction_policy::not_recently_used:
|
|
90
|
+
bucket_settings.eviction_policy = core::management::cluster::bucket_eviction_policy::not_recently_used;
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
switch (bucket.bucket_type) {
|
|
94
|
+
case management::cluster::bucket_type::unknown:
|
|
95
|
+
bucket_settings.bucket_type = core::management::cluster::bucket_type::unknown;
|
|
96
|
+
break;
|
|
97
|
+
case management::cluster::bucket_type::couchbase:
|
|
98
|
+
bucket_settings.bucket_type = core::management::cluster::bucket_type::couchbase;
|
|
99
|
+
break;
|
|
100
|
+
case management::cluster::bucket_type::memcached:
|
|
101
|
+
bucket_settings.bucket_type = core::management::cluster::bucket_type::memcached;
|
|
102
|
+
break;
|
|
103
|
+
case management::cluster::bucket_type::ephemeral:
|
|
104
|
+
bucket_settings.bucket_type = core::management::cluster::bucket_type::ephemeral;
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
return bucket_settings;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
void
|
|
111
|
+
bucket_manager::update_bucket(const management::cluster::bucket_settings& bucket_settings,
|
|
112
|
+
const update_bucket_options& options,
|
|
113
|
+
update_bucket_handler&& handler) const
|
|
114
|
+
{
|
|
115
|
+
auto request = build_update_bucket_request(map_bucket_settings(bucket_settings), options.build());
|
|
116
|
+
|
|
117
|
+
core_->execute(std::move(request), [handler = std::move(handler)](core::operations::management::bucket_update_response resp) mutable {
|
|
118
|
+
return handler(build_context(resp));
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
auto
|
|
123
|
+
bucket_manager::update_bucket(const management::cluster::bucket_settings& bucket_settings, const update_bucket_options& options) const
|
|
124
|
+
-> std::future<manager_error_context>
|
|
125
|
+
{
|
|
126
|
+
auto barrier = std::make_shared<std::promise<manager_error_context>>();
|
|
127
|
+
update_bucket(bucket_settings, options, [barrier](auto ctx) mutable { barrier->set_value(std::move(ctx)); });
|
|
128
|
+
return barrier->get_future();
|
|
129
|
+
}
|
|
130
|
+
} // namespace couchbase
|
|
@@ -24,16 +24,6 @@
|
|
|
24
24
|
|
|
25
25
|
namespace couchbase::core::impl
|
|
26
26
|
{
|
|
27
|
-
|
|
28
|
-
template<typename Response>
|
|
29
|
-
static manager_error_context
|
|
30
|
-
build_context(Response& resp, std::optional<std::error_code> ec = {})
|
|
31
|
-
{
|
|
32
|
-
return { ec ? ec.value() : resp.ctx.ec, resp.ctx.last_dispatched_to, resp.ctx.last_dispatched_from,
|
|
33
|
-
resp.ctx.retry_attempts, std::move(resp.ctx.retry_reasons), std::move(resp.ctx.client_context_id),
|
|
34
|
-
resp.ctx.http_status, std::move(resp.ctx.http_body), std::move(resp.ctx.path) };
|
|
35
|
-
}
|
|
36
|
-
|
|
37
27
|
class watch_context : public std::enable_shared_from_this<watch_context>
|
|
38
28
|
{
|
|
39
29
|
|
|
@@ -50,9 +40,18 @@ class watch_context : public std::enable_shared_from_this<watch_context>
|
|
|
50
40
|
std::chrono::milliseconds timeout_{ options_.timeout.value_or(core_->origin().second.options().query_timeout) };
|
|
51
41
|
std::atomic<size_t> attempts_{ 0 };
|
|
52
42
|
|
|
53
|
-
|
|
43
|
+
template<typename Response>
|
|
44
|
+
void finish(Response& resp, std::optional<std::error_code> ec = {})
|
|
54
45
|
{
|
|
55
|
-
handler_(
|
|
46
|
+
handler_({ manager_error_context(internal_manager_error_context{ ec ? ec.value() : resp.ctx.ec,
|
|
47
|
+
resp.ctx.last_dispatched_to,
|
|
48
|
+
resp.ctx.last_dispatched_from,
|
|
49
|
+
resp.ctx.retry_attempts,
|
|
50
|
+
std::move(resp.ctx.retry_reasons),
|
|
51
|
+
std::move(resp.ctx.client_context_id),
|
|
52
|
+
resp.ctx.http_status,
|
|
53
|
+
std::move(resp.ctx.http_body),
|
|
54
|
+
std::move(resp.ctx.path) }) });
|
|
56
55
|
timer_.cancel();
|
|
57
56
|
}
|
|
58
57
|
std::chrono::milliseconds remaining()
|
|
@@ -79,9 +78,9 @@ class watch_context : public std::enable_shared_from_this<watch_context>
|
|
|
79
78
|
complete &= it != resp.indexes.end() && it->state == "online";
|
|
80
79
|
}
|
|
81
80
|
if (complete || resp.ctx.ec == couchbase::errc::common::ambiguous_timeout) {
|
|
82
|
-
finish(
|
|
81
|
+
finish(resp);
|
|
83
82
|
} else if (remaining().count() <= 0) {
|
|
84
|
-
finish(
|
|
83
|
+
finish(resp, couchbase::errc::common::ambiguous_timeout);
|
|
85
84
|
complete = true;
|
|
86
85
|
}
|
|
87
86
|
return complete;
|
|
@@ -141,28 +140,53 @@ class watch_context : public std::enable_shared_from_this<watch_context>
|
|
|
141
140
|
core_->execute(req, resp_fn);
|
|
142
141
|
}
|
|
143
142
|
};
|
|
143
|
+
} // namespace couchbase::core::impl
|
|
144
144
|
|
|
145
|
+
namespace couchbase
|
|
146
|
+
{
|
|
145
147
|
void
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
query_context query_ctx,
|
|
151
|
-
std::string collection_name,
|
|
152
|
-
watch_query_indexes_handler&& handler)
|
|
148
|
+
query_index_manager::watch_indexes(std::string bucket_name,
|
|
149
|
+
std::vector<std::string> index_names,
|
|
150
|
+
const couchbase::watch_query_indexes_options& options,
|
|
151
|
+
couchbase::watch_query_indexes_handler&& handler)
|
|
153
152
|
{
|
|
154
|
-
auto ctx = std::make_shared<watch_context>(
|
|
153
|
+
auto ctx = std::make_shared<couchbase::core::impl::watch_context>(
|
|
154
|
+
core_, std::move(bucket_name), std::move(index_names), options.build(), core::query_context{}, "", std::move(handler));
|
|
155
155
|
ctx->execute();
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
+
auto
|
|
159
|
+
query_index_manager::watch_indexes(std::string bucket_name,
|
|
160
|
+
std::vector<std::string> index_names,
|
|
161
|
+
const couchbase::watch_query_indexes_options& options) -> std::future<manager_error_context>
|
|
162
|
+
{
|
|
163
|
+
auto barrier = std::make_shared<std::promise<manager_error_context>>();
|
|
164
|
+
watch_indexes(
|
|
165
|
+
std::move(bucket_name), std::move(index_names), options, [barrier](auto ctx) mutable { barrier->set_value(std::move(ctx)); });
|
|
166
|
+
return barrier->get_future();
|
|
167
|
+
}
|
|
168
|
+
|
|
158
169
|
void
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
couchbase::watch_query_indexes_options::built options,
|
|
163
|
-
watch_query_indexes_handler&& handler)
|
|
170
|
+
collection_query_index_manager::watch_indexes(std::vector<std::string> index_names,
|
|
171
|
+
const watch_query_indexes_options& options,
|
|
172
|
+
watch_query_indexes_handler&& handler) const
|
|
164
173
|
{
|
|
165
|
-
|
|
174
|
+
auto ctx = std::make_shared<couchbase::core::impl::watch_context>(core_,
|
|
175
|
+
bucket_name_,
|
|
176
|
+
std::move(index_names),
|
|
177
|
+
options.build(),
|
|
178
|
+
core::query_context(bucket_name_, scope_name_),
|
|
179
|
+
collection_name_,
|
|
180
|
+
std::move(handler));
|
|
181
|
+
ctx->execute();
|
|
166
182
|
}
|
|
167
183
|
|
|
168
|
-
|
|
184
|
+
auto
|
|
185
|
+
collection_query_index_manager::watch_indexes(std::vector<std::string> index_names, const couchbase::watch_query_indexes_options& options)
|
|
186
|
+
-> std::future<manager_error_context>
|
|
187
|
+
{
|
|
188
|
+
auto barrier = std::make_shared<std::promise<manager_error_context>>();
|
|
189
|
+
watch_indexes(std::move(index_names), options, [barrier](auto ctx) mutable { barrier->set_value(std::move(ctx)); });
|
|
190
|
+
return barrier->get_future();
|
|
191
|
+
}
|
|
192
|
+
} // namespace couchbase
|
|
@@ -28,6 +28,10 @@
|
|
|
28
28
|
#include <asio/read.hpp>
|
|
29
29
|
#include <asio/write.hpp>
|
|
30
30
|
|
|
31
|
+
#include <fmt/chrono.h>
|
|
32
|
+
|
|
33
|
+
#include <spdlog/fmt/bin_to_hex.h>
|
|
34
|
+
|
|
31
35
|
#include <memory>
|
|
32
36
|
#include <sstream>
|
|
33
37
|
|
|
@@ -68,22 +72,50 @@ class dns_srv_command : public std::enable_shared_from_this<dns_srv_command>
|
|
|
68
72
|
|
|
69
73
|
void execute(std::chrono::milliseconds total_timeout, std::chrono::milliseconds udp_timeout)
|
|
70
74
|
{
|
|
75
|
+
CB_LOG_TRACE("Query DNS-SRV (UDP) address=\"{}:{}\", udp_timeout={}, total_timeout={}",
|
|
76
|
+
address_.to_string(),
|
|
77
|
+
port_,
|
|
78
|
+
udp_timeout,
|
|
79
|
+
total_timeout);
|
|
71
80
|
asio::ip::udp::endpoint endpoint(address_, port_);
|
|
72
81
|
udp_.open(endpoint.protocol());
|
|
82
|
+
CB_LOG_PROTOCOL("[DNS, UDP, OUT] host=\"{}\", port={}, buffer_size={}{:a}",
|
|
83
|
+
address_.to_string(),
|
|
84
|
+
port_,
|
|
85
|
+
send_buf_.size(),
|
|
86
|
+
spdlog::to_hex(send_buf_));
|
|
73
87
|
udp_.async_send_to(
|
|
74
|
-
asio::buffer(send_buf_), endpoint, [self = shared_from_this()](std::error_code ec1, std::size_t
|
|
88
|
+
asio::buffer(send_buf_), endpoint, [self = shared_from_this()](std::error_code ec1, std::size_t bytes_transferred1) mutable {
|
|
89
|
+
CB_LOG_PROTOCOL("[DNS, UDP, OUT] host=\"{}\", port={}, rc={}, bytes_sent={}",
|
|
90
|
+
self->address_.to_string(),
|
|
91
|
+
self->port_,
|
|
92
|
+
ec1 ? ec1.message() : "ok",
|
|
93
|
+
bytes_transferred1);
|
|
75
94
|
if (ec1) {
|
|
76
95
|
self->udp_deadline_.cancel();
|
|
77
|
-
CB_LOG_DEBUG("DNS UDP write operation has got error
|
|
96
|
+
CB_LOG_DEBUG("DNS UDP write operation has got error, retrying with TCP, address=\"{}:{}\", ec={}",
|
|
97
|
+
self->address_.to_string(),
|
|
98
|
+
self->port_,
|
|
99
|
+
ec1.message());
|
|
78
100
|
return self->retry_with_tcp();
|
|
79
101
|
}
|
|
80
102
|
|
|
81
103
|
self->recv_buf_.resize(512);
|
|
82
104
|
self->udp_.async_receive_from(
|
|
83
105
|
asio::buffer(self->recv_buf_), self->udp_sender_, [self](std::error_code ec2, std::size_t bytes_transferred) mutable {
|
|
106
|
+
CB_LOG_PROTOCOL("[DNS, UDP, IN] host=\"{}\", port={}, rc={}, bytes_received={}{:a}",
|
|
107
|
+
self->address_.to_string(),
|
|
108
|
+
self->port_,
|
|
109
|
+
ec2 ? ec2.message() : "ok",
|
|
110
|
+
bytes_transferred,
|
|
111
|
+
spdlog::to_hex(self->recv_buf_.data(), self->recv_buf_.data() + bytes_transferred));
|
|
112
|
+
|
|
84
113
|
self->udp_deadline_.cancel();
|
|
85
114
|
if (ec2) {
|
|
86
|
-
CB_LOG_DEBUG("DNS UDP read operation has got error
|
|
115
|
+
CB_LOG_DEBUG("DNS UDP read operation has got error, retrying with TCP, address=\"{}:{}\", ec={}",
|
|
116
|
+
self->address_.to_string(),
|
|
117
|
+
self->port_,
|
|
118
|
+
ec2.message());
|
|
87
119
|
return self->retry_with_tcp();
|
|
88
120
|
}
|
|
89
121
|
self->recv_buf_.resize(bytes_transferred);
|
|
@@ -104,11 +136,13 @@ class dns_srv_command : public std::enable_shared_from_this<dns_srv_command>
|
|
|
104
136
|
});
|
|
105
137
|
});
|
|
106
138
|
udp_deadline_.expires_after(udp_timeout);
|
|
107
|
-
|
|
139
|
+
udp_deadline_.async_wait([self = shared_from_this()](std::error_code ec) {
|
|
108
140
|
if (ec == asio::error::operation_aborted) {
|
|
109
141
|
return;
|
|
110
142
|
}
|
|
111
|
-
CB_LOG_DEBUG("DNS UDP deadline has been reached, cancelling UDP operation and fall back to TCP"
|
|
143
|
+
CB_LOG_DEBUG("DNS UDP deadline has been reached, cancelling UDP operation and fall back to TCP, address=\"{}:{}\"",
|
|
144
|
+
self->address_.to_string(),
|
|
145
|
+
self->port_);
|
|
112
146
|
self->udp_.cancel();
|
|
113
147
|
return self->retry_with_tcp();
|
|
114
148
|
});
|
|
@@ -118,7 +152,10 @@ class dns_srv_command : public std::enable_shared_from_this<dns_srv_command>
|
|
|
118
152
|
if (ec == asio::error::operation_aborted) {
|
|
119
153
|
return;
|
|
120
154
|
}
|
|
121
|
-
CB_LOG_DEBUG("DNS deadline has been reached, cancelling in-flight operations (tcp.is_open={})",
|
|
155
|
+
CB_LOG_DEBUG("DNS deadline has been reached, cancelling in-flight operations (tcp.is_open={}, address=\"{}:{}\")",
|
|
156
|
+
self->tcp_.is_open(),
|
|
157
|
+
self->address_.to_string(),
|
|
158
|
+
self->port_);
|
|
122
159
|
self->udp_.cancel();
|
|
123
160
|
if (self->tcp_.is_open()) {
|
|
124
161
|
self->tcp_.cancel();
|
|
@@ -140,53 +177,87 @@ class dns_srv_command : public std::enable_shared_from_this<dns_srv_command>
|
|
|
140
177
|
tcp_.async_connect(endpoint, [self = shared_from_this()](std::error_code ec1) mutable {
|
|
141
178
|
if (ec1) {
|
|
142
179
|
self->deadline_.cancel();
|
|
143
|
-
CB_LOG_DEBUG(
|
|
180
|
+
CB_LOG_DEBUG(
|
|
181
|
+
"DNS TCP connection has been aborted, address=\"{}:{}\", ec={}", self->address_.to_string(), self->port_, ec1.message());
|
|
144
182
|
return self->handler_({ ec1 });
|
|
145
183
|
}
|
|
146
184
|
auto send_size = static_cast<std::uint16_t>(self->send_buf_.size());
|
|
147
185
|
self->send_buf_.insert(self->send_buf_.begin(), static_cast<std::uint8_t>(send_size & 0xffU));
|
|
148
186
|
self->send_buf_.insert(self->send_buf_.begin(), static_cast<std::uint8_t>(send_size >> 8U));
|
|
187
|
+
CB_LOG_PROTOCOL("[DNS, TCP, OUT] host=\"{}\", port={}, buffer_size={}{:a}",
|
|
188
|
+
self->address_.to_string(),
|
|
189
|
+
self->port_,
|
|
190
|
+
self->send_buf_.size(),
|
|
191
|
+
spdlog::to_hex(self->send_buf_));
|
|
149
192
|
asio::async_write(
|
|
150
|
-
self->tcp_, asio::buffer(self->send_buf_), [self](std::error_code ec2, std::size_t
|
|
193
|
+
self->tcp_, asio::buffer(self->send_buf_), [self](std::error_code ec2, std::size_t bytes_transferred2) mutable {
|
|
194
|
+
CB_LOG_PROTOCOL("[DNS, TCP, OUT] host=\"{}\", port={}, rc={}, bytes_sent={}",
|
|
195
|
+
self->address_.to_string(),
|
|
196
|
+
self->port_,
|
|
197
|
+
ec2 ? ec2.message() : "ok",
|
|
198
|
+
bytes_transferred2);
|
|
151
199
|
if (ec2) {
|
|
152
|
-
CB_LOG_DEBUG("DNS TCP write operation has been aborted, {}",
|
|
200
|
+
CB_LOG_DEBUG("DNS TCP write operation has been aborted, address=\"{}:{}\", ec={}",
|
|
201
|
+
self->address_.to_string(),
|
|
202
|
+
self->port_,
|
|
203
|
+
ec2.message());
|
|
153
204
|
self->deadline_.cancel();
|
|
154
205
|
if (ec2 == asio::error::operation_aborted) {
|
|
155
206
|
ec2 = errc::common::unambiguous_timeout;
|
|
156
207
|
}
|
|
157
208
|
return self->handler_({ ec2 });
|
|
158
209
|
}
|
|
159
|
-
asio::async_read(
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
210
|
+
asio::async_read(
|
|
211
|
+
self->tcp_,
|
|
212
|
+
asio::buffer(&self->recv_buf_size_, sizeof(std::uint16_t)),
|
|
213
|
+
[self](std::error_code ec3, std::size_t bytes_transferred3) mutable {
|
|
214
|
+
CB_LOG_PROTOCOL("[DNS, TCP, IN] host=\"{}\", port={}, rc={}, bytes_received={}{:a}",
|
|
215
|
+
self->address_.to_string(),
|
|
216
|
+
self->port_,
|
|
217
|
+
ec3 ? ec3.message() : "ok",
|
|
218
|
+
bytes_transferred3,
|
|
219
|
+
spdlog::to_hex(reinterpret_cast<std::uint8_t*>(&self->recv_buf_size_),
|
|
220
|
+
reinterpret_cast<std::uint8_t*>(&self->recv_buf_size_) + bytes_transferred3));
|
|
221
|
+
if (ec3) {
|
|
222
|
+
CB_LOG_DEBUG("DNS TCP buf size read operation has been aborted, address=\"{}:{}\", ec={}",
|
|
223
|
+
self->address_.to_string(),
|
|
224
|
+
self->port_,
|
|
225
|
+
ec3.message());
|
|
226
|
+
self->deadline_.cancel();
|
|
227
|
+
return self->handler_({ ec3 });
|
|
228
|
+
}
|
|
229
|
+
self->recv_buf_size_ = utils::byte_swap(self->recv_buf_size_);
|
|
230
|
+
self->recv_buf_.resize(self->recv_buf_size_);
|
|
231
|
+
CB_LOG_DEBUG("DNS TCP schedule read of {} bytes", self->recv_buf_size_);
|
|
232
|
+
asio::async_read(
|
|
233
|
+
self->tcp_, asio::buffer(self->recv_buf_), [self](std::error_code ec4, std::size_t bytes_transferred4) mutable {
|
|
234
|
+
self->deadline_.cancel();
|
|
235
|
+
CB_LOG_PROTOCOL("[DNS, TCP, IN] host=\"{}\", port={}, rc={}, bytes_received={}{:a}",
|
|
236
|
+
self->address_.to_string(),
|
|
237
|
+
self->port_,
|
|
238
|
+
ec4 ? ec4.message() : "ok",
|
|
239
|
+
bytes_transferred4,
|
|
240
|
+
spdlog::to_hex(self->recv_buf_.data(), self->recv_buf_.data() + bytes_transferred4));
|
|
241
|
+
|
|
242
|
+
if (ec4) {
|
|
243
|
+
CB_LOG_DEBUG("DNS TCP read operation has been aborted, address=\"{}:{}\", ec={}",
|
|
244
|
+
self->address_.to_string(),
|
|
245
|
+
self->port_,
|
|
246
|
+
ec4.message());
|
|
247
|
+
return self->handler_({ ec4 });
|
|
248
|
+
}
|
|
249
|
+
self->recv_buf_.resize(bytes_transferred4);
|
|
250
|
+
const dns_message message = dns_codec::decode(self->recv_buf_);
|
|
251
|
+
dns_srv_response resp{ ec4 };
|
|
252
|
+
resp.targets.reserve(message.answers.size());
|
|
253
|
+
for (const auto& answer : message.answers) {
|
|
254
|
+
resp.targets.emplace_back(
|
|
255
|
+
dns_srv_response::address{ utils::join_strings(answer.target.labels, "."), answer.port });
|
|
256
|
+
}
|
|
257
|
+
CB_LOG_DEBUG("DNS TCP returned {} records", resp.targets.size());
|
|
258
|
+
return self->handler_(std::move(resp));
|
|
259
|
+
});
|
|
260
|
+
});
|
|
190
261
|
});
|
|
191
262
|
});
|
|
192
263
|
}
|
|
@@ -87,7 +87,7 @@ load_resolv_conf()
|
|
|
87
87
|
|
|
88
88
|
if (dns_servers.size() > 0) {
|
|
89
89
|
CB_LOG_DEBUG(
|
|
90
|
-
"Found DNS Servers: [{}],
|
|
90
|
+
"Found DNS Servers: [{}], selected nameserver: \"{}\"", couchbase::core::utils::join_strings(dns_servers, ", "), dns_servers[0]);
|
|
91
91
|
return dns_servers[0];
|
|
92
92
|
}
|
|
93
93
|
CB_LOG_WARNING("Unable to find DNS nameserver");
|
|
@@ -118,13 +118,13 @@ load_resolv_conf(const char* conf_path)
|
|
|
118
118
|
if (space == std::string::npos || space == offset || line.size() < space + 2) {
|
|
119
119
|
continue;
|
|
120
120
|
}
|
|
121
|
-
if (
|
|
121
|
+
if (const auto keyword = line.substr(offset, space); keyword != "nameserver") {
|
|
122
122
|
continue;
|
|
123
123
|
}
|
|
124
124
|
offset = space + 1;
|
|
125
125
|
space = line.find(' ', offset);
|
|
126
|
-
auto nameserver = line.substr(offset, space);
|
|
127
|
-
CB_LOG_DEBUG("
|
|
126
|
+
auto nameserver = (space == std::string::npos) ? line.substr(offset) : line.substr(offset, space - offset);
|
|
127
|
+
CB_LOG_DEBUG("Selected nameserver: \"{}\" from \"{}\"", nameserver, conf_path);
|
|
128
128
|
return nameserver;
|
|
129
129
|
}
|
|
130
130
|
}
|
|
@@ -147,6 +147,7 @@ dns_config::system_config()
|
|
|
147
147
|
std::error_code ec;
|
|
148
148
|
asio::ip::address::from_string(nameserver, ec);
|
|
149
149
|
if (ec) {
|
|
150
|
+
CB_LOG_DEBUG("Unable to parse \"{}\" as a network address, fall back to \"{}\"", nameserver, default_nameserver);
|
|
150
151
|
nameserver = default_nameserver;
|
|
151
152
|
}
|
|
152
153
|
instance.nameserver_ = nameserver;
|
|
@@ -31,7 +31,10 @@
|
|
|
31
31
|
|
|
32
32
|
#include <couchbase/error_codes.hxx>
|
|
33
33
|
|
|
34
|
+
#include <spdlog/fmt/bin_to_hex.h>
|
|
35
|
+
|
|
34
36
|
#include <asio.hpp>
|
|
37
|
+
|
|
35
38
|
#include <list>
|
|
36
39
|
#include <memory>
|
|
37
40
|
#include <utility>
|
|
@@ -448,7 +451,20 @@ class http_session : public std::enable_shared_from_this<http_session>
|
|
|
448
451
|
stream_->async_read_some(
|
|
449
452
|
asio::buffer(input_buffer_), [self = shared_from_this()](std::error_code ec, std::size_t bytes_transferred) {
|
|
450
453
|
if (ec == asio::error::operation_aborted || self->stopped_) {
|
|
454
|
+
CB_LOG_PROTOCOL("[HTTP, IN] type={}, host=\"{}\", rc={}, bytes_received={}",
|
|
455
|
+
self->type_,
|
|
456
|
+
self->info_.remote_address(),
|
|
457
|
+
ec ? ec.message() : "ok",
|
|
458
|
+
bytes_transferred);
|
|
451
459
|
return;
|
|
460
|
+
} else {
|
|
461
|
+
CB_LOG_PROTOCOL("[HTTP, IN] type={}, host=\"{}\", rc={}, bytes_received={}{:a}",
|
|
462
|
+
self->type_,
|
|
463
|
+
self->info_.remote_address(),
|
|
464
|
+
ec ? ec.message() : "ok",
|
|
465
|
+
bytes_transferred,
|
|
466
|
+
spdlog::to_hex(self->input_buffer_.data(),
|
|
467
|
+
self->input_buffer_.data() + static_cast<std::ptrdiff_t>(bytes_transferred)));
|
|
452
468
|
}
|
|
453
469
|
self->last_active_ = std::chrono::steady_clock::now();
|
|
454
470
|
if (ec) {
|
|
@@ -495,9 +511,16 @@ class http_session : public std::enable_shared_from_this<http_session>
|
|
|
495
511
|
std::vector<asio::const_buffer> buffers;
|
|
496
512
|
buffers.reserve(writing_buffer_.size());
|
|
497
513
|
for (auto& buf : writing_buffer_) {
|
|
514
|
+
CB_LOG_PROTOCOL(
|
|
515
|
+
"[HTTP, OUT] type={}, host=\"{}\", buffer_size={}{:a}", type_, info_.remote_address(), buf.size(), spdlog::to_hex(buf));
|
|
498
516
|
buffers.emplace_back(asio::buffer(buf));
|
|
499
517
|
}
|
|
500
|
-
stream_->async_write(buffers, [self = shared_from_this()](std::error_code ec, std::size_t
|
|
518
|
+
stream_->async_write(buffers, [self = shared_from_this()](std::error_code ec, std::size_t bytes_transferred) {
|
|
519
|
+
CB_LOG_PROTOCOL("[HTTP, OUT] type={}, host=\"{}\", rc={}, bytes_sent={}",
|
|
520
|
+
self->type_,
|
|
521
|
+
self->info_.remote_address(),
|
|
522
|
+
ec ? ec.message() : "ok",
|
|
523
|
+
bytes_transferred);
|
|
501
524
|
if (ec == asio::error::operation_aborted || self->stopped_) {
|
|
502
525
|
return;
|
|
503
526
|
}
|
|
@@ -59,9 +59,13 @@ struct mcbp_command : public std::enable_shared_from_this<mcbp_command<Manager,
|
|
|
59
59
|
mcbp_command_handler handler_{};
|
|
60
60
|
std::shared_ptr<Manager> manager_{};
|
|
61
61
|
std::chrono::milliseconds timeout_{};
|
|
62
|
-
std::string id_{
|
|
62
|
+
std::string id_{
|
|
63
|
+
fmt::format("{:02x}/{}", static_cast<std::uint8_t>(encoded_request_type::body_type::opcode), uuid::to_string(uuid::random()))
|
|
64
|
+
};
|
|
63
65
|
std::shared_ptr<couchbase::tracing::request_span> span_{ nullptr };
|
|
64
66
|
std::shared_ptr<couchbase::tracing::request_span> parent_span{ nullptr };
|
|
67
|
+
std::optional<std::string> last_dispatched_from_{};
|
|
68
|
+
std::optional<std::string> last_dispatched_to_{};
|
|
65
69
|
|
|
66
70
|
mcbp_command(asio::io_context& ctx, std::shared_ptr<Manager> manager, Request req, std::chrono::milliseconds default_timeout)
|
|
67
71
|
: deadline(ctx)
|
|
@@ -109,7 +113,10 @@ struct mcbp_command : public std::enable_shared_from_this<mcbp_command<Manager,
|
|
|
109
113
|
handler_ = nullptr;
|
|
110
114
|
}
|
|
111
115
|
}
|
|
112
|
-
invoke_handler(request.retries.idempotent()
|
|
116
|
+
invoke_handler(request.retries.idempotent() || !opaque_.has_value()
|
|
117
|
+
? errc::common::unambiguous_timeout // safe to retry or has not been sent to the server
|
|
118
|
+
: errc::common::ambiguous_timeout // non-idempotent and has been sent to the server
|
|
119
|
+
);
|
|
113
120
|
}
|
|
114
121
|
|
|
115
122
|
void invoke_handler(std::error_code ec, std::optional<io::mcbp_message>&& msg = {})
|