couchbase 3.4.3 → 3.4.4

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 (148) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/ext/couchbase/CMakeLists.txt +15 -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 +34 -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 +155 -0
  14. data/ext/couchbase/core/impl/create_query_index.cxx +172 -59
  15. data/ext/couchbase/core/impl/dns_srv_tracker.cxx +2 -1
  16. data/ext/couchbase/core/impl/drop_bucket.cxx +66 -0
  17. data/ext/couchbase/core/impl/drop_query_index.cxx +138 -59
  18. data/ext/couchbase/core/impl/flush_bucket.cxx +66 -0
  19. data/ext/couchbase/core/impl/get_all_buckets.cxx +163 -0
  20. data/ext/couchbase/core/impl/get_all_query_indexes.cxx +67 -37
  21. data/ext/couchbase/core/impl/get_bucket.cxx +153 -0
  22. data/ext/couchbase/core/impl/internal_manager_error_context.cxx +113 -0
  23. data/ext/couchbase/core/impl/internal_manager_error_context.hxx +60 -0
  24. data/ext/couchbase/core/impl/key_value_error_category.cxx +2 -4
  25. data/ext/couchbase/core/impl/key_value_error_context.cxx +98 -0
  26. data/ext/couchbase/core/impl/lookup_in.cxx +1 -0
  27. data/ext/couchbase/core/impl/lookup_in_all_replicas.cxx +176 -0
  28. data/ext/couchbase/core/impl/lookup_in_all_replicas.hxx +80 -0
  29. data/ext/couchbase/core/impl/lookup_in_any_replica.cxx +167 -0
  30. data/ext/couchbase/core/impl/lookup_in_any_replica.hxx +75 -0
  31. data/ext/couchbase/core/impl/lookup_in_replica.cxx +97 -0
  32. data/ext/couchbase/core/impl/lookup_in_replica.hxx +67 -0
  33. data/ext/couchbase/core/impl/manager_error_context.cxx +100 -0
  34. data/ext/couchbase/core/impl/query.cxx +1 -0
  35. data/ext/couchbase/core/impl/query_error_context.cxx +75 -0
  36. data/ext/couchbase/core/impl/update_bucket.cxx +130 -0
  37. data/ext/couchbase/core/impl/watch_query_indexes.cxx +53 -29
  38. data/ext/couchbase/core/io/dns_client.cxx +111 -40
  39. data/ext/couchbase/core/io/dns_config.cxx +5 -4
  40. data/ext/couchbase/core/io/http_session.hxx +24 -1
  41. data/ext/couchbase/core/io/mcbp_command.hxx +9 -2
  42. data/ext/couchbase/core/io/mcbp_session.cxx +80 -43
  43. data/ext/couchbase/core/io/mcbp_session.hxx +4 -3
  44. data/ext/couchbase/core/logger/custom_rotating_file_sink.cxx +1 -1
  45. data/ext/couchbase/core/logger/logger.cxx +80 -20
  46. data/ext/couchbase/core/logger/logger.hxx +31 -0
  47. data/ext/couchbase/core/meta/features.hxx +25 -0
  48. data/ext/couchbase/core/operations/document_lookup_in_all_replicas.hxx +192 -0
  49. data/ext/couchbase/core/operations/document_lookup_in_any_replica.hxx +188 -0
  50. data/ext/couchbase/core/operations/document_query.cxx +11 -0
  51. data/ext/couchbase/core/operations/document_query.hxx +1 -0
  52. data/ext/couchbase/core/operations.hxx +2 -0
  53. data/ext/couchbase/core/origin.cxx +270 -0
  54. data/ext/couchbase/core/origin.hxx +2 -0
  55. data/ext/couchbase/core/protocol/client_response.hxx +1 -0
  56. data/ext/couchbase/core/protocol/cmd_hello.hxx +1 -0
  57. data/ext/couchbase/core/protocol/cmd_lookup_in_replica.cxx +107 -0
  58. data/ext/couchbase/core/protocol/cmd_lookup_in_replica.hxx +137 -0
  59. data/ext/couchbase/core/protocol/hello_feature.hxx +6 -0
  60. data/ext/couchbase/core/protocol/hello_feature_fmt.hxx +3 -0
  61. data/ext/couchbase/core/protocol/status.cxx +2 -2
  62. data/ext/couchbase/core/range_scan_options.cxx +3 -27
  63. data/ext/couchbase/core/range_scan_options.hxx +13 -17
  64. data/ext/couchbase/core/range_scan_orchestrator.cxx +388 -170
  65. data/ext/couchbase/core/range_scan_orchestrator.hxx +13 -2
  66. data/ext/couchbase/core/range_scan_orchestrator_options.hxx +5 -3
  67. data/ext/couchbase/core/scan_options.hxx +0 -19
  68. data/ext/couchbase/core/scan_result.cxx +19 -5
  69. data/ext/couchbase/core/scan_result.hxx +5 -2
  70. data/ext/couchbase/core/timeout_defaults.hxx +2 -3
  71. data/ext/couchbase/core/topology/capabilities.hxx +3 -0
  72. data/ext/couchbase/core/topology/capabilities_fmt.hxx +8 -0
  73. data/ext/couchbase/core/topology/collections_manifest_fmt.hxx +1 -1
  74. data/ext/couchbase/core/topology/configuration.hxx +15 -0
  75. data/ext/couchbase/core/topology/configuration_json.hxx +6 -1
  76. data/ext/couchbase/core/utils/connection_string.cxx +62 -47
  77. data/ext/couchbase/core/utils/connection_string.hxx +1 -0
  78. data/ext/couchbase/couchbase/analytics_error_context.hxx +1 -1
  79. data/ext/couchbase/couchbase/behavior_options.hxx +19 -2
  80. data/ext/couchbase/couchbase/bucket_manager.hxx +135 -0
  81. data/ext/couchbase/couchbase/build_query_index_options.hxx +0 -30
  82. data/ext/couchbase/couchbase/cluster.hxx +14 -0
  83. data/ext/couchbase/couchbase/collection.hxx +111 -0
  84. data/ext/couchbase/couchbase/collection_query_index_manager.hxx +7 -48
  85. data/ext/couchbase/couchbase/create_bucket_options.hxx +41 -0
  86. data/ext/couchbase/couchbase/create_primary_query_index_options.hxx +0 -29
  87. data/ext/couchbase/couchbase/create_query_index_options.hxx +0 -33
  88. data/ext/couchbase/couchbase/drop_bucket_options.hxx +41 -0
  89. data/ext/couchbase/couchbase/drop_primary_query_index_options.hxx +0 -30
  90. data/ext/couchbase/couchbase/drop_query_index_options.hxx +0 -31
  91. data/ext/couchbase/couchbase/error_codes.hxx +1 -2
  92. data/ext/couchbase/couchbase/error_context.hxx +10 -2
  93. data/ext/couchbase/couchbase/flush_bucket_options.hxx +41 -0
  94. data/ext/couchbase/{core/topology/error_map_fmt.hxx → couchbase/fmt/key_value_error_map_attribute.hxx} +21 -21
  95. data/ext/couchbase/couchbase/get_all_buckets_options.hxx +44 -0
  96. data/ext/couchbase/couchbase/get_all_query_indexes_options.hxx +0 -30
  97. data/ext/couchbase/couchbase/get_and_lock_options.hxx +2 -2
  98. data/ext/couchbase/couchbase/get_and_touch_options.hxx +2 -2
  99. data/ext/couchbase/couchbase/get_bucket_options.hxx +43 -0
  100. data/ext/couchbase/couchbase/get_options.hxx +2 -2
  101. data/ext/couchbase/couchbase/insert_options.hxx +3 -3
  102. data/ext/couchbase/couchbase/key_value_error_context.hxx +7 -2
  103. data/ext/couchbase/couchbase/lookup_in_all_replicas_options.hxx +109 -0
  104. data/ext/couchbase/couchbase/lookup_in_any_replica_options.hxx +101 -0
  105. data/ext/couchbase/couchbase/lookup_in_options.hxx +2 -2
  106. data/ext/couchbase/couchbase/lookup_in_replica_result.hxx +74 -0
  107. data/ext/couchbase/couchbase/lookup_in_result.hxx +26 -0
  108. data/ext/couchbase/couchbase/management/bucket_settings.hxx +116 -0
  109. data/ext/couchbase/couchbase/manager_error_context.hxx +29 -53
  110. data/ext/couchbase/couchbase/mutate_in_options.hxx +2 -2
  111. data/ext/couchbase/couchbase/query_error_context.hxx +3 -1
  112. data/ext/couchbase/couchbase/query_index_manager.hxx +16 -83
  113. data/ext/couchbase/couchbase/query_options.hxx +18 -0
  114. data/ext/couchbase/couchbase/remove_options.hxx +2 -2
  115. data/ext/couchbase/couchbase/replace_options.hxx +3 -3
  116. data/ext/couchbase/couchbase/security_options.hxx +15 -0
  117. data/ext/couchbase/couchbase/subdocument_error_context.hxx +4 -2
  118. data/ext/couchbase/couchbase/touch_options.hxx +2 -2
  119. data/ext/couchbase/couchbase/unlock_options.hxx +2 -2
  120. data/ext/couchbase/couchbase/update_bucket_options.hxx +41 -0
  121. data/ext/couchbase/couchbase/upsert_options.hxx +3 -3
  122. data/ext/couchbase/couchbase/watch_query_indexes_options.hxx +0 -31
  123. data/ext/couchbase/test/CMakeLists.txt +1 -0
  124. data/ext/couchbase/test/test_integration_collections.cxx +6 -0
  125. data/ext/couchbase/test/test_integration_crud.cxx +5 -0
  126. data/ext/couchbase/test/test_integration_examples.cxx +137 -1
  127. data/ext/couchbase/test/test_integration_management.cxx +709 -266
  128. data/ext/couchbase/test/test_integration_query.cxx +19 -7
  129. data/ext/couchbase/test/test_integration_range_scan.cxx +351 -112
  130. data/ext/couchbase/test/test_integration_search.cxx +10 -1
  131. data/ext/couchbase/test/test_integration_subdoc.cxx +655 -0
  132. data/ext/couchbase/test/test_transaction_public_async_api.cxx +13 -12
  133. data/ext/couchbase/test/test_transaction_public_blocking_api.cxx +27 -21
  134. data/ext/couchbase/test/test_unit_connection_string.cxx +29 -0
  135. data/ext/couchbase/test/test_unit_query.cxx +75 -0
  136. data/ext/couchbase.cxx +583 -29
  137. data/ext/revisions.rb +3 -3
  138. data/lib/couchbase/cluster.rb +1 -1
  139. data/lib/couchbase/collection.rb +108 -0
  140. data/lib/couchbase/collection_options.rb +100 -0
  141. data/lib/couchbase/errors.rb +5 -0
  142. data/lib/couchbase/key_value_scan.rb +125 -0
  143. data/lib/couchbase/options.rb +151 -0
  144. data/lib/couchbase/scope.rb +1 -1
  145. data/lib/couchbase/utils/time.rb +14 -1
  146. data/lib/couchbase/version.rb +1 -1
  147. metadata +41 -7
  148. data/ext/couchbase/core/impl/collection_query_index_manager.cxx +0 -93
