couchbase 3.4.3 → 3.4.4

Sign up to get free protection for your applications and to get access to all the features.
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,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
@@ -184,6 +184,8 @@ struct origin {
184
184
  return credentials_;
185
185
  }
186
186
 
187
+ [[nodiscard]] auto to_json() const -> std::string;
188
+
187
189
  private:
188
190
  couchbase::core::cluster_options options_{};
189
191
  cluster_credentials credentials_{};
@@ -148,6 +148,7 @@ class client_response
148
148
  data_.resize(body_size_);
149
149
 
150
150
  memcpy(&opaque_, header_.data() + 12, sizeof(opaque_));
151
+ opaque_ = utils::byte_swap(opaque_);
151
152
 
152
153
  memcpy(&cas_, header_.data() + 16, sizeof(cas_));
153
154
  cas_ = utils::byte_swap(cas_);
@@ -71,6 +71,7 @@ class hello_request_body
71
71
  hello_feature::collections,
72
72
  hello_feature::subdoc_create_as_deleted,
73
73
  hello_feature::preserve_ttl,
74
+ hello_feature::subdoc_replica_read,
74
75
  };
75
76
  std::vector<std::byte> value_;
76
77
 
@@ -0,0 +1,107 @@
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 "cmd_lookup_in_replica.hxx"
19
+
20
+ #include "core/utils/byteswap.hxx"
21
+ #include "core/utils/unsigned_leb128.hxx"
22
+
23
+ #include <cstring>
24
+ #include <gsl/assert>
25
+
26
+ namespace couchbase::core::protocol
27
+ {
28
+ bool
29
+ lookup_in_replica_response_body::parse(key_value_status_code status,
30
+ const header_buffer& header,
31
+ std::uint8_t framing_extras_size,
32
+ std::uint16_t key_size,
33
+ std::uint8_t extras_size,
34
+ const std::vector<std::byte>& body,
35
+ const cmd_info& /* info */)
36
+ {
37
+ Expects(header[1] == static_cast<std::byte>(opcode));
38
+ if (status == key_value_status_code::success || status == key_value_status_code::subdoc_multi_path_failure ||
39
+ status == key_value_status_code::subdoc_success_deleted || status == key_value_status_code::subdoc_multi_path_failure_deleted) {
40
+ using offset_type = std::vector<std::byte>::difference_type;
41
+ offset_type offset = framing_extras_size + key_size + extras_size;
42
+ fields_.reserve(16); /* we won't have more than 16 entries anyway */
43
+ while (static_cast<std::size_t>(offset) < body.size()) {
44
+ lookup_in_field field;
45
+
46
+ std::uint16_t entry_status = 0;
47
+ memcpy(&entry_status, body.data() + offset, sizeof(entry_status));
48
+ entry_status = utils::byte_swap(entry_status);
49
+ Expects(is_valid_status(entry_status));
50
+ field.status = static_cast<key_value_status_code>(entry_status);
51
+ offset += static_cast<offset_type>(sizeof(entry_status));
52
+
53
+ std::uint32_t entry_size = 0;
54
+ memcpy(&entry_size, body.data() + offset, sizeof(entry_size));
55
+ entry_size = utils::byte_swap(entry_size);
56
+ Expects(entry_size < 20 * 1024 * 1024);
57
+ offset += static_cast<offset_type>(sizeof(entry_size));
58
+
59
+ field.value.resize(entry_size);
60
+ memcpy(field.value.data(), body.data() + offset, entry_size);
61
+ offset += static_cast<offset_type>(entry_size);
62
+
63
+ fields_.emplace_back(field);
64
+ }
65
+ return true;
66
+ }
67
+ return false;
68
+ }
69
+
70
+ void
71
+ lookup_in_replica_request_body::id(const document_id& id)
72
+ {
73
+ key_ = make_protocol_key(id);
74
+ }
75
+
76
+ void
77
+ lookup_in_replica_request_body::fill_extras()
78
+ {
79
+ if (flags_ != 0) {
80
+ extras_.resize(sizeof(flags_));
81
+ extras_[0] = std::byte{ flags_ };
82
+ }
83
+ }
84
+
85
+ void
86
+ lookup_in_replica_request_body::fill_value()
87
+ {
88
+ size_t value_size = 0;
89
+ for (const auto& spec : specs_) {
90
+ value_size += sizeof(spec.opcode_) + sizeof(std::uint8_t) + sizeof(std::uint16_t) + spec.path_.size();
91
+ }
92
+ Expects(value_size > 0);
93
+ value_.resize(value_size);
94
+ std::vector<std::byte>::size_type offset = 0;
95
+ for (const auto& spec : specs_) {
96
+ value_[offset] = static_cast<std::byte>(spec.opcode_);
97
+ ++offset;
98
+ value_[offset] = spec.flags_;
99
+ ++offset;
100
+ std::uint16_t path_size = utils::byte_swap(gsl::narrow_cast<std::uint16_t>(spec.path_.size()));
101
+ std::memcpy(value_.data() + offset, &path_size, sizeof(path_size));
102
+ offset += sizeof(path_size);
103
+ std::memcpy(value_.data() + offset, spec.path_.data(), spec.path_.size());
104
+ offset += spec.path_.size();
105
+ }
106
+ }
107
+ } // namespace couchbase::core::protocol
@@ -0,0 +1,137 @@
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
+ #pragma once
19
+
20
+ #include "client_opcode.hxx"
21
+ #include "cmd_info.hxx"
22
+ #include "core/document_id.hxx"
23
+ #include "core/impl/subdoc/command.hxx"
24
+ #include "core/io/mcbp_message.hxx"
25
+ #include "status.hxx"
26
+
27
+ #include <gsl/assert>
28
+
29
+ namespace couchbase::core::protocol
30
+ {
31
+
32
+ class lookup_in_replica_response_body
33
+ {
34
+ public:
35
+ static const inline client_opcode opcode = client_opcode::subdoc_multi_lookup;
36
+
37
+ struct lookup_in_field {
38
+ key_value_status_code status{};
39
+ std::string value;
40
+ };
41
+
42
+ private:
43
+ std::vector<lookup_in_field> fields_{};
44
+
45
+ public:
46
+ [[nodiscard]] const std::vector<lookup_in_field>& fields() const
47
+ {
48
+ return fields_;
49
+ }
50
+
51
+ [[nodiscard]] bool parse(key_value_status_code status,
52
+ const header_buffer& header,
53
+ std::uint8_t framing_extras_size,
54
+ std::uint16_t key_size,
55
+ std::uint8_t extras_size,
56
+ const std::vector<std::byte>& body,
57
+ const cmd_info& info);
58
+ };
59
+
60
+ class lookup_in_replica_request_body
61
+ {
62
+ public:
63
+ using response_body_type = lookup_in_replica_response_body;
64
+ static const inline client_opcode opcode = client_opcode::subdoc_multi_lookup;
65
+
66
+ /**
67
+ * Tells the server to operate on replica vbucket instead of active
68
+ */
69
+ static const inline std::uint8_t doc_flag_replica_read = 0b0010'0000;
70
+
71
+ private:
72
+ std::vector<std::byte> key_;
73
+ std::vector<std::byte> extras_{};
74
+ std::vector<std::byte> value_{};
75
+
76
+ std::uint8_t flags_{ 0 };
77
+ std::vector<couchbase::core::impl::subdoc::command> specs_;
78
+
79
+ public:
80
+ void id(const document_id& id);
81
+
82
+ void read_replica(bool value)
83
+ {
84
+ if (value) {
85
+ flags_ = flags_ | doc_flag_replica_read;
86
+ }
87
+ }
88
+
89
+ void specs(const std::vector<couchbase::core::impl::subdoc::command>& specs)
90
+ {
91
+ specs_ = specs;
92
+ }
93
+
94
+ [[nodiscard]] const auto& key() const
95
+ {
96
+ return key_;
97
+ }
98
+
99
+ [[nodiscard]] const auto& framing_extras() const
100
+ {
101
+ return empty_buffer;
102
+ }
103
+
104
+ [[nodiscard]] const auto& extras()
105
+ {
106
+ if (extras_.empty()) {
107
+ fill_extras();
108
+ }
109
+ return extras_;
110
+ }
111
+
112
+ [[nodiscard]] const auto& value()
113
+ {
114
+ if (value_.empty()) {
115
+ fill_value();
116
+ }
117
+ return value_;
118
+ }
119
+
120
+ [[nodiscard]] std::size_t size()
121
+ {
122
+ if (extras_.empty()) {
123
+ fill_extras();
124
+ }
125
+ if (value_.empty()) {
126
+ fill_value();
127
+ }
128
+ return key_.size() + extras_.size() + value_.size();
129
+ }
130
+
131
+ private:
132
+ void fill_extras();
133
+
134
+ void fill_value();
135
+ };
136
+
137
+ } // namespace couchbase::core::protocol
@@ -155,6 +155,11 @@ enum class hello_feature : std::uint16_t {
155
155
  replace_body_with_xattr = 0x19,
156
156
 
157
157
  resource_units = 0x1a,
158
+
159
+ /**
160
+ * Indicates support for subdoc lookup operations on replicas
161
+ */
162
+ subdoc_replica_read = 0x1c,
158
163
  };
