couchbase 3.4.3 → 3.4.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -379,7 +379,7 @@ class mcbp_session_impl
|
|
379
379
|
Expects(protocol::is_valid_server_request_opcode(msg.header.opcode));
|
380
380
|
switch (static_cast<protocol::server_opcode>(msg.header.opcode)) {
|
381
381
|
case protocol::server_opcode::cluster_map_change_notification: {
|
382
|
-
protocol::cmd_info info{ session_->
|
382
|
+
protocol::cmd_info info{ session_->bootstrap_hostname_, session_->bootstrap_port_number_ };
|
383
383
|
if (session_->origin_.options().dump_configuration) {
|
384
384
|
std::string_view config_text{ reinterpret_cast<const char*>(msg.body.data()), msg.body.size() };
|
385
385
|
CB_LOG_TRACE(
|
@@ -404,7 +404,7 @@ class mcbp_session_impl
|
|
404
404
|
CB_LOG_WARNING("{} unexpected server request: opcode={:x}, opaque={}{:a}{:a}",
|
405
405
|
session_->log_prefix_,
|
406
406
|
msg.header.opcode,
|
407
|
-
msg.header.opaque,
|
407
|
+
utils::byte_swap(msg.header.opaque),
|
408
408
|
spdlog::to_hex(msg.header_data()),
|
409
409
|
spdlog::to_hex(msg.body));
|
410
410
|
}
|
@@ -416,7 +416,7 @@ class mcbp_session_impl
|
|
416
416
|
session_->log_prefix_,
|
417
417
|
magic,
|
418
418
|
msg.header.opcode,
|
419
|
-
msg.header.opaque,
|
419
|
+
utils::byte_swap(msg.header.opaque),
|
420
420
|
spdlog::to_hex(msg.header_data()),
|
421
421
|
spdlog::to_hex(msg.body));
|
422
422
|
break;
|
@@ -473,7 +473,7 @@ class mcbp_session_impl
|
|
473
473
|
Expects(protocol::is_valid_client_opcode(msg.header.opcode));
|
474
474
|
switch (auto opcode = static_cast<protocol::client_opcode>(msg.header.opcode)) {
|
475
475
|
case protocol::client_opcode::get_cluster_config: {
|
476
|
-
protocol::cmd_info info{ session_->
|
476
|
+
protocol::cmd_info info{ session_->bootstrap_hostname_, session_->bootstrap_port_number_ };
|
477
477
|
if (session_->origin_.options().dump_configuration) {
|
478
478
|
std::string_view config_text{ reinterpret_cast<const char*>(msg.body.data()), msg.body.size() };
|
479
479
|
CB_LOG_TRACE("{} configuration from get_cluster_config response (size={}, endpoint=\"{}:{}\"), {}",
|
@@ -781,13 +781,10 @@ class mcbp_session_impl
|
|
781
781
|
return;
|
782
782
|
}
|
783
783
|
std::tie(bootstrap_hostname_, bootstrap_port_) = origin_.next_address();
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
bucket_name_.value_or("-"),
|
789
|
-
bootstrap_hostname_,
|
790
|
-
bootstrap_port_);
|
784
|
+
bootstrap_port_number_ = gsl::narrow_cast<std::uint16_t>(std::stoul(bootstrap_port_, nullptr, 10));
|
785
|
+
bootstrap_address_ = fmt::format("{}:{}", bootstrap_hostname_, bootstrap_port_);
|
786
|
+
log_prefix_ =
|
787
|
+
fmt::format("[{}/{}/{}/{}] <{}>", client_id_, id_, stream_->log_prefix(), bucket_name_.value_or("-"), bootstrap_address_);
|
791
788
|
CB_LOG_DEBUG("{} attempt to establish MCBP connection", log_prefix_);
|
792
789
|
|
793
790
|
async_resolve(origin_.options().use_ip_protocol,
|
@@ -807,7 +804,7 @@ class mcbp_session_impl
|
|
807
804
|
return stopped_;
|
808
805
|
}
|
809
806
|
|
810
|
-
void on_stop(utils::movable_function<void(
|
807
|
+
void on_stop(utils::movable_function<void()> handler)
|
811
808
|
{
|
812
809
|
on_stop_handler_ = std::move(handler);
|
813
810
|
}
|
@@ -863,7 +860,7 @@ class mcbp_session_impl
|
|
863
860
|
config_listeners_.clear();
|
864
861
|
state_ = diag::endpoint_state::disconnected;
|
865
862
|
if (auto on_stop = std::move(on_stop_handler_); on_stop) {
|
866
|
-
on_stop(
|
863
|
+
on_stop();
|
867
864
|
}
|
868
865
|
}
|
869
866
|
|
@@ -874,7 +871,7 @@ class mcbp_session_impl
|
|
874
871
|
}
|
875
872
|
std::uint32_t opaque{ 0 };
|
876
873
|
std::memcpy(&opaque, buf.data() + 12, sizeof(opaque));
|
877
|
-
CB_LOG_TRACE("{} MCBP send, opaque={}, {:n}", log_prefix_, opaque, spdlog::to_hex(buf.begin(), buf.begin() + 24));
|
874
|
+
CB_LOG_TRACE("{} MCBP send, opaque={}, {:n}", log_prefix_, utils::byte_swap(opaque), spdlog::to_hex(buf.begin(), buf.begin() + 24));
|
878
875
|
std::scoped_lock lock(output_buffer_mutex_);
|
879
876
|
output_buffer_.emplace_back(std::move(buf));
|
880
877
|
}
|
@@ -1058,6 +1055,11 @@ class mcbp_session_impl
|
|
1058
1055
|
return config_->index_for_this_node();
|
1059
1056
|
}
|
1060
1057
|
|
1058
|
+
[[nodiscard]] const std::string& bootstrap_address() const
|
1059
|
+
{
|
1060
|
+
return bootstrap_address_;
|
1061
|
+
}
|
1062
|
+
|
1061
1063
|
[[nodiscard]] const std::string& bootstrap_hostname() const
|
1062
1064
|
{
|
1063
1065
|
return bootstrap_hostname_;
|
@@ -1068,6 +1070,11 @@ class mcbp_session_impl
|
|
1068
1070
|
return bootstrap_port_;
|
1069
1071
|
}
|
1070
1072
|
|
1073
|
+
[[nodiscard]] std::uint16_t bootstrap_port_number() const
|
1074
|
+
{
|
1075
|
+
return bootstrap_port_number_;
|
1076
|
+
}
|
1077
|
+
|
1071
1078
|
[[nodiscard]] std::uint32_t next_opaque()
|
1072
1079
|
{
|
1073
1080
|
return ++opaque_;
|
@@ -1161,15 +1168,15 @@ class mcbp_session_impl
|
|
1161
1168
|
CB_LOG_TRACE("{} configuration from not_my_vbucket response (size={}, endpoint=\"{}:{}\"), {}",
|
1162
1169
|
log_prefix_,
|
1163
1170
|
config_text.size(),
|
1164
|
-
|
1165
|
-
|
1171
|
+
bootstrap_hostname_,
|
1172
|
+
bootstrap_port_number_,
|
1166
1173
|
config_text);
|
1167
1174
|
}
|
1168
|
-
auto config = protocol::parse_config(config_text,
|
1175
|
+
auto config = protocol::parse_config(config_text, bootstrap_hostname_, bootstrap_port_number_);
|
1169
1176
|
CB_LOG_DEBUG("{} received not_my_vbucket status for {}, opaque={} with config rev={} in the payload",
|
1170
1177
|
log_prefix_,
|
1171
1178
|
protocol::client_opcode(msg.header.opcode),
|
1172
|
-
msg.header.opaque,
|
1179
|
+
utils::byte_swap(msg.header.opaque),
|
1173
1180
|
config.rev_str());
|
1174
1181
|
update_configuration(std::move(config));
|
1175
1182
|
}
|
@@ -1204,6 +1211,12 @@ class mcbp_session_impl
|
|
1204
1211
|
CB_LOG_DEBUG(R"({} server returned {} ({}), it must be transient condition, retrying)", log_prefix_, ec.value(), ec.message());
|
1205
1212
|
return initiate_bootstrap();
|
1206
1213
|
}
|
1214
|
+
if (!origin_.exhausted() && ec == errc::common::authentication_failure) {
|
1215
|
+
CB_LOG_DEBUG(
|
1216
|
+
R"({} server returned authentication_failure, but the bootstrap list is not exhausted yet. It must be transient condition, retrying)",
|
1217
|
+
log_prefix_);
|
1218
|
+
return initiate_bootstrap();
|
1219
|
+
}
|
1207
1220
|
|
1208
1221
|
if (!bootstrapped_ && bootstrap_callback_) {
|
1209
1222
|
bootstrap_deadline_.cancel();
|
@@ -1266,16 +1279,15 @@ class mcbp_session_impl
|
|
1266
1279
|
}
|
1267
1280
|
last_active_ = std::chrono::steady_clock::now();
|
1268
1281
|
if (it != endpoints_.end()) {
|
1269
|
-
|
1270
|
-
|
1271
|
-
|
1272
|
-
it->endpoint().port(),
|
1273
|
-
origin_.options().connect_timeout.count());
|
1282
|
+
auto hostname = it->endpoint().address().to_string();
|
1283
|
+
auto port = it->endpoint().port();
|
1284
|
+
CB_LOG_DEBUG("{} connecting to {}:{}, timeout={}ms", log_prefix_, hostname, port, origin_.options().connect_timeout.count());
|
1274
1285
|
connection_deadline_.expires_after(origin_.options().connect_timeout);
|
1275
|
-
connection_deadline_.async_wait([self = shared_from_this()](const auto timer_ec) {
|
1286
|
+
connection_deadline_.async_wait([self = shared_from_this(), hostname, port](const auto timer_ec) {
|
1276
1287
|
if (timer_ec == asio::error::operation_aborted || self->stopped_) {
|
1277
1288
|
return;
|
1278
1289
|
}
|
1290
|
+
CB_LOG_DEBUG("{} unable to connect to {}:{} in time, reconnecting", self->log_prefix_, hostname, port);
|
1279
1291
|
return self->stream_->close([self](std::error_code) { self->initiate_bootstrap(); });
|
1280
1292
|
});
|
1281
1293
|
stream_->async_connect(it->endpoint(),
|
@@ -1353,7 +1365,20 @@ class mcbp_session_impl
|
|
1353
1365
|
asio::buffer(input_buffer_),
|
1354
1366
|
[self = shared_from_this(), stream_id = stream_->id()](std::error_code ec, std::size_t bytes_transferred) {
|
1355
1367
|
if (ec == asio::error::operation_aborted || self->stopped_) {
|
1368
|
+
CB_LOG_PROTOCOL("[MCBP, IN] host=\"{}\", port={}, rc={}, bytes_received={}",
|
1369
|
+
self->endpoint_address_,
|
1370
|
+
self->endpoint_.port(),
|
1371
|
+
ec ? ec.message() : "ok",
|
1372
|
+
bytes_transferred);
|
1356
1373
|
return;
|
1374
|
+
} else {
|
1375
|
+
CB_LOG_PROTOCOL("[MCBP, IN] host=\"{}\", port={}, rc={}, bytes_received={}{:a}",
|
1376
|
+
self->endpoint_address_,
|
1377
|
+
self->endpoint_.port(),
|
1378
|
+
ec ? ec.message() : "ok",
|
1379
|
+
bytes_transferred,
|
1380
|
+
spdlog::to_hex(self->input_buffer_.data(),
|
1381
|
+
self->input_buffer_.data() + static_cast<std::ptrdiff_t>(bytes_transferred)));
|
1357
1382
|
}
|
1358
1383
|
self->last_active_ = std::chrono::steady_clock::now();
|
1359
1384
|
if (ec) {
|
@@ -1382,8 +1407,10 @@ class mcbp_session_impl
|
|
1382
1407
|
if (self->stopped_) {
|
1383
1408
|
return;
|
1384
1409
|
}
|
1385
|
-
CB_LOG_TRACE(
|
1386
|
-
|
1410
|
+
CB_LOG_TRACE("{} MCBP recv, opaque={}, {:n}",
|
1411
|
+
self->log_prefix_,
|
1412
|
+
utils::byte_swap(msg.header.opaque),
|
1413
|
+
spdlog::to_hex(msg.header_data()));
|
1387
1414
|
if (self->bootstrapped_) {
|
1388
1415
|
self->handler_->handle(std::move(msg));
|
1389
1416
|
} else {
|
@@ -1419,13 +1446,21 @@ class mcbp_session_impl
|
|
1419
1446
|
std::vector<asio::const_buffer> buffers;
|
1420
1447
|
buffers.reserve(writing_buffer_.size());
|
1421
1448
|
for (auto& buf : writing_buffer_) {
|
1449
|
+
CB_LOG_PROTOCOL(
|
1450
|
+
"[MCBP, OUT] host=\"{}\", port={}, buffer_size={}{:a}", endpoint_address_, endpoint_.port(), buf.size(), spdlog::to_hex(buf));
|
1422
1451
|
buffers.emplace_back(asio::buffer(buf));
|
1423
1452
|
}
|
1424
|
-
stream_->async_write(buffers, [self = shared_from_this()](std::error_code ec, std::size_t
|
1453
|
+
stream_->async_write(buffers, [self = shared_from_this()](std::error_code ec, std::size_t bytes_transferred) {
|
1454
|
+
CB_LOG_PROTOCOL("[MCBP, OUT] host=\"{}\", port={}, rc={}, bytes_sent={}",
|
1455
|
+
self->endpoint_address_,
|
1456
|
+
self->endpoint_.port(),
|
1457
|
+
ec ? ec.message() : "ok",
|
1458
|
+
bytes_transferred);
|
1425
1459
|
if (ec == asio::error::operation_aborted || self->stopped_) {
|
1426
1460
|
return;
|
1427
1461
|
}
|
1428
1462
|
self->last_active_ = std::chrono::steady_clock::now();
|
1463
|
+
|
1429
1464
|
if (ec) {
|
1430
1465
|
CB_LOG_ERROR(R"({} IO error while writing to the socket("{}"): {} ({}))",
|
1431
1466
|
self->log_prefix_,
|
@@ -1462,7 +1497,7 @@ class mcbp_session_impl
|
|
1462
1497
|
std::mutex command_handlers_mutex_{};
|
1463
1498
|
std::map<std::uint32_t, command_handler> command_handlers_{};
|
1464
1499
|
std::vector<std::shared_ptr<config_listener>> config_listeners_{};
|
1465
|
-
utils::movable_function<void(
|
1500
|
+
utils::movable_function<void()> on_stop_handler_{};
|
1466
1501
|
|
1467
1502
|
std::atomic_bool bootstrapped_{ false };
|
1468
1503
|
std::atomic_bool stopped_{ false };
|
@@ -1482,6 +1517,8 @@ class mcbp_session_impl
|
|
1482
1517
|
std::mutex writing_buffer_mutex_{};
|
1483
1518
|
std::string bootstrap_hostname_{};
|
1484
1519
|
std::string bootstrap_port_{};
|
1520
|
+
std::string bootstrap_address_{};
|
1521
|
+
std::uint16_t bootstrap_port_number_{};
|
1485
1522
|
asio::ip::tcp::endpoint endpoint_{}; // connected endpoint
|
1486
1523
|
std::string endpoint_address_{}; // cached string with endpoint address
|
1487
1524
|
asio::ip::tcp::endpoint local_endpoint_{};
|
@@ -1582,22 +1619,16 @@ mcbp_session::supports_feature(protocol::hello_feature feature)
|
|
1582
1619
|
return impl_->supports_feature(feature);
|
1583
1620
|
}
|
1584
1621
|
|
1585
|
-
|
1586
|
-
// mcbp_session::id() const
|
1587
|
-
// {
|
1588
|
-
// return impl_->id();
|
1589
|
-
// }
|
1590
|
-
std::string
|
1622
|
+
const std::string&
|
1591
1623
|
mcbp_session::id() const
|
1592
1624
|
{
|
1593
|
-
|
1594
|
-
|
1595
|
-
|
1596
|
-
|
1597
|
-
|
1598
|
-
|
1599
|
-
|
1600
|
-
return fmt::format("{}, nullptr", reinterpret_cast<const void*>(this));
|
1625
|
+
return impl_->id();
|
1626
|
+
}
|
1627
|
+
|
1628
|
+
const std::string&
|
1629
|
+
mcbp_session::bootstrap_address() const
|
1630
|
+
{
|
1631
|
+
return impl_->bootstrap_address();
|
1601
1632
|
}
|
1602
1633
|
|
1603
1634
|
std::string
|
@@ -1624,6 +1655,12 @@ mcbp_session::bootstrap_port() const
|
|
1624
1655
|
return impl_->bootstrap_port();
|
1625
1656
|
}
|
1626
1657
|
|
1658
|
+
std::uint16_t
|
1659
|
+
mcbp_session::bootstrap_port_number() const
|
1660
|
+
{
|
1661
|
+
return impl_->bootstrap_port_number();
|
1662
|
+
}
|
1663
|
+
|
1627
1664
|
void
|
1628
1665
|
mcbp_session::write_and_subscribe(std::uint32_t opaque, std::vector<std::byte>&& data, command_handler&& handler)
|
1629
1666
|
{
|
@@ -1637,7 +1674,7 @@ mcbp_session::bootstrap(utils::movable_function<void(std::error_code, topology::
|
|
1637
1674
|
}
|
1638
1675
|
|
1639
1676
|
void
|
1640
|
-
mcbp_session::on_stop(utils::movable_function<void(
|
1677
|
+
mcbp_session::on_stop(utils::movable_function<void()> handler)
|
1641
1678
|
{
|
1642
1679
|
return impl_->on_stop(std::move(handler));
|
1643
1680
|
}
|
@@ -101,17 +101,18 @@ class mcbp_session
|
|
101
101
|
[[nodiscard]] mcbp_context context() const;
|
102
102
|
[[nodiscard]] bool supports_feature(protocol::hello_feature feature);
|
103
103
|
[[nodiscard]] std::vector<protocol::hello_feature> supported_features() const;
|
104
|
-
|
105
|
-
[[nodiscard]] std::string id() const;
|
104
|
+
[[nodiscard]] const std::string& id() const;
|
106
105
|
[[nodiscard]] std::string remote_address() const;
|
107
106
|
[[nodiscard]] std::string local_address() const;
|
107
|
+
[[nodiscard]] const std::string& bootstrap_address() const;
|
108
108
|
[[nodiscard]] const std::string& bootstrap_hostname() const;
|
109
109
|
[[nodiscard]] const std::string& bootstrap_port() const;
|
110
|
+
[[nodiscard]] std::uint16_t bootstrap_port_number() const;
|
110
111
|
void write_and_subscribe(std::shared_ptr<mcbp::queue_request>, std::shared_ptr<response_handler> handler);
|
111
112
|
void write_and_subscribe(std::uint32_t opaque, std::vector<std::byte>&& data, command_handler&& handler);
|
112
113
|
void bootstrap(utils::movable_function<void(std::error_code, topology::configuration)>&& handler,
|
113
114
|
bool retry_on_bucket_not_found = false);
|
114
|
-
void on_stop(utils::movable_function<void(
|
115
|
+
void on_stop(utils::movable_function<void()> handler);
|
115
116
|
void stop(retry_reason reason);
|
116
117
|
[[nodiscard]] std::size_t index() const;
|
117
118
|
[[nodiscard]] bool has_config() const;
|
@@ -127,7 +127,7 @@ custom_rotating_file_sink<Mutex>::add_hook(const std::string& hook)
|
|
127
127
|
|
128
128
|
// Payload shouldn't contain anything yet, overwrite it
|
129
129
|
Expects(msg.payload.size() == 0);
|
130
|
-
msg.payload =
|
130
|
+
msg.payload = hookToAdd;
|
131
131
|
|
132
132
|
spdlog::memory_buf_t formatted;
|
133
133
|
formatter->format(msg, formatted);
|
@@ -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.
|
@@ -29,3 +29,28 @@
|
|
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
|