couchbase 4.2.5-dev.3 → 4.2.6-dev

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 (122) hide show
  1. package/README.md +81 -9
  2. package/deps/couchbase-cxx-client/CMakeLists.txt +9 -1
  3. package/deps/couchbase-cxx-client/bin/api.rb +234 -0
  4. package/deps/couchbase-cxx-client/bin/create-search-index +18 -135
  5. package/deps/couchbase-cxx-client/bin/init-cluster +17 -139
  6. package/deps/couchbase-cxx-client/bin/load-sample-buckets +54 -0
  7. package/deps/couchbase-cxx-client/core/cluster.hxx +33 -12
  8. package/deps/couchbase-cxx-client/core/cluster_options.hxx +3 -0
  9. package/deps/couchbase-cxx-client/core/crud_component.cxx +51 -22
  10. package/deps/couchbase-cxx-client/core/impl/build_deferred_query_indexes.cxx +115 -50
  11. package/deps/couchbase-cxx-client/core/impl/cluster.cxx +6 -0
  12. package/deps/couchbase-cxx-client/core/impl/create_bucket.cxx +155 -0
  13. package/deps/couchbase-cxx-client/core/impl/create_query_index.cxx +172 -59
  14. package/deps/couchbase-cxx-client/core/impl/dns_srv_tracker.cxx +2 -1
  15. package/deps/couchbase-cxx-client/core/impl/drop_bucket.cxx +66 -0
  16. package/deps/couchbase-cxx-client/core/impl/drop_query_index.cxx +138 -59
  17. package/deps/couchbase-cxx-client/core/impl/flush_bucket.cxx +66 -0
  18. package/deps/couchbase-cxx-client/core/impl/get_all_buckets.cxx +163 -0
  19. package/deps/couchbase-cxx-client/core/impl/get_all_query_indexes.cxx +67 -37
  20. package/deps/couchbase-cxx-client/core/impl/get_bucket.cxx +153 -0
  21. package/deps/couchbase-cxx-client/core/impl/internal_manager_error_context.cxx +113 -0
  22. package/deps/couchbase-cxx-client/core/impl/internal_manager_error_context.hxx +60 -0
  23. package/deps/couchbase-cxx-client/core/impl/key_value_error_category.cxx +2 -4
  24. package/deps/couchbase-cxx-client/core/impl/manager_error_context.cxx +100 -0
  25. package/deps/couchbase-cxx-client/core/impl/query.cxx +1 -0
  26. package/deps/couchbase-cxx-client/core/impl/update_bucket.cxx +130 -0
  27. package/deps/couchbase-cxx-client/core/impl/watch_query_indexes.cxx +53 -29
  28. package/deps/couchbase-cxx-client/core/io/dns_client.cxx +71 -38
  29. package/deps/couchbase-cxx-client/core/io/dns_config.cxx +5 -4
  30. package/deps/couchbase-cxx-client/core/io/mcbp_session.cxx +5 -6
  31. package/deps/couchbase-cxx-client/core/meta/features.hxx +6 -0
  32. package/deps/couchbase-cxx-client/core/operations/document_query.cxx +11 -0
  33. package/deps/couchbase-cxx-client/core/operations/document_query.hxx +1 -0
  34. package/deps/couchbase-cxx-client/core/origin.cxx +270 -0
  35. package/deps/couchbase-cxx-client/core/origin.hxx +2 -0
  36. package/deps/couchbase-cxx-client/core/protocol/status.cxx +2 -2
  37. package/deps/couchbase-cxx-client/core/range_scan_options.cxx +3 -27
  38. package/deps/couchbase-cxx-client/core/range_scan_options.hxx +13 -17
  39. package/deps/couchbase-cxx-client/core/range_scan_orchestrator.cxx +367 -170
  40. package/deps/couchbase-cxx-client/core/range_scan_orchestrator.hxx +13 -2
  41. package/deps/couchbase-cxx-client/core/range_scan_orchestrator_options.hxx +5 -3
  42. package/deps/couchbase-cxx-client/core/scan_options.hxx +0 -19
  43. package/deps/couchbase-cxx-client/core/scan_result.cxx +19 -5
  44. package/deps/couchbase-cxx-client/core/scan_result.hxx +5 -2
  45. package/deps/couchbase-cxx-client/core/timeout_defaults.hxx +2 -3
  46. package/deps/couchbase-cxx-client/core/topology/capabilities.hxx +1 -0
  47. package/deps/couchbase-cxx-client/core/topology/capabilities_fmt.hxx +2 -0
  48. package/deps/couchbase-cxx-client/core/topology/collections_manifest_fmt.hxx +1 -1
  49. package/deps/couchbase-cxx-client/core/topology/configuration.hxx +5 -0
  50. package/deps/couchbase-cxx-client/core/topology/configuration_json.hxx +2 -0
  51. package/deps/couchbase-cxx-client/core/utils/connection_string.cxx +4 -0
  52. package/deps/couchbase-cxx-client/couchbase/behavior_options.hxx +19 -2
  53. package/deps/couchbase-cxx-client/couchbase/bucket_manager.hxx +135 -0
  54. package/deps/couchbase-cxx-client/couchbase/build_query_index_options.hxx +0 -30
  55. package/deps/couchbase-cxx-client/couchbase/cluster.hxx +14 -0
  56. package/deps/couchbase-cxx-client/couchbase/collection_query_index_manager.hxx +7 -48
  57. package/deps/couchbase-cxx-client/couchbase/create_bucket_options.hxx +41 -0
  58. package/deps/couchbase-cxx-client/couchbase/create_primary_query_index_options.hxx +0 -29
  59. package/deps/couchbase-cxx-client/couchbase/create_query_index_options.hxx +0 -33
  60. package/deps/couchbase-cxx-client/couchbase/drop_bucket_options.hxx +41 -0
  61. package/deps/couchbase-cxx-client/couchbase/drop_primary_query_index_options.hxx +0 -30
  62. package/deps/couchbase-cxx-client/couchbase/drop_query_index_options.hxx +0 -31
  63. package/deps/couchbase-cxx-client/couchbase/error_codes.hxx +1 -2
  64. package/deps/couchbase-cxx-client/couchbase/flush_bucket_options.hxx +41 -0
  65. package/deps/couchbase-cxx-client/couchbase/get_all_buckets_options.hxx +44 -0
  66. package/deps/couchbase-cxx-client/couchbase/get_all_query_indexes_options.hxx +0 -30
  67. package/deps/couchbase-cxx-client/couchbase/get_bucket_options.hxx +43 -0
  68. package/deps/couchbase-cxx-client/couchbase/management/bucket_settings.hxx +116 -0
  69. package/deps/couchbase-cxx-client/couchbase/manager_error_context.hxx +29 -53
  70. package/deps/couchbase-cxx-client/couchbase/query_index_manager.hxx +16 -83
  71. package/deps/couchbase-cxx-client/couchbase/query_options.hxx +18 -0
  72. package/deps/couchbase-cxx-client/couchbase/security_options.hxx +15 -0
  73. package/deps/couchbase-cxx-client/couchbase/update_bucket_options.hxx +41 -0
  74. package/deps/couchbase-cxx-client/couchbase/watch_query_indexes_options.hxx +0 -31
  75. package/deps/couchbase-cxx-client/docs/cbc-analytics.md +1 -0
  76. package/deps/couchbase-cxx-client/docs/cbc-get.md +1 -0
  77. package/deps/couchbase-cxx-client/docs/cbc-pillowfight.md +1 -0
  78. package/deps/couchbase-cxx-client/docs/cbc-query.md +1 -0
  79. package/deps/couchbase-cxx-client/docs/cbc.md +10 -0
  80. package/deps/couchbase-cxx-client/test/CMakeLists.txt +1 -0
  81. package/deps/couchbase-cxx-client/test/test_integration_collections.cxx +6 -0
  82. package/deps/couchbase-cxx-client/test/test_integration_crud.cxx +5 -0
  83. package/deps/couchbase-cxx-client/test/test_integration_examples.cxx +137 -1
  84. package/deps/couchbase-cxx-client/test/test_integration_management.cxx +709 -266
  85. package/deps/couchbase-cxx-client/test/test_integration_query.cxx +19 -7
  86. package/deps/couchbase-cxx-client/test/test_integration_range_scan.cxx +351 -112
  87. package/deps/couchbase-cxx-client/test/test_integration_search.cxx +10 -1
  88. package/deps/couchbase-cxx-client/test/test_transaction_public_async_api.cxx +13 -12
  89. package/deps/couchbase-cxx-client/test/test_transaction_public_blocking_api.cxx +27 -21
  90. package/deps/couchbase-cxx-client/test/test_unit_query.cxx +75 -0
  91. package/deps/couchbase-cxx-client/test/utils/server_version.hxx +5 -0
  92. package/deps/couchbase-cxx-client/test/utils/wait_until.cxx +29 -10
  93. package/deps/couchbase-cxx-client/test/utils/wait_until.hxx +3 -1
  94. package/deps/couchbase-cxx-client/tools/utils.cxx +4 -1
  95. package/dist/binding.d.ts +21 -16
  96. package/dist/binding.js +1 -4
  97. package/dist/bindingutilities.d.ts +6 -1
  98. package/dist/bindingutilities.js +36 -1
  99. package/dist/collection.d.ts +65 -3
  100. package/dist/collection.js +107 -0
  101. package/dist/crudoptypes.d.ts +34 -0
  102. package/dist/crudoptypes.js +18 -1
  103. package/dist/queryexecutor.js +1 -0
  104. package/dist/querytypes.d.ts +7 -0
  105. package/dist/rangeScan.d.ts +107 -0
  106. package/dist/rangeScan.js +91 -0
  107. package/dist/streamablepromises.d.ts +6 -0
  108. package/dist/streamablepromises.js +25 -1
  109. package/package.json +13 -14
  110. package/scripts/createPlatformPackages.js +1 -4
  111. package/src/addondata.hpp +1 -0
  112. package/src/binding.cpp +5 -2
  113. package/src/connection.cpp +108 -2
  114. package/src/connection.hpp +1 -0
  115. package/src/constants.cpp +2 -12
  116. package/src/jstocbpp_autogen.hpp +49 -22
  117. package/src/jstocbpp_basic.hpp +2 -8
  118. package/src/mutationtoken.cpp +13 -0
  119. package/src/scan_iterator.cpp +90 -0
  120. package/src/scan_iterator.hpp +30 -0
  121. package/tools/gen-bindings-json.py +9 -8
  122. package/deps/couchbase-cxx-client/core/impl/collection_query_index_manager.cxx +0 -93
