couchbase 3.4.0 → 3.4.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (130) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/ext/couchbase/CMakeLists.txt +10 -3
  4. data/ext/couchbase/cmake/CompilerWarnings.cmake +12 -4
  5. data/ext/couchbase/cmake/Documentation.cmake +4 -3
  6. data/ext/couchbase/cmake/OpenSSL.cmake +52 -7
  7. data/ext/couchbase/cmake/ThirdPartyDependencies.cmake +4 -0
  8. data/ext/couchbase/cmake/VersionInfo.cmake +39 -3
  9. data/ext/couchbase/cmake/test_openssl.cxx +7 -0
  10. data/ext/couchbase/core/cluster_options.hxx +0 -1
  11. data/ext/couchbase/core/config_profile.cxx +23 -1
  12. data/ext/couchbase/core/config_profile.hxx +2 -12
  13. data/ext/couchbase/core/crypto/CMakeLists.txt +5 -1
  14. data/ext/couchbase/core/impl/analytics.cxx +236 -0
  15. data/ext/couchbase/core/impl/cluster.cxx +0 -1
  16. data/ext/couchbase/core/impl/collection_query_index_manager.cxx +3 -3
  17. data/ext/couchbase/core/impl/dns_srv_tracker.cxx +5 -3
  18. data/ext/couchbase/core/impl/get_all_query_indexes.cxx +3 -3
  19. data/ext/couchbase/core/impl/query.cxx +5 -5
  20. data/ext/couchbase/core/impl/transaction_get_result.cxx +54 -0
  21. data/ext/couchbase/core/io/dns_client.cxx +225 -0
  22. data/ext/couchbase/core/io/dns_client.hxx +19 -188
  23. data/ext/couchbase/core/meta/CMakeLists.txt +7 -5
  24. data/ext/couchbase/core/meta/version.cxx +19 -0
  25. data/ext/couchbase/core/operations/document_search.cxx +5 -2
  26. data/ext/couchbase/core/operations/document_search.hxx +0 -1
  27. data/ext/couchbase/core/transactions/active_transaction_record.hxx +2 -2
  28. data/ext/couchbase/core/transactions/atr_cleanup_entry.cxx +1 -0
  29. data/ext/couchbase/core/transactions/attempt_context_impl.cxx +65 -31
  30. data/ext/couchbase/core/transactions/attempt_context_impl.hxx +44 -23
  31. data/ext/couchbase/core/transactions/forward_compat.hxx +2 -2
  32. data/ext/couchbase/core/transactions/internal/transaction_context.hxx +13 -13
  33. data/ext/couchbase/core/transactions/internal/transaction_fields.hxx +1 -0
  34. data/ext/couchbase/core/transactions/internal/transactions_cleanup.hxx +7 -1
  35. data/ext/couchbase/core/transactions/staged_mutation.cxx +1 -1
  36. data/ext/couchbase/core/transactions/staged_mutation.hxx +12 -2
  37. data/ext/couchbase/core/transactions/transaction_context.cxx +9 -11
  38. data/ext/couchbase/core/transactions/transaction_get_result.cxx +41 -31
  39. data/ext/couchbase/core/transactions/transaction_get_result.hxx +7 -3
  40. data/ext/couchbase/core/transactions/transaction_links.hxx +13 -1
  41. data/ext/couchbase/core/transactions/transactions_cleanup.cxx +144 -155
  42. data/ext/couchbase/core/transactions/waitable_op_list.hxx +1 -0
  43. data/ext/couchbase/core/utils/connection_string.cxx +10 -3
  44. data/ext/couchbase/core/utils/connection_string.hxx +3 -3
  45. data/ext/couchbase/couchbase/analytics_error_context.hxx +143 -0
  46. data/ext/couchbase/couchbase/analytics_meta_data.hxx +155 -0
  47. data/ext/couchbase/couchbase/analytics_metrics.hxx +163 -0
  48. data/ext/couchbase/couchbase/analytics_options.hxx +359 -0
  49. data/ext/couchbase/couchbase/analytics_result.hxx +102 -0
  50. data/ext/couchbase/couchbase/analytics_scan_consistency.hxx +46 -0
  51. data/ext/couchbase/couchbase/analytics_status.hxx +41 -0
  52. data/ext/couchbase/couchbase/analytics_warning.hxx +85 -0
  53. data/ext/couchbase/couchbase/cluster.hxx +35 -2
  54. data/ext/couchbase/couchbase/cluster_options.hxx +10 -10
  55. data/ext/couchbase/couchbase/collection.hxx +22 -17
  56. data/ext/couchbase/couchbase/collection_query_index_manager.hxx +1 -1
  57. data/ext/couchbase/couchbase/common_options.hxx +1 -1
  58. data/ext/couchbase/couchbase/configuration_profile.hxx +1 -1
  59. data/ext/couchbase/couchbase/configuration_profiles_registry.hxx +0 -1
  60. data/ext/couchbase/couchbase/create_primary_query_index_options.hxx +1 -1
  61. data/ext/couchbase/couchbase/drop_primary_query_index_options.hxx +1 -1
  62. data/ext/couchbase/couchbase/drop_query_index_options.hxx +1 -1
  63. data/ext/couchbase/couchbase/fmt/analytics_status.hxx +76 -0
  64. data/ext/couchbase/couchbase/fmt/cas.hxx +12 -0
  65. data/ext/couchbase/couchbase/fmt/durability_level.hxx +6 -0
  66. data/ext/couchbase/couchbase/fmt/key_value_extended_error_info.hxx +6 -0
  67. data/ext/couchbase/couchbase/fmt/key_value_status_code.hxx +6 -0
  68. data/ext/couchbase/couchbase/fmt/mutation_token.hxx +6 -0
  69. data/ext/couchbase/couchbase/fmt/query_scan_consistency.hxx +6 -0
  70. data/ext/couchbase/couchbase/fmt/query_status.hxx +6 -0
  71. data/ext/couchbase/couchbase/fmt/retry_reason.hxx +6 -0
  72. data/ext/couchbase/couchbase/fmt/tls_verify_mode.hxx +6 -0
  73. data/ext/couchbase/couchbase/get_all_query_indexes_options.hxx +5 -4
  74. data/ext/couchbase/couchbase/query_index_manager.hxx +4 -2
  75. data/ext/couchbase/couchbase/query_options.hxx +0 -1
  76. data/ext/couchbase/couchbase/scope.hxx +34 -1
  77. data/ext/couchbase/couchbase/subdoc/array_add_unique.hxx +2 -0
  78. data/ext/couchbase/couchbase/subdoc/array_append.hxx +2 -0
  79. data/ext/couchbase/couchbase/subdoc/array_insert.hxx +2 -0
  80. data/ext/couchbase/couchbase/subdoc/array_prepend.hxx +2 -0
  81. data/ext/couchbase/couchbase/subdoc/count.hxx +2 -0
  82. data/ext/couchbase/couchbase/subdoc/counter.hxx +2 -0
  83. data/ext/couchbase/couchbase/subdoc/exists.hxx +2 -0
  84. data/ext/couchbase/couchbase/subdoc/get.hxx +2 -0
  85. data/ext/couchbase/couchbase/subdoc/insert.hxx +2 -0
  86. data/ext/couchbase/couchbase/subdoc/remove.hxx +2 -0
  87. data/ext/couchbase/couchbase/subdoc/replace.hxx +3 -1
  88. data/ext/couchbase/couchbase/subdoc/upsert.hxx +2 -0
  89. data/ext/couchbase/couchbase/transaction_op_error_context.hxx +4 -4
  90. data/ext/couchbase/couchbase/transactions/attempt_context.hxx +1 -1
  91. data/ext/couchbase/couchbase/transactions/transaction_get_result.hxx +36 -51
  92. data/ext/couchbase/couchbase/transactions/transactions_config.hxx +1 -1
  93. data/ext/couchbase/test/CMakeLists.txt +3 -2
  94. data/ext/couchbase/test/test_helper.hxx +1 -1
  95. data/ext/couchbase/test/test_integration_analytics.cxx +289 -13
  96. data/ext/couchbase/test/test_integration_crud.cxx +8 -1
  97. data/ext/couchbase/test/test_integration_examples.cxx +182 -0
  98. data/ext/couchbase/test/test_integration_management.cxx +15 -3
  99. data/ext/couchbase/test/test_integration_search.cxx +601 -0
  100. data/ext/couchbase/test/test_transaction_transaction_simple.cxx +73 -0
  101. data/ext/couchbase/test/test_unit_config_profiles.cxx +12 -12
  102. data/ext/couchbase/test/test_unit_connection_string.cxx +35 -0
  103. data/ext/couchbase/test/test_unit_transaction_utils.cxx +76 -19
  104. data/ext/couchbase/third_party/snappy/CMakeLists.txt +150 -27
  105. data/ext/couchbase/third_party/snappy/cmake/config.h.in +28 -24
  106. data/ext/couchbase/third_party/snappy/snappy-internal.h +189 -25
  107. data/ext/couchbase/third_party/snappy/snappy-sinksource.cc +26 -9
  108. data/ext/couchbase/third_party/snappy/snappy-sinksource.h +11 -11
  109. data/ext/couchbase/third_party/snappy/snappy-stubs-internal.cc +1 -1
  110. data/ext/couchbase/third_party/snappy/snappy-stubs-internal.h +227 -308
  111. data/ext/couchbase/third_party/snappy/snappy-stubs-public.h.in +0 -11
  112. data/ext/couchbase/third_party/snappy/snappy.cc +1176 -410
  113. data/ext/couchbase/third_party/snappy/snappy.h +19 -4
  114. data/ext/couchbase.cxx +506 -26
  115. data/ext/extconf.rb +2 -1
  116. data/ext/revisions.rb +3 -2
  117. data/lib/couchbase/binary_collection.rb +4 -4
  118. data/lib/couchbase/cluster.rb +13 -9
  119. data/lib/couchbase/cluster_registry.rb +7 -2
  120. data/lib/couchbase/collection.rb +5 -0
  121. data/lib/couchbase/configuration.rb +3 -4
  122. data/lib/couchbase/errors.rb +10 -0
  123. data/lib/couchbase/management/collection_query_index_manager.rb +183 -0
  124. data/lib/couchbase/management/query_index_manager.rb +35 -3
  125. data/lib/couchbase/management.rb +1 -0
  126. data/lib/couchbase/options.rb +87 -5
  127. data/lib/couchbase/search_options.rb +158 -240
  128. data/lib/couchbase/version.rb +1 -1
  129. metadata +21 -6
  130. 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
- get_all_indexes_handler&& handler)
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
- get_all_indexes_handler&& handler)
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-2021 Couchbase, Inc.
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/join_strings.hxx"
21
- #include "dns_codec.hxx"
20
+ #include "core/utils/movable_function.hxx"
22
21
  #include "dns_config.hxx"
23
22
 
24
- #include <couchbase/error_codes.hxx>
23
+ #include <asio/io_context.hpp>
25
24
 
26
- #include <asio/ip/tcp.hpp>
27
- #include <asio/read.hpp>
28
- #include <asio/write.hpp>
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
- template<class Handler>
211
- void query_srv(const std::string& name, const std::string& service, const dns_config& config, Handler&& handler)
212
- {
213
- std::error_code ec;
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
- ${PROJECT_BINARY_DIR}/generated
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
- target_link_libraries(couchbase_meta PUBLIC OpenSSL::SSL OpenSSL::Crypto)
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 (scope_name) {
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
- val.optional<std::uint32_t>(ATR_FIELD_EXPIRES_AFTER_MSECS),
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),