couchbase 3.4.3 → 3.4.5

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 (179) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/ext/couchbase/CMakeLists.txt +22 -1
  4. data/ext/couchbase/core/bucket.cxx +183 -152
  5. data/ext/couchbase/core/bucket.hxx +17 -4
  6. data/ext/couchbase/core/cluster.hxx +41 -13
  7. data/ext/couchbase/core/cluster_options.hxx +3 -0
  8. data/ext/couchbase/core/crud_component.cxx +51 -22
  9. data/ext/couchbase/core/error_context/key_value.cxx +2 -1
  10. data/ext/couchbase/core/error_context/key_value.hxx +10 -12
  11. data/ext/couchbase/core/impl/build_deferred_query_indexes.cxx +115 -50
  12. data/ext/couchbase/core/impl/cluster.cxx +6 -0
  13. data/ext/couchbase/core/impl/create_bucket.cxx +158 -0
  14. data/ext/couchbase/core/impl/create_collection.cxx +83 -0
  15. data/ext/couchbase/core/impl/create_query_index.cxx +172 -59
  16. data/ext/couchbase/core/impl/create_scope.cxx +69 -0
  17. data/ext/couchbase/core/impl/dns_srv_tracker.cxx +2 -1
  18. data/ext/couchbase/core/impl/drop_bucket.cxx +66 -0
  19. data/ext/couchbase/core/impl/drop_collection.cxx +76 -0
  20. data/ext/couchbase/core/impl/drop_query_index.cxx +138 -59
  21. data/ext/couchbase/core/impl/drop_scope.cxx +68 -0
  22. data/ext/couchbase/core/impl/flush_bucket.cxx +66 -0
  23. data/ext/couchbase/core/impl/get_all_buckets.cxx +178 -0
  24. data/ext/couchbase/core/impl/get_all_query_indexes.cxx +67 -37
  25. data/ext/couchbase/core/impl/get_all_scopes.cxx +94 -0
  26. data/ext/couchbase/core/impl/get_bucket.cxx +168 -0
  27. data/ext/couchbase/core/impl/internal_manager_error_context.cxx +113 -0
  28. data/ext/couchbase/core/impl/internal_manager_error_context.hxx +60 -0
  29. data/ext/couchbase/core/impl/key_value_error_category.cxx +2 -4
  30. data/ext/couchbase/core/impl/key_value_error_context.cxx +98 -0
  31. data/ext/couchbase/core/impl/lookup_in.cxx +1 -0
  32. data/ext/couchbase/core/impl/lookup_in_all_replicas.cxx +178 -0
  33. data/ext/couchbase/core/impl/lookup_in_all_replicas.hxx +80 -0
  34. data/ext/couchbase/core/impl/lookup_in_any_replica.cxx +169 -0
  35. data/ext/couchbase/core/impl/lookup_in_any_replica.hxx +75 -0
  36. data/ext/couchbase/core/impl/lookup_in_replica.cxx +104 -0
  37. data/ext/couchbase/core/impl/lookup_in_replica.hxx +67 -0
  38. data/ext/couchbase/core/impl/manager_error_context.cxx +100 -0
  39. data/ext/couchbase/core/impl/query.cxx +1 -0
  40. data/ext/couchbase/core/impl/query_error_context.cxx +75 -0
  41. data/ext/couchbase/core/impl/update_bucket.cxx +133 -0
  42. data/ext/couchbase/core/impl/update_collection.cxx +83 -0
  43. data/ext/couchbase/core/impl/watch_query_indexes.cxx +53 -29
  44. data/ext/couchbase/core/io/dns_client.cxx +111 -40
  45. data/ext/couchbase/core/io/dns_config.cxx +5 -4
  46. data/ext/couchbase/core/io/http_session.hxx +24 -1
  47. data/ext/couchbase/core/io/mcbp_command.hxx +9 -2
  48. data/ext/couchbase/core/io/mcbp_session.cxx +80 -43
  49. data/ext/couchbase/core/io/mcbp_session.hxx +4 -3
  50. data/ext/couchbase/core/logger/custom_rotating_file_sink.cxx +1 -1
  51. data/ext/couchbase/core/logger/logger.cxx +80 -20
  52. data/ext/couchbase/core/logger/logger.hxx +31 -0
  53. data/ext/couchbase/core/management/bucket_settings.hxx +8 -5
  54. data/ext/couchbase/core/management/bucket_settings_json.hxx +12 -2
  55. data/ext/couchbase/core/meta/features.hxx +42 -0
  56. data/ext/couchbase/core/operations/document_lookup_in.cxx +8 -1
  57. data/ext/couchbase/core/operations/document_lookup_in_all_replicas.hxx +192 -0
  58. data/ext/couchbase/core/operations/document_lookup_in_any_replica.hxx +188 -0
  59. data/ext/couchbase/core/operations/document_query.cxx +11 -0
  60. data/ext/couchbase/core/operations/document_query.hxx +1 -0
  61. data/ext/couchbase/core/operations/management/CMakeLists.txt +1 -0
  62. data/ext/couchbase/core/operations/management/bucket_create.cxx +30 -9
  63. data/ext/couchbase/core/operations/management/bucket_update.cxx +27 -6
  64. data/ext/couchbase/core/operations/management/collection_create.cxx +5 -1
  65. data/ext/couchbase/core/operations/management/collection_create.hxx +1 -0
  66. data/ext/couchbase/core/operations/management/collection_update.cxx +87 -0
  67. data/ext/couchbase/core/operations/management/collection_update.hxx +54 -0
  68. data/ext/couchbase/core/operations/management/collections.hxx +1 -0
  69. data/ext/couchbase/core/operations.hxx +2 -0
  70. data/ext/couchbase/core/origin.cxx +270 -0
  71. data/ext/couchbase/core/origin.hxx +2 -0
  72. data/ext/couchbase/core/protocol/client_response.hxx +1 -0
  73. data/ext/couchbase/core/protocol/cmd_hello.hxx +1 -0
  74. data/ext/couchbase/core/protocol/cmd_lookup_in_replica.cxx +107 -0
  75. data/ext/couchbase/core/protocol/cmd_lookup_in_replica.hxx +137 -0
  76. data/ext/couchbase/core/protocol/hello_feature.hxx +6 -0
  77. data/ext/couchbase/core/protocol/hello_feature_fmt.hxx +3 -0
  78. data/ext/couchbase/core/protocol/status.cxx +2 -2
  79. data/ext/couchbase/core/range_scan_options.cxx +3 -27
  80. data/ext/couchbase/core/range_scan_options.hxx +13 -17
  81. data/ext/couchbase/core/range_scan_orchestrator.cxx +388 -170
  82. data/ext/couchbase/core/range_scan_orchestrator.hxx +13 -2
  83. data/ext/couchbase/core/range_scan_orchestrator_options.hxx +5 -3
  84. data/ext/couchbase/core/scan_options.hxx +0 -19
  85. data/ext/couchbase/core/scan_result.cxx +19 -5
  86. data/ext/couchbase/core/scan_result.hxx +5 -2
  87. data/ext/couchbase/core/timeout_defaults.hxx +3 -4
  88. data/ext/couchbase/core/topology/capabilities.hxx +4 -0
  89. data/ext/couchbase/core/topology/capabilities_fmt.hxx +11 -0
  90. data/ext/couchbase/core/topology/collections_manifest.hxx +2 -0
  91. data/ext/couchbase/core/topology/collections_manifest_fmt.hxx +1 -1
  92. data/ext/couchbase/core/topology/collections_manifest_json.hxx +3 -0
  93. data/ext/couchbase/core/topology/configuration.hxx +20 -0
  94. data/ext/couchbase/core/topology/configuration_json.hxx +8 -1
  95. data/ext/couchbase/core/utils/connection_string.cxx +62 -47
  96. data/ext/couchbase/core/utils/connection_string.hxx +1 -0
  97. data/ext/couchbase/couchbase/analytics_error_context.hxx +1 -1
  98. data/ext/couchbase/couchbase/behavior_options.hxx +19 -2
  99. data/ext/couchbase/couchbase/bucket.hxx +14 -0
  100. data/ext/couchbase/couchbase/bucket_manager.hxx +135 -0
  101. data/ext/couchbase/couchbase/build_query_index_options.hxx +0 -30
  102. data/ext/couchbase/couchbase/cluster.hxx +14 -0
  103. data/ext/couchbase/couchbase/collection.hxx +111 -0
  104. data/ext/couchbase/couchbase/collection_manager.hxx +160 -0
  105. data/ext/couchbase/couchbase/collection_query_index_manager.hxx +7 -48
  106. data/ext/couchbase/couchbase/create_bucket_options.hxx +41 -0
  107. data/ext/couchbase/couchbase/create_collection_options.hxx +44 -0
  108. data/ext/couchbase/couchbase/create_primary_query_index_options.hxx +0 -29
  109. data/ext/couchbase/couchbase/create_query_index_options.hxx +0 -33
  110. data/ext/couchbase/couchbase/create_scope_options.hxx +41 -0
  111. data/ext/couchbase/couchbase/drop_bucket_options.hxx +41 -0
  112. data/ext/couchbase/couchbase/drop_collection_options.hxx +41 -0
  113. data/ext/couchbase/couchbase/drop_primary_query_index_options.hxx +0 -30
  114. data/ext/couchbase/couchbase/drop_query_index_options.hxx +0 -31
  115. data/ext/couchbase/couchbase/drop_scope_options.hxx +41 -0
  116. data/ext/couchbase/couchbase/error_codes.hxx +1 -2
  117. data/ext/couchbase/couchbase/error_context.hxx +10 -2
  118. data/ext/couchbase/couchbase/flush_bucket_options.hxx +41 -0
  119. data/ext/couchbase/{core/topology/error_map_fmt.hxx → couchbase/fmt/key_value_error_map_attribute.hxx} +21 -21
  120. data/ext/couchbase/couchbase/get_all_buckets_options.hxx +44 -0
  121. data/ext/couchbase/couchbase/get_all_query_indexes_options.hxx +0 -30
  122. data/ext/couchbase/couchbase/get_all_scopes_options.hxx +44 -0
  123. data/ext/couchbase/couchbase/get_and_lock_options.hxx +2 -2
  124. data/ext/couchbase/couchbase/get_and_touch_options.hxx +2 -2
  125. data/ext/couchbase/couchbase/get_bucket_options.hxx +43 -0
  126. data/ext/couchbase/couchbase/get_options.hxx +2 -2
  127. data/ext/couchbase/couchbase/insert_options.hxx +3 -3
  128. data/ext/couchbase/couchbase/key_value_error_context.hxx +7 -2
  129. data/ext/couchbase/couchbase/lookup_in_all_replicas_options.hxx +109 -0
  130. data/ext/couchbase/couchbase/lookup_in_any_replica_options.hxx +101 -0
  131. data/ext/couchbase/couchbase/lookup_in_options.hxx +2 -2
  132. data/ext/couchbase/couchbase/lookup_in_replica_result.hxx +74 -0
  133. data/ext/couchbase/couchbase/lookup_in_result.hxx +26 -0
  134. data/ext/couchbase/couchbase/management/bucket_settings.hxx +119 -0
  135. data/ext/couchbase/couchbase/management/collection_spec.hxx +29 -0
  136. data/ext/couchbase/couchbase/management/scope_spec.hxx +29 -0
  137. data/ext/couchbase/couchbase/manager_error_context.hxx +29 -53
  138. data/ext/couchbase/couchbase/mutate_in_options.hxx +2 -2
  139. data/ext/couchbase/couchbase/query_error_context.hxx +3 -1
  140. data/ext/couchbase/couchbase/query_index_manager.hxx +16 -83
  141. data/ext/couchbase/couchbase/query_options.hxx +18 -0
  142. data/ext/couchbase/couchbase/remove_options.hxx +2 -2
  143. data/ext/couchbase/couchbase/replace_options.hxx +3 -3
  144. data/ext/couchbase/couchbase/security_options.hxx +15 -0
  145. data/ext/couchbase/couchbase/subdocument_error_context.hxx +4 -2
  146. data/ext/couchbase/couchbase/touch_options.hxx +2 -2
  147. data/ext/couchbase/couchbase/unlock_options.hxx +2 -2
  148. data/ext/couchbase/couchbase/update_bucket_options.hxx +41 -0
  149. data/ext/couchbase/couchbase/update_collection_options.hxx +44 -0
  150. data/ext/couchbase/couchbase/upsert_options.hxx +3 -3
  151. data/ext/couchbase/couchbase/watch_query_indexes_options.hxx +0 -31
  152. data/ext/couchbase/test/CMakeLists.txt +1 -0
  153. data/ext/couchbase/test/test_integration_collections.cxx +6 -0
  154. data/ext/couchbase/test/test_integration_crud.cxx +5 -0
  155. data/ext/couchbase/test/test_integration_examples.cxx +137 -1
  156. data/ext/couchbase/test/test_integration_management.cxx +1009 -309
  157. data/ext/couchbase/test/test_integration_query.cxx +19 -7
  158. data/ext/couchbase/test/test_integration_range_scan.cxx +351 -112
  159. data/ext/couchbase/test/test_integration_search.cxx +10 -1
  160. data/ext/couchbase/test/test_integration_subdoc.cxx +721 -7
  161. data/ext/couchbase/test/test_transaction_public_async_api.cxx +13 -12
  162. data/ext/couchbase/test/test_transaction_public_blocking_api.cxx +27 -21
  163. data/ext/couchbase/test/test_unit_connection_string.cxx +29 -0
  164. data/ext/couchbase/test/test_unit_query.cxx +75 -0
  165. data/ext/couchbase.cxx +735 -60
  166. data/ext/revisions.rb +3 -3
  167. data/lib/couchbase/cluster.rb +1 -1
  168. data/lib/couchbase/collection.rb +108 -0
  169. data/lib/couchbase/collection_options.rb +100 -1
  170. data/lib/couchbase/errors.rb +5 -0
  171. data/lib/couchbase/key_value_scan.rb +125 -0
  172. data/lib/couchbase/management/bucket_manager.rb +22 -15
  173. data/lib/couchbase/management/collection_manager.rb +158 -9
  174. data/lib/couchbase/options.rb +151 -0
  175. data/lib/couchbase/scope.rb +1 -1
  176. data/lib/couchbase/utils/time.rb +14 -1
  177. data/lib/couchbase/version.rb +1 -1
  178. metadata +59 -8
  179. data/ext/couchbase/core/impl/collection_query_index_manager.cxx +0 -93