@@ -0,0 +1,130 @@
1
+ /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * Copyright 2020-Present Couchbase, Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ #include <couchbase/manager_error_context.hxx>
19
+ #include <utility>
20
+
21
+ #include "core/cluster.hxx"
22
+ #include "core/operations/management/bucket_update.hxx"
23
+ #include "couchbase/bucket_manager.hxx"
24
+
25
+ namespace couchbase
26
+ {
27
+ template<typename Response>
28
+ static manager_error_context
29
+ build_context(Response& resp)
30
+ {
31
+ return manager_error_context(internal_manager_error_context{ resp.ctx.ec,
32
+ resp.ctx.last_dispatched_to,
33
+ resp.ctx.last_dispatched_from,
34
+ resp.ctx.retry_attempts,
35
+ std::move(resp.ctx.retry_reasons),
36
+ std::move(resp.ctx.client_context_id),
37
+ resp.ctx.http_status,
38
+ std::move(resp.ctx.http_body),
39
+ std::move(resp.ctx.path) });
40
+ }
41
+
42
+ static core::operations::management::bucket_update_request
43
+ build_update_bucket_request(couchbase::core::management::cluster::bucket_settings bucket_settings,
44
+ const update_bucket_options::built& options)
45
+ {
46
+ core::operations::management::bucket_update_request request{ std::move(bucket_settings), {}, options.timeout };
47
+ return request;
48
+ }
49
+
50
+ static couchbase::core::management::cluster::bucket_settings
51
+ map_bucket_settings(const couchbase::management::cluster::bucket_settings& bucket)
52
+ {
53
+ couchbase::core::management::cluster::bucket_settings bucket_settings{};
54
+
55
+ bucket_settings.name = bucket.name;
56
+ bucket_settings.ram_quota_mb = bucket.ram_quota_mb;
57
+ bucket_settings.max_expiry = bucket.max_expiry;
58
+ bucket_settings.minimum_durability_level = bucket.minimum_durability_level;
59
+ bucket_settings.num_replicas = bucket.num_replicas;
60
+ bucket_settings.replica_indexes = bucket.replica_indexes;
61
+ bucket_settings.flush_enabled = bucket.flush_enabled;
62
+ switch (bucket.conflict_resolution_type) {
63
+ case management::cluster::bucket_conflict_resolution::unknown:
64
+ bucket_settings.conflict_resolution_type = core::management::cluster::bucket_conflict_resolution::unknown;
65
+ break;
66
+ case management::cluster::bucket_conflict_resolution::timestamp:
67
+ bucket_settings.conflict_resolution_type = core::management::cluster::bucket_conflict_resolution::timestamp;
68
+ break;
69
+ case management::cluster::bucket_conflict_resolution::sequence_number:
70
+ bucket_settings.conflict_resolution_type = core::management::cluster::bucket_conflict_resolution::sequence_number;
71
+ break;
72
+ case management::cluster::bucket_conflict_resolution::custom:
73
+ bucket_settings.conflict_resolution_type = core::management::cluster::bucket_conflict_resolution::custom;
74
+ break;
75
+ }
76
+ switch (bucket.eviction_policy) {
77
+ case management::cluster::bucket_eviction_policy::unknown:
78
+ bucket_settings.eviction_policy = core::management::cluster::bucket_eviction_policy::unknown;
79
+ break;
80
+ case management::cluster::bucket_eviction_policy::full:
81
+ bucket_settings.eviction_policy = core::management::cluster::bucket_eviction_policy::full;
82
+ break;
83
+ case management::cluster::bucket_eviction_policy::value_only:
84
+ bucket_settings.eviction_policy = core::management::cluster::bucket_eviction_policy::value_only;
85
+ break;
86
+ case management::cluster::bucket_eviction_policy::no_eviction:
87
+ bucket_settings.eviction_policy = core::management::cluster::bucket_eviction_policy::no_eviction;
88
+ break;
89
+ case management::cluster::bucket_eviction_policy::not_recently_used:
90
+ bucket_settings.eviction_policy = core::management::cluster::bucket_eviction_policy::not_recently_used;
91
+ break;
92
+ }
93
+ switch (bucket.bucket_type) {
94
+ case management::cluster::bucket_type::unknown:
95
+ bucket_settings.bucket_type = core::management::cluster::bucket_type::unknown;
96
+ break;
97
+ case management::cluster::bucket_type::couchbase:
98
+ bucket_settings.bucket_type = core::management::cluster::bucket_type::couchbase;
99
+ break;
100
+ case management::cluster::bucket_type::memcached:
101
+ bucket_settings.bucket_type = core::management::cluster::bucket_type::memcached;
102
+ break;
103
+ case management::cluster::bucket_type::ephemeral:
104
+ bucket_settings.bucket_type = core::management::cluster::bucket_type::ephemeral;
105
+ break;
106
+ }
107
+ return bucket_settings;
108
+ }
109
+
110
+ void
111
+ bucket_manager::update_bucket(const management::cluster::bucket_settings& bucket_settings,
112
+ const update_bucket_options& options,
113
+ update_bucket_handler&& handler) const
114
+ {
115
+ auto request = build_update_bucket_request(map_bucket_settings(bucket_settings), options.build());
116
+
117
+ core_->execute(std::move(request), [handler = std::move(handler)](core::operations::management::bucket_update_response resp) mutable {
118
+ return handler(build_context(resp));
119
+ });
120
+ }
121
+
122
+ auto
123
+ bucket_manager::update_bucket(const management::cluster::bucket_settings& bucket_settings, const update_bucket_options& options) const
124
+ -> std::future<manager_error_context>
125
+ {
126
+ auto barrier = std::make_shared<std::promise<manager_error_context>>();
127
+ update_bucket(bucket_settings, options, [barrier](auto ctx) mutable { barrier->set_value(std::move(ctx)); });
128
+ return barrier->get_future();
129
+ }
130
+ } // namespace couchbase
@@ -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,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 = {})