couchbase 3.0.1 → 3.0.2

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 (140) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +73 -4
  3. data/ext/build_config.hxx.in +2 -0
  4. data/ext/build_version.hxx.in +11 -8
  5. data/ext/cmake/BuildTracing.cmake +1 -1
  6. data/ext/cmake/CompilerWarnings.cmake +5 -0
  7. data/ext/cmake/Testing.cmake +3 -6
  8. data/ext/couchbase/bucket.hxx +9 -1
  9. data/ext/couchbase/cbsasl/client.h +1 -1
  10. data/ext/couchbase/cluster.hxx +89 -6
  11. data/ext/couchbase/configuration.hxx +2 -0
  12. data/ext/couchbase/couchbase.cxx +1647 -507
  13. data/ext/couchbase/diagnostics.hxx +0 -3
  14. data/ext/couchbase/io/dns_client.hxx +2 -2
  15. data/ext/couchbase/io/http_command.hxx +6 -3
  16. data/ext/couchbase/io/http_session.hxx +14 -18
  17. data/ext/couchbase/io/http_session_manager.hxx +83 -2
  18. data/ext/couchbase/io/mcbp_command.hxx +4 -1
  19. data/ext/couchbase/io/mcbp_context.hxx +37 -0
  20. data/ext/couchbase/io/mcbp_session.hxx +91 -30
  21. data/ext/couchbase/operations.hxx +5 -0
  22. data/ext/couchbase/operations/analytics_dataset_create.hxx +3 -2
  23. data/ext/couchbase/operations/analytics_dataset_drop.hxx +3 -2
  24. data/ext/couchbase/operations/analytics_dataset_get_all.hxx +3 -2
  25. data/ext/couchbase/operations/analytics_dataverse_create.hxx +3 -2
  26. data/ext/couchbase/operations/analytics_dataverse_drop.hxx +3 -2
  27. data/ext/couchbase/operations/analytics_get_pending_mutations.hxx +3 -2
  28. data/ext/couchbase/operations/analytics_index_create.hxx +3 -2
  29. data/ext/couchbase/operations/analytics_index_drop.hxx +3 -2
  30. data/ext/couchbase/operations/analytics_index_get_all.hxx +5 -2
  31. data/ext/couchbase/operations/analytics_link_connect.hxx +3 -2
  32. data/ext/couchbase/operations/analytics_link_disconnect.hxx +3 -2
  33. data/ext/couchbase/operations/bucket_create.hxx +3 -2
  34. data/ext/couchbase/operations/bucket_drop.hxx +3 -2
  35. data/ext/couchbase/operations/bucket_flush.hxx +3 -2
  36. data/ext/couchbase/operations/bucket_get.hxx +3 -2
  37. data/ext/couchbase/operations/bucket_get_all.hxx +3 -2
  38. data/ext/couchbase/operations/bucket_update.hxx +3 -2
  39. data/ext/couchbase/operations/cluster_developer_preview_enable.hxx +3 -2
  40. data/ext/couchbase/operations/collection_create.hxx +3 -2
  41. data/ext/couchbase/operations/collection_drop.hxx +3 -2
  42. data/ext/couchbase/operations/collections_manifest_get.hxx +3 -2
  43. data/ext/couchbase/operations/document_analytics.hxx +3 -2
  44. data/ext/couchbase/operations/document_append.hxx +77 -0
  45. data/ext/couchbase/operations/document_decrement.hxx +3 -2
  46. data/ext/couchbase/operations/document_exists.hxx +3 -2
  47. data/ext/couchbase/operations/document_get.hxx +3 -2
  48. data/ext/couchbase/operations/document_get_and_lock.hxx +3 -2
  49. data/ext/couchbase/operations/document_get_and_touch.hxx +3 -2
  50. data/ext/couchbase/operations/document_get_projected.hxx +3 -2
  51. data/ext/couchbase/operations/document_increment.hxx +3 -2
  52. data/ext/couchbase/operations/document_insert.hxx +3 -2
  53. data/ext/couchbase/operations/document_lookup_in.hxx +8 -2
  54. data/ext/couchbase/operations/document_mutate_in.hxx +13 -2
  55. data/ext/couchbase/operations/document_prepend.hxx +77 -0
  56. data/ext/couchbase/operations/document_query.hxx +3 -2
  57. data/ext/couchbase/operations/document_remove.hxx +5 -2
  58. data/ext/couchbase/operations/document_replace.hxx +3 -2
  59. data/ext/couchbase/operations/document_search.hxx +3 -2
  60. data/ext/couchbase/operations/document_touch.hxx +3 -2
  61. data/ext/couchbase/operations/document_unlock.hxx +3 -2
  62. data/ext/couchbase/operations/document_upsert.hxx +3 -2
  63. data/ext/couchbase/operations/document_view.hxx +3 -2
  64. data/ext/couchbase/operations/group_drop.hxx +3 -2
  65. data/ext/couchbase/operations/group_get.hxx +3 -2
  66. data/ext/couchbase/operations/group_get_all.hxx +3 -2
  67. data/ext/couchbase/operations/group_upsert.hxx +3 -2
  68. data/ext/couchbase/operations/http_noop.hxx +78 -0
  69. data/ext/couchbase/operations/mcbp_noop.hxx +61 -0
  70. data/ext/couchbase/operations/query_index_build_deferred.hxx +3 -2
  71. data/ext/couchbase/operations/query_index_create.hxx +3 -2
  72. data/ext/couchbase/operations/query_index_drop.hxx +3 -2
  73. data/ext/couchbase/operations/query_index_get_all.hxx +3 -2
  74. data/ext/couchbase/operations/role_get_all.hxx +3 -2
  75. data/ext/couchbase/operations/scope_create.hxx +3 -2
  76. data/ext/couchbase/operations/scope_drop.hxx +3 -2
  77. data/ext/couchbase/operations/scope_get_all.hxx +3 -2
  78. data/ext/couchbase/operations/search_get_stats.hxx +3 -2
  79. data/ext/couchbase/operations/search_index_analyze_document.hxx +3 -2
  80. data/ext/couchbase/operations/search_index_control_ingest.hxx +3 -2
  81. data/ext/couchbase/operations/search_index_control_plan_freeze.hxx +3 -2
  82. data/ext/couchbase/operations/search_index_control_query.hxx +3 -2
  83. data/ext/couchbase/operations/search_index_drop.hxx +3 -2
  84. data/ext/couchbase/operations/search_index_get.hxx +3 -2
  85. data/ext/couchbase/operations/search_index_get_all.hxx +3 -2
  86. data/ext/couchbase/operations/search_index_get_documents_count.hxx +3 -2
  87. data/ext/couchbase/operations/search_index_get_stats.hxx +3 -2
  88. data/ext/couchbase/operations/search_index_upsert.hxx +3 -2
  89. data/ext/couchbase/operations/user_drop.hxx +3 -2
  90. data/ext/couchbase/operations/user_get.hxx +3 -2
  91. data/ext/couchbase/operations/user_get_all.hxx +3 -2
  92. data/ext/couchbase/operations/user_upsert.hxx +3 -2
  93. data/ext/couchbase/operations/view_index_drop.hxx +3 -2
  94. data/ext/couchbase/operations/view_index_get.hxx +3 -2
  95. data/ext/couchbase/operations/view_index_get_all.hxx +3 -2
  96. data/ext/couchbase/operations/view_index_upsert.hxx +3 -2
  97. data/ext/couchbase/platform/terminate_handler.cc +5 -2
  98. data/ext/couchbase/protocol/client_opcode.hxx +368 -0
  99. data/ext/couchbase/protocol/cmd_append.hxx +145 -0
  100. data/ext/couchbase/protocol/cmd_hello.hxx +1 -0
  101. data/ext/couchbase/protocol/cmd_lookup_in.hxx +11 -3
  102. data/ext/couchbase/protocol/cmd_mutate_in.hxx +46 -4
  103. data/ext/couchbase/protocol/cmd_noop.hxx +82 -0
  104. data/ext/couchbase/protocol/cmd_prepend.hxx +145 -0
  105. data/ext/couchbase/protocol/durability_level.hxx +16 -0
  106. data/ext/couchbase/protocol/hello_feature.hxx +9 -0
  107. data/ext/couchbase/protocol/unsigned_leb128.h +2 -2
  108. data/ext/couchbase/service_type.hxx +1 -1
  109. data/ext/couchbase/version.hxx +18 -4
  110. data/ext/extconf.rb +9 -6
  111. data/ext/test/CMakeLists.txt +5 -0
  112. data/ext/test/test_helper.hxx +3 -3
  113. data/ext/test/test_helper_native.hxx +2 -5
  114. data/ext/test/test_native_binary_operations.cxx +186 -0
  115. data/ext/test/test_native_diagnostics.cxx +54 -3
  116. data/ext/test/test_ruby_trivial_crud.cxx +1 -1
  117. data/lib/couchbase.rb +1 -0
  118. data/lib/couchbase/analytics_options.rb +1 -71
  119. data/lib/couchbase/binary_collection.rb +60 -22
  120. data/lib/couchbase/binary_collection_options.rb +0 -76
  121. data/lib/couchbase/bucket.rb +40 -36
  122. data/lib/couchbase/cluster.rb +89 -156
  123. data/lib/couchbase/collection.rb +290 -72
  124. data/lib/couchbase/collection_options.rb +30 -243
  125. data/lib/couchbase/datastructures/couchbase_list.rb +5 -16
  126. data/lib/couchbase/datastructures/couchbase_map.rb +5 -16
  127. data/lib/couchbase/datastructures/couchbase_queue.rb +5 -16
  128. data/lib/couchbase/datastructures/couchbase_set.rb +5 -16
  129. data/lib/couchbase/diagnostics.rb +181 -0
  130. data/lib/couchbase/json_transcoder.rb +1 -1
  131. data/lib/couchbase/{common_options.rb → logger.rb} +24 -11
  132. data/lib/couchbase/management/query_index_manager.rb +1 -1
  133. data/lib/couchbase/management/user_manager.rb +3 -0
  134. data/lib/couchbase/options.rb +2094 -0
  135. data/lib/couchbase/query_options.rb +1 -144
  136. data/lib/couchbase/scope.rb +8 -25
  137. data/lib/couchbase/search_options.rb +0 -93
  138. data/lib/couchbase/version.rb +20 -1
  139. data/lib/couchbase/view_options.rb +1 -91
  140. metadata +19 -7
