couchbase 3.4.1 → 3.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/ext/couchbase/CMakeLists.txt +2 -0
  4. data/ext/couchbase/cmake/ThirdPartyDependencies.cmake +4 -0
  5. data/ext/couchbase/core/cluster_options.hxx +0 -1
  6. data/ext/couchbase/core/config_profile.cxx +23 -1
  7. data/ext/couchbase/core/config_profile.hxx +2 -12
  8. data/ext/couchbase/core/impl/analytics.cxx +236 -0
  9. data/ext/couchbase/core/impl/cluster.cxx +0 -1
  10. data/ext/couchbase/core/impl/dns_srv_tracker.cxx +5 -3
  11. data/ext/couchbase/core/impl/query.cxx +5 -5
  12. data/ext/couchbase/core/io/dns_client.cxx +225 -0
  13. data/ext/couchbase/core/io/dns_client.hxx +19 -188
  14. data/ext/couchbase/core/transactions/active_transaction_record.hxx +2 -2
  15. data/ext/couchbase/core/transactions/attempt_context_impl.cxx +3 -0
  16. data/ext/couchbase/core/transactions/attempt_context_impl.hxx +1 -1
  17. data/ext/couchbase/core/transactions/internal/transaction_context.hxx +12 -12
  18. data/ext/couchbase/core/transactions/internal/transactions_cleanup.hxx +7 -1
  19. data/ext/couchbase/core/transactions/transaction_context.cxx +1 -0
  20. data/ext/couchbase/core/transactions/transactions_cleanup.cxx +144 -155
  21. data/ext/couchbase/core/utils/connection_string.cxx +10 -3
  22. data/ext/couchbase/core/utils/connection_string.hxx +3 -3
  23. data/ext/couchbase/couchbase/analytics_error_context.hxx +143 -0
  24. data/ext/couchbase/couchbase/analytics_meta_data.hxx +155 -0
  25. data/ext/couchbase/couchbase/analytics_metrics.hxx +163 -0
  26. data/ext/couchbase/couchbase/analytics_options.hxx +359 -0
  27. data/ext/couchbase/couchbase/analytics_result.hxx +102 -0
  28. data/ext/couchbase/couchbase/analytics_scan_consistency.hxx +46 -0
  29. data/ext/couchbase/couchbase/analytics_status.hxx +41 -0
  30. data/ext/couchbase/couchbase/analytics_warning.hxx +85 -0
  31. data/ext/couchbase/couchbase/cluster.hxx +33 -0
  32. data/ext/couchbase/couchbase/fmt/analytics_status.hxx +76 -0
  33. data/ext/couchbase/couchbase/query_options.hxx +0 -1
  34. data/ext/couchbase/couchbase/scope.hxx +33 -0
  35. data/ext/couchbase/couchbase/transactions/attempt_context.hxx +1 -1
  36. data/ext/couchbase/test/CMakeLists.txt +1 -2
  37. data/ext/couchbase/test/test_helper.hxx +1 -1
  38. data/ext/couchbase/test/test_integration_analytics.cxx +289 -13
  39. data/ext/couchbase/test/test_integration_crud.cxx +8 -1
  40. data/ext/couchbase/test/test_integration_examples.cxx +41 -0
  41. data/ext/couchbase/test/test_integration_management.cxx +15 -3
  42. data/ext/couchbase/test/test_integration_search.cxx +601 -0
  43. data/ext/couchbase/test/test_transaction_transaction_simple.cxx +73 -0
  44. data/ext/couchbase/test/test_unit_config_profiles.cxx +12 -12
  45. data/ext/couchbase/test/test_unit_connection_string.cxx +35 -0
  46. data/ext/couchbase/third_party/snappy/CMakeLists.txt +150 -27
  47. data/ext/couchbase/third_party/snappy/cmake/config.h.in +28 -24
  48. data/ext/couchbase/third_party/snappy/snappy-internal.h +189 -25
  49. data/ext/couchbase/third_party/snappy/snappy-sinksource.cc +26 -9
  50. data/ext/couchbase/third_party/snappy/snappy-sinksource.h +11 -11
  51. data/ext/couchbase/third_party/snappy/snappy-stubs-internal.cc +1 -1
  52. data/ext/couchbase/third_party/snappy/snappy-stubs-internal.h +227 -308
  53. data/ext/couchbase/third_party/snappy/snappy-stubs-public.h.in +0 -11
  54. data/ext/couchbase/third_party/snappy/snappy.cc +1176 -410
  55. data/ext/couchbase/third_party/snappy/snappy.h +19 -4
  56. data/ext/couchbase.cxx +27 -6
  57. data/ext/revisions.rb +3 -3
  58. data/lib/couchbase/cluster.rb +13 -9
  59. data/lib/couchbase/cluster_registry.rb +7 -2
  60. data/lib/couchbase/configuration.rb +3 -4
  61. data/lib/couchbase/options.rb +85 -2
  62. data/lib/couchbase/search_options.rb +158 -240
  63. data/lib/couchbase/version.rb +1 -1
  64. metadata +17 -6
  65. data/ext/couchbase/core/CMakeLists.txt +0 -0
