couchbase 3.4.1 → 3.4.2

Sign up to get free protection for your applications and to get access to all the features.
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