@@ -45,15 +45,16 @@ struct collection_drop_request {
45
45
  std::chrono::milliseconds timeout{ timeout_defaults::management_timeout };
46
46
  std::string client_context_id{ uuid::to_string(uuid::random()) };
47
47
 
48
- void encode_to(encoded_request_type& encoded, http_context&)
48
+ [[nodiscard]] std::error_code encode_to(encoded_request_type& encoded, http_context&)
49
49
  {
50
50
  encoded.method = "DELETE";
51
51
  encoded.path = fmt::format("/pools/default/buckets/{}/collections/{}/{}", bucket_name, scope_name, collection_name);
52
+ return {};
52
53
  }
53
54
  };
54
55
 
55
56
  collection_drop_response
56
- make_response(std::error_code ec, collection_drop_request& request, collection_drop_request::encoded_response_type encoded)
57
+ make_response(std::error_code ec, collection_drop_request& request, collection_drop_request::encoded_response_type&& encoded)
57
58
  {
58
59
  collection_drop_response response{ request.client_context_id, ec };
59
60
  if (!ec) {
@@ -47,16 +47,17 @@ struct collections_manifest_get_request {
47
47
  std::chrono::milliseconds timeout{ timeout_defaults::key_value_timeout };
48
48
  io::retry_context<io::retry_strategy::best_effort> retries{ true };
49
49
 
50
- void encode_to(encoded_request_type& encoded)
50
+ [[nodiscard]] std::error_code encode_to(encoded_request_type& encoded, mcbp_context&&)
51
51
  {
52
52
  encoded.opaque(opaque);
53
+ return {};
53
54
  }
54
55
  };
55
56
 
56
57
  collections_manifest_get_response
57
58
  make_response(std::error_code ec,
58
59
  collections_manifest_get_request& request,
59
- collections_manifest_get_request::encoded_response_type encoded)
60
+ collections_manifest_get_request::encoded_response_type&& encoded)
60
61
  {
61
62
  collections_manifest_get_response response{ request.id, encoded.opaque(), ec };
62
63
  if (ec && response.opaque == 0) {
@@ -166,7 +166,7 @@ struct analytics_request {
166
166
  std::vector<tao::json::value> positional_parameters{};
167
167
  std::map<std::string, tao::json::value> named_parameters{};
168
168
 
169
- void encode_to(encoded_request_type& encoded, http_context& context)
169
+ [[nodiscard]] std::error_code encode_to(encoded_request_type& encoded, http_context& context)
170
170
  {
171
171
  tao::json::value body{ { "statement", statement },
172
172
  { "client_context_id", client_context_id },
@@ -212,11 +212,12 @@ struct analytics_request {
212
212
  } else {
213
213
  spdlog::debug("ANALYTICS: {}", tao::json::to_string(body["statement"]));
214
214
  }
215
+ return {};
215
216
  }
216
217
  };
217
218
 
218
219
  analytics_response
219
- make_response(std::error_code ec, analytics_request& request, analytics_request::encoded_response_type encoded)
220
+ make_response(std::error_code ec, analytics_request& request, analytics_request::encoded_response_type&& encoded)
220
221
  {
221
222
  analytics_response response{ request.client_context_id, ec };
222
223
  if (!ec) {
@@ -0,0 +1,77 @@
1
+ /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * Copyright 2020 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 <protocol/cmd_append.hxx>
21
+ #include <protocol/durability_level.hxx>
22
+ #include <io/retry_context.hxx>
23
+
24
+ namespace couchbase::operations
25
+ {
26
+
27
+ struct append_response {
28
+ document_id id;
29
+ std::uint32_t opaque;
30
+ std::error_code ec{};
31
+ std::uint64_t cas{};
32
+ mutation_token token{};
33
+ };
34
+
35
+ struct append_request {
36
+ using encoded_request_type = protocol::client_request<protocol::append_request_body>;
37
+ using encoded_response_type = protocol::client_response<protocol::append_response_body>;
38
+
39
+ document_id id;
40
+ std::string value;
41
+ uint16_t partition{};
42
+ uint32_t opaque{};
43
+ protocol::durability_level durability_level{ protocol::durability_level::none };
44
+ std::optional<std::uint16_t> durability_timeout{};
45
+ std::chrono::milliseconds timeout{ timeout_defaults::key_value_timeout };
46
+ io::retry_context<io::retry_strategy::best_effort> retries{ false };
47
+
48
+ [[nodiscard]] std::error_code encode_to(encoded_request_type& encoded, mcbp_context&&)
49
+ {
50
+ encoded.opaque(opaque);
51
+ encoded.partition(partition);
52
+ encoded.body().id(id);
53
+ encoded.body().content(value);
54
+ if (durability_level != protocol::durability_level::none) {
55
+ encoded.body().durability(durability_level, durability_timeout);
56
+ }
57
+ return {};
58
+ }
59
+ };
60
+
61
+ append_response
62
+ make_response(std::error_code ec, append_request& request, append_request::encoded_response_type&& encoded)
63
+ {
64
+ append_response response{ request.id, encoded.opaque(), ec };
65
+ if (ec && response.opaque == 0) {
66
+ response.opaque = request.opaque;
67
+ }
68
+ if (!ec) {
69
+ response.cas = encoded.cas();
70
+ response.token = encoded.body().token();
71
+ response.token.partition_id = request.partition;
72
+ response.token.bucket_name = response.id.bucket;
73
+ }
74
+ return response;
75
+ }
76
+
77
+ } // namespace couchbase::operations
@@ -48,7 +48,7 @@ struct decrement_request {
48
48
  std::chrono::milliseconds timeout{ timeout_defaults::key_value_timeout };
49
49
  io::retry_context<io::retry_strategy::best_effort> retries{ false };
50
50
 
51
- void encode_to(encoded_request_type& encoded)
51
+ [[nodiscard]] std::error_code encode_to(encoded_request_type& encoded, mcbp_context&&)
52
52
  {
53
53
  encoded.opaque(opaque);
54
54
  encoded.partition(partition);
@@ -64,11 +64,12 @@ struct decrement_request {
64
64
  if (durability_level != protocol::durability_level::none) {
65
65
  encoded.body().durability(durability_level, durability_timeout);
66
66
  }
67
+ return {};
67
68
  }
68
69
  };
69
70
 
70
71
  decrement_response
71
- make_response(std::error_code ec, decrement_request& request, decrement_request::encoded_response_type encoded)
72
+ make_response(std::error_code ec, decrement_request& request, decrement_request::encoded_response_type&& encoded)
72
73
  {
73
74
  decrement_response response{ request.id, encoded.opaque(), ec };
74
75
  if (ec && response.opaque == 0) {
@@ -45,15 +45,16 @@ struct exists_request {
45
45
  std::chrono::milliseconds timeout{ timeout_defaults::key_value_timeout };
46
46
  io::retry_context<io::retry_strategy::best_effort> retries{ false };
47
47
 
48
- void encode_to(encoded_request_type& encoded)
48
+ [[nodiscard]] std::error_code encode_to(encoded_request_type& encoded, mcbp_context&&)
49
49
  {
50
50
  encoded.opaque(opaque);
51
51
  encoded.body().id(partition, id);
52
+ return {};
52
53
  }
53
54
  };
54
55
 
55
56
  exists_response
56
- make_response(std::error_code ec, exists_request& request, exists_request::encoded_response_type encoded)
57
+ make_response(std::error_code ec, exists_request& request, exists_request::encoded_response_type&& encoded)
57
58
  {
58
59
  exists_response response{ request.id, encoded.opaque(), ec, request.partition };
59
60
  if (!ec) {
@@ -43,16 +43,17 @@ struct get_request {
43
43
  std::chrono::milliseconds timeout{ timeout_defaults::key_value_timeout };
44
44
  io::retry_context<io::retry_strategy::best_effort> retries{ true };
45
45
 
46
- void encode_to(encoded_request_type& encoded)
46
+ [[nodiscard]] std::error_code encode_to(encoded_request_type& encoded, mcbp_context&&)
47
47
  {
48
48
  encoded.opaque(opaque);
49
49
  encoded.partition(partition);
50
50
  encoded.body().id(id);
51
+ return {};
51
52
  }
52
53
  };
53
54
 
54
55
  get_response
55
- make_response(std::error_code ec, get_request& request, get_request::encoded_response_type encoded)
56
+ make_response(std::error_code ec, get_request& request, get_request::encoded_response_type&& encoded)
56
57
  {
57
58
  get_response response{ request.id, encoded.opaque(), ec };
58
59
  if (ec && response.opaque == 0) {
@@ -44,17 +44,18 @@ struct get_and_lock_request {
44
44
  std::chrono::milliseconds timeout{ timeout_defaults::key_value_timeout };
45
45
  io::retry_context<io::retry_strategy::best_effort> retries{ false };
46
46
 
47
- void encode_to(encoded_request_type& encoded)
47
+ [[nodiscard]] std::error_code encode_to(encoded_request_type& encoded, mcbp_context&&)
48
48
  {
49
49
  encoded.opaque(opaque);
50
50
  encoded.partition(partition);
51
51
  encoded.body().id(id);
52
52
  encoded.body().lock_time(lock_time);
53
+ return {};
53
54
  }
54
55
  };
55
56
 
56
57
  get_and_lock_response
57
- make_response(std::error_code ec, get_and_lock_request& request, get_and_lock_request::encoded_response_type encoded)
58
+ make_response(std::error_code ec, get_and_lock_request& request, get_and_lock_request::encoded_response_type&& encoded)
58
59
  {
59
60
  get_and_lock_response response{ request.id, encoded.opaque(), ec };
60
61
  if (ec && response.opaque == 0) {
@@ -44,17 +44,18 @@ struct get_and_touch_request {
44
44
  std::chrono::milliseconds timeout{ timeout_defaults::key_value_timeout };
45
45
  io::retry_context<io::retry_strategy::best_effort> retries{ false };
46
46
 
47
- void encode_to(encoded_request_type& encoded)
47
+ [[nodiscard]] std::error_code encode_to(encoded_request_type& encoded, mcbp_context&&)
48
48
  {
49
49
  encoded.opaque(opaque);
50
50
  encoded.partition(partition);
51
51
  encoded.body().id(id);
52
52
  encoded.body().expiry(expiry);
53
+ return {};
53
54
  }
54
55
  };
55
56
 
56
57
  get_and_touch_response
57
- make_response(std::error_code ec, get_and_touch_request& request, get_and_touch_request::encoded_response_type encoded)
58
+ make_response(std::error_code ec, get_and_touch_request& request, get_and_touch_request::encoded_response_type&& encoded)
58
59
  {
59
60
  get_and_touch_response response{ request.id, encoded.opaque(), ec };
60
61
  if (ec && response.opaque == 0) {
@@ -48,7 +48,7 @@ struct get_projected_request {
48
48
  std::chrono::milliseconds timeout{ timeout_defaults::key_value_timeout };
49
49
  io::retry_context<io::retry_strategy::best_effort> retries{ true };
50
50
 
51
- void encode_to(encoded_request_type& encoded)
51
+ [[nodiscard]] std::error_code encode_to(encoded_request_type& encoded, mcbp_context&&)
52
52
  {
53
53
  encoded.opaque(opaque);
54
54
  encoded.partition(partition);
@@ -76,6 +76,7 @@ struct get_projected_request {
76
76
  }
77
77
  }
78
78
  encoded.body().specs(specs);
79
+ return {};
79
80
  }
80
81
  };
81
82
 
@@ -197,7 +198,7 @@ subdoc_apply_projection(tao::json::value& root, const std::string& path, tao::js
197
198
  } // namespace priv
198
199
 
199
200
  get_projected_response
200
- make_response(std::error_code ec, get_projected_request& request, get_projected_request::encoded_response_type encoded)
201
+ make_response(std::error_code ec, get_projected_request& request, get_projected_request::encoded_response_type&& encoded)
201
202
  {
202
203
  get_projected_response response{ request.id, encoded.opaque(), ec };
203
204
  if (ec && response.opaque == 0) {
@@ -50,7 +50,7 @@ struct increment_request {
50
50
  std::chrono::milliseconds timeout{ timeout_defaults::key_value_timeout };
51
51
  io::retry_context<io::retry_strategy::best_effort> retries{ false };
52
52
 
53
- void encode_to(encoded_request_type& encoded)
53
+ [[nodiscard]] std::error_code encode_to(encoded_request_type& encoded, mcbp_context&&)
54
54
  {
55
55
  encoded.opaque(opaque);
56
56
  encoded.partition(partition);
@@ -66,11 +66,12 @@ struct increment_request {
66
66
  if (durability_level != protocol::durability_level::none) {
67
67
  encoded.body().durability(durability_level, durability_timeout);
68
68
  }
69
+ return {};
69
70
  }
70
71
  };
71
72
 
72
73
  increment_response
73
- make_response(std::error_code ec, increment_request& request, increment_request::encoded_response_type encoded)
74
+ make_response(std::error_code ec, increment_request& request, increment_request::encoded_response_type&& encoded)
74
75
  {
75
76
  increment_response response{ request.id, encoded.opaque(), ec };
76
77
  if (ec && response.opaque == 0) {
@@ -48,7 +48,7 @@ struct insert_request {
48
48
  std::chrono::milliseconds timeout{ timeout_defaults::key_value_timeout };
49
49
  io::retry_context<io::retry_strategy::best_effort> retries{ false };
50
50
 
51
- void encode_to(encoded_request_type& encoded)
51
+ [[nodiscard]] std::error_code encode_to(encoded_request_type& encoded, mcbp_context&&)
52
52
  {
53
53
  encoded.opaque(opaque);
54
54
  encoded.partition(partition);
@@ -59,11 +59,12 @@ struct insert_request {
59
59
  if (durability_level != protocol::durability_level::none) {
60
60
  encoded.body().durability(durability_level, durability_timeout);
61
61
  }
62
+ return {};
62
63
  }
63
64
  };
64
65
 
65
66
  insert_response
66
- make_response(std::error_code ec, insert_request& request, insert_request::encoded_response_type encoded)
67
+ make_response(std::error_code ec, insert_request& request, insert_request::encoded_response_type&& encoded)
67
68
  {
68
69
  insert_response response{ request.id, encoded.opaque(), ec };
69
70
  if (ec && response.opaque == 0) {
@@ -39,6 +39,7 @@ struct lookup_in_response {
39
39
  std::error_code ec{};
40
40
  std::uint64_t cas{};
41
41
  std::vector<field> fields{};
42
+ bool deleted{ false };
42
43
  };
43
44
 
44
45
  struct lookup_in_request {
@@ -53,7 +54,7 @@ struct lookup_in_request {
53
54
  std::chrono::milliseconds timeout{ timeout_defaults::key_value_timeout };
54
55
  io::retry_context<io::retry_strategy::best_effort> retries{ false };
55
56
 
56
- void encode_to(encoded_request_type& encoded)
57
+ [[nodiscard]] std::error_code encode_to(encoded_request_type& encoded, mcbp_context&&)
57
58
  {
58
59
  for (std::size_t i = 0; i < specs.entries.size(); ++i) {
59
60
  auto& entry = specs.entries[i];
@@ -72,16 +73,21 @@ struct lookup_in_request {
72
73
  encoded.body().id(id);
73
74
  encoded.body().access_deleted(access_deleted);
74
75
  encoded.body().specs(specs);
76
+ return {};
75
77
  }
76
78
  };
77
79
 
78
80
  lookup_in_response
79
- make_response(std::error_code ec, lookup_in_request& request, lookup_in_request::encoded_response_type encoded)
81
+ make_response(std::error_code ec, lookup_in_request& request, lookup_in_request::encoded_response_type&& encoded)
80
82
  {
81
83
  lookup_in_response response{ request.id, encoded.opaque(), ec };
82
84
  if (ec && response.opaque == 0) {
83
85
  response.opaque = request.opaque;
84
86
  }
87
+ if (encoded.status() == protocol::status::subdoc_success_deleted ||
88
+ encoded.status() == protocol::status::subdoc_multi_path_failure_deleted) {
89
+ response.deleted = true;
90
+ }
85
91
  if (!ec) {
86
92
  response.cas = encoded.cas();
87
93
  response.fields.resize(request.specs.entries.size());
@@ -50,6 +50,7 @@ struct mutate_in_response {
50
50
  mutation_token token{};
51
51
  std::vector<field> fields{};
52
52
  std::optional<std::size_t> first_error_index{};
53
+ bool deleted{ false };
53
54
  };
54
55
 
55
56
  struct mutate_in_request {
@@ -61,6 +62,7 @@ struct mutate_in_request {
61
62
  uint32_t opaque{};
62
63
  uint64_t cas{ 0 };
63
64
  bool access_deleted{ false };
65
+ bool create_as_deleted{ false };
64
66
  std::optional<std::uint32_t> expiry{};
65
67
  protocol::mutate_in_request_body::store_semantics_type store_semantics{
66
68
  protocol::mutate_in_request_body::store_semantics_type::replace
@@ -71,8 +73,11 @@ struct mutate_in_request {
71
73
  std::chrono::milliseconds timeout{ timeout_defaults::key_value_timeout };
72
74
  io::retry_context<io::retry_strategy::best_effort> retries{ false };
73
75
 
74
- void encode_to(encoded_request_type& encoded)
76
+ [[nodiscard]] std::error_code encode_to(encoded_request_type& encoded, mcbp_context&& ctx)
75
77
  {
78
+ if (create_as_deleted && !ctx.supports_feature(protocol::hello_feature::subdoc_create_as_deleted)) {
79
+ return std::make_error_code(error::common_errc::unsupported_operation);
80
+ }
76
81
  for (std::size_t i = 0; i < specs.entries.size(); ++i) {
77
82
  auto& entry = specs.entries[i];
78
83
  entry.original_index = i;
@@ -93,21 +98,27 @@ struct mutate_in_request {
93
98
  encoded.body().expiry(*expiry);
94
99
  }
95
100
  encoded.body().access_deleted(access_deleted);
101
+ encoded.body().create_as_deleted(create_as_deleted);
96
102
  encoded.body().store_semantics(store_semantics);
97
103
  encoded.body().specs(specs);
98
104
  if (durability_level != protocol::durability_level::none) {
99
105
  encoded.body().durability(durability_level, durability_timeout);
100
106
  }
107
+ return {};
101
108
  }
102
109
  };
103
110
 
104
111
  mutate_in_response
105
- make_response(std::error_code ec, mutate_in_request& request, mutate_in_request::encoded_response_type encoded)
112
+ make_response(std::error_code ec, mutate_in_request& request, mutate_in_request::encoded_response_type&& encoded)
106
113
  {
107
114
  mutate_in_response response{ request.id, encoded.opaque(), ec };
108
115
  if (ec && response.opaque == 0) {
109
116
  response.opaque = request.opaque;
110
117
  }
118
+ if (encoded.status() == protocol::status::subdoc_success_deleted ||
119
+ encoded.status() == protocol::status::subdoc_multi_path_failure_deleted) {
120
+ response.deleted = true;
121
+ }
111
122
  if (!ec) {
112
123
  response.cas = encoded.cas();
113
124
  response.token = encoded.body().token();
@@ -0,0 +1,77 @@
1
+ /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * Copyright 2020 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 <protocol/cmd_prepend.hxx>
21
+ #include <protocol/durability_level.hxx>
22
+ #include <io/retry_context.hxx>
23
+
24
+ namespace couchbase::operations
25
+ {
26
+
27
+ struct prepend_response {
28
+ document_id id;
29
+ std::uint32_t opaque;
30
+ std::error_code ec{};
31
+ std::uint64_t cas{};
32
+ mutation_token token{};
33
+ };
34
+
35
+ struct prepend_request {
36
+ using encoded_request_type = protocol::client_request<protocol::prepend_request_body>;
37
+ using encoded_response_type = protocol::client_response<protocol::prepend_response_body>;
38
+
39
+ document_id id;
40
+ std::string value;
41
+ uint16_t partition{};
42
+ uint32_t opaque{};
43
+ protocol::durability_level durability_level{ protocol::durability_level::none };
44
+ std::optional<std::uint16_t> durability_timeout{};
45
+ std::chrono::milliseconds timeout{ timeout_defaults::key_value_timeout };
46
+ io::retry_context<io::retry_strategy::best_effort> retries{ false };
47
+
48
+ [[nodiscard]] std::error_code encode_to(encoded_request_type& encoded, mcbp_context&&)
49
+ {
50
+ encoded.opaque(opaque);
51
+ encoded.partition(partition);
52
+ encoded.body().id(id);
53
+ encoded.body().content(value);
54
+ if (durability_level != protocol::durability_level::none) {
55
+ encoded.body().durability(durability_level, durability_timeout);
56
+ }
57
+ return {};
58
+ }
59
+ };
60
+
61
+ prepend_response
62
+ make_response(std::error_code ec, prepend_request& request, prepend_request::encoded_response_type&& encoded)
63
+ {
64
+ prepend_response response{ request.id, encoded.opaque(), ec };
65
+ if (ec && response.opaque == 0) {
66
+ response.opaque = request.opaque;
67
+ }
68
+ if (!ec) {
69
+ response.cas = encoded.cas();
70
+ response.token = encoded.body().token();
71
+ response.token.partition_id = request.partition;
72
+ response.token.bucket_name = response.id.bucket;
73
+ }
74
+ return response;
75
+ }
76
+
77
+ } // namespace couchbase::operations