@@ -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,22 +72,50 @@ 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={}",
76
+ address_.to_string(),
77
+ port_,
78
+ udp_timeout,
79
+ total_timeout);
71
80
  asio::ip::udp::endpoint endpoint(address_, port_);
72
81
  udp_.open(endpoint.protocol());
82
+ CB_LOG_PROTOCOL("[DNS, UDP, OUT] host=\"{}\", port={}, buffer_size={}{:a}",
83
+ address_.to_string(),
84
+ port_,
85
+ send_buf_.size(),
86
+ spdlog::to_hex(send_buf_));
73
87
  udp_.async_send_to(
74
- asio::buffer(send_buf_), endpoint, [self = shared_from_this()](std::error_code ec1, std::size_t /* bytes_transferred */) mutable {
88
+ asio::buffer(send_buf_), endpoint, [self = shared_from_this()](std::error_code ec1, std::size_t bytes_transferred1) mutable {
89
+ CB_LOG_PROTOCOL("[DNS, UDP, OUT] host=\"{}\", port={}, rc={}, bytes_sent={}",
90
+ self->address_.to_string(),
91
+ self->port_,
92
+ ec1 ? ec1.message() : "ok",
93
+ bytes_transferred1);
75
94
  if (ec1) {
76
95
  self->udp_deadline_.cancel();
77
- CB_LOG_DEBUG("DNS UDP write operation has got error {}, retrying with TCP", ec1.message());
96
+ CB_LOG_DEBUG("DNS UDP write operation has got error, retrying with TCP, address=\"{}:{}\", ec={}",
97
+ self->address_.to_string(),
98
+ self->port_,
99
+ ec1.message());
78
100
  return self->retry_with_tcp();
79
101
  }
80
102
 
81
103
  self->recv_buf_.resize(512);
82
104
  self->udp_.async_receive_from(
83
105
  asio::buffer(self->recv_buf_), self->udp_sender_, [self](std::error_code ec2, std::size_t bytes_transferred) mutable {
106
+ CB_LOG_PROTOCOL("[DNS, UDP, IN] host=\"{}\", port={}, rc={}, bytes_received={}{:a}",
107
+ self->address_.to_string(),
108
+ self->port_,
109
+ ec2 ? ec2.message() : "ok",
110
+ bytes_transferred,
111
+ spdlog::to_hex(self->recv_buf_.data(), self->recv_buf_.data() + bytes_transferred));
112
+
84
113
  self->udp_deadline_.cancel();
85
114
  if (ec2) {
86
- CB_LOG_DEBUG("DNS UDP read operation has got error {}, retrying with TCP", ec2.message());
115
+ CB_LOG_DEBUG("DNS UDP read operation has got error, retrying with TCP, address=\"{}:{}\", ec={}",
116
+ self->address_.to_string(),
117
+ self->port_,
118
+ ec2.message());
87
119
  return self->retry_with_tcp();
88
120
  }
89
121
  self->recv_buf_.resize(bytes_transferred);
@@ -104,11 +136,13 @@ class dns_srv_command : public std::enable_shared_from_this<dns_srv_command>
104
136
  });
105
137
  });
106
138
  udp_deadline_.expires_after(udp_timeout);
107
- deadline_.async_wait([self = shared_from_this()](std::error_code ec) {
139
+ udp_deadline_.async_wait([self = shared_from_this()](std::error_code ec) {
108
140
  if (ec == asio::error::operation_aborted) {
109
141
  return;
110
142
  }
111
- CB_LOG_DEBUG("DNS UDP deadline has been reached, cancelling UDP operation and fall back to TCP");
143
+ CB_LOG_DEBUG("DNS UDP deadline has been reached, cancelling UDP operation and fall back to TCP, address=\"{}:{}\"",
144
+ self->address_.to_string(),
145
+ self->port_);
112
146
  self->udp_.cancel();
113
147
  return self->retry_with_tcp();
114
148
  });
@@ -118,7 +152,10 @@ class dns_srv_command : public std::enable_shared_from_this<dns_srv_command>
118
152
  if (ec == asio::error::operation_aborted) {
119
153
  return;
120
154
  }
121
- CB_LOG_DEBUG("DNS deadline has been reached, cancelling in-flight operations (tcp.is_open={})", self->tcp_.is_open());
155
+ CB_LOG_DEBUG("DNS deadline has been reached, cancelling in-flight operations (tcp.is_open={}, address=\"{}:{}\")",
156
+ self->tcp_.is_open(),
157
+ self->address_.to_string(),
158
+ self->port_);
122
159
  self->udp_.cancel();
123
160
  if (self->tcp_.is_open()) {
124
161
  self->tcp_.cancel();
@@ -140,53 +177,87 @@ class dns_srv_command : public std::enable_shared_from_this<dns_srv_command>
140
177
  tcp_.async_connect(endpoint, [self = shared_from_this()](std::error_code ec1) mutable {
141
178
  if (ec1) {
142
179
  self->deadline_.cancel();
143
- CB_LOG_DEBUG("DNS TCP connection has been aborted, {}", ec1.message());
180
+ CB_LOG_DEBUG(
181
+ "DNS TCP connection has been aborted, address=\"{}:{}\", ec={}", self->address_.to_string(), self->port_, ec1.message());
144
182
  return self->handler_({ ec1 });
145
183
  }
146
184
  auto send_size = static_cast<std::uint16_t>(self->send_buf_.size());
147
185
  self->send_buf_.insert(self->send_buf_.begin(), static_cast<std::uint8_t>(send_size & 0xffU));
148
186
  self->send_buf_.insert(self->send_buf_.begin(), static_cast<std::uint8_t>(send_size >> 8U));
187
+ CB_LOG_PROTOCOL("[DNS, TCP, OUT] host=\"{}\", port={}, buffer_size={}{:a}",
188
+ self->address_.to_string(),
189
+ self->port_,
190
+ self->send_buf_.size(),
191
+ spdlog::to_hex(self->send_buf_));
149
192
  asio::async_write(
150
- self->tcp_, asio::buffer(self->send_buf_), [self](std::error_code ec2, std::size_t /* bytes_transferred */) mutable {
193
+ self->tcp_, asio::buffer(self->send_buf_), [self](std::error_code ec2, std::size_t bytes_transferred2) mutable {
194
+ CB_LOG_PROTOCOL("[DNS, TCP, OUT] host=\"{}\", port={}, rc={}, bytes_sent={}",
195
+ self->address_.to_string(),
196
+ self->port_,
197
+ ec2 ? ec2.message() : "ok",
198
+ bytes_transferred2);
151
199
  if (ec2) {
152
- CB_LOG_DEBUG("DNS TCP write operation has been aborted, {}", ec2.message());
200
+ CB_LOG_DEBUG("DNS TCP write operation has been aborted, address=\"{}:{}\", ec={}",
201
+ self->address_.to_string(),
202
+ self->port_,
203
+ ec2.message());
153
204
  self->deadline_.cancel();
154
205
  if (ec2 == asio::error::operation_aborted) {
155
206
  ec2 = errc::common::unambiguous_timeout;
156
207
  }
157
208
  return self->handler_({ ec2 });
158
209
  }
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
- });
210
+ asio::async_read(
211
+ self->tcp_,
212
+ asio::buffer(&self->recv_buf_size_, sizeof(std::uint16_t)),
213
+ [self](std::error_code ec3, std::size_t bytes_transferred3) mutable {
214
+ CB_LOG_PROTOCOL("[DNS, TCP, IN] host=\"{}\", port={}, rc={}, bytes_received={}{:a}",
215
+ self->address_.to_string(),
216
+ self->port_,
217
+ ec3 ? ec3.message() : "ok",
218
+ bytes_transferred3,
219
+ spdlog::to_hex(reinterpret_cast<std::uint8_t*>(&self->recv_buf_size_),
220
+ reinterpret_cast<std::uint8_t*>(&self->recv_buf_size_) + bytes_transferred3));
221
+ if (ec3) {
222
+ CB_LOG_DEBUG("DNS TCP buf size read operation has been aborted, address=\"{}:{}\", ec={}",
223
+ self->address_.to_string(),
224
+ self->port_,
225
+ ec3.message());
226
+ self->deadline_.cancel();
227
+ return self->handler_({ ec3 });
228
+ }
229
+ self->recv_buf_size_ = utils::byte_swap(self->recv_buf_size_);
230
+ self->recv_buf_.resize(self->recv_buf_size_);
231
+ CB_LOG_DEBUG("DNS TCP schedule read of {} bytes", self->recv_buf_size_);
232
+ asio::async_read(
233
+ self->tcp_, asio::buffer(self->recv_buf_), [self](std::error_code ec4, std::size_t bytes_transferred4) mutable {
234
+ self->deadline_.cancel();
235
+ CB_LOG_PROTOCOL("[DNS, TCP, IN] host=\"{}\", port={}, rc={}, bytes_received={}{:a}",
236
+ self->address_.to_string(),
237
+ self->port_,
238
+ ec4 ? ec4.message() : "ok",
239
+ bytes_transferred4,
240
+ spdlog::to_hex(self->recv_buf_.data(), self->recv_buf_.data() + bytes_transferred4));
241
+
242
+ if (ec4) {
243
+ CB_LOG_DEBUG("DNS TCP read operation has been aborted, address=\"{}:{}\", ec={}",
244
+ self->address_.to_string(),
245
+ self->port_,
246
+ ec4.message());
247
+ return self->handler_({ ec4 });
248
+ }
249
+ self->recv_buf_.resize(bytes_transferred4);
250
+ const dns_message message = dns_codec::decode(self->recv_buf_);
251
+ dns_srv_response resp{ ec4 };
252
+ resp.targets.reserve(message.answers.size());
253
+ for (const auto& answer : message.answers) {
254
+ resp.targets.emplace_back(
255
+ dns_srv_response::address{ utils::join_strings(answer.target.labels, "."), answer.port });
256
+ }
257
+ CB_LOG_DEBUG("DNS TCP returned {} records", resp.targets.size());
258
+ return self->handler_(std::move(resp));
259
+ });
260
+ });
190
261
  });
191
262
  });
192
263
  }
@@ -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;
@@ -31,7 +31,10 @@
31
31
 
32
32
  #include <couchbase/error_codes.hxx>
33
33
 
34
+ #include <spdlog/fmt/bin_to_hex.h>
35
+
34
36
  #include <asio.hpp>
37
+
35
38
  #include <list>
36
39
  #include <memory>
37
40
  #include <utility>
@@ -448,7 +451,20 @@ class http_session : public std::enable_shared_from_this<http_session>
448
451
  stream_->async_read_some(
449
452
  asio::buffer(input_buffer_), [self = shared_from_this()](std::error_code ec, std::size_t bytes_transferred) {
450
453
  if (ec == asio::error::operation_aborted || self->stopped_) {
454
+ CB_LOG_PROTOCOL("[HTTP, IN] type={}, host=\"{}\", rc={}, bytes_received={}",
455
+ self->type_,
456
+ self->info_.remote_address(),
457
+ ec ? ec.message() : "ok",
458
+ bytes_transferred);
451
459
  return;
460
+ } else {
461
+ CB_LOG_PROTOCOL("[HTTP, IN] type={}, host=\"{}\", rc={}, bytes_received={}{:a}",
462
+ self->type_,
463
+ self->info_.remote_address(),
464
+ ec ? ec.message() : "ok",
465
+ bytes_transferred,
466
+ spdlog::to_hex(self->input_buffer_.data(),
467
+ self->input_buffer_.data() + static_cast<std::ptrdiff_t>(bytes_transferred)));
452
468
  }
453
469
  self->last_active_ = std::chrono::steady_clock::now();
454
470
  if (ec) {
@@ -495,9 +511,16 @@ class http_session : public std::enable_shared_from_this<http_session>
495
511
  std::vector<asio::const_buffer> buffers;
496
512
  buffers.reserve(writing_buffer_.size());
497
513
  for (auto& buf : writing_buffer_) {
514
+ CB_LOG_PROTOCOL(
515
+ "[HTTP, OUT] type={}, host=\"{}\", buffer_size={}{:a}", type_, info_.remote_address(), buf.size(), spdlog::to_hex(buf));
498
516
  buffers.emplace_back(asio::buffer(buf));
499
517
  }
500
- stream_->async_write(buffers, [self = shared_from_this()](std::error_code ec, std::size_t /* bytes_transferred */) {
518
+ stream_->async_write(buffers, [self = shared_from_this()](std::error_code ec, std::size_t bytes_transferred) {
519
+ CB_LOG_PROTOCOL("[HTTP, OUT] type={}, host=\"{}\", rc={}, bytes_sent={}",
520
+ self->type_,
521
+ self->info_.remote_address(),
522
+ ec ? ec.message() : "ok",
523
+ bytes_transferred);
501
524
  if (ec == asio::error::operation_aborted || self->stopped_) {
502
525
  return;
503
526
  }
@@ -59,9 +59,13 @@ struct mcbp_command : public std::enable_shared_from_this<mcbp_command<Manager,
59
59
  mcbp_command_handler handler_{};
60
60
  std::shared_ptr<Manager> manager_{};
61
61
  std::chrono::milliseconds timeout_{};
62
- std::string id_{ uuid::to_string(uuid::random()) };
62
+ std::string id_{
63
+ fmt::format("{:02x}/{}", static_cast<std::uint8_t>(encoded_request_type::body_type::opcode), uuid::to_string(uuid::random()))
64
+ };
63
65
  std::shared_ptr<couchbase::tracing::request_span> span_{ nullptr };
64
66
  std::shared_ptr<couchbase::tracing::request_span> parent_span{ nullptr };
67
+ std::optional<std::string> last_dispatched_from_{};
68
+ std::optional<std::string> last_dispatched_to_{};
65
69
 
66
70
  mcbp_command(asio::io_context& ctx, std::shared_ptr<Manager> manager, Request req, std::chrono::milliseconds default_timeout)
67
71
  : deadline(ctx)
@@ -109,7 +113,10 @@ struct mcbp_command : public std::enable_shared_from_this<mcbp_command<Manager,
109
113
  handler_ = nullptr;
110
114
  }
111
115
  }
112
- invoke_handler(request.retries.idempotent() ? errc::common::unambiguous_timeout : errc::common::ambiguous_timeout);
116
+ invoke_handler(request.retries.idempotent() || !opaque_.has_value()
117
+ ? errc::common::unambiguous_timeout // safe to retry or has not been sent to the server
118
+ : errc::common::ambiguous_timeout // non-idempotent and has been sent to the server
119
+ );
113
120
  }
114
121
 
115
122
  void invoke_handler(std::error_code ec, std::optional<io::mcbp_message>&& msg = {})
@@ -379,7 +379,7 @@ class mcbp_session_impl
379
379
  Expects(protocol::is_valid_server_request_opcode(msg.header.opcode));
380
380
  switch (static_cast<protocol::server_opcode>(msg.header.opcode)) {
381
381
  case protocol::server_opcode::cluster_map_change_notification: {
382
- protocol::cmd_info info{ session_->endpoint_address_, session_->endpoint_.port() };
382
+ protocol::cmd_info info{ session_->bootstrap_hostname_, session_->bootstrap_port_number_ };
383
383
  if (session_->origin_.options().dump_configuration) {
384
384
  std::string_view config_text{ reinterpret_cast<const char*>(msg.body.data()), msg.body.size() };
385
385
  CB_LOG_TRACE(
@@ -404,7 +404,7 @@ class mcbp_session_impl
404
404
  CB_LOG_WARNING("{} unexpected server request: opcode={:x}, opaque={}{:a}{:a}",
405
405
  session_->log_prefix_,
406
406
  msg.header.opcode,
407
- msg.header.opaque,
407
+ utils::byte_swap(msg.header.opaque),
408
408
  spdlog::to_hex(msg.header_data()),
409
409
  spdlog::to_hex(msg.body));
410
410
  }
@@ -416,7 +416,7 @@ class mcbp_session_impl
416
416
  session_->log_prefix_,
417
417
  magic,
418
418
  msg.header.opcode,
419
- msg.header.opaque,
419
+ utils::byte_swap(msg.header.opaque),
420
420
  spdlog::to_hex(msg.header_data()),
421
421
  spdlog::to_hex(msg.body));
422
422
  break;
@@ -473,7 +473,7 @@ class mcbp_session_impl
473
473
  Expects(protocol::is_valid_client_opcode(msg.header.opcode));
474
474
  switch (auto opcode = static_cast<protocol::client_opcode>(msg.header.opcode)) {
475
475
  case protocol::client_opcode::get_cluster_config: {
476
- protocol::cmd_info info{ session_->endpoint_address_, session_->endpoint_.port() };
476
+ protocol::cmd_info info{ session_->bootstrap_hostname_, session_->bootstrap_port_number_ };
477
477
  if (session_->origin_.options().dump_configuration) {
478
478
  std::string_view config_text{ reinterpret_cast<const char*>(msg.body.data()), msg.body.size() };
479
479
  CB_LOG_TRACE("{} configuration from get_cluster_config response (size={}, endpoint=\"{}:{}\"), {}",
@@ -781,13 +781,10 @@ class mcbp_session_impl
781
781
  return;
782
782
  }
783
783
  std::tie(bootstrap_hostname_, bootstrap_port_) = origin_.next_address();
784
- log_prefix_ = fmt::format("[{}/{}/{}/{}] <{}:{}>",
785
- client_id_,
786
- id_,
787
- stream_->log_prefix(),
788
- bucket_name_.value_or("-"),
789
- bootstrap_hostname_,
790
- bootstrap_port_);
784
+ bootstrap_port_number_ = gsl::narrow_cast<std::uint16_t>(std::stoul(bootstrap_port_, nullptr, 10));
785
+ bootstrap_address_ = fmt::format("{}:{}", bootstrap_hostname_, bootstrap_port_);
786
+ log_prefix_ =
787
+ fmt::format("[{}/{}/{}/{}] <{}>", client_id_, id_, stream_->log_prefix(), bucket_name_.value_or("-"), bootstrap_address_);
791
788
  CB_LOG_DEBUG("{} attempt to establish MCBP connection", log_prefix_);
792
789
 
793
790
  async_resolve(origin_.options().use_ip_protocol,
@@ -807,7 +804,7 @@ class mcbp_session_impl
807
804
  return stopped_;
808
805
  }
809
806
 
810
- void on_stop(utils::movable_function<void(retry_reason)> handler)
807
+ void on_stop(utils::movable_function<void()> handler)
811
808
  {
812
809
  on_stop_handler_ = std::move(handler);
813
810
  }
@@ -863,7 +860,7 @@ class mcbp_session_impl
863
860
  config_listeners_.clear();
864
861
  state_ = diag::endpoint_state::disconnected;
865
862
  if (auto on_stop = std::move(on_stop_handler_); on_stop) {
866
- on_stop(reason);
863
+ on_stop();
867
864
  }
868
865
  }
869
866
 
@@ -874,7 +871,7 @@ class mcbp_session_impl
874
871
  }
875
872
  std::uint32_t opaque{ 0 };
876
873
  std::memcpy(&opaque, buf.data() + 12, sizeof(opaque));
877
- CB_LOG_TRACE("{} MCBP send, opaque={}, {:n}", log_prefix_, opaque, spdlog::to_hex(buf.begin(), buf.begin() + 24));
874
+ CB_LOG_TRACE("{} MCBP send, opaque={}, {:n}", log_prefix_, utils::byte_swap(opaque), spdlog::to_hex(buf.begin(), buf.begin() + 24));
878
875
  std::scoped_lock lock(output_buffer_mutex_);
879
876
  output_buffer_.emplace_back(std::move(buf));
880
877
  }
@@ -1058,6 +1055,11 @@ class mcbp_session_impl
1058
1055
  return config_->index_for_this_node();
1059
1056
  }
1060
1057
 
1058
+ [[nodiscard]] const std::string& bootstrap_address() const
1059
+ {
1060
+ return bootstrap_address_;
1061
+ }
1062
+
1061
1063
  [[nodiscard]] const std::string& bootstrap_hostname() const
1062
1064
  {
1063
1065
  return bootstrap_hostname_;
@@ -1068,6 +1070,11 @@ class mcbp_session_impl
1068
1070
  return bootstrap_port_;
1069
1071
  }
1070
1072
 
1073
+ [[nodiscard]] std::uint16_t bootstrap_port_number() const
1074
+ {
1075
+ return bootstrap_port_number_;
1076
+ }
1077
+
1071
1078
  [[nodiscard]] std::uint32_t next_opaque()
1072
1079
  {
1073
1080
  return ++opaque_;
@@ -1161,15 +1168,15 @@ class mcbp_session_impl
1161
1168
  CB_LOG_TRACE("{} configuration from not_my_vbucket response (size={}, endpoint=\"{}:{}\"), {}",
1162
1169
  log_prefix_,
1163
1170
  config_text.size(),
1164
- endpoint_address_,
1165
- endpoint_.port(),
1171
+ bootstrap_hostname_,
1172
+ bootstrap_port_number_,
1166
1173
  config_text);
1167
1174
  }
1168
- auto config = protocol::parse_config(config_text, endpoint_address_, endpoint_.port());
1175
+ auto config = protocol::parse_config(config_text, bootstrap_hostname_, bootstrap_port_number_);
1169
1176
  CB_LOG_DEBUG("{} received not_my_vbucket status for {}, opaque={} with config rev={} in the payload",
1170
1177
  log_prefix_,
1171
1178
  protocol::client_opcode(msg.header.opcode),
1172
- msg.header.opaque,
1179
+ utils::byte_swap(msg.header.opaque),
1173
1180
  config.rev_str());
1174
1181
  update_configuration(std::move(config));
1175
1182
  }
@@ -1204,6 +1211,12 @@ class mcbp_session_impl
1204
1211
  CB_LOG_DEBUG(R"({} server returned {} ({}), it must be transient condition, retrying)", log_prefix_, ec.value(), ec.message());
1205
1212
  return initiate_bootstrap();
1206
1213
  }
1214
+ if (!origin_.exhausted() && ec == errc::common::authentication_failure) {
1215
+ CB_LOG_DEBUG(
1216
+ R"({} server returned authentication_failure, but the bootstrap list is not exhausted yet. It must be transient condition, retrying)",
1217
+ log_prefix_);
1218
+ return initiate_bootstrap();
1219
+ }
1207
1220
 
1208
1221
  if (!bootstrapped_ && bootstrap_callback_) {
1209
1222
  bootstrap_deadline_.cancel();
@@ -1266,16 +1279,15 @@ class mcbp_session_impl
1266
1279
  }
1267
1280
  last_active_ = std::chrono::steady_clock::now();
1268
1281
  if (it != endpoints_.end()) {
1269
- CB_LOG_DEBUG("{} connecting to {}:{}, timeout={}ms",
1270
- log_prefix_,
1271
- it->endpoint().address().to_string(),
1272
- it->endpoint().port(),
1273
- 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());
1274
1285
  connection_deadline_.expires_after(origin_.options().connect_timeout);
1275
- 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) {
1276
1287
  if (timer_ec == asio::error::operation_aborted || self->stopped_) {
1277
1288
  return;
1278
1289
  }
1290
+ CB_LOG_DEBUG("{} unable to connect to {}:{} in time, reconnecting", self->log_prefix_, hostname, port);
1279
1291
  return self->stream_->close([self](std::error_code) { self->initiate_bootstrap(); });
1280
1292
  });
1281
1293
  stream_->async_connect(it->endpoint(),
@@ -1353,7 +1365,20 @@ class mcbp_session_impl
1353
1365
  asio::buffer(input_buffer_),
1354
1366
  [self = shared_from_this(), stream_id = stream_->id()](std::error_code ec, std::size_t bytes_transferred) {
1355
1367
  if (ec == asio::error::operation_aborted || self->stopped_) {
1368
+ CB_LOG_PROTOCOL("[MCBP, IN] host=\"{}\", port={}, rc={}, bytes_received={}",
1369
+ self->endpoint_address_,
1370
+ self->endpoint_.port(),
1371
+ ec ? ec.message() : "ok",
1372
+ bytes_transferred);
1356
1373
  return;
1374
+ } else {
1375
+ CB_LOG_PROTOCOL("[MCBP, IN] host=\"{}\", port={}, rc={}, bytes_received={}{:a}",
1376
+ self->endpoint_address_,
1377
+ self->endpoint_.port(),
1378
+ ec ? ec.message() : "ok",
1379
+ bytes_transferred,
1380
+ spdlog::to_hex(self->input_buffer_.data(),
1381
+ self->input_buffer_.data() + static_cast<std::ptrdiff_t>(bytes_transferred)));
1357
1382
  }
1358
1383
  self->last_active_ = std::chrono::steady_clock::now();
1359
1384
  if (ec) {
@@ -1382,8 +1407,10 @@ class mcbp_session_impl
1382
1407
  if (self->stopped_) {
1383
1408
  return;
1384
1409
  }
1385
- CB_LOG_TRACE(
1386
- "{} MCBP recv, opaque={}, {:n}", self->log_prefix_, msg.header.opaque, spdlog::to_hex(msg.header_data()));
1410
+ CB_LOG_TRACE("{} MCBP recv, opaque={}, {:n}",
1411
+ self->log_prefix_,
1412
+ utils::byte_swap(msg.header.opaque),
1413
+ spdlog::to_hex(msg.header_data()));
1387
1414
  if (self->bootstrapped_) {
1388
1415
  self->handler_->handle(std::move(msg));
1389
1416
  } else {
@@ -1419,13 +1446,21 @@ class mcbp_session_impl
1419
1446
  std::vector<asio::const_buffer> buffers;
1420
1447
  buffers.reserve(writing_buffer_.size());
1421
1448
  for (auto& buf : writing_buffer_) {
1449
+ CB_LOG_PROTOCOL(
1450
+ "[MCBP, OUT] host=\"{}\", port={}, buffer_size={}{:a}", endpoint_address_, endpoint_.port(), buf.size(), spdlog::to_hex(buf));
1422
1451
  buffers.emplace_back(asio::buffer(buf));
1423
1452
  }
1424
- stream_->async_write(buffers, [self = shared_from_this()](std::error_code ec, std::size_t /*unused*/) {
1453
+ stream_->async_write(buffers, [self = shared_from_this()](std::error_code ec, std::size_t bytes_transferred) {
1454
+ CB_LOG_PROTOCOL("[MCBP, OUT] host=\"{}\", port={}, rc={}, bytes_sent={}",
1455
+ self->endpoint_address_,
1456
+ self->endpoint_.port(),
1457
+ ec ? ec.message() : "ok",
1458
+ bytes_transferred);
1425
1459
  if (ec == asio::error::operation_aborted || self->stopped_) {
1426
1460
  return;
1427
1461
  }
1428
1462
  self->last_active_ = std::chrono::steady_clock::now();
1463
+
1429
1464
  if (ec) {
1430
1465
  CB_LOG_ERROR(R"({} IO error while writing to the socket("{}"): {} ({}))",
1431
1466
  self->log_prefix_,
@@ -1462,7 +1497,7 @@ class mcbp_session_impl
1462
1497
  std::mutex command_handlers_mutex_{};
1463
1498
  std::map<std::uint32_t, command_handler> command_handlers_{};
1464
1499
  std::vector<std::shared_ptr<config_listener>> config_listeners_{};
1465
- utils::movable_function<void(retry_reason)> on_stop_handler_{};
1500
+ utils::movable_function<void()> on_stop_handler_{};
1466
1501
 
1467
1502
  std::atomic_bool bootstrapped_{ false };
1468
1503
  std::atomic_bool stopped_{ false };
@@ -1482,6 +1517,8 @@ class mcbp_session_impl
1482
1517
  std::mutex writing_buffer_mutex_{};
1483
1518
  std::string bootstrap_hostname_{};
1484
1519
  std::string bootstrap_port_{};
1520
+ std::string bootstrap_address_{};
1521
+ std::uint16_t bootstrap_port_number_{};
1485
1522
  asio::ip::tcp::endpoint endpoint_{}; // connected endpoint
1486
1523
  std::string endpoint_address_{}; // cached string with endpoint address
1487
1524
  asio::ip::tcp::endpoint local_endpoint_{};
@@ -1582,22 +1619,16 @@ mcbp_session::supports_feature(protocol::hello_feature feature)
1582
1619
  return impl_->supports_feature(feature);
1583
1620
  }
1584
1621
 
1585
- // const std::string&
1586
- // mcbp_session::id() const
1587
- // {
1588
- // return impl_->id();
1589
- // }
1590
- std::string
1622
+ const std::string&
1591
1623
  mcbp_session::id() const
1592
1624
  {
1593
- if (impl_) {
1594
- return fmt::format("{}, {}, {}, refcnt={}",
1595
- reinterpret_cast<const void*>(this),
1596
- reinterpret_cast<const void*>(impl_.get()),
1597
- impl_->id(),
1598
- impl_.use_count());
1599
- }
1600
- return fmt::format("{}, nullptr", reinterpret_cast<const void*>(this));
1625
+ return impl_->id();
1626
+ }
1627
+
1628
+ const std::string&
1629
+ mcbp_session::bootstrap_address() const
1630
+ {
1631
+ return impl_->bootstrap_address();
1601
1632
  }
1602
1633
 
1603
1634
  std::string
@@ -1624,6 +1655,12 @@ mcbp_session::bootstrap_port() const
1624
1655
  return impl_->bootstrap_port();
1625
1656
  }
1626
1657
 
1658
+ std::uint16_t
1659
+ mcbp_session::bootstrap_port_number() const
1660
+ {
1661
+ return impl_->bootstrap_port_number();
1662
+ }
1663
+
1627
1664
  void
1628
1665
  mcbp_session::write_and_subscribe(std::uint32_t opaque, std::vector<std::byte>&& data, command_handler&& handler)
1629
1666
  {
@@ -1637,7 +1674,7 @@ mcbp_session::bootstrap(utils::movable_function<void(std::error_code, topology::
1637
1674
  }
1638
1675
 
1639
1676
  void
1640
- mcbp_session::on_stop(utils::movable_function<void(retry_reason)> handler)
1677
+ mcbp_session::on_stop(utils::movable_function<void()> handler)
1641
1678
  {
1642
1679
  return impl_->on_stop(std::move(handler));
1643
1680
  }
@@ -101,17 +101,18 @@ class mcbp_session
101
101
  [[nodiscard]] mcbp_context context() const;
102
102
  [[nodiscard]] bool supports_feature(protocol::hello_feature feature);
103
103
  [[nodiscard]] std::vector<protocol::hello_feature> supported_features() const;
104
- //[[nodiscard]] const std::string& id() const;
105
- [[nodiscard]] std::string id() const;
104
+ [[nodiscard]] const std::string& id() const;
106
105
  [[nodiscard]] std::string remote_address() const;
107
106
  [[nodiscard]] std::string local_address() const;
107
+ [[nodiscard]] const std::string& bootstrap_address() const;
108
108
  [[nodiscard]] const std::string& bootstrap_hostname() const;
109
109
  [[nodiscard]] const std::string& bootstrap_port() const;
110
+ [[nodiscard]] std::uint16_t bootstrap_port_number() const;
110
111
  void write_and_subscribe(std::shared_ptr<mcbp::queue_request>, std::shared_ptr<response_handler> handler);
111
112
  void write_and_subscribe(std::uint32_t opaque, std::vector<std::byte>&& data, command_handler&& handler);
112
113
  void bootstrap(utils::movable_function<void(std::error_code, topology::configuration)>&& handler,
113
114
  bool retry_on_bucket_not_found = false);
114
- void on_stop(utils::movable_function<void(retry_reason)> handler);
115
+ void on_stop(utils::movable_function<void()> handler);
115
116
  void stop(retry_reason reason);
116
117
  [[nodiscard]] std::size_t index() const;
117
118
  [[nodiscard]] bool has_config() const;
@@ -127,7 +127,7 @@ custom_rotating_file_sink<Mutex>::add_hook(const std::string& hook)
127
127
 
128
128
  // Payload shouldn't contain anything yet, overwrite it
129
129
  Expects(msg.payload.size() == 0);
130
- msg.payload = hook;
130
+ msg.payload = hookToAdd;
131
131
 
132
132
  spdlog::memory_buf_t formatted;
133
133
  formatter->format(msg, formatted);