@@ -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
  };
@@ -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),
@@ -1147,6 +1147,9 @@ attempt_context_impl::get_with_query(const core::document_id& id, bool optional,
1147
1147
  // make a transaction_get_result from the row...
1148
1148
  try {
1149
1149
  if (resp.rows.empty()) {
1150
+ if (optional) {
1151
+ return op_completed_with_callback(std::move(cb), std::optional<transaction_get_result>());
1152
+ }
1150
1153
  return op_completed_with_error(
1151
1154
  std::move(cb), transaction_operation_failed(FAIL_DOC_NOT_FOUND, "document not found"));
1152
1155
  }
@@ -456,7 +456,7 @@ class attempt_context_impl
456
456
 
457
457
  void state(attempt_state s)
458
458
  {
459
- overall_.current_attempt().state = s;
459
+ overall_.current_attempt_state(s);
460
460
  }
461
461
 
462
462
  [[nodiscard]] const std::string atr_id()
@@ -49,30 +49,29 @@ class transaction_context
49
49
 
50
50
  [[nodiscard]] std::size_t num_attempts() const
51
51
  {
52
+ std::lock_guard<std::mutex> lock(mutex_);
52
53
  return attempts_.size();
53
54
  }
54
- [[nodiscard]] const std::vector<transaction_attempt>& attempts() const
55
- {
56
- return attempts_;
57
- }
58
- [[nodiscard]] std::vector<transaction_attempt>& attempts()
59
- {
60
- return const_cast<std::vector<transaction_attempt>&>(const_cast<const transaction_context*>(this)->attempts());
61
- }
62
55
  [[nodiscard]] const transaction_attempt& current_attempt() const
63
56
  {
57
+ std::lock_guard<std::mutex> lock(mutex_);
64
58
  if (attempts_.empty()) {
65
59
  throw std::runtime_error("transaction context has no attempts yet");
66
60
  }
67
61
  return attempts_.back();
68
62
  }
69
- [[nodiscard]] transaction_attempt& current_attempt()
70
- {
71
- return const_cast<transaction_attempt&>(const_cast<const transaction_context*>(this)->current_attempt());
72
- }
73
63
 
74
64
  void add_attempt();
75
65
 
66
+ void current_attempt_state(attempt_state s)
67
+ {
68
+ std::lock_guard<std::mutex> lock(mutex_);
69
+ if (attempts_.empty()) {
70
+ throw std::runtime_error("transaction_context has no attempts yet");
71
+ }
72
+ attempts_.back().state = s;
73
+ }
74
+
76
75
  [[nodiscard]] std::shared_ptr<core::cluster> cluster_ref()
77
76
  {
78
77
  return transactions_.cluster_ref();
@@ -191,6 +190,7 @@ class transaction_context
191
190
  std::string atr_collection_;
192
191
  transactions_cleanup& cleanup_;
193
192
  std::shared_ptr<attempt_context_impl> current_attempt_context_;
193
+ mutable std::mutex mutex_;
194
194
 
195
195
  std::unique_ptr<exp_delay> delay_;
196
196
  };
@@ -145,6 +145,12 @@ class transactions_cleanup
145
145
 
146
146
  void attempts_loop();
147
147
 
148
+ bool is_running()
149
+ {
150
+ std::unique_lock<std::mutex> lock(mutex_);
151
+ return running_;
152
+ }
153
+
148
154
  template<class R, class P>
149
155
  bool interruptable_wait(std::chrono::duration<R, P> time);
150
156
 
@@ -153,7 +159,7 @@ class transactions_cleanup
153
159
  void create_client_record(const couchbase::transactions::transaction_keyspace& keyspace);
154
160
  const atr_cleanup_stats handle_atr_cleanup(const core::document_id& atr_id,
155
161
  std::vector<transactions_cleanup_attempt>* result = nullptr);
156
- std::atomic<bool> running_{ false };
162
+ bool running_{ false };
157
163
  };
158
164
  } // namespace transactions
159
165
  } // namespace couchbase::core
@@ -45,6 +45,7 @@ void
45
45
  transaction_context::add_attempt()
46
46
  {
47
47
  transaction_attempt attempt{};
48
+ std::lock_guard<std::mutex> lock(mutex_);
48
49
  attempts_.push_back(attempt);
49
50
  }
50
51