@@ -24,16 +24,6 @@
24
24
 
25
25
  namespace couchbase::core::impl
26
26
  {
27
-
28
- template<typename Response>
29
- static manager_error_context
30
- build_context(Response& resp, std::optional<std::error_code> ec = {})
31
- {
32
- return { ec ? ec.value() : resp.ctx.ec, resp.ctx.last_dispatched_to, resp.ctx.last_dispatched_from,
33
- resp.ctx.retry_attempts, std::move(resp.ctx.retry_reasons), std::move(resp.ctx.client_context_id),
34
- resp.ctx.http_status, std::move(resp.ctx.http_body), std::move(resp.ctx.path) };
35
- }
36
-
37
27
  class watch_context : public std::enable_shared_from_this<watch_context>
38
28
  {
39
29
 
@@ -50,9 +40,18 @@ class watch_context : public std::enable_shared_from_this<watch_context>
50
40
  std::chrono::milliseconds timeout_{ options_.timeout.value_or(core_->origin().second.options().query_timeout) };
51
41
  std::atomic<size_t> attempts_{ 0 };
52
42
 
53
- void finish(manager_error_context error_ctx)
43
+ template<typename Response>
44
+ void finish(Response& resp, std::optional<std::error_code> ec = {})
54
45
  {
55
- handler_(error_ctx);
46
+ handler_({ manager_error_context(internal_manager_error_context{ ec ? ec.value() : resp.ctx.ec,
47
+ resp.ctx.last_dispatched_to,
48
+ resp.ctx.last_dispatched_from,
49
+ resp.ctx.retry_attempts,
50
+ std::move(resp.ctx.retry_reasons),
51
+ std::move(resp.ctx.client_context_id),
52
+ resp.ctx.http_status,
53
+ std::move(resp.ctx.http_body),
54
+ std::move(resp.ctx.path) }) });
56
55
  timer_.cancel();
57
56
  }
58
57
  std::chrono::milliseconds remaining()
@@ -79,9 +78,9 @@ class watch_context : public std::enable_shared_from_this<watch_context>
79
78
  complete &= it != resp.indexes.end() && it->state == "online";
80
79
  }
81
80
  if (complete || resp.ctx.ec == couchbase::errc::common::ambiguous_timeout) {
82
- finish(build_context(resp));
81
+ finish(resp);
83
82
  } else if (remaining().count() <= 0) {
84
- finish(build_context(resp, couchbase::errc::common::ambiguous_timeout));
83
+ finish(resp, couchbase::errc::common::ambiguous_timeout);
85
84
  complete = true;
86
85
  }
87
86
  return complete;
@@ -141,28 +140,53 @@ class watch_context : public std::enable_shared_from_this<watch_context>
141
140
  core_->execute(req, resp_fn);
142
141
  }
