couchbase 3.4.3 → 3.4.5
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 +22 -1
- data/ext/couchbase/core/bucket.cxx +183 -152
- data/ext/couchbase/core/bucket.hxx +17 -4
- data/ext/couchbase/core/cluster.hxx +41 -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 +158 -0
- data/ext/couchbase/core/impl/create_collection.cxx +83 -0
- data/ext/couchbase/core/impl/create_query_index.cxx +172 -59
- data/ext/couchbase/core/impl/create_scope.cxx +69 -0
- 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_collection.cxx +76 -0
- data/ext/couchbase/core/impl/drop_query_index.cxx +138 -59
- data/ext/couchbase/core/impl/drop_scope.cxx +68 -0
- data/ext/couchbase/core/impl/flush_bucket.cxx +66 -0
- data/ext/couchbase/core/impl/get_all_buckets.cxx +178 -0
- data/ext/couchbase/core/impl/get_all_query_indexes.cxx +67 -37
- data/ext/couchbase/core/impl/get_all_scopes.cxx +94 -0
- data/ext/couchbase/core/impl/get_bucket.cxx +168 -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 +178 -0
- data/ext/couchbase/core/impl/lookup_in_all_replicas.hxx +80 -0
- data/ext/couchbase/core/impl/lookup_in_any_replica.cxx +169 -0
- data/ext/couchbase/core/impl/lookup_in_any_replica.hxx +75 -0
- data/ext/couchbase/core/impl/lookup_in_replica.cxx +104 -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 +133 -0
- data/ext/couchbase/core/impl/update_collection.cxx +83 -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/management/bucket_settings.hxx +8 -5
- data/ext/couchbase/core/management/bucket_settings_json.hxx +12 -2
- data/ext/couchbase/core/meta/features.hxx +42 -0
- data/ext/couchbase/core/operations/document_lookup_in.cxx +8 -1
- 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/management/CMakeLists.txt +1 -0
- data/ext/couchbase/core/operations/management/bucket_create.cxx +30 -9
- data/ext/couchbase/core/operations/management/bucket_update.cxx +27 -6
- data/ext/couchbase/core/operations/management/collection_create.cxx +5 -1
- data/ext/couchbase/core/operations/management/collection_create.hxx +1 -0
- data/ext/couchbase/core/operations/management/collection_update.cxx +87 -0
- data/ext/couchbase/core/operations/management/collection_update.hxx +54 -0
- data/ext/couchbase/core/operations/management/collections.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 +3 -4
- data/ext/couchbase/core/topology/capabilities.hxx +4 -0
- data/ext/couchbase/core/topology/capabilities_fmt.hxx +11 -0
- data/ext/couchbase/core/topology/collections_manifest.hxx +2 -0
- data/ext/couchbase/core/topology/collections_manifest_fmt.hxx +1 -1
- data/ext/couchbase/core/topology/collections_manifest_json.hxx +3 -0
- data/ext/couchbase/core/topology/configuration.hxx +20 -0
- data/ext/couchbase/core/topology/configuration_json.hxx +8 -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.hxx +14 -0
- 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_manager.hxx +160 -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_collection_options.hxx +44 -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/create_scope_options.hxx +41 -0
- data/ext/couchbase/couchbase/drop_bucket_options.hxx +41 -0
- data/ext/couchbase/couchbase/drop_collection_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/drop_scope_options.hxx +41 -0
- 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_all_scopes_options.hxx +44 -0
- 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 +119 -0
- data/ext/couchbase/couchbase/management/collection_spec.hxx +29 -0
- data/ext/couchbase/couchbase/management/scope_spec.hxx +29 -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/update_collection_options.hxx +44 -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 +1009 -309
- 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 +721 -7
- 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 +735 -60
- 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 -1
- data/lib/couchbase/errors.rb +5 -0
- data/lib/couchbase/key_value_scan.rb +125 -0
- data/lib/couchbase/management/bucket_manager.rb +22 -15
- data/lib/couchbase/management/collection_manager.rb +158 -9
- 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 +59 -8
- data/ext/couchbase/core/impl/collection_query_index_manager.cxx +0 -93
|
@@ -22,7 +22,8 @@
|
|
|
22
22
|
#include <spdlog/sinks/stdout_color_sinks.h>
|
|
23
23
|
#include <spdlog/spdlog.h>
|
|
24
24
|
|
|
25
|
-
static const std::string
|
|
25
|
+
static const std::string file_logger_name{ "couchbase_cxx_client_file_logger" };
|
|
26
|
+
static const std::string protocol_logger_name{ "couchbase_cxx_client_protocol_logger" };
|
|
26
27
|
|
|
27
28
|
/**
|
|
28
29
|
* Custom log pattern which the loggers will use.
|
|
@@ -39,7 +40,12 @@ static const std::string log_pattern{ "[%Y-%m-%d %T.%e] [%P,%t] [%^%l%$] %oms, %
|
|
|
39
40
|
* messages and send them to the sinks, which do the actual writing (to file,
|
|
40
41
|
* to stream etc.) or further processing.
|
|
41
42
|
*/
|
|
42
|
-
static std::shared_ptr<spdlog::logger> file_logger;
|
|
43
|
+
static std::shared_ptr<spdlog::logger> file_logger{};
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Instance of the protocol logger.
|
|
47
|
+
*/
|
|
48
|
+
static std::shared_ptr<spdlog::logger> protocol_logger{};
|
|
43
49
|
|
|
44
50
|
namespace couchbase::core::logger
|
|
45
51
|
{
|
|
@@ -146,13 +152,11 @@ is_initialized()
|
|
|
146
152
|
return file_logger != nullptr;
|
|
147
153
|
}
|
|
148
154
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
* specified in a separate settings object.
|
|
152
|
-
*/
|
|
153
|
-
std::optional<std::string>
|
|
154
|
-
create_file_logger(const configuration& logger_settings)
|
|
155
|
+
std::pair<std::optional<std::string>, std::shared_ptr<spdlog::logger>>
|
|
156
|
+
create_file_logger_impl(const std::string logger_name, const configuration& logger_settings)
|
|
155
157
|
{
|
|
158
|
+
std::shared_ptr<spdlog::logger> logger{};
|
|
159
|
+
|
|
156
160
|
auto fname = logger_settings.filename;
|
|
157
161
|
auto buffersz = logger_settings.buffer_size;
|
|
158
162
|
auto cyclesz = logger_settings.cycle_size;
|
|
@@ -218,7 +222,7 @@ create_file_logger(const configuration& logger_settings)
|
|
|
218
222
|
spdlog::drop(logger_name);
|
|
219
223
|
|
|
220
224
|
if (logger_settings.unit_test) {
|
|
221
|
-
|
|
225
|
+
logger = std::make_shared<spdlog::logger>(logger_name, sink);
|
|
222
226
|
} else {
|
|
223
227
|
// Create the default thread pool for async logging
|
|
224
228
|
spdlog::init_thread_pool(buffersz, 1);
|
|
@@ -226,23 +230,71 @@ create_file_logger(const configuration& logger_settings)
|
|
|
226
230
|
// Get the thread pool so that we can actually construct the
|
|
227
231
|
// object with already created sinks...
|
|
228
232
|
auto tp = spdlog::thread_pool();
|
|
229
|
-
|
|
233
|
+
logger = std::make_shared<spdlog::async_logger>(logger_name, sink, tp, spdlog::async_overflow_policy::block);
|
|
230
234
|
}
|
|
231
235
|
|
|
232
|
-
|
|
233
|
-
|
|
236
|
+
logger->set_pattern(log_pattern);
|
|
237
|
+
logger->set_level(translate_level(logger_settings.log_level));
|
|
234
238
|
|
|
235
239
|
// Set the flushing interval policy
|
|
236
240
|
spdlog::flush_every(std::chrono::seconds(1));
|
|
237
241
|
|
|
238
|
-
spdlog::register_logger(
|
|
242
|
+
spdlog::register_logger(logger);
|
|
239
243
|
} catch (const spdlog::spdlog_ex& ex) {
|
|
240
244
|
std::string msg = std::string{ "Log initialization failed: " } + ex.what();
|
|
241
|
-
return
|
|
245
|
+
return { msg, {} };
|
|
246
|
+
}
|
|
247
|
+
return { {}, logger };
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Initialises the loggers. Called if the logger configuration is
|
|
252
|
+
* specified in a separate settings object.
|
|
253
|
+
*/
|
|
254
|
+
std::optional<std::string>
|
|
255
|
+
create_file_logger(const configuration& logger_settings)
|
|
256
|
+
{
|
|
257
|
+
auto [error, logger] = create_file_logger_impl(file_logger_name, logger_settings);
|
|
258
|
+
if (error) {
|
|
259
|
+
return error;
|
|
260
|
+
}
|
|
261
|
+
file_logger = std::move(logger);
|
|
262
|
+
return {};
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
std::optional<std::string>
|
|
266
|
+
create_protocol_logger(const configuration& logger_settings)
|
|
267
|
+
{
|
|
268
|
+
if (logger_settings.filename.empty()) {
|
|
269
|
+
return "File name is missing";
|
|
270
|
+
}
|
|
271
|
+
auto config = logger_settings;
|
|
272
|
+
config.log_level = couchbase::core::logger::level::trace;
|
|
273
|
+
auto [error, logger] = create_file_logger_impl(protocol_logger_name, config);
|
|
274
|
+
if (error) {
|
|
275
|
+
return error;
|
|
242
276
|
}
|
|
277
|
+
protocol_logger = std::move(logger);
|
|
243
278
|
return {};
|
|
244
279
|
}
|
|
245
280
|
|
|
281
|
+
bool
|
|
282
|
+
should_log_protocol()
|
|
283
|
+
{
|
|
284
|
+
return protocol_logger != nullptr;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
namespace detail
|
|
288
|
+
{
|
|
289
|
+
void
|
|
290
|
+
log_protocol(const char* file, int line, const char* function, std::string_view msg)
|
|
291
|
+
{
|
|
292
|
+
if (should_log_protocol()) {
|
|
293
|
+
return protocol_logger->log(spdlog::source_loc{ file, line, function }, spdlog::level::level_enum::trace, msg);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
} // namespace detail
|
|
297
|
+
|
|
246
298
|
spdlog::logger*
|
|
247
299
|
get()
|
|
248
300
|
{
|
|
@@ -252,17 +304,20 @@ get()
|
|
|
252
304
|
void
|
|
253
305
|
reset()
|
|
254
306
|
{
|
|
255
|
-
spdlog::drop(
|
|
307
|
+
spdlog::drop(file_logger_name);
|
|
256
308
|
file_logger.reset();
|
|
309
|
+
|
|
310
|
+
spdlog::drop(protocol_logger_name);
|
|
311
|
+
protocol_logger.reset();
|
|
257
312
|
}
|
|
258
313
|
|
|
259
314
|
void
|
|
260
315
|
create_blackhole_logger()
|
|
261
316
|
{
|
|
262
317
|
// delete if already exists
|
|
263
|
-
spdlog::drop(
|
|
318
|
+
spdlog::drop(file_logger_name);
|
|
264
319
|
|
|
265
|
-
file_logger = std::make_shared<spdlog::logger>(
|
|
320
|
+
file_logger = std::make_shared<spdlog::logger>(file_logger_name, std::make_shared<spdlog::sinks::null_sink_mt>());
|
|
266
321
|
|
|
267
322
|
file_logger->set_level(spdlog::level::off);
|
|
268
323
|
file_logger->set_pattern(log_pattern);
|
|
@@ -274,11 +329,11 @@ void
|
|
|
274
329
|
create_console_logger()
|
|
275
330
|
{
|
|
276
331
|
// delete if already exists
|
|
277
|
-
spdlog::drop(
|
|
332
|
+
spdlog::drop(file_logger_name);
|
|
278
333
|
|
|
279
334
|
auto stderrsink = std::make_shared<spdlog::sinks::stderr_color_sink_mt>();
|
|
280
335
|
|
|
281
|
-
file_logger = std::make_shared<spdlog::logger>(
|
|
336
|
+
file_logger = std::make_shared<spdlog::logger>(file_logger_name, stderrsink);
|
|
282
337
|
file_logger->set_level(spdlog::level::info);
|
|
283
338
|
file_logger->set_pattern(log_pattern);
|
|
284
339
|
|
|
@@ -322,8 +377,13 @@ void
|
|
|
322
377
|
set_log_levels(level lvl)
|
|
323
378
|
{
|
|
324
379
|
auto level = translate_level(lvl);
|
|
325
|
-
// Apply the function to each registered spdlog::logger
|
|
380
|
+
// Apply the function to each registered spdlog::logger except protocol logger
|
|
326
381
|
spdlog::apply_all([level](std::shared_ptr<spdlog::logger> l) {
|
|
382
|
+
if (l->name() == protocol_logger_name) {
|
|
383
|
+
l->set_level(spdlog::level::trace);
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
|
|
327
387
|
try {
|
|
328
388
|
l->set_level(level);
|
|
329
389
|
} catch (const spdlog::spdlog_ex& e) {
|
|
@@ -54,6 +54,17 @@ level_from_str(const std::string& str);
|
|
|
54
54
|
std::optional<std::string>
|
|
55
55
|
create_file_logger(const configuration& logger_settings);
|
|
56
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Protocol logger writes only communication logs with the nodes.
|
|
59
|
+
*
|
|
60
|
+
* It accepts the same settings as a file logger, and writes only to the filesystem.
|
|
61
|
+
*
|
|
62
|
+
* @param logger_settings
|
|
63
|
+
* @return
|
|
64
|
+
*/
|
|
65
|
+
std::optional<std::string>
|
|
66
|
+
create_protocol_logger(const configuration& logger_settings);
|
|
67
|
+
|
|
57
68
|
/**
|
|
58
69
|
* Initialize the logger with the blackhole logger object
|
|
59
70
|
*
|
|
@@ -144,6 +155,9 @@ set_log_levels(level lvl);
|
|
|
144
155
|
bool
|
|
145
156
|
should_log(level lvl);
|
|
146
157
|
|
|
158
|
+
bool
|
|
159
|
+
should_log_protocol();
|
|
160
|
+
|
|
147
161
|
namespace detail
|
|
148
162
|
{
|
|
149
163
|
/**
|
|
@@ -153,6 +167,9 @@ namespace detail
|
|
|
153
167
|
*/
|
|
154
168
|
void
|
|
155
169
|
log(const char* file, int line, const char* function, level lvl, std::string_view msg);
|
|
170
|
+
|
|
171
|
+
void
|
|
172
|
+
log_protocol(const char* file, int line, const char* function, std::string_view msg);
|
|
156
173
|
} // namespace detail
|
|
157
174
|
|
|
158
175
|
/**
|
|
@@ -168,6 +185,13 @@ log(const char* file, int line, const char* function, level lvl, const String& m
|
|
|
168
185
|
detail::log(file, line, function, lvl, fmt::format(msg, std::forward<Args>(args)...));
|
|
169
186
|
}
|
|
170
187
|
|
|
188
|
+
template<typename String, typename... Args>
|
|
189
|
+
inline void
|
|
190
|
+
log_protocol(const char* file, int line, const char* function, const String& msg, Args&&... args)
|
|
191
|
+
{
|
|
192
|
+
detail::log_protocol(file, line, function, fmt::format(msg, std::forward<Args>(args)...));
|
|
193
|
+
}
|
|
194
|
+
|
|
171
195
|
/**
|
|
172
196
|
* Tell the logger to flush its buffers
|
|
173
197
|
*/
|
|
@@ -214,6 +238,13 @@ is_initialized();
|
|
|
214
238
|
#define CB_LOG_CRITICAL(...) \
|
|
215
239
|
COUCHBASE_LOG(__FILE__, __LINE__, COUCHBASE_LOGGER_FUNCTION, couchbase::core::logger::level::critical, __VA_ARGS__)
|
|
216
240
|
|
|
241
|
+
#define CB_LOG_PROTOCOL(...) \
|
|
242
|
+
do { \
|
|
243
|
+
if (couchbase::core::logger::should_log_protocol()) { \
|
|
244
|
+
couchbase::core::logger::log_protocol(__FILE__, __LINE__, COUCHBASE_LOGGER_FUNCTION, __VA_ARGS__); \
|
|
245
|
+
} \
|
|
246
|
+
} while (false)
|
|
247
|
+
|
|
217
248
|
/**
|
|
218
249
|
* Convenience macros which log with the given level, and message, if the given
|
|
219
250
|
* level is currently enabled.
|
|
@@ -105,16 +105,19 @@ struct bucket_settings {
|
|
|
105
105
|
|
|
106
106
|
std::string name;
|
|
107
107
|
std::string uuid;
|
|
108
|
+
std::uint64_t ram_quota_mb{ 0 }; // If not explicitly set, defaults to 100 on create_bucket, unset on update_bucket
|
|
108
109
|
cluster::bucket_type bucket_type{ cluster::bucket_type::unknown };
|
|
109
|
-
std::
|
|
110
|
-
std::uint32_t max_expiry{ 0 };
|
|
110
|
+
std::optional<std::uint32_t> max_expiry{};
|
|
111
111
|
bucket_compression compression_mode{ bucket_compression::unknown };
|
|
112
112
|
std::optional<couchbase::durability_level> minimum_durability_level{};
|
|
113
|
-
std::uint32_t num_replicas{
|
|
114
|
-
bool replica_indexes{
|
|
115
|
-
bool flush_enabled{
|
|
113
|
+
std::optional<std::uint32_t> num_replicas{};
|
|
114
|
+
std::optional<bool> replica_indexes{};
|
|
115
|
+
std::optional<bool> flush_enabled{};
|
|
116
116
|
bucket_eviction_policy eviction_policy{ bucket_eviction_policy::unknown };
|
|
117
117
|
bucket_conflict_resolution conflict_resolution_type{ bucket_conflict_resolution::unknown };
|
|
118
|
+
std::optional<bool> history_retention_collection_default{};
|
|
119
|
+
std::optional<std::uint32_t> history_retention_bytes;
|
|
120
|
+
std::optional<std::uint32_t> history_retention_duration{};
|
|
118
121
|
|
|
119
122
|
/**
|
|
120
123
|
* UNCOMMITTED: This API may change in the future
|
|
@@ -33,10 +33,20 @@ struct traits<couchbase::core::management::cluster::bucket_settings> {
|
|
|
33
33
|
result.uuid = v.at("uuid").get_string();
|
|
34
34
|
const static std::uint64_t megabyte = 1024LLU * 1024LLU;
|
|
35
35
|
result.ram_quota_mb = v.at("quota").at("rawRAM").get_unsigned() / megabyte;
|
|
36
|
-
result.num_replicas = v.at("replicaNumber").template as<std::uint32_t
|
|
36
|
+
result.num_replicas = v.at("replicaNumber").template as<std::optional<std::uint32_t>>();
|
|
37
37
|
|
|
38
38
|
if (auto* max_ttl = v.find("maxTTL"); max_ttl != nullptr) {
|
|
39
|
-
result.max_expiry = max_ttl->template as<std::uint32_t
|
|
39
|
+
result.max_expiry = max_ttl->template as<std::optional<std::uint32_t>>();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (auto* history_retention_default = v.find("historyRetentionCollectionDefault"); history_retention_default != nullptr) {
|
|
43
|
+
result.history_retention_collection_default = history_retention_default->template as<std::optional<bool>>();
|
|
44
|
+
}
|
|
45
|
+
if (auto* history_retention_bytes = v.find("historyRetentionBytes"); history_retention_bytes != nullptr) {
|
|
46
|
+
result.history_retention_bytes = history_retention_bytes->template as<std::optional<std::uint32_t>>();
|
|
47
|
+
}
|
|
48
|
+
if (auto* history_retention_duration = v.find("historyRetentionSeconds"); history_retention_duration != nullptr) {
|
|
49
|
+
result.history_retention_duration = history_retention_duration->template as<std::optional<std::uint32_t>>();
|
|
40
50
|
}
|
|
41
51
|
|
|
42
52
|
if (auto& str = v.at("bucketType").get_string(); str == "couchbase" || str == "membase") {
|
|
@@ -29,3 +29,45 @@
|
|
|
29
29
|
* couchbase::core::meta::sdk_version() function is available
|
|
30
30
|
*/
|
|
31
31
|
#define COUCHBASE_CXX_CLIENT_HAS_SDK_SEMVER 1
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* couchbase::core::cluster_options and couchbase::security_options support
|
|
35
|
+
* passing TLS trust certificate by value
|
|
36
|
+
*/
|
|
37
|
+
#define COUCHBASE_CXX_CLIENT_CAN_PASS_TLS_TRUST_CERTIFICATE_BY_VALUE 1
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Range scan is available in the core
|
|
41
|
+
* couchbase::core::range_scan_orchestrator and relevant options in the core API
|
|
42
|
+
*/
|
|
43
|
+
#define COUCHBASE_CXX_CLIENT_CORE_HAS_RANGE_SCAN 1
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Query with reads from replica is available:
|
|
47
|
+
* - use_replica field in couchbase::core::operations::query_request
|
|
48
|
+
* - couchbase::query_options::use_replica()
|
|
49
|
+
*/
|
|
50
|
+
#define COUCHBASE_CXX_CLIENT_QUERY_READ_FROM_REPLICA 1
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Subdoc read from replica is available in the core
|
|
54
|
+
* couchbase::core::lookup_in_replica support
|
|
55
|
+
*/
|
|
56
|
+
#define COUCHBASE_CXX_CLIENT_CORE_HAS_SUBDOC_READ_REPLICA 1
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Collection management is accessible from the public API
|
|
60
|
+
* couchbase::bucket::collections() support
|
|
61
|
+
*/
|
|
62
|
+
#define COUCHBASE_CXX_CLIENT_HAS_PUBLIC_COLLECTION_MANAGEMENT 1
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Support for bucket no-deduplication feature in bucket and collection management
|
|
66
|
+
*/
|
|
67
|
+
#define COUCHBASE_CXX_CLIENT_HAS_BUCKET_NO_DEDUP 1
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Collection query index management is available in the public API
|
|
71
|
+
* couchbase::collection::query_indexes() support
|
|
72
|
+
*/
|
|
73
|
+
#define COUCHBASE_CXX_CLIENT_HAS_COLLECTION_QUERY_INDEX_MANAGEMENT 1
|
|
@@ -70,6 +70,9 @@ lookup_in_request::make_response(key_value_error_context&& ctx, const encoded_re
|
|
|
70
70
|
fields[i].status = res_entry.status;
|
|
71
71
|
fields[i].ec =
|
|
72
72
|
protocol::map_status_code(protocol::client_opcode::subdoc_multi_mutation, static_cast<std::uint16_t>(res_entry.status));
|
|
73
|
+
if (fields[i].opcode == protocol::subdoc_opcode::exists && fields[i].ec == errc::key_value::path_not_found) {
|
|
74
|
+
fields[i].ec.clear();
|
|
75
|
+
}
|
|
73
76
|
if (!fields[i].ec && !ctx.ec()) {
|
|
74
77
|
ec = fields[i].ec;
|
|
75
78
|
}
|
|
@@ -79,7 +82,11 @@ lookup_in_request::make_response(key_value_error_context&& ctx, const encoded_re
|
|
|
79
82
|
}
|
|
80
83
|
fields[i].exists =
|
|
81
84
|
res_entry.status == key_value_status_code::success || res_entry.status == key_value_status_code::subdoc_success_deleted;
|
|
82
|
-
fields[i].
|
|
85
|
+
if (fields[i].opcode == protocol::subdoc_opcode::exists && !fields[i].ec) {
|
|
86
|
+
fields[i].value = utils::json::generate_binary(fields[i].exists);
|
|
87
|
+
} else {
|
|
88
|
+
fields[i].value = utils::to_binary(res_entry.value);
|
|
89
|
+
}
|
|
83
90
|
}
|
|
84
91
|
if (!ec) {
|
|
85
92
|
cas = encoded.cas();
|
|
@@ -0,0 +1,192 @@
|
|
|
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 "core/error_context/key_value.hxx"
|
|
21
|
+
#include "core/impl/lookup_in_replica.hxx"
|
|
22
|
+
#include "core/impl/subdoc/command.hxx"
|
|
23
|
+
#include "core/operations/document_lookup_in.hxx"
|
|
24
|
+
#include "core/operations/operation_traits.hxx"
|
|
25
|
+
#include "core/utils/movable_function.hxx"
|
|
26
|
+
#include "couchbase/codec/encoded_value.hxx"
|
|
27
|
+
#include "couchbase/error_codes.hxx"
|
|
28
|
+
|
|
29
|
+
#include <functional>
|
|
30
|
+
#include <memory>
|
|
31
|
+
#include <mutex>
|
|
32
|
+
|
|
33
|
+
namespace couchbase::core::operations
|
|
34
|
+
{
|
|
35
|
+
struct lookup_in_all_replicas_response {
|
|
36
|
+
struct entry {
|
|
37
|
+
struct lookup_in_entry {
|
|
38
|
+
std::string path;
|
|
39
|
+
codec::binary value;
|
|
40
|
+
std::size_t original_index;
|
|
41
|
+
bool exists;
|
|
42
|
+
protocol::subdoc_opcode opcode;
|
|
43
|
+
key_value_status_code status;
|
|
44
|
+
std::error_code ec{};
|
|
45
|
+
};
|
|
46
|
+
std::vector<lookup_in_entry> fields{};
|
|
47
|
+
couchbase::cas cas{};
|
|
48
|
+
bool deleted{ false };
|
|
49
|
+
bool is_replica{ true };
|
|
50
|
+
};
|
|
51
|
+
subdocument_error_context ctx{};
|
|
52
|
+
std::vector<entry> entries{};
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
struct lookup_in_all_replicas_request {
|
|
56
|
+
using response_type = lookup_in_all_replicas_response;
|
|
57
|
+
using encoded_request_type = core::protocol::client_request<core::protocol::lookup_in_replica_request_body>;
|
|
58
|
+
using encoded_response_type = core::protocol::client_response<core::protocol::lookup_in_replica_response_body>;
|
|
59
|
+
|
|
60
|
+
core::document_id id;
|
|
61
|
+
std::vector<couchbase::core::impl::subdoc::command> specs{};
|
|
62
|
+
std::optional<std::chrono::milliseconds> timeout{};
|
|
63
|
+
std::shared_ptr<couchbase::tracing::request_span> parent_span{ nullptr };
|
|
64
|
+
|
|
65
|
+
template<typename Core, typename Handler>
|
|
66
|
+
void execute(Core core, Handler handler)
|
|
67
|
+
{
|
|
68
|
+
core->with_bucket_configuration(
|
|
69
|
+
id.bucket(),
|
|
70
|
+
[core, id = id, timeout = timeout, specs = specs, parent_span = parent_span, h = std::forward<Handler>(handler)](
|
|
71
|
+
std::error_code ec, const topology::configuration& config) mutable {
|
|
72
|
+
if (!config.supports_subdoc_read_replica()) {
|
|
73
|
+
ec = errc::common::feature_not_available;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (ec) {
|
|
77
|
+
std::optional<std::string> first_error_path{};
|
|
78
|
+
std::optional<std::size_t> first_error_index{};
|
|
79
|
+
return h(response_type{
|
|
80
|
+
make_subdocument_error_context(make_key_value_error_context(ec, id), ec, first_error_path, first_error_index, false) });
|
|
81
|
+
}
|
|
82
|
+
using handler_type = utils::movable_function<void(response_type)>;
|
|
83
|
+
|
|
84
|
+
struct replica_context {
|
|
85
|
+
replica_context(handler_type handler, std::uint32_t expected_responses)
|
|
86
|
+
: handler_(std::move(handler))
|
|
87
|
+
, expected_responses_(expected_responses)
|
|
88
|
+
{
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
handler_type handler_;
|
|
92
|
+
std::uint32_t expected_responses_;
|
|
93
|
+
bool done_{ false };
|
|
94
|
+
std::mutex mutex_{};
|
|
95
|
+
std::vector<lookup_in_all_replicas_response::entry> result_{};
|
|
96
|
+
};
|
|
97
|
+
auto ctx = std::make_shared<replica_context>(std::move(h), config.num_replicas.value_or(0U) + 1U);
|
|
98
|
+
|
|
99
|
+
for (std::size_t idx = 1U; idx <= config.num_replicas.value_or(0U); ++idx) {
|
|
100
|
+
document_id replica_id{ id };
|
|
101
|
+
replica_id.node_index(idx);
|
|
102
|
+
core->execute(impl::lookup_in_replica_request{ std::move(replica_id), specs, timeout, parent_span },
|
|
103
|
+
[ctx](impl::lookup_in_replica_response&& resp) {
|
|
104
|
+
handler_type local_handler{};
|
|
105
|
+
{
|
|
106
|
+
std::scoped_lock lock(ctx->mutex_);
|
|
107
|
+
if (ctx->done_) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
--ctx->expected_responses_;
|
|
111
|
+
if (resp.ctx.ec()) {
|
|
112
|
+
if (ctx->expected_responses_ > 0) {
|
|
113
|
+
// just ignore the response
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
} else {
|
|
117
|
+
lookup_in_all_replicas_response::entry top_entry{};
|
|
118
|
+
top_entry.cas = resp.cas;
|
|
119
|
+
top_entry.deleted = resp.deleted;
|
|
120
|
+
top_entry.is_replica = true;
|
|
121
|
+
for (auto& field : resp.fields) {
|
|
122
|
+
lookup_in_all_replicas_response::entry::lookup_in_entry lookup_in_entry{};
|
|
123
|
+
lookup_in_entry.path = field.path;
|
|
124
|
+
lookup_in_entry.value = field.value;
|
|
125
|
+
lookup_in_entry.status = field.status;
|
|
126
|
+
lookup_in_entry.ec = field.ec;
|
|
127
|
+
lookup_in_entry.exists = field.exists;
|
|
128
|
+
lookup_in_entry.original_index = field.original_index;
|
|
129
|
+
lookup_in_entry.opcode = field.opcode;
|
|
130
|
+
top_entry.fields.emplace_back(lookup_in_entry);
|
|
131
|
+
}
|
|
132
|
+
ctx->result_.emplace_back(lookup_in_all_replicas_response::entry{ top_entry });
|
|
133
|
+
}
|
|
134
|
+
if (ctx->expected_responses_ == 0) {
|
|
135
|
+
ctx->done_ = true;
|
|
136
|
+
std::swap(local_handler, ctx->handler_);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
if (local_handler) {
|
|
140
|
+
return local_handler({ std::move(resp.ctx), std::move(ctx->result_) });
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
core->execute(lookup_in_request{ document_id{ id }, {}, {}, false, specs, timeout }, [ctx](lookup_in_response&& resp) {
|
|
146
|
+
handler_type local_handler{};
|
|
147
|
+
{
|
|
148
|
+
std::scoped_lock lock(ctx->mutex_);
|
|
149
|
+
if (ctx->done_) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
--ctx->expected_responses_;
|
|
153
|
+
if (resp.ctx.ec()) {
|
|
154
|
+
if (ctx->expected_responses_ > 0) {
|
|
155
|
+
// just ignore the response
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
} else {
|
|
159
|
+
lookup_in_all_replicas_response::entry top_entry{};
|
|
160
|
+
top_entry.cas = resp.cas;
|
|
161
|
+
top_entry.deleted = resp.deleted;
|
|
162
|
+
top_entry.is_replica = false;
|
|
163
|
+
for (auto& field : resp.fields) {
|
|
164
|
+
lookup_in_all_replicas_response::entry::lookup_in_entry lookup_in_entry{};
|
|
165
|
+
lookup_in_entry.path = field.path;
|
|
166
|
+
lookup_in_entry.value = field.value;
|
|
167
|
+
lookup_in_entry.status = field.status;
|
|
168
|
+
lookup_in_entry.ec = field.ec;
|
|
169
|
+
lookup_in_entry.exists = field.exists;
|
|
170
|
+
lookup_in_entry.original_index = field.original_index;
|
|
171
|
+
lookup_in_entry.opcode = field.opcode;
|
|
172
|
+
top_entry.fields.emplace_back(lookup_in_entry);
|
|
173
|
+
}
|
|
174
|
+
ctx->result_.emplace_back(lookup_in_all_replicas_response::entry{ top_entry });
|
|
175
|
+
}
|
|
176
|
+
if (ctx->expected_responses_ == 0) {
|
|
177
|
+
ctx->done_ = true;
|
|
178
|
+
std::swap(local_handler, ctx->handler_);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
if (local_handler) {
|
|
182
|
+
return local_handler({ std::move(resp.ctx), std::move(ctx->result_) });
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
template<>
|
|
190
|
+
struct is_compound_operation<lookup_in_all_replicas_request> : public std::true_type {
|
|
191
|
+
};
|
|
192
|
+
} // namespace couchbase::core::operations
|