couchbase 3.0.1 → 3.0.2
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 +73 -4
- data/ext/build_config.hxx.in +2 -0
- data/ext/build_version.hxx.in +11 -8
- data/ext/cmake/BuildTracing.cmake +1 -1
- data/ext/cmake/CompilerWarnings.cmake +5 -0
- data/ext/cmake/Testing.cmake +3 -6
- data/ext/couchbase/bucket.hxx +9 -1
- data/ext/couchbase/cbsasl/client.h +1 -1
- data/ext/couchbase/cluster.hxx +89 -6
- data/ext/couchbase/configuration.hxx +2 -0
- data/ext/couchbase/couchbase.cxx +1647 -507
- data/ext/couchbase/diagnostics.hxx +0 -3
- data/ext/couchbase/io/dns_client.hxx +2 -2
- data/ext/couchbase/io/http_command.hxx +6 -3
- data/ext/couchbase/io/http_session.hxx +14 -18
- data/ext/couchbase/io/http_session_manager.hxx +83 -2
- data/ext/couchbase/io/mcbp_command.hxx +4 -1
- data/ext/couchbase/io/mcbp_context.hxx +37 -0
- data/ext/couchbase/io/mcbp_session.hxx +91 -30
- data/ext/couchbase/operations.hxx +5 -0
- data/ext/couchbase/operations/analytics_dataset_create.hxx +3 -2
- data/ext/couchbase/operations/analytics_dataset_drop.hxx +3 -2
- data/ext/couchbase/operations/analytics_dataset_get_all.hxx +3 -2
- data/ext/couchbase/operations/analytics_dataverse_create.hxx +3 -2
- data/ext/couchbase/operations/analytics_dataverse_drop.hxx +3 -2
- data/ext/couchbase/operations/analytics_get_pending_mutations.hxx +3 -2
- data/ext/couchbase/operations/analytics_index_create.hxx +3 -2
- data/ext/couchbase/operations/analytics_index_drop.hxx +3 -2
- data/ext/couchbase/operations/analytics_index_get_all.hxx +5 -2
- data/ext/couchbase/operations/analytics_link_connect.hxx +3 -2
- data/ext/couchbase/operations/analytics_link_disconnect.hxx +3 -2
- data/ext/couchbase/operations/bucket_create.hxx +3 -2
- data/ext/couchbase/operations/bucket_drop.hxx +3 -2
- data/ext/couchbase/operations/bucket_flush.hxx +3 -2
- data/ext/couchbase/operations/bucket_get.hxx +3 -2
- data/ext/couchbase/operations/bucket_get_all.hxx +3 -2
- data/ext/couchbase/operations/bucket_update.hxx +3 -2
- data/ext/couchbase/operations/cluster_developer_preview_enable.hxx +3 -2
- data/ext/couchbase/operations/collection_create.hxx +3 -2
- data/ext/couchbase/operations/collection_drop.hxx +3 -2
- data/ext/couchbase/operations/collections_manifest_get.hxx +3 -2
- data/ext/couchbase/operations/document_analytics.hxx +3 -2
- data/ext/couchbase/operations/document_append.hxx +77 -0
- data/ext/couchbase/operations/document_decrement.hxx +3 -2
- data/ext/couchbase/operations/document_exists.hxx +3 -2
- data/ext/couchbase/operations/document_get.hxx +3 -2
- data/ext/couchbase/operations/document_get_and_lock.hxx +3 -2
- data/ext/couchbase/operations/document_get_and_touch.hxx +3 -2
- data/ext/couchbase/operations/document_get_projected.hxx +3 -2
- data/ext/couchbase/operations/document_increment.hxx +3 -2
- data/ext/couchbase/operations/document_insert.hxx +3 -2
- data/ext/couchbase/operations/document_lookup_in.hxx +8 -2
- data/ext/couchbase/operations/document_mutate_in.hxx +13 -2
- data/ext/couchbase/operations/document_prepend.hxx +77 -0
- data/ext/couchbase/operations/document_query.hxx +3 -2
- data/ext/couchbase/operations/document_remove.hxx +5 -2
- data/ext/couchbase/operations/document_replace.hxx +3 -2
- data/ext/couchbase/operations/document_search.hxx +3 -2
- data/ext/couchbase/operations/document_touch.hxx +3 -2
- data/ext/couchbase/operations/document_unlock.hxx +3 -2
- data/ext/couchbase/operations/document_upsert.hxx +3 -2
- data/ext/couchbase/operations/document_view.hxx +3 -2
- data/ext/couchbase/operations/group_drop.hxx +3 -2
- data/ext/couchbase/operations/group_get.hxx +3 -2
- data/ext/couchbase/operations/group_get_all.hxx +3 -2
- data/ext/couchbase/operations/group_upsert.hxx +3 -2
- data/ext/couchbase/operations/http_noop.hxx +78 -0
- data/ext/couchbase/operations/mcbp_noop.hxx +61 -0
- data/ext/couchbase/operations/query_index_build_deferred.hxx +3 -2
- data/ext/couchbase/operations/query_index_create.hxx +3 -2
- data/ext/couchbase/operations/query_index_drop.hxx +3 -2
- data/ext/couchbase/operations/query_index_get_all.hxx +3 -2
- data/ext/couchbase/operations/role_get_all.hxx +3 -2
- data/ext/couchbase/operations/scope_create.hxx +3 -2
- data/ext/couchbase/operations/scope_drop.hxx +3 -2
- data/ext/couchbase/operations/scope_get_all.hxx +3 -2
- data/ext/couchbase/operations/search_get_stats.hxx +3 -2
- data/ext/couchbase/operations/search_index_analyze_document.hxx +3 -2
- data/ext/couchbase/operations/search_index_control_ingest.hxx +3 -2
- data/ext/couchbase/operations/search_index_control_plan_freeze.hxx +3 -2
- data/ext/couchbase/operations/search_index_control_query.hxx +3 -2
- data/ext/couchbase/operations/search_index_drop.hxx +3 -2
- data/ext/couchbase/operations/search_index_get.hxx +3 -2
- data/ext/couchbase/operations/search_index_get_all.hxx +3 -2
- data/ext/couchbase/operations/search_index_get_documents_count.hxx +3 -2
- data/ext/couchbase/operations/search_index_get_stats.hxx +3 -2
- data/ext/couchbase/operations/search_index_upsert.hxx +3 -2
- data/ext/couchbase/operations/user_drop.hxx +3 -2
- data/ext/couchbase/operations/user_get.hxx +3 -2
- data/ext/couchbase/operations/user_get_all.hxx +3 -2
- data/ext/couchbase/operations/user_upsert.hxx +3 -2
- data/ext/couchbase/operations/view_index_drop.hxx +3 -2
- data/ext/couchbase/operations/view_index_get.hxx +3 -2
- data/ext/couchbase/operations/view_index_get_all.hxx +3 -2
- data/ext/couchbase/operations/view_index_upsert.hxx +3 -2
- data/ext/couchbase/platform/terminate_handler.cc +5 -2
- data/ext/couchbase/protocol/client_opcode.hxx +368 -0
- data/ext/couchbase/protocol/cmd_append.hxx +145 -0
- data/ext/couchbase/protocol/cmd_hello.hxx +1 -0
- data/ext/couchbase/protocol/cmd_lookup_in.hxx +11 -3
- data/ext/couchbase/protocol/cmd_mutate_in.hxx +46 -4
- data/ext/couchbase/protocol/cmd_noop.hxx +82 -0
- data/ext/couchbase/protocol/cmd_prepend.hxx +145 -0
- data/ext/couchbase/protocol/durability_level.hxx +16 -0
- data/ext/couchbase/protocol/hello_feature.hxx +9 -0
- data/ext/couchbase/protocol/unsigned_leb128.h +2 -2
- data/ext/couchbase/service_type.hxx +1 -1
- data/ext/couchbase/version.hxx +18 -4
- data/ext/extconf.rb +9 -6
- data/ext/test/CMakeLists.txt +5 -0
- data/ext/test/test_helper.hxx +3 -3
- data/ext/test/test_helper_native.hxx +2 -5
- data/ext/test/test_native_binary_operations.cxx +186 -0
- data/ext/test/test_native_diagnostics.cxx +54 -3
- data/ext/test/test_ruby_trivial_crud.cxx +1 -1
- data/lib/couchbase.rb +1 -0
- data/lib/couchbase/analytics_options.rb +1 -71
- data/lib/couchbase/binary_collection.rb +60 -22
- data/lib/couchbase/binary_collection_options.rb +0 -76
- data/lib/couchbase/bucket.rb +40 -36
- data/lib/couchbase/cluster.rb +89 -156
- data/lib/couchbase/collection.rb +290 -72
- data/lib/couchbase/collection_options.rb +30 -243
- data/lib/couchbase/datastructures/couchbase_list.rb +5 -16
- data/lib/couchbase/datastructures/couchbase_map.rb +5 -16
- data/lib/couchbase/datastructures/couchbase_queue.rb +5 -16
- data/lib/couchbase/datastructures/couchbase_set.rb +5 -16
- data/lib/couchbase/diagnostics.rb +181 -0
- data/lib/couchbase/json_transcoder.rb +1 -1
- data/lib/couchbase/{common_options.rb → logger.rb} +24 -11
- data/lib/couchbase/management/query_index_manager.rb +1 -1
- data/lib/couchbase/management/user_manager.rb +3 -0
- data/lib/couchbase/options.rb +2094 -0
- data/lib/couchbase/query_options.rb +1 -144
- data/lib/couchbase/scope.rb +8 -25
- data/lib/couchbase/search_options.rb +0 -93
- data/lib/couchbase/version.rb +20 -1
- data/lib/couchbase/view_options.rb +1 -91
- metadata +19 -7
|
@@ -90,7 +90,6 @@ struct endpoint_ping_info {
|
|
|
90
90
|
struct ping_result {
|
|
91
91
|
std::string id;
|
|
92
92
|
std::string sdk;
|
|
93
|
-
std::uint64_t config_rev;
|
|
94
93
|
std::map<service_type, std::vector<endpoint_ping_info>> services{};
|
|
95
94
|
|
|
96
95
|
const int version{ 2 };
|
|
@@ -242,8 +241,6 @@ struct traits<couchbase::diag::ping_result> {
|
|
|
242
241
|
{ "version", r.version },
|
|
243
242
|
{ "id", r.id },
|
|
244
243
|
{ "sdk", r.sdk },
|
|
245
|
-
/* the highest known configuration revision */
|
|
246
|
-
{ "config_rev", r.config_rev },
|
|
247
244
|
{ "services", services },
|
|
248
245
|
};
|
|
249
246
|
}
|
|
@@ -109,7 +109,7 @@ class dns_client
|
|
|
109
109
|
resp.targets.emplace_back(
|
|
110
110
|
dns_srv_response::address{ fmt::format("{}", fmt::join(answer.target.labels, ".")), answer.port });
|
|
111
111
|
}
|
|
112
|
-
return handler(resp);
|
|
112
|
+
return handler(std::move(resp));
|
|
113
113
|
});
|
|
114
114
|
});
|
|
115
115
|
deadline_.expires_after(timeout);
|
|
@@ -179,7 +179,7 @@ class dns_client
|
|
|
179
179
|
resp.targets.emplace_back(dns_srv_response::address{
|
|
180
180
|
fmt::format("{}", fmt::join(answer.target.labels, ".")), answer.port });
|
|
181
181
|
}
|
|
182
|
-
return handler(resp);
|
|
182
|
+
return handler(std::move(resp));
|
|
183
183
|
});
|
|
184
184
|
});
|
|
185
185
|
});
|
|
@@ -41,8 +41,11 @@ struct http_command : public std::enable_shared_from_this<http_command<Request>>
|
|
|
41
41
|
template<typename Handler>
|
|
42
42
|
void send_to(std::shared_ptr<io::http_session> session, Handler&& handler)
|
|
43
43
|
{
|
|
44
|
-
encoded.type =
|
|
45
|
-
request.encode_to(encoded, session->http_context());
|
|
44
|
+
encoded.type = request.type;
|
|
45
|
+
auto encoding_ec = request.encode_to(encoded, session->http_context());
|
|
46
|
+
if (encoding_ec) {
|
|
47
|
+
return handler(make_response(encoding_ec, request, {}));
|
|
48
|
+
}
|
|
46
49
|
encoded.headers["client-context-id"] = request.client_context_id;
|
|
47
50
|
auto log_prefix = session->log_prefix();
|
|
48
51
|
spdlog::trace(R"({} HTTP request: {}, method={}, path="{}", client_context_id="{}", timeout={}ms)",
|
|
@@ -77,7 +80,7 @@ struct http_command : public std::enable_shared_from_this<http_command<Request>>
|
|
|
77
80
|
resp.status_code,
|
|
78
81
|
spdlog::to_hex(resp.body));
|
|
79
82
|
try {
|
|
80
|
-
handler(make_response(ec, self->request,
|
|
83
|
+
handler(make_response(ec, self->request, std::move(msg)));
|
|
81
84
|
} catch (priv::retry_http_request) {
|
|
82
85
|
self->send_to(session, std::forward<Handler>(handler));
|
|
83
86
|
}
|
|
@@ -60,14 +60,7 @@ class http_session : public std::enable_shared_from_this<http_session>
|
|
|
60
60
|
, credentials_(credentials)
|
|
61
61
|
, hostname_(hostname)
|
|
62
62
|
, service_(service)
|
|
63
|
-
, user_agent_(fmt::format("
|
|
64
|
-
BACKEND_VERSION_MAJOR,
|
|
65
|
-
BACKEND_VERSION_MINOR,
|
|
66
|
-
BACKEND_VERSION_PATCH,
|
|
67
|
-
BACKEND_GIT_REVISION,
|
|
68
|
-
client_id_,
|
|
69
|
-
id_,
|
|
70
|
-
BACKEND_SYSTEM))
|
|
63
|
+
, user_agent_(fmt::format("{}; client/{}; session/{}; {}", couchbase::sdk_id(), client_id_, id_, BACKEND_SYSTEM))
|
|
71
64
|
, log_prefix_(fmt::format("[{}/{}]", client_id_, id_))
|
|
72
65
|
, http_ctx_(std::move(http_ctx))
|
|
73
66
|
{
|
|
@@ -92,14 +85,7 @@ class http_session : public std::enable_shared_from_this<http_session>
|
|
|
92
85
|
, credentials_(credentials)
|
|
93
86
|
, hostname_(hostname)
|
|
94
87
|
, service_(service)
|
|
95
|
-
, user_agent_(fmt::format("
|
|
96
|
-
BACKEND_VERSION_MAJOR,
|
|
97
|
-
BACKEND_VERSION_MINOR,
|
|
98
|
-
BACKEND_VERSION_PATCH,
|
|
99
|
-
BACKEND_GIT_REVISION,
|
|
100
|
-
client_id_,
|
|
101
|
-
id_,
|
|
102
|
-
BACKEND_SYSTEM))
|
|
88
|
+
, user_agent_(fmt::format("{}; client/{}; session/{}; {}", couchbase::sdk_id(), client_id_, id_, BACKEND_SYSTEM))
|
|
103
89
|
, log_prefix_(fmt::format("[{}/{}]", client_id_, id_))
|
|
104
90
|
, http_ctx_(std::move(http_ctx))
|
|
105
91
|
{
|
|
@@ -115,6 +101,16 @@ class http_session : public std::enable_shared_from_this<http_session>
|
|
|
115
101
|
return http_ctx_;
|
|
116
102
|
}
|
|
117
103
|
|
|
104
|
+
std::string remote_address() const
|
|
105
|
+
{
|
|
106
|
+
return fmt::format("{}:{}", endpoint_address_, endpoint_.port());
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
std::string local_address() const
|
|
110
|
+
{
|
|
111
|
+
return fmt::format("{}:{}", local_endpoint_address_, local_endpoint_.port());
|
|
112
|
+
}
|
|
113
|
+
|
|
118
114
|
[[nodiscard]] diag::endpoint_diag_info diag_info() const
|
|
119
115
|
{
|
|
120
116
|
return { type_,
|
|
@@ -122,8 +118,8 @@ class http_session : public std::enable_shared_from_this<http_session>
|
|
|
122
118
|
last_active_.time_since_epoch().count() == 0 ? std::nullopt
|
|
123
119
|
: std::make_optional(std::chrono::duration_cast<std::chrono::microseconds>(
|
|
124
120
|
std::chrono::steady_clock::now() - last_active_)),
|
|
125
|
-
|
|
126
|
-
|
|
121
|
+
remote_address(),
|
|
122
|
+
local_address(),
|
|
127
123
|
state_ };
|
|
128
124
|
}
|
|
129
125
|
|
|
@@ -20,6 +20,8 @@
|
|
|
20
20
|
#include <io/http_session.hxx>
|
|
21
21
|
#include <service_type.hxx>
|
|
22
22
|
#include <io/http_context.hxx>
|
|
23
|
+
#include <operations/http_noop.hxx>
|
|
24
|
+
#include <io/http_command.hxx>
|
|
23
25
|
|
|
24
26
|
#include <random>
|
|
25
27
|
|
|
@@ -55,12 +57,91 @@ class http_session_manager : public std::enable_shared_from_this<http_session_ma
|
|
|
55
57
|
|
|
56
58
|
for (const auto& list : busy_sessions_) {
|
|
57
59
|
for (const auto& session : list.second) {
|
|
58
|
-
|
|
60
|
+
if (session) {
|
|
61
|
+
res.services[list.first].emplace_back(session->diag_info());
|
|
62
|
+
}
|
|
59
63
|
}
|
|
60
64
|
}
|
|
61
65
|
for (const auto& list : idle_sessions_) {
|
|
62
66
|
for (const auto& session : list.second) {
|
|
63
|
-
|
|
67
|
+
if (session) {
|
|
68
|
+
res.services[list.first].emplace_back(session->diag_info());
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
template<typename Collector>
|
|
75
|
+
void ping(std::set<service_type> services, std::shared_ptr<Collector> collector, const couchbase::cluster_credentials& credentials)
|
|
76
|
+
{
|
|
77
|
+
std::array<service_type, 4> known_types{ service_type::query, service_type::analytics, service_type::search, service_type::views };
|
|
78
|
+
for (auto& node : config_.nodes) {
|
|
79
|
+
for (auto type : known_types) {
|
|
80
|
+
if (services.find(type) == services.end()) {
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
std::uint16_t port = 0;
|
|
84
|
+
port = node.port_or(options_.network, type, options_.enable_tls, 0);
|
|
85
|
+
if (port != 0) {
|
|
86
|
+
std::scoped_lock lock(sessions_mutex_);
|
|
87
|
+
std::shared_ptr<http_session> session;
|
|
88
|
+
session = options_.enable_tls ? std::make_shared<http_session>(type,
|
|
89
|
+
client_id_,
|
|
90
|
+
ctx_,
|
|
91
|
+
tls_,
|
|
92
|
+
credentials,
|
|
93
|
+
node.hostname_for(options_.network),
|
|
94
|
+
std::to_string(port),
|
|
95
|
+
http_context{ config_, options_, query_cache_ })
|
|
96
|
+
: std::make_shared<http_session>(type,
|
|
97
|
+
client_id_,
|
|
98
|
+
ctx_,
|
|
99
|
+
credentials,
|
|
100
|
+
node.hostname_for(options_.network),
|
|
101
|
+
std::to_string(port),
|
|
102
|
+
http_context{ config_, options_, query_cache_ });
|
|
103
|
+
session->start();
|
|
104
|
+
session->on_stop([type, id = session->id(), self = this->shared_from_this()]() {
|
|
105
|
+
for (auto& s : self->busy_sessions_[type]) {
|
|
106
|
+
if (s && s->id() == id) {
|
|
107
|
+
s.reset();
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
for (auto& s : self->idle_sessions_[type]) {
|
|
111
|
+
if (s && s->id() == id) {
|
|
112
|
+
s.reset();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
busy_sessions_[type].push_back(session);
|
|
117
|
+
operations::http_noop_request request{};
|
|
118
|
+
request.type = type;
|
|
119
|
+
auto cmd = std::make_shared<operations::http_command<operations::http_noop_request>>(ctx_, request);
|
|
120
|
+
cmd->send_to(session,
|
|
121
|
+
[start = std::chrono::steady_clock::now(),
|
|
122
|
+
self = shared_from_this(),
|
|
123
|
+
type,
|
|
124
|
+
session,
|
|
125
|
+
handler = collector->build_reporter()](operations::http_noop_response&& resp) mutable {
|
|
126
|
+
diag::ping_state state = diag::ping_state::ok;
|
|
127
|
+
std::optional<std::string> error{};
|
|
128
|
+
if (resp.ec) {
|
|
129
|
+
state = diag::ping_state::error;
|
|
130
|
+
error.emplace(fmt::format(
|
|
131
|
+
"code={}, message={}, http_code={}", resp.ec.value(), resp.ec.message(), resp.status_code));
|
|
132
|
+
}
|
|
133
|
+
handler(diag::endpoint_ping_info{
|
|
134
|
+
type,
|
|
135
|
+
session->id(),
|
|
136
|
+
std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - start),
|
|
137
|
+
session->remote_address(),
|
|
138
|
+
session->local_address(),
|
|
139
|
+
state,
|
|
140
|
+
{},
|
|
141
|
+
error });
|
|
142
|
+
self->check_in(type, session);
|
|
143
|
+
});
|
|
144
|
+
}
|
|
64
145
|
}
|
|
65
146
|
}
|
|
66
147
|
}
|
|
@@ -167,7 +167,10 @@ struct mcbp_command : public std::enable_shared_from_this<mcbp_command<Manager,
|
|
|
167
167
|
}
|
|
168
168
|
}
|
|
169
169
|
}
|
|
170
|
-
request.encode_to(encoded);
|
|
170
|
+
auto encoding_ec = request.encode_to(encoded, session_->context());
|
|
171
|
+
if (encoding_ec) {
|
|
172
|
+
return invoke_handler(encoding_ec);
|
|
173
|
+
}
|
|
171
174
|
|
|
172
175
|
session_->write_and_subscribe(
|
|
173
176
|
request.opaque,
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
2
|
+
/*
|
|
3
|
+
* Copyright 2020 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 <vector>
|
|
21
|
+
#include <configuration.hxx>
|
|
22
|
+
#include <protocol/hello_feature.hxx>
|
|
23
|
+
|
|
24
|
+
namespace couchbase
|
|
25
|
+
{
|
|
26
|
+
|
|
27
|
+
struct mcbp_context {
|
|
28
|
+
const std::optional<configuration>& config;
|
|
29
|
+
const std::vector<protocol::hello_feature>& supported_features;
|
|
30
|
+
|
|
31
|
+
[[nodiscard]] bool supports_feature(protocol::hello_feature feature)
|
|
32
|
+
{
|
|
33
|
+
return std::find(supported_features.begin(), supported_features.end(), feature) != supported_features.end();
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
} // namespace couchbase
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
#include <io/mcbp_parser.hxx>
|
|
30
30
|
#include <io/streams.hxx>
|
|
31
31
|
#include <io/retry_orchestrator.hxx>
|
|
32
|
+
#include <io/mcbp_context.hxx>
|
|
32
33
|
|
|
33
34
|
#include <timeout_defaults.hxx>
|
|
34
35
|
|
|
@@ -36,6 +37,7 @@
|
|
|
36
37
|
#include <protocol/client_request.hxx>
|
|
37
38
|
#include <protocol/client_response.hxx>
|
|
38
39
|
#include <protocol/server_request.hxx>
|
|
40
|
+
#include <protocol/cmd_noop.hxx>
|
|
39
41
|
#include <protocol/cmd_hello.hxx>
|
|
40
42
|
#include <protocol/cmd_sasl_list_mechs.hxx>
|
|
41
43
|
#include <protocol/cmd_sasl_auth.hxx>
|
|
@@ -127,10 +129,8 @@ class mcbp_session : public std::enable_shared_from_this<mcbp_session>
|
|
|
127
129
|
{ "SCRAM-SHA512", "SCRAM-SHA256", "SCRAM-SHA1", "PLAIN" })
|
|
128
130
|
{
|
|
129
131
|
tao::json::value user_agent{
|
|
130
|
-
{ "a",
|
|
131
|
-
|
|
132
|
-
"ruby/{}.{}.{}/{}", BACKEND_VERSION_MAJOR, BACKEND_VERSION_MINOR, BACKEND_VERSION_PATCH, BACKEND_GIT_REVISION) },
|
|
133
|
-
{ "i", fmt::format("{}/{}", session_->client_id_, session_->id_) }
|
|
132
|
+
{ "a", couchbase::sdk_id() },
|
|
133
|
+
{ "i", fmt::format("{}/{}", session_->client_id_, session_->id_) },
|
|
134
134
|
};
|
|
135
135
|
protocol::client_request<protocol::hello_request_body> hello_req;
|
|
136
136
|
hello_req.opaque(session_->next_opaque());
|
|
@@ -387,6 +387,7 @@ class mcbp_session : public std::enable_shared_from_this<mcbp_session>
|
|
|
387
387
|
resp.opaque());
|
|
388
388
|
}
|
|
389
389
|
} break;
|
|
390
|
+
case protocol::client_opcode::noop:
|
|
390
391
|
case protocol::client_opcode::get_collections_manifest:
|
|
391
392
|
case protocol::client_opcode::get_collection_id:
|
|
392
393
|
case protocol::client_opcode::get:
|
|
@@ -396,6 +397,8 @@ class mcbp_session : public std::enable_shared_from_this<mcbp_session>
|
|
|
396
397
|
case protocol::client_opcode::insert:
|
|
397
398
|
case protocol::client_opcode::replace:
|
|
398
399
|
case protocol::client_opcode::upsert:
|
|
400
|
+
case protocol::client_opcode::append:
|
|
401
|
+
case protocol::client_opcode::prepend:
|
|
399
402
|
case protocol::client_opcode::remove:
|
|
400
403
|
case protocol::client_opcode::observe:
|
|
401
404
|
case protocol::client_opcode::unlock:
|
|
@@ -405,8 +408,9 @@ class mcbp_session : public std::enable_shared_from_this<mcbp_session>
|
|
|
405
408
|
case protocol::client_opcode::subdoc_multi_mutation: {
|
|
406
409
|
std::uint32_t opaque = msg.header.opaque;
|
|
407
410
|
std::uint16_t status = ntohs(msg.header.specific);
|
|
411
|
+
session_->command_handlers_mutex_.lock();
|
|
408
412
|
auto handler = session_->command_handlers_.find(opaque);
|
|
409
|
-
if (handler != session_->command_handlers_.end()) {
|
|
413
|
+
if (handler != session_->command_handlers_.end() && handler->second) {
|
|
410
414
|
auto ec = session_->map_status_code(opcode, status);
|
|
411
415
|
spdlog::trace("{} MCBP invoke operation handler: opcode={}, opaque={}, status={}, ec={}",
|
|
412
416
|
session_->log_prefix_,
|
|
@@ -414,10 +418,12 @@ class mcbp_session : public std::enable_shared_from_this<mcbp_session>
|
|
|
414
418
|
opaque,
|
|
415
419
|
protocol::status_to_string(status),
|
|
416
420
|
ec.message());
|
|
417
|
-
auto fun = handler->second;
|
|
421
|
+
auto fun = std::move(handler->second);
|
|
418
422
|
session_->command_handlers_.erase(handler);
|
|
423
|
+
session_->command_handlers_mutex_.unlock();
|
|
419
424
|
fun(ec, retry_reason::do_not_retry, std::move(msg));
|
|
420
425
|
} else {
|
|
426
|
+
session_->command_handlers_mutex_.unlock();
|
|
421
427
|
spdlog::debug("{} unexpected orphan response: opcode={}, opaque={}, status={}",
|
|
422
428
|
session_->log_prefix_,
|
|
423
429
|
opcode,
|
|
@@ -537,6 +543,16 @@ class mcbp_session : public std::enable_shared_from_this<mcbp_session>
|
|
|
537
543
|
return log_prefix_;
|
|
538
544
|
}
|
|
539
545
|
|
|
546
|
+
std::string remote_address() const
|
|
547
|
+
{
|
|
548
|
+
return fmt::format("{}:{}", endpoint_address_, endpoint_.port());
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
std::string local_address() const
|
|
552
|
+
{
|
|
553
|
+
return fmt::format("{}:{}", local_endpoint_address_, local_endpoint_.port());
|
|
554
|
+
}
|
|
555
|
+
|
|
540
556
|
[[nodiscard]] diag::endpoint_diag_info diag_info() const
|
|
541
557
|
{
|
|
542
558
|
return { service_type::kv,
|
|
@@ -544,12 +560,44 @@ class mcbp_session : public std::enable_shared_from_this<mcbp_session>
|
|
|
544
560
|
last_active_.time_since_epoch().count() == 0 ? std::nullopt
|
|
545
561
|
: std::make_optional(std::chrono::duration_cast<std::chrono::microseconds>(
|
|
546
562
|
std::chrono::steady_clock::now() - last_active_)),
|
|
547
|
-
|
|
548
|
-
|
|
563
|
+
remote_address(),
|
|
564
|
+
local_address(),
|
|
549
565
|
state_,
|
|
550
566
|
bucket_name_ };
|
|
551
567
|
}
|
|
552
568
|
|
|
569
|
+
template<typename Handler>
|
|
570
|
+
void ping(Handler&& handler)
|
|
571
|
+
{
|
|
572
|
+
protocol::client_request<protocol::mcbp_noop_request_body> req;
|
|
573
|
+
req.opaque(next_opaque());
|
|
574
|
+
write_and_subscribe(req.opaque(),
|
|
575
|
+
req.data(false),
|
|
576
|
+
[start = std::chrono::steady_clock::now(), self = shared_from_this(), handler](
|
|
577
|
+
std::error_code ec, retry_reason reason, io::mcbp_message&& /* msg */) {
|
|
578
|
+
diag::ping_state state = diag::ping_state::ok;
|
|
579
|
+
std::optional<std::string> error{};
|
|
580
|
+
if (ec) {
|
|
581
|
+
state = diag::ping_state::error;
|
|
582
|
+
error.emplace(fmt::format("code={}, message={}, reason={}", ec.value(), ec.message(), reason));
|
|
583
|
+
}
|
|
584
|
+
handler(diag::endpoint_ping_info{
|
|
585
|
+
service_type::kv,
|
|
586
|
+
self->id_,
|
|
587
|
+
std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - start),
|
|
588
|
+
self->remote_address(),
|
|
589
|
+
self->local_address(),
|
|
590
|
+
state,
|
|
591
|
+
self->bucket_name_,
|
|
592
|
+
error });
|
|
593
|
+
});
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
[[nodiscard]] mcbp_context context() const
|
|
597
|
+
{
|
|
598
|
+
return { config_, supported_features_ };
|
|
599
|
+
}
|
|
600
|
+
|
|
553
601
|
void bootstrap(std::function<void(std::error_code, configuration)>&& handler, bool retry_on_bucket_not_found = false)
|
|
554
602
|
{
|
|
555
603
|
retry_bootstrap_on_bucket_not_found_ = retry_on_bucket_not_found;
|
|
@@ -648,11 +696,18 @@ class mcbp_session : public std::enable_shared_from_this<mcbp_session>
|
|
|
648
696
|
if (handler_) {
|
|
649
697
|
handler_->stop();
|
|
650
698
|
}
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
699
|
+
{
|
|
700
|
+
std::scoped_lock lock(command_handlers_mutex_);
|
|
701
|
+
for (auto& handler : command_handlers_) {
|
|
702
|
+
if (handler.second) {
|
|
703
|
+
spdlog::debug(
|
|
704
|
+
"{} MCBP cancel operation during session close, opaque={}, ec={}", log_prefix_, handler.first, ec.message());
|
|
705
|
+
auto fun = std::move(handler.second);
|
|
706
|
+
fun(ec, reason, {});
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
command_handlers_.clear();
|
|
654
710
|
}
|
|
655
|
-
command_handlers_.clear();
|
|
656
711
|
config_listeners_.clear();
|
|
657
712
|
if (on_stop_handler_) {
|
|
658
713
|
on_stop_handler_(reason);
|
|
@@ -700,7 +755,10 @@ class mcbp_session : public std::enable_shared_from_this<mcbp_session>
|
|
|
700
755
|
handler(std::make_error_code(error::common_errc::request_canceled), retry_reason::socket_closed_while_in_flight, {});
|
|
701
756
|
return;
|
|
702
757
|
}
|
|
703
|
-
|
|
758
|
+
{
|
|
759
|
+
std::scoped_lock lock(command_handlers_mutex_);
|
|
760
|
+
command_handlers_.emplace(opaque, std::move(handler));
|
|
761
|
+
}
|
|
704
762
|
if (bootstrapped_ && stream_->is_open()) {
|
|
705
763
|
write_and_flush(data);
|
|
706
764
|
} else {
|
|
@@ -715,13 +773,19 @@ class mcbp_session : public std::enable_shared_from_this<mcbp_session>
|
|
|
715
773
|
if (stopped_) {
|
|
716
774
|
return false;
|
|
717
775
|
}
|
|
776
|
+
command_handlers_mutex_.lock();
|
|
718
777
|
auto handler = command_handlers_.find(opaque);
|
|
719
778
|
if (handler != command_handlers_.end()) {
|
|
720
779
|
spdlog::debug("{} MCBP cancel operation, opaque={}, ec={} ({})", log_prefix_, opaque, ec.value(), ec.message());
|
|
721
|
-
handler->second
|
|
722
|
-
|
|
723
|
-
|
|
780
|
+
if (handler->second) {
|
|
781
|
+
auto fun = std::move(handler->second);
|
|
782
|
+
command_handlers_.erase(handler);
|
|
783
|
+
command_handlers_mutex_.unlock();
|
|
784
|
+
fun(ec, reason, {});
|
|
785
|
+
return true;
|
|
786
|
+
}
|
|
724
787
|
}
|
|
788
|
+
command_handlers_mutex_.unlock();
|
|
725
789
|
return false;
|
|
726
790
|
}
|
|
727
791
|
|
|
@@ -1142,22 +1206,19 @@ class mcbp_session : public std::enable_shared_from_this<mcbp_session>
|
|
|
1142
1206
|
self->last_active_ = std::chrono::steady_clock::now();
|
|
1143
1207
|
if (ec) {
|
|
1144
1208
|
if (stream_id != self->stream_->id()) {
|
|
1145
|
-
spdlog::error(
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
stream_id,
|
|
1152
|
-
self->stream_->id());
|
|
1209
|
+
spdlog::error(R"({} ignore IO error while reading from the socket: {} ({}), old_id="{}", new_id="{}")",
|
|
1210
|
+
self->log_prefix_,
|
|
1211
|
+
ec.value(),
|
|
1212
|
+
ec.message(),
|
|
1213
|
+
stream_id,
|
|
1214
|
+
self->stream_->id());
|
|
1153
1215
|
return;
|
|
1154
1216
|
}
|
|
1155
|
-
spdlog::error(R"({} IO error while reading from the socket("{}"): {} ({})
|
|
1217
|
+
spdlog::error(R"({} IO error while reading from the socket("{}"): {} ({}))",
|
|
1156
1218
|
self->log_prefix_,
|
|
1157
1219
|
self->stream_->id(),
|
|
1158
1220
|
ec.value(),
|
|
1159
|
-
ec.message()
|
|
1160
|
-
self->command_handlers_.size());
|
|
1221
|
+
ec.message());
|
|
1161
1222
|
return self->stop(retry_reason::socket_closed_while_in_flight);
|
|
1162
1223
|
}
|
|
1163
1224
|
self->parser_.feed(self->input_buffer_.data(), self->input_buffer_.data() + ssize_t(bytes_transferred));
|
|
@@ -1212,12 +1273,11 @@ class mcbp_session : public std::enable_shared_from_this<mcbp_session>
|
|
|
1212
1273
|
}
|
|
1213
1274
|
self->last_active_ = std::chrono::steady_clock::now();
|
|
1214
1275
|
if (ec) {
|
|
1215
|
-
spdlog::error(R"({} IO error while writing to the socket("{}"): {} ({})
|
|
1276
|
+
spdlog::error(R"({} IO error while writing to the socket("{}"): {} ({}))",
|
|
1216
1277
|
self->log_prefix_,
|
|
1217
1278
|
self->stream_->id(),
|
|
1218
1279
|
ec.value(),
|
|
1219
|
-
ec.message()
|
|
1220
|
-
self->command_handlers_.size());
|
|
1280
|
+
ec.message());
|
|
1221
1281
|
return self->stop(retry_reason::socket_closed_while_in_flight);
|
|
1222
1282
|
}
|
|
1223
1283
|
{
|
|
@@ -1242,6 +1302,7 @@ class mcbp_session : public std::enable_shared_from_this<mcbp_session>
|
|
|
1242
1302
|
mcbp_parser parser_;
|
|
1243
1303
|
std::unique_ptr<message_handler> handler_;
|
|
1244
1304
|
std::function<void(std::error_code, const configuration&)> bootstrap_handler_{};
|
|
1305
|
+
std::mutex command_handlers_mutex_{};
|
|
1245
1306
|
std::map<uint32_t, std::function<void(std::error_code, retry_reason, io::mcbp_message&&)>> command_handlers_{};
|
|
1246
1307
|
std::vector<std::function<void(const configuration&)>> config_listeners_{};
|
|
1247
1308
|
std::function<void(io::retry_reason)> on_stop_handler_{};
|