143
142
  };
143
+ } // namespace couchbase::core::impl
144
144
 
145
+ namespace couchbase
146
+ {
145
147
  void
146
- initiate_watch_query_indexes(std::shared_ptr<couchbase::core::cluster> core,
147
- std::string bucket_name,
148
- std::vector<std::string> index_names,
149
- couchbase::watch_query_indexes_options::built options,
150
- query_context query_ctx,
151
- std::string collection_name,
152
- watch_query_indexes_handler&& handler)
148
+ query_index_manager::watch_indexes(std::string bucket_name,
149
+ std::vector<std::string> index_names,
150
+ const couchbase::watch_query_indexes_options& options,
151
+ couchbase::watch_query_indexes_handler&& handler)
153
152
  {
154
- auto ctx = std::make_shared<watch_context>(core, bucket_name, index_names, options, query_ctx, collection_name, std::move(handler));
153
+ auto ctx = std::make_shared<couchbase::core::impl::watch_context>(
154
+ core_, std::move(bucket_name), std::move(index_names), options.build(), core::query_context{}, "", std::move(handler));
155
155
  ctx->execute();
156
156
  }
157
157
 
158
+ auto
159
+ query_index_manager::watch_indexes(std::string bucket_name,
160
+ std::vector<std::string> index_names,
161
+ const couchbase::watch_query_indexes_options& options) -> std::future<manager_error_context>
162
+ {
163
+ auto barrier = std::make_shared<std::promise<manager_error_context>>();
164
+ watch_indexes(
165
+ std::move(bucket_name), std::move(index_names), options, [barrier](auto ctx) mutable { barrier->set_value(std::move(ctx)); });
166
+ return barrier->get_future();
167
+ }
168
+
158
169
  void
159
- initiate_watch_query_indexes(std::shared_ptr<couchbase::core::cluster> core,
160
- std::string bucket_name,
161
- std::vector<std::string> index_names,
162
- couchbase::watch_query_indexes_options::built options,
163
- watch_query_indexes_handler&& handler)
170
+ collection_query_index_manager::watch_indexes(std::vector<std::string> index_names,
171
+ const watch_query_indexes_options& options,
172
+ watch_query_indexes_handler&& handler) const
164
173
  {
165
- initiate_watch_query_indexes(core, std::move(bucket_name), std::move(index_names), options, {}, "", std::move(handler));
174
+ auto ctx = std::make_shared<couchbase::core::impl::watch_context>(core_,
175
+ bucket_name_,
176
+ std::move(index_names),
177
+ options.build(),
178
+ core::query_context(bucket_name_, scope_name_),
179
+ collection_name_,
180
+ std::move(handler));
181
+ ctx->execute();
166
182
  }
167
183
 
168
- } // namespace couchbase::core::impl
184
+ auto
185
+ collection_query_index_manager::watch_indexes(std::vector<std::string> index_names, const couchbase::watch_query_indexes_options& options)
186
+ -> std::future<manager_error_context>
187
+ {
188
+ auto barrier = std::make_shared<std::promise<manager_error_context>>();
189
+ watch_indexes(std::move(index_names), options, [barrier](auto ctx) mutable { barrier->set_value(std::move(ctx)); });
190
+ return barrier->get_future();
191
+ }
192
+ } // namespace couchbase
@@ -28,6 +28,10 @@
28
28
  #include <asio/read.hpp>
