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,270 @@
|
|
|
1
|
+
/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
2
|
+
/*
|
|
3
|
+
* Copyright 2020-2021 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 "origin.hxx"
|
|
19
|
+
|
|
20
|
+
#include <fmt/chrono.h>
|
|
21
|
+
#include <fmt/format.h>
|
|
22
|
+
|
|
23
|
+
#include <tao/json.hpp>
|
|
24
|
+
|
|
25
|
+
namespace tao::json
|
|
26
|
+
{
|
|
27
|
+
|
|
28
|
+
template<>
|
|
29
|
+
struct traits<std::chrono::milliseconds> {
|
|
30
|
+
template<template<typename...> class Traits>
|
|
31
|
+
static void assign(tao::json::basic_value<Traits>& v, const std::chrono::milliseconds& o)
|
|
32
|
+
{
|
|
33
|
+
v = fmt::format("{}", o);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
template<>
|
|
38
|
+
struct traits<std::chrono::nanoseconds> {
|
|
39
|
+
template<template<typename...> class Traits>
|
|
40
|
+
static void assign(tao::json::basic_value<Traits>& v, const std::chrono::nanoseconds& o)
|
|
41
|
+
{
|
|
42
|
+
v = fmt::format("{}", o);
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
template<>
|
|
47
|
+
struct traits<couchbase::core::tls_verify_mode> {
|
|
48
|
+
template<template<typename...> class Traits>
|
|
49
|
+
static void assign(tao::json::basic_value<Traits>& v, const couchbase::core::tls_verify_mode& o)
|
|
50
|
+
{
|
|
51
|
+
switch (o) {
|
|
52
|
+
case couchbase::core::tls_verify_mode::none:
|
|
53
|
+
v = "none";
|
|
54
|
+
break;
|
|
55
|
+
case couchbase::core::tls_verify_mode::peer:
|
|
56
|
+
v = "peer";
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
template<>
|
|
63
|
+
struct traits<couchbase::core::io::ip_protocol> {
|
|
64
|
+
template<template<typename...> class Traits>
|
|
65
|
+
static void assign(tao::json::basic_value<Traits>& v, const couchbase::core::io::ip_protocol& o)
|
|
66
|
+
{
|
|
67
|
+
switch (o) {
|
|
68
|
+
case couchbase::core::io::ip_protocol::any:
|
|
69
|
+
v = "any";
|
|
70
|
+
break;
|
|
71
|
+
case couchbase::core::io::ip_protocol::force_ipv4:
|
|
72
|
+
v = "force_ipv4";
|
|
73
|
+
break;
|
|
74
|
+
case couchbase::core::io::ip_protocol::force_ipv6:
|
|
75
|
+
v = "force_ipv6";
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
template<>
|
|
82
|
+
struct traits<couchbase::core::io::dns::dns_config> {
|
|
83
|
+
template<template<typename...> class Traits>
|
|
84
|
+
static void assign(tao::json::basic_value<Traits>& v, const couchbase::core::io::dns::dns_config& o)
|
|
85
|
+
{
|
|
86
|
+
v = {
|
|
87
|
+
{ "port", o.port() },
|
|
88
|
+
{ "nameserver", o.nameserver() },
|
|
89
|
+
{ "timeout", o.timeout() },
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
template<>
|
|
95
|
+
struct traits<couchbase::core::tracing::threshold_logging_options> {
|
|
96
|
+
template<template<typename...> class Traits>
|
|
97
|
+
static void assign(tao::json::basic_value<Traits>& v, const couchbase::core::tracing::threshold_logging_options& o)
|
|
98
|
+
{
|
|
99
|
+
v = {
|
|
100
|
+
{ "orphaned_emit_interval", o.orphaned_emit_interval },
|
|
101
|
+
{ "orphaned_sample_size", o.orphaned_sample_size },
|
|
102
|
+
{ "threshold_emit_interval", o.threshold_emit_interval },
|
|
103
|
+
{ "threshold_sample_size", o.threshold_sample_size },
|
|
104
|
+
{ "key_value_threshold", o.key_value_threshold },
|
|
105
|
+
{ "query_threshold", o.query_threshold },
|
|
106
|
+
{ "view_threshold", o.view_threshold },
|
|
107
|
+
{ "search_threshold", o.search_threshold },
|
|
108
|
+
{ "analytics_threshold", o.analytics_threshold },
|
|
109
|
+
{ "management_threshold", o.management_threshold },
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
template<>
|
|
115
|
+
struct traits<couchbase::core::metrics::logging_meter_options> {
|
|
116
|
+
template<template<typename...> class Traits>
|
|
117
|
+
static void assign(tao::json::basic_value<Traits>& v, const couchbase::core::metrics::logging_meter_options& o)
|
|
118
|
+
{
|
|
119
|
+
v = {
|
|
120
|
+
{ "emit_interval", o.emit_interval },
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
template<>
|
|
126
|
+
struct traits<couchbase::durability_level> {
|
|
127
|
+
template<template<typename...> class Traits>
|
|
128
|
+
static void assign(tao::json::basic_value<Traits>& v, const couchbase::durability_level& o)
|
|
129
|
+
{
|
|
130
|
+
switch (o) {
|
|
131
|
+
case couchbase::durability_level::none:
|
|
132
|
+
v = "none";
|
|
133
|
+
break;
|
|
134
|
+
case couchbase::durability_level::majority:
|
|
135
|
+
v = "majority";
|
|
136
|
+
break;
|
|
137
|
+
case couchbase::durability_level::majority_and_persist_to_active:
|
|
138
|
+
v = "majority_and_persist_to_active";
|
|
139
|
+
break;
|
|
140
|
+
case couchbase::durability_level::persist_to_majority:
|
|
141
|
+
v = "persist_to_majority";
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
template<>
|
|
148
|
+
struct traits<couchbase::query_scan_consistency> {
|
|
149
|
+
template<template<typename...> class Traits>
|
|
150
|
+
static void assign(tao::json::basic_value<Traits>& v, const couchbase::query_scan_consistency& o)
|
|
151
|
+
{
|
|
152
|
+
switch (o) {
|
|
153
|
+
case couchbase::query_scan_consistency::not_bounded:
|
|
154
|
+
v = "not_bounded";
|
|
155
|
+
break;
|
|
156
|
+
case couchbase::query_scan_consistency::request_plus:
|
|
157
|
+
v = "request_plus";
|
|
158
|
+
break;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
template<>
|
|
164
|
+
struct traits<couchbase::transactions::transactions_config::built> {
|
|
165
|
+
template<template<typename...> class Traits>
|
|
166
|
+
static void assign(tao::json::basic_value<Traits>& v, const couchbase::transactions::transactions_config::built& o)
|
|
167
|
+
{
|
|
168
|
+
v = {
|
|
169
|
+
{ "expiration_time", o.expiration_time },
|
|
170
|
+
{ "durability_level", o.level },
|
|
171
|
+
{
|
|
172
|
+
"query_config",
|
|
173
|
+
{
|
|
174
|
+
{ "scan_consistency", o.query_config.scan_consistency },
|
|
175
|
+
},
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
"cleanup_config",
|
|
179
|
+
{
|
|
180
|
+
{ "cleanup_lost_attempts", o.cleanup_config.cleanup_lost_attempts },
|
|
181
|
+
{ "cleanup_client_attempts", o.cleanup_config.cleanup_client_attempts },
|
|
182
|
+
{ "cleanup_window", o.cleanup_config.cleanup_window },
|
|
183
|
+
{ "collections", tao::json::empty_array },
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
};
|
|
187
|
+
if (const auto& p = o.kv_timeout; p.has_value()) {
|
|
188
|
+
v["key_value_timeout"] = p.value();
|
|
189
|
+
}
|
|
190
|
+
if (const auto& p = o.metadata_collection; p.has_value()) {
|
|
191
|
+
v["metadata_collection"] = {
|
|
192
|
+
{ "bucket", p.value().bucket },
|
|
193
|
+
{ "scope", p.value().scope },
|
|
194
|
+
{ "collection", p.value().collection },
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
for (const auto& c : o.cleanup_config.collections) {
|
|
198
|
+
v["cleanup_config"]["collections"].emplace_back(tao::json::value{
|
|
199
|
+
{ "bucket", c.bucket },
|
|
200
|
+
{ "scope", c.scope },
|
|
201
|
+
{ "collection", c.collection },
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
} // namespace tao::json
|
|
208
|
+
|
|
209
|
+
namespace couchbase::core
|
|
210
|
+
{
|
|
211
|
+
auto
|
|
212
|
+
origin::to_json() const -> std::string
|
|
213
|
+
{
|
|
214
|
+
tao::json::value json = {
|
|
215
|
+
{
|
|
216
|
+
"options",
|
|
217
|
+
{
|
|
218
|
+
{ "bootstrap_timeout", options_.bootstrap_timeout },
|
|
219
|
+
{ "resolve_timeout", options_.resolve_timeout },
|
|
220
|
+
{ "connect_timeout", options_.connect_timeout },
|
|
221
|
+
{ "key_value_timeout", options_.key_value_timeout },
|
|
222
|
+
{ "key_value_durable_timeout", options_.key_value_durable_timeout },
|
|
223
|
+
{ "view_timeout", options_.view_timeout },
|
|
224
|
+
{ "query_timeout", options_.query_timeout },
|
|
225
|
+
{ "analytics_timeout", options_.analytics_timeout },
|
|
226
|
+
{ "search_timeout", options_.search_timeout },
|
|
227
|
+
{ "management_timeout", options_.management_timeout },
|
|
228
|
+
{ "enable_tls", options_.enable_tls },
|
|
229
|
+
{ "trust_certificate", options_.trust_certificate },
|
|
230
|
+
{ "enable_mutation_tokens", options_.enable_mutation_tokens },
|
|
231
|
+
{ "enable_tcp_keep_alive", options_.enable_tcp_keep_alive },
|
|
232
|
+
{ "use_ip_protocol", options_.use_ip_protocol },
|
|
233
|
+
{ "enable_dns_srv", options_.enable_dns_srv },
|
|
234
|
+
{ "dns_config", options_.dns_config },
|
|
235
|
+
{ "show_queries", options_.show_queries },
|
|
236
|
+
{ "enable_unordered_execution", options_.enable_unordered_execution },
|
|
237
|
+
{ "enable_clustermap_notification", options_.enable_clustermap_notification },
|
|
238
|
+
{ "enable_compression", options_.enable_compression },
|
|
239
|
+
{ "enable_tracing", options_.enable_tracing },
|
|
240
|
+
{ "enable_metrics", options_.enable_metrics },
|
|
241
|
+
{ "tcp_keep_alive_interval", options_.tcp_keep_alive_interval },
|
|
242
|
+
{ "config_poll_interval", options_.config_poll_interval },
|
|
243
|
+
{ "config_poll_floor", options_.config_poll_floor },
|
|
244
|
+
{ "config_idle_redial_timeout", options_.config_idle_redial_timeout },
|
|
245
|
+
{ "max_http_connections", options_.max_http_connections },
|
|
246
|
+
{ "idle_http_connection_timeout", options_.idle_http_connection_timeout },
|
|
247
|
+
{ "user_agent_extra", options_.user_agent_extra },
|
|
248
|
+
{ "dump_configuration", options_.dump_configuration },
|
|
249
|
+
{ "disable_mozilla_ca_certificates", options_.disable_mozilla_ca_certificates },
|
|
250
|
+
{ "metrics_options", options_.metrics_options },
|
|
251
|
+
{ "network", options_.network },
|
|
252
|
+
{ "tls_verify", options_.tls_verify },
|
|
253
|
+
{ "tracing_options", options_.tracing_options },
|
|
254
|
+
{ "transactions_options", options_.transactions },
|
|
255
|
+
},
|
|
256
|
+
},
|
|
257
|
+
};
|
|
258
|
+
{
|
|
259
|
+
tao::json::value nodes = tao::json::empty_array;
|
|
260
|
+
for (const auto& [hostname, port] : nodes_) {
|
|
261
|
+
nodes.emplace_back(tao::json::value{
|
|
262
|
+
{ "hostname", hostname },
|
|
263
|
+
{ "port", port },
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
json["bootstrap_nodes"] = nodes;
|
|
267
|
+
}
|
|
268
|
+
return tao::json::to_string(json);
|
|
269
|
+
}
|
|
270
|
+
} // namespace couchbase::core
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
2
|
+
/*
|
|
3
|
+
* Copyright 2020-2021 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 "cmd_lookup_in_replica.hxx"
|
|
19
|
+
|
|
20
|
+
#include "core/utils/byteswap.hxx"
|
|
21
|
+
#include "core/utils/unsigned_leb128.hxx"
|
|
22
|
+
|
|
23
|
+
#include <cstring>
|
|
24
|
+
#include <gsl/assert>
|
|
25
|
+
|
|
26
|
+
namespace couchbase::core::protocol
|
|
27
|
+
{
|
|
28
|
+
bool
|
|
29
|
+
lookup_in_replica_response_body::parse(key_value_status_code status,
|
|
30
|
+
const header_buffer& header,
|
|
31
|
+
std::uint8_t framing_extras_size,
|
|
32
|
+
std::uint16_t key_size,
|
|
33
|
+
std::uint8_t extras_size,
|
|
34
|
+
const std::vector<std::byte>& body,
|
|
35
|
+
const cmd_info& /* info */)
|
|
36
|
+
{
|
|
37
|
+
Expects(header[1] == static_cast<std::byte>(opcode));
|
|
38
|
+
if (status == key_value_status_code::success || status == key_value_status_code::subdoc_multi_path_failure ||
|
|
39
|
+
status == key_value_status_code::subdoc_success_deleted || status == key_value_status_code::subdoc_multi_path_failure_deleted) {
|
|
40
|
+
using offset_type = std::vector<std::byte>::difference_type;
|
|
41
|
+
offset_type offset = framing_extras_size + key_size + extras_size;
|
|
42
|
+
fields_.reserve(16); /* we won't have more than 16 entries anyway */
|
|
43
|
+
while (static_cast<std::size_t>(offset) < body.size()) {
|
|
44
|
+
lookup_in_field field;
|
|
45
|
+
|
|
46
|
+
std::uint16_t entry_status = 0;
|
|
47
|
+
memcpy(&entry_status, body.data() + offset, sizeof(entry_status));
|
|
48
|
+
entry_status = utils::byte_swap(entry_status);
|
|
49
|
+
Expects(is_valid_status(entry_status));
|
|
50
|
+
field.status = static_cast<key_value_status_code>(entry_status);
|
|
51
|
+
offset += static_cast<offset_type>(sizeof(entry_status));
|
|
52
|
+
|
|
53
|
+
std::uint32_t entry_size = 0;
|
|
54
|
+
memcpy(&entry_size, body.data() + offset, sizeof(entry_size));
|
|
55
|
+
entry_size = utils::byte_swap(entry_size);
|
|
56
|
+
Expects(entry_size < 20 * 1024 * 1024);
|
|
57
|
+
offset += static_cast<offset_type>(sizeof(entry_size));
|
|
58
|
+
|
|
59
|
+
field.value.resize(entry_size);
|
|
60
|
+
memcpy(field.value.data(), body.data() + offset, entry_size);
|
|
61
|
+
offset += static_cast<offset_type>(entry_size);
|
|
62
|
+
|
|
63
|
+
fields_.emplace_back(field);
|
|
64
|
+
}
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
void
|
|
71
|
+
lookup_in_replica_request_body::id(const document_id& id)
|
|
72
|
+
{
|
|
73
|
+
key_ = make_protocol_key(id);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
void
|
|
77
|
+
lookup_in_replica_request_body::fill_extras()
|
|
78
|
+
{
|
|
79
|
+
if (flags_ != 0) {
|
|
80
|
+
extras_.resize(sizeof(flags_));
|
|
81
|
+
extras_[0] = std::byte{ flags_ };
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
void
|
|
86
|
+
lookup_in_replica_request_body::fill_value()
|
|
87
|
+
{
|
|
88
|
+
size_t value_size = 0;
|
|
89
|
+
for (const auto& spec : specs_) {
|
|
90
|
+
value_size += sizeof(spec.opcode_) + sizeof(std::uint8_t) + sizeof(std::uint16_t) + spec.path_.size();
|
|
91
|
+
}
|
|
92
|
+
Expects(value_size > 0);
|
|
93
|
+
value_.resize(value_size);
|
|
94
|
+
std::vector<std::byte>::size_type offset = 0;
|
|
95
|
+
for (const auto& spec : specs_) {
|
|
96
|
+
value_[offset] = static_cast<std::byte>(spec.opcode_);
|
|
97
|
+
++offset;
|
|
98
|
+
value_[offset] = spec.flags_;
|
|
99
|
+
++offset;
|
|
100
|
+
std::uint16_t path_size = utils::byte_swap(gsl::narrow_cast<std::uint16_t>(spec.path_.size()));
|
|
101
|
+
std::memcpy(value_.data() + offset, &path_size, sizeof(path_size));
|
|
102
|
+
offset += sizeof(path_size);
|
|
103
|
+
std::memcpy(value_.data() + offset, spec.path_.data(), spec.path_.size());
|
|
104
|
+
offset += spec.path_.size();
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
} // namespace couchbase::core::protocol
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
2
|
+
/*
|
|
3
|
+
* Copyright 2020-2021 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
|
+
#pragma once
|
|
19
|
+
|
|
20
|
+
#include "client_opcode.hxx"
|
|
21
|
+
#include "cmd_info.hxx"
|
|
22
|
+
#include "core/document_id.hxx"
|
|
23
|
+
#include "core/impl/subdoc/command.hxx"
|
|
24
|
+
#include "core/io/mcbp_message.hxx"
|
|
25
|
+
#include "status.hxx"
|
|
26
|
+
|
|
27
|
+
#include <gsl/assert>
|
|
28
|
+
|
|
29
|
+
namespace couchbase::core::protocol
|
|
30
|
+
{
|
|
31
|
+
|
|
32
|
+
class lookup_in_replica_response_body
|
|
33
|
+
{
|
|
34
|
+
public:
|
|
35
|
+
static const inline client_opcode opcode = client_opcode::subdoc_multi_lookup;
|
|
36
|
+
|
|
37
|
+
struct lookup_in_field {
|
|
38
|
+
key_value_status_code status{};
|
|
39
|
+
std::string value;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
private:
|
|
43
|
+
std::vector<lookup_in_field> fields_{};
|
|
44
|
+
|
|
45
|
+
public:
|
|
46
|
+
[[nodiscard]] const std::vector<lookup_in_field>& fields() const
|
|
47
|
+
{
|
|
48
|
+
return fields_;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
[[nodiscard]] bool parse(key_value_status_code status,
|
|
52
|
+
const header_buffer& header,
|
|
53
|
+
std::uint8_t framing_extras_size,
|
|
54
|
+
std::uint16_t key_size,
|
|
55
|
+
std::uint8_t extras_size,
|
|
56
|
+
const std::vector<std::byte>& body,
|
|
57
|
+
const cmd_info& info);
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
class lookup_in_replica_request_body
|
|
61
|
+
{
|
|
62
|
+
public:
|
|
63
|
+
using response_body_type = lookup_in_replica_response_body;
|
|
64
|
+
static const inline client_opcode opcode = client_opcode::subdoc_multi_lookup;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Tells the server to operate on replica vbucket instead of active
|
|
68
|
+
*/
|
|
69
|
+
static const inline std::uint8_t doc_flag_replica_read = 0b0010'0000;
|
|
70
|
+
|
|
71
|
+
private:
|
|
72
|
+
std::vector<std::byte> key_;
|
|
73
|
+
std::vector<std::byte> extras_{};
|
|
74
|
+
std::vector<std::byte> value_{};
|
|
75
|
+
|
|
76
|
+
std::uint8_t flags_{ 0 };
|
|
77
|
+
std::vector<couchbase::core::impl::subdoc::command> specs_;
|
|
78
|
+
|
|
79
|
+
public:
|
|
80
|
+
void id(const document_id& id);
|
|
81
|
+
|
|
82
|
+
void read_replica(bool value)
|
|
83
|
+
{
|
|
84
|
+
if (value) {
|
|
85
|
+
flags_ = flags_ | doc_flag_replica_read;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
void specs(const std::vector<couchbase::core::impl::subdoc::command>& specs)
|
|
90
|
+
{
|
|
91
|
+
specs_ = specs;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
[[nodiscard]] const auto& key() const
|
|
95
|
+
{
|
|
96
|
+
return key_;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
[[nodiscard]] const auto& framing_extras() const
|
|
100
|
+
{
|
|
101
|
+
return empty_buffer;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
[[nodiscard]] const auto& extras()
|
|
105
|
+
{
|
|
106
|
+
if (extras_.empty()) {
|
|
107
|
+
fill_extras();
|
|
108
|
+
}
|
|
109
|
+
return extras_;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
[[nodiscard]] const auto& value()
|
|
113
|
+
{
|
|
114
|
+
if (value_.empty()) {
|
|
115
|
+
fill_value();
|
|
116
|
+
}
|
|
117
|
+
return value_;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
[[nodiscard]] std::size_t size()
|
|
121
|
+
{
|
|
122
|
+
if (extras_.empty()) {
|
|
123
|
+
fill_extras();
|
|
124
|
+
}
|
|
125
|
+
if (value_.empty()) {
|
|
126
|
+
fill_value();
|
|
127
|
+
}
|
|
128
|
+
return key_.size() + extras_.size() + value_.size();
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
private:
|
|
132
|
+
void fill_extras();
|
|
133
|
+
|
|
134
|
+
void fill_value();
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
} // namespace couchbase::core::protocol
|
|
@@ -155,6 +155,11 @@ enum class hello_feature : std::uint16_t {
|
|
|
155
155
|
replace_body_with_xattr = 0x19,
|
|
156
156
|
|
|
157
157
|
resource_units = 0x1a,
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Indicates support for subdoc lookup operations on replicas
|
|
161
|
+
*/
|
|
162
|
+
subdoc_replica_read = 0x1c,
|
|
158
163
|
};
|
|
159
164
|
|
|
160
165
|
constexpr bool
|
|
@@ -185,6 +190,7 @@ is_valid_hello_feature(std::uint16_t code)
|
|
|
185
190
|
case hello_feature::subdoc_document_macro_support:
|
|
186
191
|
case hello_feature::replace_body_with_xattr:
|
|
187
192
|
case hello_feature::resource_units:
|
|
193
|
+
case hello_feature::subdoc_replica_read:
|
|
188
194
|
return true;
|
|
189
195
|
}
|
|
190
196
|
return false;
|
|
@@ -106,6 +106,9 @@ struct fmt::formatter<couchbase::core::protocol::hello_feature> {
|
|
|
106
106
|
case couchbase::core::protocol::hello_feature::resource_units:
|
|
107
107
|
name = "resource_units";
|
|
108
108
|
break;
|
|
109
|
+
case couchbase::core::protocol::hello_feature::subdoc_replica_read:
|
|
110
|
+
name = "subdoc_replica_read";
|
|
111
|
+
break;
|
|
109
112
|
}
|
|
110
113
|
return format_to(ctx.out(), "{}", name);
|
|
111
114
|
}
|
|
@@ -189,10 +189,10 @@ map_status_code(protocol::client_opcode opcode, std::uint16_t status)
|
|
|
189
189
|
case key_value_status_code::opaque_no_match:
|
|
190
190
|
|
|
191
191
|
case key_value_status_code::range_scan_cancelled:
|
|
192
|
-
return errc::
|
|
192
|
+
return errc::common::request_canceled;
|
|
193
193
|
|
|
194
194
|
case key_value_status_code::range_scan_vb_uuid_not_equal:
|
|
195
|
-
return errc::key_value::
|
|
195
|
+
return errc::key_value::mutation_token_outdated;
|
|
196
196
|
|
|
197
197
|
case key_value_status_code::unknown:
|
|
198
198
|
break;
|
|
@@ -19,34 +19,10 @@
|
|
|
19
19
|
|
|
20
20
|
namespace couchbase::core
|
|
21
21
|
{
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
, end_{ std::move(end) }
|
|
25
|
-
{
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
range_scan::range_scan(std::string_view start, std::string_view end)
|
|
29
|
-
: start_{ utils::to_binary(start) }
|
|
30
|
-
, end_{ utils::to_binary(end) }
|
|
31
|
-
{
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
range_scan::range_scan(std::string_view start, bool exclusive_start, std::string_view end, bool exclusive_end)
|
|
35
|
-
: start_{ utils::to_binary(start), exclusive_start }
|
|
36
|
-
, end_{ utils::to_binary(end), exclusive_end }
|
|
37
|
-
{
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
range_scan::range_scan(std::vector<std::byte> start, std::vector<std::byte> end)
|
|
41
|
-
: start_{ std::move(start) }
|
|
42
|
-
, end_{ std::move(end) }
|
|
43
|
-
{
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
range_scan::range_scan(std::vector<std::byte> start, bool exclusive_start, std::vector<std::byte> end, bool exclusive_end)
|
|
47
|
-
: start_{ std::move(start), exclusive_start }
|
|
48
|
-
, end_{ std::move(end), exclusive_end }
|
|
22
|
+
auto
|
|
23
|
+
prefix_scan::to_range_scan() const -> range_scan
|
|
49
24
|
{
|
|
25
|
+
return { scan_term{ prefix, false }, scan_term{ prefix + "\xf4\x8f\xfb\xfb" } };
|
|
50
26
|
}
|
|
51
27
|
|
|
52
28
|
auto
|