159
164
 
160
165
  constexpr bool
@@ -185,6 +190,7 @@ is_valid_hello_feature(std::uint16_t code)
185
190
  case hello_feature::subdoc_document_macro_support:
186
191
  case hello_feature::replace_body_with_xattr:
187
192
  case hello_feature::resource_units:
193
+ case hello_feature::subdoc_replica_read:
188
194
  return true;
189
195
  }
190
196
  return false;
@@ -106,6 +106,9 @@ struct fmt::formatter<couchbase::core::protocol::hello_feature> {
106
106
  case couchbase::core::protocol::hello_feature::resource_units:
107
107
  name = "resource_units";
108
108
  break;
109
+ case couchbase::core::protocol::hello_feature::subdoc_replica_read:
110
+ name = "subdoc_replica_read";
111
+ break;
109
112
  }
110
113
  return format_to(ctx.out(), "{}", name);
111
114
  }
@@ -189,10 +189,10 @@ map_status_code(protocol::client_opcode opcode, std::uint16_t status)
189
189
  case key_value_status_code::opaque_no_match:
190
190
 
191
191
  case key_value_status_code::range_scan_cancelled:
192
- return errc::key_value::range_scan_cancelled;
192
+ return errc::common::request_canceled;
193
193
 
194
194
  case key_value_status_code::range_scan_vb_uuid_not_equal:
195
- return errc::key_value::range_scan_vb_uuid_not_equal;
195
+ return errc::key_value::mutation_token_outdated;
196
196
 
197
197
  case key_value_status_code::unknown:
198
198
  break;
@@ -19,34 +19,10 @@
19
19
 
20
20
  namespace couchbase::core
21
21
  {
22
- range_scan::range_scan(scan_term start, scan_term end)
23
- : start_{ std::move(start) }
24
- , end_{ std::move(end) }
25
- {
26
- }
27
-
28
- range_scan::range_scan(std::string_view start, std::string_view end)
29
- : start_{ utils::to_binary(start) }
30
- , end_{ utils::to_binary(end) }
31
- {
32
- }
33
-
34
- range_scan::range_scan(std::string_view start, bool exclusive_start, std::string_view end, bool exclusive_end)
35
- : start_{ utils::to_binary(start), exclusive_start }
36
- , end_{ utils::to_binary(end), exclusive_end }
37
- {
38
- }
39
-
40
- range_scan::range_scan(std::vector<std::byte> start, std::vector<std::byte> end)
41
- : start_{ std::move(start) }
42
- , end_{ std::move(end) }
43
- {
44
- }
45
-
46
- range_scan::range_scan(std::vector<std::byte> start, bool exclusive_start, std::vector<std::byte> end, bool exclusive_end)
47
- : start_{ std::move(start), exclusive_start }
48
- , end_{ std::move(end), exclusive_end }
22
+ auto
23
+ prefix_scan::to_range_scan() const -> range_scan
49
24
  {
25
+ return { scan_term{ prefix, false }, scan_term{ prefix + "\xf4\x8f\xfb\xfb" } };
50
26
  }
51
27
 
52
28
  auto