29
29
  #include <asio/write.hpp>
30
30
 
31
+ #include <fmt/chrono.h>
32
+
33
+ #include <spdlog/fmt/bin_to_hex.h>
34
+
31
35
  #include <memory>
32
36
  #include <sstream>
33
37
 
@@ -68,13 +72,22 @@ class dns_srv_command : public std::enable_shared_from_this<dns_srv_command>
68
72
 
69
73
  void execute(std::chrono::milliseconds total_timeout, std::chrono::milliseconds udp_timeout)
70
74
  {
75
+ CB_LOG_TRACE("Query DNS-SRV (UDP) address=\"{}:{}\", udp_timeout={}, total_timeout={}{:a}",
76
+ address_.to_string(),
77
+ port_,
78
+ udp_timeout,
79
+ total_timeout,
80
+ spdlog::to_hex(send_buf_));
71
81
  asio::ip::udp::endpoint endpoint(address_, port_);
72
82
  udp_.open(endpoint.protocol());
73
83
  udp_.async_send_to(
74
84
  asio::buffer(send_buf_), endpoint, [self = shared_from_this()](std::error_code ec1, std::size_t /* bytes_transferred */) mutable {
75
85
  if (ec1) {
76
86
  self->udp_deadline_.cancel();
77
- CB_LOG_DEBUG("DNS UDP write operation has got error {}, retrying with TCP", ec1.message());
87
+ CB_LOG_DEBUG("DNS UDP write operation has got error, retrying with TCP, address=\"{}:{}\", ec={}",
88
+ self->address_.to_string(),
89
+ self->port_,
90
+ ec1.message());
78
91
  return self->retry_with_tcp();
79
92
  }
80
93
 
@@ -83,7 +96,10 @@ class dns_srv_command : public std::enable_shared_from_this<dns_srv_command>
83
96
  asio::buffer(self->recv_buf_), self->udp_sender_, [self](std::error_code ec2, std::size_t bytes_transferred) mutable {
84
97
  self->udp_deadline_.cancel();
85
98
  if (ec2) {
86
- CB_LOG_DEBUG("DNS UDP read operation has got error {}, retrying with TCP", ec2.message());
99
+ CB_LOG_DEBUG("DNS UDP read operation has got error, retrying with TCP, address=\"{}:{}\", ec={}",
100
+ self->address_.to_string(),
101
+ self->port_,
102
+ ec2.message());
87
103
  return self->retry_with_tcp();
88
104
  }
89
105
  self->recv_buf_.resize(bytes_transferred);
@@ -104,11 +120,13 @@ class dns_srv_command : public std::enable_shared_from_this<dns_srv_command>
104
120
  });
105
121
  });
106
122
  udp_deadline_.expires_after(udp_timeout);
