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,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