couchbase 3.4.0 → 3.4.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 +2 -2
- data/ext/couchbase/CMakeLists.txt +10 -3
- data/ext/couchbase/cmake/CompilerWarnings.cmake +12 -4
- data/ext/couchbase/cmake/Documentation.cmake +4 -3
- data/ext/couchbase/cmake/OpenSSL.cmake +52 -7
- data/ext/couchbase/cmake/ThirdPartyDependencies.cmake +4 -0
- data/ext/couchbase/cmake/VersionInfo.cmake +39 -3
- data/ext/couchbase/cmake/test_openssl.cxx +7 -0
- data/ext/couchbase/core/cluster_options.hxx +0 -1
- data/ext/couchbase/core/config_profile.cxx +23 -1
- data/ext/couchbase/core/config_profile.hxx +2 -12
- data/ext/couchbase/core/crypto/CMakeLists.txt +5 -1
- data/ext/couchbase/core/impl/analytics.cxx +236 -0
- data/ext/couchbase/core/impl/cluster.cxx +0 -1
- data/ext/couchbase/core/impl/collection_query_index_manager.cxx +3 -3
- data/ext/couchbase/core/impl/dns_srv_tracker.cxx +5 -3
- data/ext/couchbase/core/impl/get_all_query_indexes.cxx +3 -3
- data/ext/couchbase/core/impl/query.cxx +5 -5
- data/ext/couchbase/core/impl/transaction_get_result.cxx +54 -0
- data/ext/couchbase/core/io/dns_client.cxx +225 -0
- data/ext/couchbase/core/io/dns_client.hxx +19 -188
- data/ext/couchbase/core/meta/CMakeLists.txt +7 -5
- data/ext/couchbase/core/meta/version.cxx +19 -0
- data/ext/couchbase/core/operations/document_search.cxx +5 -2
- data/ext/couchbase/core/operations/document_search.hxx +0 -1
- data/ext/couchbase/core/transactions/active_transaction_record.hxx +2 -2
- data/ext/couchbase/core/transactions/atr_cleanup_entry.cxx +1 -0
- data/ext/couchbase/core/transactions/attempt_context_impl.cxx +65 -31
- data/ext/couchbase/core/transactions/attempt_context_impl.hxx +44 -23
- data/ext/couchbase/core/transactions/forward_compat.hxx +2 -2
- data/ext/couchbase/core/transactions/internal/transaction_context.hxx +13 -13
- data/ext/couchbase/core/transactions/internal/transaction_fields.hxx +1 -0
- data/ext/couchbase/core/transactions/internal/transactions_cleanup.hxx +7 -1
- data/ext/couchbase/core/transactions/staged_mutation.cxx +1 -1
- data/ext/couchbase/core/transactions/staged_mutation.hxx +12 -2
- data/ext/couchbase/core/transactions/transaction_context.cxx +9 -11
- data/ext/couchbase/core/transactions/transaction_get_result.cxx +41 -31
- data/ext/couchbase/core/transactions/transaction_get_result.hxx +7 -3
- data/ext/couchbase/core/transactions/transaction_links.hxx +13 -1
- data/ext/couchbase/core/transactions/transactions_cleanup.cxx +144 -155
- data/ext/couchbase/core/transactions/waitable_op_list.hxx +1 -0
- data/ext/couchbase/core/utils/connection_string.cxx +10 -3
- data/ext/couchbase/core/utils/connection_string.hxx +3 -3
- data/ext/couchbase/couchbase/analytics_error_context.hxx +143 -0
- data/ext/couchbase/couchbase/analytics_meta_data.hxx +155 -0
- data/ext/couchbase/couchbase/analytics_metrics.hxx +163 -0
- data/ext/couchbase/couchbase/analytics_options.hxx +359 -0
- data/ext/couchbase/couchbase/analytics_result.hxx +102 -0
- data/ext/couchbase/couchbase/analytics_scan_consistency.hxx +46 -0
- data/ext/couchbase/couchbase/analytics_status.hxx +41 -0
- data/ext/couchbase/couchbase/analytics_warning.hxx +85 -0
- data/ext/couchbase/couchbase/cluster.hxx +35 -2
- data/ext/couchbase/couchbase/cluster_options.hxx +10 -10
- data/ext/couchbase/couchbase/collection.hxx +22 -17
- data/ext/couchbase/couchbase/collection_query_index_manager.hxx +1 -1
- data/ext/couchbase/couchbase/common_options.hxx +1 -1
- data/ext/couchbase/couchbase/configuration_profile.hxx +1 -1
- data/ext/couchbase/couchbase/configuration_profiles_registry.hxx +0 -1
- data/ext/couchbase/couchbase/create_primary_query_index_options.hxx +1 -1
- data/ext/couchbase/couchbase/drop_primary_query_index_options.hxx +1 -1
- data/ext/couchbase/couchbase/drop_query_index_options.hxx +1 -1
- data/ext/couchbase/couchbase/fmt/analytics_status.hxx +76 -0
- data/ext/couchbase/couchbase/fmt/cas.hxx +12 -0
- data/ext/couchbase/couchbase/fmt/durability_level.hxx +6 -0
- data/ext/couchbase/couchbase/fmt/key_value_extended_error_info.hxx +6 -0
- data/ext/couchbase/couchbase/fmt/key_value_status_code.hxx +6 -0
- data/ext/couchbase/couchbase/fmt/mutation_token.hxx +6 -0
- data/ext/couchbase/couchbase/fmt/query_scan_consistency.hxx +6 -0
- data/ext/couchbase/couchbase/fmt/query_status.hxx +6 -0
- data/ext/couchbase/couchbase/fmt/retry_reason.hxx +6 -0
- data/ext/couchbase/couchbase/fmt/tls_verify_mode.hxx +6 -0
- data/ext/couchbase/couchbase/get_all_query_indexes_options.hxx +5 -4
- data/ext/couchbase/couchbase/query_index_manager.hxx +4 -2
- data/ext/couchbase/couchbase/query_options.hxx +0 -1
- data/ext/couchbase/couchbase/scope.hxx +34 -1
- data/ext/couchbase/couchbase/subdoc/array_add_unique.hxx +2 -0
- data/ext/couchbase/couchbase/subdoc/array_append.hxx +2 -0
- data/ext/couchbase/couchbase/subdoc/array_insert.hxx +2 -0
- data/ext/couchbase/couchbase/subdoc/array_prepend.hxx +2 -0
- data/ext/couchbase/couchbase/subdoc/count.hxx +2 -0
- data/ext/couchbase/couchbase/subdoc/counter.hxx +2 -0
- data/ext/couchbase/couchbase/subdoc/exists.hxx +2 -0
- data/ext/couchbase/couchbase/subdoc/get.hxx +2 -0
- data/ext/couchbase/couchbase/subdoc/insert.hxx +2 -0
- data/ext/couchbase/couchbase/subdoc/remove.hxx +2 -0
- data/ext/couchbase/couchbase/subdoc/replace.hxx +3 -1
- data/ext/couchbase/couchbase/subdoc/upsert.hxx +2 -0
- data/ext/couchbase/couchbase/transaction_op_error_context.hxx +4 -4
- data/ext/couchbase/couchbase/transactions/attempt_context.hxx +1 -1
- data/ext/couchbase/couchbase/transactions/transaction_get_result.hxx +36 -51
- data/ext/couchbase/couchbase/transactions/transactions_config.hxx +1 -1
- data/ext/couchbase/test/CMakeLists.txt +3 -2
- data/ext/couchbase/test/test_helper.hxx +1 -1
- data/ext/couchbase/test/test_integration_analytics.cxx +289 -13
- data/ext/couchbase/test/test_integration_crud.cxx +8 -1
- data/ext/couchbase/test/test_integration_examples.cxx +182 -0
- data/ext/couchbase/test/test_integration_management.cxx +15 -3
- data/ext/couchbase/test/test_integration_search.cxx +601 -0
- data/ext/couchbase/test/test_transaction_transaction_simple.cxx +73 -0
- data/ext/couchbase/test/test_unit_config_profiles.cxx +12 -12
- data/ext/couchbase/test/test_unit_connection_string.cxx +35 -0
- data/ext/couchbase/test/test_unit_transaction_utils.cxx +76 -19
- data/ext/couchbase/third_party/snappy/CMakeLists.txt +150 -27
- data/ext/couchbase/third_party/snappy/cmake/config.h.in +28 -24
- data/ext/couchbase/third_party/snappy/snappy-internal.h +189 -25
- data/ext/couchbase/third_party/snappy/snappy-sinksource.cc +26 -9
- data/ext/couchbase/third_party/snappy/snappy-sinksource.h +11 -11
- data/ext/couchbase/third_party/snappy/snappy-stubs-internal.cc +1 -1
- data/ext/couchbase/third_party/snappy/snappy-stubs-internal.h +227 -308
- data/ext/couchbase/third_party/snappy/snappy-stubs-public.h.in +0 -11
- data/ext/couchbase/third_party/snappy/snappy.cc +1176 -410
- data/ext/couchbase/third_party/snappy/snappy.h +19 -4
- data/ext/couchbase.cxx +506 -26
- data/ext/extconf.rb +2 -1
- data/ext/revisions.rb +3 -2
- data/lib/couchbase/binary_collection.rb +4 -4
- data/lib/couchbase/cluster.rb +13 -9
- data/lib/couchbase/cluster_registry.rb +7 -2
- data/lib/couchbase/collection.rb +5 -0
- data/lib/couchbase/configuration.rb +3 -4
- data/lib/couchbase/errors.rb +10 -0
- data/lib/couchbase/management/collection_query_index_manager.rb +183 -0
- data/lib/couchbase/management/query_index_manager.rb +35 -3
- data/lib/couchbase/management.rb +1 -0
- data/lib/couchbase/options.rb +87 -5
- data/lib/couchbase/search_options.rb +158 -240
- data/lib/couchbase/version.rb +1 -1
- metadata +21 -6
- data/ext/couchbase/core/CMakeLists.txt +0 -0
@@ -45,7 +45,7 @@ initiate_get_all_query_indexes(std::shared_ptr<couchbase::core::cluster> core,
|
|
45
45
|
couchbase::get_all_query_indexes_options::built options,
|
46
46
|
query_context query_ctx,
|
47
47
|
std::string collection_name,
|
48
|
-
|
48
|
+
get_all_query_indexes_handler&& handler)
|
49
49
|
{
|
50
50
|
core->execute(
|
51
51
|
operations::management::query_index_get_all_request{
|
@@ -68,9 +68,9 @@ void
|
|
68
68
|
initiate_get_all_query_indexes(std::shared_ptr<couchbase::core::cluster> core,
|
69
69
|
std::string bucket_name,
|
70
70
|
couchbase::get_all_query_indexes_options::built options,
|
71
|
-
|
71
|
+
get_all_query_indexes_handler&& handler)
|
72
72
|
{
|
73
73
|
initiate_get_all_query_indexes(core, std::move(bucket_name), options, {}, "", std::move(handler));
|
74
74
|
}
|
75
75
|
|
76
|
-
} // namespace couchbase::core::impl
|
76
|
+
} // namespace couchbase::core::impl
|
@@ -152,10 +152,10 @@ build_result(operations::query_response& resp)
|
|
152
152
|
}
|
153
153
|
|
154
154
|
static core::operations::query_request
|
155
|
-
build_query_request(query_options::built options)
|
155
|
+
build_query_request(std::string statement, query_options::built options)
|
156
156
|
{
|
157
157
|
operations::query_request request{
|
158
|
-
|
158
|
+
std::move(statement),
|
159
159
|
options.adhoc,
|
160
160
|
options.metrics,
|
161
161
|
options.readonly,
|
@@ -222,8 +222,9 @@ build_transaction_query_result(operations::query_response resp, std::error_code
|
|
222
222
|
core::operations::query_request
|
223
223
|
build_transaction_query_request(query_options::built opts)
|
224
224
|
{
|
225
|
-
return build_query_request(opts);
|
225
|
+
return build_query_request("", opts);
|
226
226
|
}
|
227
|
+
|
227
228
|
void
|
228
229
|
initiate_query_operation(std::shared_ptr<couchbase::core::cluster> core,
|
229
230
|
std::string statement,
|
@@ -231,8 +232,7 @@ initiate_query_operation(std::shared_ptr<couchbase::core::cluster> core,
|
|
231
232
|
query_options::built options,
|
232
233
|
query_handler&& handler)
|
233
234
|
{
|
234
|
-
auto request = build_query_request(options);
|
235
|
-
request.statement = std::move(statement);
|
235
|
+
auto request = build_query_request(std::move(statement), options);
|
236
236
|
if (query_context) {
|
237
237
|
request.query_context = std::move(query_context);
|
238
238
|
}
|
@@ -0,0 +1,54 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
#include <core/transactions/transaction_get_result.hxx>
|
4
|
+
#include <couchbase/transactions/transaction_get_result.hxx>
|
5
|
+
|
6
|
+
namespace couchbase::transactions
|
7
|
+
{
|
8
|
+
|
9
|
+
transaction_get_result::transaction_get_result()
|
10
|
+
: base_(std::make_shared<couchbase::core::transactions::transaction_get_result>())
|
11
|
+
{
|
12
|
+
}
|
13
|
+
|
14
|
+
const std::vector<std::byte>&
|
15
|
+
transaction_get_result::content() const
|
16
|
+
{
|
17
|
+
return base_->content();
|
18
|
+
}
|
19
|
+
void
|
20
|
+
transaction_get_result::content(std::vector<std::byte> content)
|
21
|
+
{
|
22
|
+
return base_->content(content);
|
23
|
+
}
|
24
|
+
void
|
25
|
+
transaction_get_result::content(std::vector<std::byte>&& content)
|
26
|
+
{
|
27
|
+
return base_->content(content);
|
28
|
+
}
|
29
|
+
const std::string
|
30
|
+
transaction_get_result::key() const
|
31
|
+
{
|
32
|
+
return base_->key();
|
33
|
+
}
|
34
|
+
const std::string
|
35
|
+
transaction_get_result::bucket() const
|
36
|
+
{
|
37
|
+
return base_->bucket();
|
38
|
+
}
|
39
|
+
const std::string
|
40
|
+
transaction_get_result::scope() const
|
41
|
+
{
|
42
|
+
return base_->scope();
|
43
|
+
}
|
44
|
+
const std::string
|
45
|
+
transaction_get_result::collection() const
|
46
|
+
{
|
47
|
+
return base_->collection();
|
48
|
+
}
|
49
|
+
const couchbase::cas
|
50
|
+
transaction_get_result::cas() const
|
51
|
+
{
|
52
|
+
return base_->cas();
|
53
|
+
}
|
54
|
+
} // namespace couchbase::transactions
|
@@ -0,0 +1,225 @@
|
|
1
|
+
/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
2
|
+
/*
|
3
|
+
* Copyright 2020-Present Couchbase, Inc.
|
4
|
+
*
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
* you may not use this file except in compliance with the License.
|
7
|
+
* You may obtain a copy of the License at
|
8
|
+
*
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
*
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
* See the License for the specific language governing permissions and
|
15
|
+
* limitations under the License.
|
16
|
+
*/
|
17
|
+
|
18
|
+
#include "dns_client.hxx"
|
19
|
+
|
20
|
+
#include "core/logger/logger.hxx"
|
21
|
+
#include "core/utils/join_strings.hxx"
|
22
|
+
#include "dns_codec.hxx"
|
23
|
+
#include "dns_config.hxx"
|
24
|
+
|
25
|
+
#include <couchbase/error_codes.hxx>
|
26
|
+
|
27
|
+
#include <asio/ip/tcp.hpp>
|
28
|
+
#include <asio/read.hpp>
|
29
|
+
#include <asio/write.hpp>
|
30
|
+
|
31
|
+
#include <memory>
|
32
|
+
#include <sstream>
|
33
|
+
|
34
|
+
namespace couchbase::core::io::dns
|
35
|
+
{
|
36
|
+
class dns_srv_command : public std::enable_shared_from_this<dns_srv_command>
|
37
|
+
{
|
38
|
+
public:
|
39
|
+
dns_srv_command(asio::io_context& ctx,
|
40
|
+
const std::string& name,
|
41
|
+
const std::string& service,
|
42
|
+
const asio::ip::address& address,
|
43
|
+
std::uint16_t port,
|
44
|
+
utils::movable_function<void(couchbase::core::io::dns::dns_srv_response&& resp)> handler)
|
45
|
+
: deadline_(ctx)
|
46
|
+
, udp_deadline_(ctx)
|
47
|
+
, udp_(ctx)
|
48
|
+
, tcp_(ctx)
|
49
|
+
, address_(address)
|
50
|
+
, port_(port)
|
51
|
+
, handler_(std::move(handler))
|
52
|
+
{
|
53
|
+
static std::string protocol{ "_tcp" };
|
54
|
+
dns_message request{};
|
55
|
+
question_record qr;
|
56
|
+
qr.klass = resource_class::in;
|
57
|
+
qr.type = resource_type::srv;
|
58
|
+
qr.name.labels.push_back(service);
|
59
|
+
qr.name.labels.push_back(protocol);
|
60
|
+
std::string label;
|
61
|
+
std::istringstream name_stream(name);
|
62
|
+
while (std::getline(name_stream, label, '.')) {
|
63
|
+
qr.name.labels.push_back(label);
|
64
|
+
}
|
65
|
+
request.questions.emplace_back(qr);
|
66
|
+
send_buf_ = dns_codec::encode(request);
|
67
|
+
}
|
68
|
+
|
69
|
+
void execute(std::chrono::milliseconds total_timeout, std::chrono::milliseconds udp_timeout)
|
70
|
+
{
|
71
|
+
asio::ip::udp::endpoint endpoint(address_, port_);
|
72
|
+
udp_.open(endpoint.protocol());
|
73
|
+
udp_.async_send_to(
|
74
|
+
asio::buffer(send_buf_), endpoint, [self = shared_from_this()](std::error_code ec1, std::size_t /* bytes_transferred */) mutable {
|
75
|
+
if (ec1) {
|
76
|
+
self->udp_deadline_.cancel();
|
77
|
+
CB_LOG_DEBUG("DNS UDP write operation has got error {}, retrying with TCP", ec1.message());
|
78
|
+
return self->retry_with_tcp();
|
79
|
+
}
|
80
|
+
|
81
|
+
self->recv_buf_.resize(512);
|
82
|
+
self->udp_.async_receive_from(
|
83
|
+
asio::buffer(self->recv_buf_), self->udp_sender_, [self](std::error_code ec2, std::size_t bytes_transferred) mutable {
|
84
|
+
self->udp_deadline_.cancel();
|
85
|
+
if (ec2) {
|
86
|
+
CB_LOG_DEBUG("DNS UDP read operation has got error {}, retrying with TCP", ec2.message());
|
87
|
+
return self->retry_with_tcp();
|
88
|
+
}
|
89
|
+
self->recv_buf_.resize(bytes_transferred);
|
90
|
+
const dns_message message = dns_codec::decode(self->recv_buf_);
|
91
|
+
if (message.header.flags.tc == truncation::yes) {
|
92
|
+
self->udp_.close();
|
93
|
+
CB_LOG_DEBUG("DNS UDP read operation returned truncated response, retrying with TCP");
|
94
|
+
return self->retry_with_tcp();
|
95
|
+
}
|
96
|
+
self->deadline_.cancel();
|
97
|
+
dns_srv_response resp{ ec2 };
|
98
|
+
resp.targets.reserve(message.answers.size());
|
99
|
+
for (const auto& answer : message.answers) {
|
100
|
+
resp.targets.emplace_back(dns_srv_response::address{ utils::join_strings(answer.target.labels, "."), answer.port });
|
101
|
+
}
|
102
|
+
CB_LOG_DEBUG("DNS UDP returned {} records", resp.targets.size());
|
103
|
+
return self->handler_(std::move(resp));
|
104
|
+
});
|
105
|
+
});
|
106
|
+
udp_deadline_.expires_after(udp_timeout);
|
107
|
+
deadline_.async_wait([self = shared_from_this()](std::error_code ec) {
|
108
|
+
if (ec == asio::error::operation_aborted) {
|
109
|
+
return;
|
110
|
+
}
|
111
|
+
CB_LOG_DEBUG("DNS UDP deadline has been reached, cancelling UDP operation and fall back to TCP");
|
112
|
+
self->udp_.cancel();
|
113
|
+
return self->retry_with_tcp();
|
114
|
+
});
|
115
|
+
|
116
|
+
deadline_.expires_after(total_timeout);
|
117
|
+
deadline_.async_wait([self = shared_from_this()](std::error_code ec) {
|
118
|
+
if (ec == asio::error::operation_aborted) {
|
119
|
+
return;
|
120
|
+
}
|
121
|
+
CB_LOG_DEBUG("DNS deadline has been reached, cancelling in-flight operations (tcp.is_open={})", self->tcp_.is_open());
|
122
|
+
self->udp_.cancel();
|
123
|
+
if (self->tcp_.is_open()) {
|
124
|
+
self->tcp_.cancel();
|
125
|
+
}
|
126
|
+
});
|
127
|
+
}
|
128
|
+
|
129
|
+
private:
|
130
|
+
void retry_with_tcp()
|
131
|
+
{
|
132
|
+
if (bool expected_state{ false }; !retrying_with_tcp_.compare_exchange_strong(expected_state, true)) {
|
133
|
+
return;
|
134
|
+
}
|
135
|
+
|
136
|
+
const asio::ip::tcp::no_delay no_delay(true);
|
137
|
+
std::error_code ignore_ec;
|
138
|
+
tcp_.set_option(no_delay, ignore_ec);
|
139
|
+
const asio::ip::tcp::endpoint endpoint(address_, port_);
|
140
|
+
tcp_.async_connect(endpoint, [self = shared_from_this()](std::error_code ec1) mutable {
|
141
|
+
if (ec1) {
|
142
|
+
self->deadline_.cancel();
|
143
|
+
CB_LOG_DEBUG("DNS TCP connection has been aborted, {}", ec1.message());
|
144
|
+
return self->handler_({ ec1 });
|
145
|
+
}
|
146
|
+
auto send_size = static_cast<std::uint16_t>(self->send_buf_.size());
|
147
|
+
self->send_buf_.insert(self->send_buf_.begin(), static_cast<std::uint8_t>(send_size & 0xffU));
|
148
|
+
self->send_buf_.insert(self->send_buf_.begin(), static_cast<std::uint8_t>(send_size >> 8U));
|
149
|
+
asio::async_write(
|
150
|
+
self->tcp_, asio::buffer(self->send_buf_), [self](std::error_code ec2, std::size_t /* bytes_transferred */) mutable {
|
151
|
+
if (ec2) {
|
152
|
+
CB_LOG_DEBUG("DNS TCP write operation has been aborted, {}", ec2.message());
|
153
|
+
self->deadline_.cancel();
|
154
|
+
if (ec2 == asio::error::operation_aborted) {
|
155
|
+
ec2 = errc::common::unambiguous_timeout;
|
156
|
+
}
|
157
|
+
return self->handler_({ ec2 });
|
158
|
+
}
|
159
|
+
asio::async_read(self->tcp_,
|
160
|
+
asio::buffer(&self->recv_buf_size_, sizeof(std::uint16_t)),
|
161
|
+
[self](std::error_code ec3, std::size_t /* bytes_transferred */) mutable {
|
162
|
+
if (ec3) {
|
163
|
+
CB_LOG_DEBUG("DNS TCP buf size read operation has been aborted, {}", ec3.message());
|
164
|
+
self->deadline_.cancel();
|
165
|
+
return self->handler_({ ec3 });
|
166
|
+
}
|
167
|
+
self->recv_buf_size_ = utils::byte_swap(self->recv_buf_size_);
|
168
|
+
self->recv_buf_.resize(self->recv_buf_size_);
|
169
|
+
CB_LOG_DEBUG("DNS TCP schedule read of {} bytes", self->recv_buf_size_);
|
170
|
+
asio::async_read(self->tcp_,
|
171
|
+
asio::buffer(self->recv_buf_),
|
172
|
+
[self](std::error_code ec4, std::size_t bytes_transferred) mutable {
|
173
|
+
self->deadline_.cancel();
|
174
|
+
if (ec4) {
|
175
|
+
CB_LOG_DEBUG("DNS TCP read operation has been aborted, {}", ec4.message());
|
176
|
+
return self->handler_({ ec4 });
|
177
|
+
}
|
178
|
+
self->recv_buf_.resize(bytes_transferred);
|
179
|
+
const dns_message message = dns_codec::decode(self->recv_buf_);
|
180
|
+
dns_srv_response resp{ ec4 };
|
181
|
+
resp.targets.reserve(message.answers.size());
|
182
|
+
for (const auto& answer : message.answers) {
|
183
|
+
resp.targets.emplace_back(dns_srv_response::address{
|
184
|
+
utils::join_strings(answer.target.labels, "."), answer.port });
|
185
|
+
}
|
186
|
+
CB_LOG_DEBUG("DNS TCP returned {} records", resp.targets.size());
|
187
|
+
return self->handler_(std::move(resp));
|
188
|
+
});
|
189
|
+
});
|
190
|
+
});
|
191
|
+
});
|
192
|
+
}
|
193
|
+
|
194
|
+
asio::steady_timer deadline_;
|
195
|
+
asio::steady_timer udp_deadline_;
|
196
|
+
asio::ip::udp::socket udp_;
|
197
|
+
asio::ip::udp::endpoint udp_sender_{};
|
198
|
+
asio::ip::tcp::socket tcp_;
|
199
|
+
|
200
|
+
asio::ip::address address_;
|
201
|
+
std::uint16_t port_;
|
202
|
+
utils::movable_function<void(couchbase::core::io::dns::dns_srv_response&& resp)> handler_;
|
203
|
+
|
204
|
+
std::vector<std::uint8_t> send_buf_{};
|
205
|
+
std::uint16_t recv_buf_size_{ 0 };
|
206
|
+
std::vector<std::uint8_t> recv_buf_{};
|
207
|
+
|
208
|
+
std::atomic_bool retrying_with_tcp_{ false };
|
209
|
+
};
|
210
|
+
|
211
|
+
void
|
212
|
+
dns_client::query_srv(const std::string& name,
|
213
|
+
const std::string& service,
|
214
|
+
const dns_config& config,
|
215
|
+
utils::movable_function<void(dns_srv_response&&)>&& handler)
|
216
|
+
{
|
217
|
+
std::error_code ec;
|
218
|
+
auto address = asio::ip::address::from_string(config.nameserver(), ec);
|
219
|
+
if (ec) {
|
220
|
+
return handler({ ec });
|
221
|
+
}
|
222
|
+
auto cmd = std::make_shared<dns_srv_command>(ctx_, name, service, address, config.port(), std::move(handler));
|
223
|
+
return cmd->execute(config.timeout(), config.timeout() / 2);
|
224
|
+
}
|
225
|
+
} // namespace couchbase::core::io::dns
|
@@ -1,6 +1,6 @@
|
|
1
1
|
/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
2
2
|
/*
|
3
|
-
* Copyright 2020-
|
3
|
+
* Copyright 2020-Present Couchbase, Inc.
|
4
4
|
*
|
5
5
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
6
6
|
* you may not use this file except in compliance with the License.
|
@@ -17,207 +17,38 @@
|
|
17
17
|
|
18
18
|
#pragma once
|
19
19
|
|
20
|
-
#include "core/utils/
|
21
|
-
#include "dns_codec.hxx"
|
20
|
+
#include "core/utils/movable_function.hxx"
|
22
21
|
#include "dns_config.hxx"
|
23
22
|
|
24
|
-
#include <
|
23
|
+
#include <asio/io_context.hpp>
|
25
24
|
|
26
|
-
#include <
|
27
|
-
#include <
|
28
|
-
#include <
|
29
|
-
|
30
|
-
#include <memory>
|
31
|
-
#include <sstream>
|
25
|
+
#include <cinttypes>
|
26
|
+
#include <string>
|
27
|
+
#include <vector>
|
32
28
|
|
33
29
|
namespace couchbase::core::io::dns
|
34
30
|
{
|
31
|
+
struct dns_srv_response {
|
32
|
+
struct address {
|
33
|
+
std::string hostname;
|
34
|
+
std::uint16_t port;
|
35
|
+
};
|
36
|
+
std::error_code ec;
|
37
|
+
std::vector<address> targets{};
|
38
|
+
};
|
39
|
+
|
35
40
|
class dns_client
|
36
41
|
{
|
37
42
|
public:
|
38
|
-
struct dns_srv_response {
|
39
|
-
struct address {
|
40
|
-
std::string hostname;
|
41
|
-
std::uint16_t port;
|
42
|
-
};
|
43
|
-
std::error_code ec;
|
44
|
-
std::vector<address> targets{};
|
45
|
-
};
|
46
|
-
|
47
|
-
class dns_srv_command : public std::enable_shared_from_this<dns_srv_command>
|
48
|
-
{
|
49
|
-
public:
|
50
|
-
dns_srv_command(asio::io_context& ctx,
|
51
|
-
const std::string& name,
|
52
|
-
const std::string& service,
|
53
|
-
const asio::ip::address& address,
|
54
|
-
std::uint16_t port)
|
55
|
-
: deadline_(ctx)
|
56
|
-
, udp_(ctx)
|
57
|
-
, tcp_(ctx)
|
58
|
-
, address_(address)
|
59
|
-
, port_(port)
|
60
|
-
{
|
61
|
-
static std::string protocol{ "_tcp" };
|
62
|
-
dns_message request{};
|
63
|
-
question_record qr;
|
64
|
-
qr.klass = resource_class::in;
|
65
|
-
qr.type = resource_type::srv;
|
66
|
-
qr.name.labels.push_back(service);
|
67
|
-
qr.name.labels.push_back(protocol);
|
68
|
-
std::string label;
|
69
|
-
std::istringstream name_stream(name);
|
70
|
-
while (std::getline(name_stream, label, '.')) {
|
71
|
-
qr.name.labels.push_back(label);
|
72
|
-
}
|
73
|
-
request.questions.emplace_back(qr);
|
74
|
-
send_buf_ = dns_codec::encode(request);
|
75
|
-
}
|
76
|
-
|
77
|
-
template<class Handler>
|
78
|
-
void execute(std::chrono::milliseconds timeout, Handler&& handler)
|
79
|
-
{
|
80
|
-
asio::ip::udp::endpoint endpoint(address_, port_);
|
81
|
-
udp_.open(endpoint.protocol());
|
82
|
-
udp_.async_send_to(asio::buffer(send_buf_),
|
83
|
-
endpoint,
|
84
|
-
[self = shared_from_this(), handler = std::forward<Handler>(handler)](
|
85
|
-
std::error_code ec1, std::size_t /* bytes_transferred */) mutable {
|
86
|
-
if (ec1 == asio::error::operation_aborted) {
|
87
|
-
self->deadline_.cancel();
|
88
|
-
return handler({ errc::common::unambiguous_timeout });
|
89
|
-
}
|
90
|
-
if (ec1) {
|
91
|
-
self->deadline_.cancel();
|
92
|
-
return handler({ ec1 });
|
93
|
-
}
|
94
|
-
|
95
|
-
self->recv_buf_.resize(512);
|
96
|
-
self->udp_.async_receive_from(asio::buffer(self->recv_buf_),
|
97
|
-
self->udp_sender_,
|
98
|
-
[self, handler = std::forward<Handler>(handler)](
|
99
|
-
std::error_code ec2, std::size_t bytes_transferred) mutable {
|
100
|
-
self->deadline_.cancel();
|
101
|
-
if (ec2) {
|
102
|
-
return handler({ ec2 });
|
103
|
-
}
|
104
|
-
self->recv_buf_.resize(bytes_transferred);
|
105
|
-
dns_message message = dns_codec::decode(self->recv_buf_);
|
106
|
-
if (message.header.flags.tc == truncation::yes) {
|
107
|
-
self->udp_.close();
|
108
|
-
return self->retry_with_tcp(std::forward<Handler>(handler));
|
109
|
-
}
|
110
|
-
dns_srv_response resp{ ec2 };
|
111
|
-
resp.targets.reserve(message.answers.size());
|
112
|
-
for (const auto& answer : message.answers) {
|
113
|
-
resp.targets.emplace_back(dns_srv_response::address{
|
114
|
-
utils::join_strings(answer.target.labels, "."), answer.port });
|
115
|
-
}
|
116
|
-
return handler(std::move(resp));
|
117
|
-
});
|
118
|
-
});
|
119
|
-
deadline_.expires_after(timeout);
|
120
|
-
deadline_.async_wait([self = shared_from_this()](std::error_code ec) {
|
121
|
-
if (ec == asio::error::operation_aborted) {
|
122
|
-
return;
|
123
|
-
}
|
124
|
-
self->udp_.cancel();
|
125
|
-
if (self->tcp_.is_open()) {
|
126
|
-
self->tcp_.cancel();
|
127
|
-
}
|
128
|
-
});
|
129
|
-
}
|
130
|
-
|
131
|
-
private:
|
132
|
-
template<class Handler>
|
133
|
-
void retry_with_tcp(Handler&& handler)
|
134
|
-
{
|
135
|
-
asio::ip::tcp::no_delay no_delay(true);
|
136
|
-
std::error_code ignore_ec;
|
137
|
-
tcp_.set_option(no_delay, ignore_ec);
|
138
|
-
asio::ip::tcp::endpoint endpoint(address_, port_);
|
139
|
-
tcp_.async_connect(
|
140
|
-
endpoint, [self = shared_from_this(), handler = std::forward<Handler>(handler)](std::error_code ec1) mutable {
|
141
|
-
if (ec1) {
|
142
|
-
self->deadline_.cancel();
|
143
|
-
return handler({ ec1 });
|
144
|
-
}
|
145
|
-
auto send_size = static_cast<std::uint16_t>(self->send_buf_.size());
|
146
|
-
self->send_buf_.insert(self->send_buf_.begin(), std::uint8_t(send_size & 0xffU));
|
147
|
-
self->send_buf_.insert(self->send_buf_.begin(), std::uint8_t(send_size >> 8U));
|
148
|
-
asio::async_write(
|
149
|
-
self->tcp_,
|
150
|
-
asio::buffer(self->send_buf_),
|
151
|
-
[self, handler = std::forward<Handler>(handler)](std::error_code ec2, std::size_t /* bytes_transferred */) mutable {
|
152
|
-
if (ec2) {
|
153
|
-
self->deadline_.cancel();
|
154
|
-
if (ec2 == asio::error::operation_aborted) {
|
155
|
-
ec2 = errc::common::unambiguous_timeout;
|
156
|
-
}
|
157
|
-
return handler({ ec2 });
|
158
|
-
}
|
159
|
-
asio::async_read(self->tcp_,
|
160
|
-
asio::buffer(&self->recv_buf_size_, sizeof(std::uint16_t)),
|
161
|
-
[self, handler = std::forward<Handler>(handler)](std::error_code ec3,
|
162
|
-
std::size_t /* bytes_transferred */) mutable {
|
163
|
-
if (ec3) {
|
164
|
-
self->deadline_.cancel();
|
165
|
-
return handler({ ec3 });
|
166
|
-
}
|
167
|
-
self->recv_buf_size_ = utils::byte_swap(self->recv_buf_size_);
|
168
|
-
self->recv_buf_.resize(self->recv_buf_size_);
|
169
|
-
asio::async_read(self->tcp_,
|
170
|
-
asio::buffer(self->recv_buf_),
|
171
|
-
[self, handler = std::forward<Handler>(handler)](
|
172
|
-
std::error_code ec4, std::size_t bytes_transferred) mutable {
|
173
|
-
self->deadline_.cancel();
|
174
|
-
if (ec4) {
|
175
|
-
return handler({ ec4 });
|
176
|
-
}
|
177
|
-
self->recv_buf_.resize(bytes_transferred);
|
178
|
-
dns_message message = dns_codec::decode(self->recv_buf_);
|
179
|
-
dns_srv_response resp{ ec4 };
|
180
|
-
resp.targets.reserve(message.answers.size());
|
181
|
-
for (const auto& answer : message.answers) {
|
182
|
-
resp.targets.emplace_back(dns_srv_response::address{
|
183
|
-
utils::join_strings(answer.target.labels, "."), answer.port });
|
184
|
-
}
|
185
|
-
return handler(std::move(resp));
|
186
|
-
});
|
187
|
-
});
|
188
|
-
});
|
189
|
-
});
|
190
|
-
}
|
191
|
-
|
192
|
-
asio::steady_timer deadline_;
|
193
|
-
asio::ip::udp::socket udp_;
|
194
|
-
asio::ip::udp::endpoint udp_sender_{};
|
195
|
-
asio::ip::tcp::socket tcp_;
|
196
|
-
|
197
|
-
asio::ip::address address_;
|
198
|
-
std::uint16_t port_;
|
199
|
-
|
200
|
-
std::vector<std::uint8_t> send_buf_{};
|
201
|
-
std::uint16_t recv_buf_size_{ 0 };
|
202
|
-
std::vector<std::uint8_t> recv_buf_{};
|
203
|
-
};
|
204
|
-
|
205
43
|
explicit dns_client(asio::io_context& ctx)
|
206
44
|
: ctx_(ctx)
|
207
45
|
{
|
208
46
|
}
|
209
47
|
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
auto address = asio::ip::address::from_string(config.nameserver(), ec);
|
215
|
-
if (ec) {
|
216
|
-
return handler({ ec });
|
217
|
-
}
|
218
|
-
auto cmd = std::make_shared<dns_srv_command>(ctx_, name, service, address, config.port());
|
219
|
-
cmd->execute(config.timeout(), std::forward<Handler>(handler));
|
220
|
-
}
|
48
|
+
void query_srv(const std::string& name,
|
49
|
+
const std::string& service,
|
50
|
+
const dns_config& config,
|
51
|
+
utils::movable_function<void(couchbase::core::io::dns::dns_srv_response&& resp)>&& handler);
|
221
52
|
|
222
53
|
asio::io_context& ctx_;
|
223
54
|
};
|
@@ -7,11 +7,13 @@ target_link_libraries(
|
|
7
7
|
snappy
|
8
8
|
fmt::fmt
|
9
9
|
spdlog::spdlog)
|
10
|
-
target_include_directories(couchbase_meta PRIVATE
|
11
|
-
|
12
|
-
${PROJECT_SOURCE_DIR}
|
13
|
-
${PROJECT_SOURCE_DIR}/third_party/http_parser)
|
10
|
+
target_include_directories(couchbase_meta PRIVATE ${PROJECT_BINARY_DIR}/generated ${PROJECT_SOURCE_DIR}
|
11
|
+
${PROJECT_SOURCE_DIR}/third_party/http_parser)
|
14
12
|
|
15
13
|
if(NOT COUCHBASE_CXX_CLIENT_POST_LINKED_OPENSSL)
|
16
|
-
|
14
|
+
if (TARGET PkgConfig::PKG_CONFIG_OPENSSL)
|
15
|
+
target_link_libraries(couchbase_meta PUBLIC PkgConfig::PKG_CONFIG_OPENSSL)
|
16
|
+
else()
|
17
|
+
target_link_libraries(couchbase_meta PUBLIC OpenSSL::SSL OpenSSL::Crypto)
|
18
|
+
endif()
|
17
19
|
endif()
|
@@ -100,9 +100,28 @@ sdk_build_info()
|
|
100
100
|
info["openssl_runtime"] = OpenSSL_version(OPENSSL_VERSION);
|
101
101
|
#elif defined(SSLEAY_VERSION)
|
102
102
|
info["openssl_runtime"] = SSLeay_version(SSLEAY_VERSION);
|
103
|
+
#endif
|
104
|
+
#if defined(OPENSSL_INFO_CONFIG_DIR)
|
105
|
+
info["openssl_config_dir"] = OPENSSL_info(OPENSSL_INFO_CONFIG_DIR);
|
106
|
+
#elif defined(OPENSSL_DIR)
|
107
|
+
if (std::string config_dir(OpenSSL_version(OPENSSL_DIR)); !config_dir.empty()) {
|
108
|
+
if (auto quote = config_dir.find('"'); quote != std::string::npos && quote + 2 < config_dir.size()) {
|
109
|
+
info["openssl_config_dir"] = config_dir.substr(quote + 1, config_dir.size() - quote - 2);
|
110
|
+
} else {
|
111
|
+
info["openssl_config_dir"] = config_dir;
|
112
|
+
}
|
113
|
+
}
|
103
114
|
#endif
|
104
115
|
info["openssl_default_cert_dir"] = X509_get_default_cert_dir();
|
105
116
|
info["openssl_default_cert_file"] = X509_get_default_cert_file();
|
117
|
+
info["openssl_ssl_interface_include_directories"] = OPENSSL_SSL_INTERFACE_INCLUDE_DIRECTORIES;
|
118
|
+
info["openssl_ssl_interface_link_libraries"] = OPENSSL_SSL_INTERFACE_LINK_LIBRARIES;
|
119
|
+
info["openssl_ssl_imported_location"] = OPENSSL_SSL_IMPORTED_LOCATION;
|
120
|
+
info["openssl_crypto_interface_imported_location"] = OPENSSL_CRYPTO_IMPORTED_LOCATION;
|
121
|
+
info["openssl_crypto_interface_include_directories"] = OPENSSL_CRYPTO_INTERFACE_INCLUDE_DIRECTORIES;
|
122
|
+
info["openssl_crypto_interface_link_libraries"] = OPENSSL_CRYPTO_INTERFACE_LINK_LIBRARIES;
|
123
|
+
info["openssl_pkg_config_interface_include_directories"] = OPENSSL_PKG_CONFIG_INTERFACE_INCLUDE_DIRECTORIES;
|
124
|
+
info["openssl_pkg_config_interface_link_libraries"] = OPENSSL_PKG_CONFIG_INTERFACE_LINK_LIBRARIES;
|
106
125
|
info["__cplusplus"] = fmt::format("{}", __cplusplus);
|
107
126
|
#if defined(_MSC_VER)
|
108
127
|
info["_MSC_VER"] = fmt::format("{}", _MSC_VER);
|
@@ -92,11 +92,14 @@ search_request::encode_to(search_request::encoded_request_type& encoded, http_co
|
|
92
92
|
{ "vectors", { { index_name, scan_vectors } } },
|
93
93
|
};
|
94
94
|
}
|
95
|
-
if (
|
96
|
-
body["scope"] = scope_name.value();
|
95
|
+
if (!collections.empty()) {
|
97
96
|
body["collections"] = collections;
|
98
97
|
}
|
99
98
|
|
99
|
+
for (const auto& [key, value] : raw) {
|
100
|
+
body[key] = utils::json::parse(value);
|
101
|
+
}
|
102
|
+
|
100
103
|
encoded.type = type;
|
101
104
|
encoded.headers["content-type"] = "application/json";
|
102
105
|
encoded.method = "POST";
|
@@ -130,7 +130,6 @@ struct search_request {
|
|
130
130
|
std::optional<couchbase::core::search_highlight_style> highlight_style{};
|
131
131
|
std::vector<std::string> highlight_fields{};
|
132
132
|
std::vector<std::string> fields{};
|
133
|
-
std::optional<std::string> scope_name{};
|
134
133
|
std::vector<std::string> collections{};
|
135
134
|
|
136
135
|
std::optional<couchbase::core::search_scan_consistency> scan_consistency{};
|
@@ -153,7 +153,7 @@ class active_transaction_record
|
|
153
153
|
if (const auto* compat = val.find(ATR_FIELD_FORWARD_COMPAT); compat != nullptr) {
|
154
154
|
forward_compat = *compat;
|
155
155
|
}
|
156
|
-
|
156
|
+
std::optional<uint32_t> expires_after_msec = std::max(val.optional<int32_t>(ATR_FIELD_EXPIRES_AFTER_MSECS).value_or(0), 0);
|
157
157
|
entries.emplace_back(resp.ctx.bucket(),
|
158
158
|
resp.ctx.id(),
|
159
159
|
key,
|
@@ -163,7 +163,7 @@ class active_transaction_record
|
|
163
163
|
parse_mutation_cas(val.optional<std::string>(ATR_FIELD_TIMESTAMP_COMPLETE).value_or("")),
|
164
164
|
parse_mutation_cas(val.optional<std::string>(ATR_FIELD_TIMESTAMP_ROLLBACK_START).value_or("")),
|
165
165
|
parse_mutation_cas(val.optional<std::string>(ATR_FIELD_TIMESTAMP_ROLLBACK_COMPLETE).value_or("")),
|
166
|
-
|
166
|
+
expires_after_msec,
|
167
167
|
process_document_ids(val, ATR_FIELD_DOCS_INSERTED),
|
168
168
|
process_document_ids(val, ATR_FIELD_DOCS_REPLACED),
|
169
169
|
process_document_ids(val, ATR_FIELD_DOCS_REMOVED),
|