107
- deadline_.async_wait([self = shared_from_this()](std::error_code ec) {
123
+ udp_deadline_.async_wait([self = shared_from_this()](std::error_code ec) {
108
124
  if (ec == asio::error::operation_aborted) {
109
125
  return;
110
126
  }
111
- CB_LOG_DEBUG("DNS UDP deadline has been reached, cancelling UDP operation and fall back to TCP");
127
+ CB_LOG_DEBUG("DNS UDP deadline has been reached, cancelling UDP operation and fall back to TCP, address=\"{}:{}\"",
128
+ self->address_.to_string(),
129
+ self->port_);
112
130
  self->udp_.cancel();
113
131
  return self->retry_with_tcp();
114
132
  });
@@ -118,7 +136,10 @@ class dns_srv_command : public std::enable_shared_from_this<dns_srv_command>
118
136
  if (ec == asio::error::operation_aborted) {
119
137
  return;
120
138
  }
121
- CB_LOG_DEBUG("DNS deadline has been reached, cancelling in-flight operations (tcp.is_open={})", self->tcp_.is_open());
139
+ CB_LOG_DEBUG("DNS deadline has been reached, cancelling in-flight operations (tcp.is_open={}, address=\"{}:{}\")",
140
+ self->tcp_.is_open(),
141
+ self->address_.to_string(),
142
+ self->port_);
122
143
  self->udp_.cancel();
123
144
  if (self->tcp_.is_open()) {
124
145
  self->tcp_.cancel();
@@ -140,53 +161,65 @@ class dns_srv_command : public std::enable_shared_from_this<dns_srv_command>
140
161
  tcp_.async_connect(endpoint, [self = shared_from_this()](std::error_code ec1) mutable {
141
162
  if (ec1) {
142
163
  self->deadline_.cancel();
143
- CB_LOG_DEBUG("DNS TCP connection has been aborted, {}", ec1.message());
164
+ CB_LOG_DEBUG(
165
+ "DNS TCP connection has been aborted, address=\"{}:{}\", ec={}", self->address_.to_string(), self->port_, ec1.message());
144
166
  return self->handler_({ ec1 });
145
167
  }
146
168
  auto send_size = static_cast<std::uint16_t>(self->send_buf_.size());
147
169
  self->send_buf_.insert(self->send_buf_.begin(), static_cast<std::uint8_t>(send_size & 0xffU));
148
170
  self->send_buf_.insert(self->send_buf_.begin(), static_cast<std::uint8_t>(send_size >> 8U));
171
+ CB_LOG_TRACE(
172
+ "Query DNS-SRV (TCP) address=\"{}:{}\"{:a}", self->address_.to_string(), self->port_, spdlog::to_hex(self->send_buf_));
149
173
  asio::async_write(
150
174
  self->tcp_, asio::buffer(self->send_buf_), [self](std::error_code ec2, std::size_t /* bytes_transferred */) mutable {
151
175
  if (ec2) {
152
- CB_LOG_DEBUG("DNS TCP write operation has been aborted, {}", ec2.message());
176
+ CB_LOG_DEBUG("DNS TCP write operation has been aborted, address=\"{}:{}\", ec={}",
177
+ self->address_.to_string(),
178
+ self->port_,
179
+ ec2.message());
153
180
  self->deadline_.cancel();
154
181
  if (ec2 == asio::error::operation_aborted) {
155
182
  ec2 = errc::common::unambiguous_timeout;
156
183
  }
157
184
  return self->handler_({ ec2 });
158
185
  }
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
- });
186
+ asio::async_read(
187
+ self->tcp_,
188
+ asio::buffer(&self->recv_buf_size_, sizeof(std::uint16_t)),
189
+ [self](std::error_code ec3, std::size_t /* bytes_transferred */) mutable {
190
+ if (ec3) {
191
+ CB_LOG_DEBUG("DNS TCP buf size read operation has been aborted, address=\"{}:{}\", ec={}",
192
+ self->address_.to_string(),
193
+ self->port_,
194
+ ec3.message());
195
+ self->deadline_.cancel();
196
+ return self->handler_({ ec3 });
197
+ }
198
+ self->recv_buf_size_ = utils::byte_swap(self->recv_buf_size_);
199
+ self->recv_buf_.resize(self->recv_buf_size_);
200
+ CB_LOG_DEBUG("DNS TCP schedule read of {} bytes", self->recv_buf_size_);
201
+ asio::async_read(
202
+ self->tcp_, asio::buffer(self->recv_buf_), [self](std::error_code ec4, std::size_t bytes_transferred) mutable {
203
+ self->deadline_.cancel();
204
+ if (ec4) {
205
+ CB_LOG_DEBUG("DNS TCP read operation has been aborted, address=\"{}:{}\", ec={}",
206
+ self->address_.to_string(),
207
+ self->port_,
208
+ ec4.message());
209
+ return self->handler_({ ec4 });
210
+ }
211
+ self->recv_buf_.resize(bytes_transferred);
212
+ const dns_message message = dns_codec::decode(self->recv_buf_);
213
+ dns_srv_response resp{ ec4 };
214
+ resp.targets.reserve(message.answers.size());
215
+ for (const auto& answer : message.answers) {
216
+ resp.targets.emplace_back(
217
+ dns_srv_response::address{ utils::join_strings(answer.target.labels, "."), answer.port });
218
+ }
219
+ CB_LOG_DEBUG("DNS TCP returned {} records", resp.targets.size());
220
+ return self->handler_(std::move(resp));
221
+ });
222
+ });
190
223
  });
191
224
  });
192
225
  }
@@ -87,7 +87,7 @@ load_resolv_conf()
87
87
 
