couchbase 3.0.1 → 3.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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_{};
|