88
88
  if (dns_servers.size() > 0) {
89
89
  CB_LOG_DEBUG(
90
- "Found DNS Servers: [{}], using nameserver: {}", couchbase::core::utils::join_strings(dns_servers, ", "), dns_servers[0]);
90
+ "Found DNS Servers: [{}], selected nameserver: \"{}\"", couchbase::core::utils::join_strings(dns_servers, ", "), dns_servers[0]);
91
91
  return dns_servers[0];
92
92
  }
93
93
  CB_LOG_WARNING("Unable to find DNS nameserver");
@@ -118,13 +118,13 @@ load_resolv_conf(const char* conf_path)
118
118
  if (space == std::string::npos || space == offset || line.size() < space + 2) {
119
119
  continue;
120
120
  }
121
- if (std::string keyword = line.substr(offset, space); keyword != "nameserver") {
121
+ if (const auto keyword = line.substr(offset, space); keyword != "nameserver") {
122
122
  continue;
123
123
  }
124
124
  offset = space + 1;
125
125
  space = line.find(' ', offset);
126
- auto nameserver = line.substr(offset, space);
127
- CB_LOG_DEBUG("Using nameserver: {}", nameserver);
126
+ auto nameserver = (space == std::string::npos) ? line.substr(offset) : line.substr(offset, space - offset);
127
+ CB_LOG_DEBUG("Selected nameserver: \"{}\" from \"{}\"", nameserver, conf_path);
128
128
  return nameserver;
129
129
  }
130
130
  }
@@ -147,6 +147,7 @@ dns_config::system_config()
147
147
  std::error_code ec;
148
148
  asio::ip::address::from_string(nameserver, ec);
149
149
  if (ec) {
150
+ CB_LOG_DEBUG("Unable to parse \"{}\" as a network address, fall back to \"{}\"", nameserver, default_nameserver);
150
151
  nameserver = default_nameserver;
151
152
  }
152
153
  instance.nameserver_ = nameserver;
@@ -1279,16 +1279,15 @@ class mcbp_session_impl
1279
1279
  }
1280
1280
  last_active_ = std::chrono::steady_clock::now();
1281
1281
  if (it != endpoints_.end()) {
1282
- CB_LOG_DEBUG("{} connecting to {}:{}, timeout={}ms",
1283
- log_prefix_,
1284
- it->endpoint().address().to_string(),
1285
- it->endpoint().port(),
1286
- origin_.options().connect_timeout.count());
1282
+ auto hostname = it->endpoint().address().to_string();
1283
+ auto port = it->endpoint().port();
1284
+ CB_LOG_DEBUG("{} connecting to {}:{}, timeout={}ms", log_prefix_, hostname, port, origin_.options().connect_timeout.count());
1287
1285
  connection_deadline_.expires_after(origin_.options().connect_timeout);
1288
- connection_deadline_.async_wait([self = shared_from_this()](const auto timer_ec) {
1286
+ connection_deadline_.async_wait([self = shared_from_this(), hostname, port](const auto timer_ec) {
1289
1287
  if (timer_ec == asio::error::operation_aborted || self->stopped_) {
1290
1288
  return;
1291
1289
  }
1290
+ CB_LOG_DEBUG("{} unable to connect to {}:{} in time, reconnecting", self->log_prefix_, hostname, port);
1292
1291
  return self->stream_->close([self](std::error_code) { self->initiate_bootstrap(); });
1293
1292
  });
1294
1293
  stream_->async_connect(it->endpoint(),
@@ -29,3 +29,9 @@
29
29
  * couchbase::core::meta::sdk_version() function is available
30
30
  */
31
31
  #define COUCHBASE_CXX_CLIENT_HAS_SDK_SEMVER 1
32
+
33
+ /**
34
+ * couchbase::core::cluster_options and couchbase::security_options support
35
+ * passing TLS trust certificate by value
36
+ */
37
+ #define COUCHBASE_CXX_CLIENT_CAN_PASS_TLS_TRUST_CERTIFICATE_BY_VALUE 1
@@ -85,6 +85,17 @@ query_request::encode_to(query_request::encoded_request_type& encoded, http_cont
85
85
  case couchbase::query_profile::off:
86
86
  break;
87
87
  }
88
+ if (use_replica.has_value()) {
89
+ if (context.config.supports_read_from_replica()) {
90
+ if (use_replica.value()) {
91
+ body["use_replica"] = "on";
92
+ } else {
93
+ body["use_replica"] = "off";
94
+ }
95
+ } else {
96
+ return errc::common::feature_not_available;
97
+ }
98
+ }
88
99
  if (max_parallelism) {
89
100
  body["max_parallelism"] = std::to_string(max_parallelism.value());
90
101
  }
@@ -91,6 +91,7 @@ struct query_request {
91
91
  bool flex_index{ false };
92
92
  bool preserve_expiry{ false };
93
93
 
94
+ std::optional<bool> use_replica{};
94
95
  std::optional<std::uint64_t> max_parallelism{};
95
96
  std::optional<std::uint64_t> scan_cap{};
96
97
  std::optional<std::chrono::milliseconds> scan_wait{};
@@ -0,0 +1,270 @@
1
+ /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * Copyright 2020-2021 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 "origin.hxx"
19
+
20
+ #include <fmt/chrono.h>
21
+ #include <fmt/format.h>
22
+
23
+ #include <tao/json.hpp>
24
+
25
+ namespace tao::json
26
+ {
27
+
28
+ template<>
29
+ struct traits<std::chrono::milliseconds> {
30
+ template<template<typename...> class Traits>
31
+ static void assign(tao::json::basic_value<Traits>& v, const std::chrono::milliseconds& o)
32
+ {
33
+ v = fmt::format("{}", o);
34
+ }
35
+ };
36
+
37
+ template<>
38
+ struct traits<std::chrono::nanoseconds> {
39
+ template<template<typename...> class Traits>
40
+ static void assign(tao::json::basic_value<Traits>& v, const std::chrono::nanoseconds& o)
41
+ {
42
+ v = fmt::format("{}", o);
43
+ }
44
+ };
45
+
46
+ template<>
47
+ struct traits<couchbase::core::tls_verify_mode> {
48
+ template<template<typename...> class Traits>
49
+ static void assign(tao::json::basic_value<Traits>& v, const couchbase::core::tls_verify_mode& o)
50
+ {
51
+ switch (o) {
52
+ case couchbase::core::tls_verify_mode::none:
53
+ v = "none";
54
+ break;
55
+ case couchbase::core::tls_verify_mode::peer:
56
+ v = "peer";
57
+ break;
58
+ }
59
+ }
60
+ };
61
+
62
+ template<>
63
+ struct traits<couchbase::core::io::ip_protocol> {
64
+ template<template<typename...> class Traits>
65
+ static void assign(tao::json::basic_value<Traits>& v, const couchbase::core::io::ip_protocol& o)
66
+ {
67
+ switch (o) {
68
+ case couchbase::core::io::ip_protocol::any:
69
+ v = "any";
70
+ break;
71
+ case couchbase::core::io::ip_protocol::force_ipv4:
72
+ v = "force_ipv4";
73
+ break;
74
+ case couchbase::core::io::ip_protocol::force_ipv6:
75
+ v = "force_ipv6";
76
+ break;
77
+ }
78
+ }
79
+ };
80
+
81
+ template<>
82
+ struct traits<couchbase::core::io::dns::dns_config> {
83
+ template<template<typename...> class Traits>
84
+ static void assign(tao::json::basic_value<Traits>& v, const couchbase::core::io::dns::dns_config& o)
85
+ {
86
+ v = {
87
+ { "port", o.port() },
88
+ { "nameserver", o.nameserver() },
89
+ { "timeout", o.timeout() },
90
+ };
91
+ }
92
+ };
93
+
94
+ template<>
95
+ struct traits<couchbase::core::tracing::threshold_logging_options> {
96
+ template<template<typename...> class Traits>
97
+ static void assign(tao::json::basic_value<Traits>& v, const couchbase::core::tracing::threshold_logging_options& o)
98
+ {
99
+ v = {
100
+ { "orphaned_emit_interval", o.orphaned_emit_interval },
101
+ { "orphaned_sample_size", o.orphaned_sample_size },
102
+ { "threshold_emit_interval", o.threshold_emit_interval },
103
+ { "threshold_sample_size", o.threshold_sample_size },
104
+ { "key_value_threshold", o.key_value_threshold },
105
+ { "query_threshold", o.query_threshold },
106
+ { "view_threshold", o.view_threshold },
107
+ { "search_threshold", o.search_threshold },
108
+ { "analytics_threshold", o.analytics_threshold },
109
+ { "management_threshold", o.management_threshold },
110
+ };
111
+ }
112
+ };
113
+
114
+ template<>
115
+ struct traits<couchbase::core::metrics::logging_meter_options> {
116
+ template<template<typename...> class Traits>
117
+ static void assign(tao::json::basic_value<Traits>& v, const couchbase::core::metrics::logging_meter_options& o)
118
+ {
119
+ v = {
120
+ { "emit_interval", o.emit_interval },
121
+ };
122
+ }
123
+ };
124
+
125
+ template<>
126
+ struct traits<couchbase::durability_level> {
127
+ template<template<typename...> class Traits>
128
+ static void assign(tao::json::basic_value<Traits>& v, const couchbase::durability_level& o)
129
+ {
130
+ switch (o) {
131
+ case couchbase::durability_level::none:
132
+ v = "none";
133
+ break;
134
+ case couchbase::durability_level::majority:
135
+ v = "majority";
136
+ break;
137
+ case couchbase::durability_level::majority_and_persist_to_active:
138
+ v = "majority_and_persist_to_active";
139
+ break;
140
+ case couchbase::durability_level::persist_to_majority:
141
+ v = "persist_to_majority";
142
+ break;
143
+ }
144
+ }
145
+ };
146
+
147
+ template<>
148
+ struct traits<couchbase::query_scan_consistency> {
149
+ template<template<typename...> class Traits>
150
+ static void assign(tao::json::basic_value<Traits>& v, const couchbase::query_scan_consistency& o)
151
+ {
152
+ switch (o) {
153
+ case couchbase::query_scan_consistency::not_bounded:
154
+ v = "not_bounded";
155
+ break;
156
+ case couchbase::query_scan_consistency::request_plus:
157
+ v = "request_plus";
158
+ break;
159
+ }
160
+ }
161
+ };
162
+
163
+ template<>
164
+ struct traits<couchbase::transactions::transactions_config::built> {
165
+ template<template<typename...> class Traits>
166
+ static void assign(tao::json::basic_value<Traits>& v, const couchbase::transactions::transactions_config::built& o)
167
+ {
168
+ v = {
169
+ { "expiration_time", o.expiration_time },
170
+ { "durability_level", o.level },
171
+ {
172
+ "query_config",
173
+ {
174
+ { "scan_consistency", o.query_config.scan_consistency },
175
+ },
176
+ },
177
+ {
178
+ "cleanup_config",
179
+ {
180
+ { "cleanup_lost_attempts", o.cleanup_config.cleanup_lost_attempts },
181
+ { "cleanup_client_attempts", o.cleanup_config.cleanup_client_attempts },
182
+ { "cleanup_window", o.cleanup_config.cleanup_window },
183
+ { "collections", tao::json::empty_array },
184
+ },
185
+ },
186
+ };
187
+ if (const auto& p = o.kv_timeout; p.has_value()) {
188
+ v["key_value_timeout"] = p.value();
189
+ }
190
+ if (const auto& p = o.metadata_collection; p.has_value()) {
191
+ v["metadata_collection"] = {
192
+ { "bucket", p.value().bucket },
193
+ { "scope", p.value().scope },
194
+ { "collection", p.value().collection },
195
+ };
196
+ }
197
+ for (const auto& c : o.cleanup_config.collections) {
198
+ v["cleanup_config"]["collections"].emplace_back(tao::json::value{
199
+ { "bucket", c.bucket },
200
+ { "scope", c.scope },
201
+ { "collection", c.collection },
202
+ });
203
+ }
204
+ }
205
+ };
206
+
207
+ } // namespace tao::json
208
+
209
+ namespace couchbase::core
210
+ {
211
+ auto
212
+ origin::to_json() const -> std::string
213
+ {
214
+ tao::json::value json = {
215
+ {
216
+ "options",
217
+ {
218
+ { "bootstrap_timeout", options_.bootstrap_timeout },
219
+ { "resolve_timeout", options_.resolve_timeout },
220
+ { "connect_timeout", options_.connect_timeout },
221
+ { "key_value_timeout", options_.key_value_timeout },
222
+ { "key_value_durable_timeout", options_.key_value_durable_timeout },
223
+ { "view_timeout", options_.view_timeout },
224
+ { "query_timeout", options_.query_timeout },
225
+ { "analytics_timeout", options_.analytics_timeout },
226
+ { "search_timeout", options_.search_timeout },
227
+ { "management_timeout", options_.management_timeout },
228
+ { "enable_tls", options_.enable_tls },
229
+ { "trust_certificate", options_.trust_certificate },
230
+ { "enable_mutation_tokens", options_.enable_mutation_tokens },
231
+ { "enable_tcp_keep_alive", options_.enable_tcp_keep_alive },
232
+ { "use_ip_protocol", options_.use_ip_protocol },
233
+ { "enable_dns_srv", options_.enable_dns_srv },
234
+ { "dns_config", options_.dns_config },
235
+ { "show_queries", options_.show_queries },
236
+ { "enable_unordered_execution", options_.enable_unordered_execution },
237
+ { "enable_clustermap_notification", options_.enable_clustermap_notification },
238
+ { "enable_compression", options_.enable_compression },
239
+ { "enable_tracing", options_.enable_tracing },
240
+ { "enable_metrics", options_.enable_metrics },
241
+ { "tcp_keep_alive_interval", options_.tcp_keep_alive_interval },
242
+ { "config_poll_interval", options_.config_poll_interval },
243
+ { "config_poll_floor", options_.config_poll_floor },
244
+ { "config_idle_redial_timeout", options_.config_idle_redial_timeout },
245
+ { "max_http_connections", options_.max_http_connections },
246
+ { "idle_http_connection_timeout", options_.idle_http_connection_timeout },
247
+ { "user_agent_extra", options_.user_agent_extra },
248
+ { "dump_configuration", options_.dump_configuration },
249
+ { "disable_mozilla_ca_certificates", options_.disable_mozilla_ca_certificates },
250
+ { "metrics_options", options_.metrics_options },
251
+ { "network", options_.network },
252
+ { "tls_verify", options_.tls_verify },
253
+ { "tracing_options", options_.tracing_options },
254
+ { "transactions_options", options_.transactions },
255
+ },
256
+ },
257
+ };
258
+ {
259
+ tao::json::value nodes = tao::json::empty_array;
260
+ for (const auto& [hostname, port] : nodes_) {
261
+ nodes.emplace_back(tao::json::value{
262
+ { "hostname", hostname },
263
+ { "port", port },
264
+ });
265
+ }
266
+ json["bootstrap_nodes"] = nodes;
267
+ }
268
+ return tao::json::to_string(json);
269
+ }
270
+ } // namespace couchbase::core