couchbase 3.8.2 → 3.9.0

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 (473) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/ext/CMakeLists.txt +16 -1
  4. data/ext/cache/cpm/{CPM_0.42.0.cmake → CPM_0.43.1.cmake} +18 -2
  5. data/ext/cache/extconf_include.rb +6 -6
  6. data/ext/cache/mozilla-ca-bundle.crt +121 -55
  7. data/ext/cache/mozilla-ca-bundle.sha256 +1 -1
  8. data/ext/couchbase/CMakeLists.txt +130 -21
  9. data/ext/couchbase/cmake/APKBUILD.in +25 -4
  10. data/ext/couchbase/cmake/Bundler.cmake +143 -34
  11. data/ext/couchbase/cmake/CPM.cmake +126 -12
  12. data/ext/couchbase/cmake/Cache.cmake +7 -1
  13. data/ext/couchbase/cmake/CompilerOptions.cmake +1 -1
  14. data/ext/couchbase/cmake/CompilerWarnings.cmake +17 -6
  15. data/ext/couchbase/cmake/GrpcProtobuf.cmake +481 -0
  16. data/ext/couchbase/cmake/OpenSSL.cmake +10 -3
  17. data/ext/couchbase/cmake/Packaging.cmake +519 -65
  18. data/ext/couchbase/cmake/Protostellar.cmake +250 -0
  19. data/ext/couchbase/cmake/Sanitizers.cmake +61 -50
  20. data/ext/couchbase/cmake/StaticAnalyzers.cmake +16 -5
  21. data/ext/couchbase/cmake/TestFramework.cmake +283 -0
  22. data/ext/couchbase/cmake/TestFrameworkAddTests.cmake +51 -0
  23. data/ext/couchbase/cmake/Testing.cmake +27 -9
  24. data/ext/couchbase/cmake/ThirdPartyDependencies.cmake +141 -8
  25. data/ext/couchbase/cmake/VersionInfo.cmake +50 -0
  26. data/ext/couchbase/cmake/build_config.hxx.in +2 -1
  27. data/ext/couchbase/cmake/couchbase-cxx-client.spec.in +101 -23
  28. data/ext/couchbase/cmake/couchbase_cxx_client_static-config.cmake.in +7 -0
  29. data/ext/couchbase/cmake/couchbase_cxx_client_static.pc.in +2 -0
  30. data/ext/couchbase/cmake/gRPC_Generate.cmake +58 -0
  31. data/ext/couchbase/cmake/protobuf_Generate.cmake +69 -0
  32. data/ext/couchbase/cmake/require-git-checkout.cmake +25 -0
  33. data/ext/couchbase/cmake/tarball_glob.txt +49 -0
  34. data/ext/couchbase/core/agent_group.cxx +0 -8
  35. data/ext/couchbase/core/agent_group.hxx +0 -4
  36. data/ext/couchbase/core/analytics_stream.cxx +314 -0
  37. data/ext/couchbase/core/analytics_stream.hxx +129 -0
  38. data/ext/couchbase/core/analytics_stream_component.cxx +245 -0
  39. data/ext/couchbase/core/analytics_stream_component.hxx +67 -0
  40. data/ext/couchbase/core/app_telemetry_meter.cxx +25 -3
  41. data/ext/couchbase/core/app_telemetry_meter.hxx +77 -0
  42. data/ext/couchbase/core/app_telemetry_reporter.cxx +7 -6
  43. data/ext/couchbase/core/bucket.cxx +381 -87
  44. data/ext/couchbase/core/bucket.hxx +105 -25
  45. data/ext/couchbase/core/bucket_unit_test_api.hxx +57 -0
  46. data/ext/couchbase/core/capella.hxx +91 -0
  47. data/ext/couchbase/core/cluster.cxx +1554 -398
  48. data/ext/couchbase/core/cluster.hxx +39 -8
  49. data/ext/couchbase/core/cluster_agent.cxx +0 -8
  50. data/ext/couchbase/core/cluster_agent.hxx +0 -4
  51. data/ext/couchbase/core/cluster_options.hxx +26 -3
  52. data/ext/couchbase/core/collections_component.cxx +39 -15
  53. data/ext/couchbase/core/config_profiles.cxx +1 -1
  54. data/ext/couchbase/core/crud_component.cxx +2 -2
  55. data/ext/couchbase/core/crud_options.hxx +34 -0
  56. data/ext/couchbase/core/crypto/cbcrypto.cc +18 -13
  57. data/ext/couchbase/core/document_id_redaction.hxx +81 -0
  58. data/ext/couchbase/core/error_context/base_error_context.hxx +7 -6
  59. data/ext/couchbase/core/error_context/key_value.cxx +25 -2
  60. data/ext/couchbase/core/error_context/key_value.hxx +60 -33
  61. data/ext/couchbase/core/error_context/key_value_error_context.hxx +16 -15
  62. data/ext/couchbase/core/error_context/search.hxx +5 -0
  63. data/ext/couchbase/core/error_context/search_json.hxx +3 -0
  64. data/ext/couchbase/core/error_context/subdocument_error_context.hxx +19 -18
  65. data/ext/couchbase/core/error_context/view.hxx +5 -0
  66. data/ext/couchbase/core/free_form_http_request.cxx +237 -4
  67. data/ext/couchbase/core/free_form_http_request.hxx +41 -8
  68. data/ext/couchbase/core/http_component.cxx +300 -284
  69. data/ext/couchbase/core/http_component.hxx +0 -4
  70. data/ext/couchbase/core/impl/analytics.cxx +38 -5
  71. data/ext/couchbase/core/impl/analytics.hxx +34 -0
  72. data/ext/couchbase/core/impl/bootstrap_error.hxx +0 -3
  73. data/ext/couchbase/core/impl/collection.cxx +215 -202
  74. data/ext/couchbase/core/impl/collection_manager.cxx +1 -1
  75. data/ext/couchbase/core/impl/dns_srv_tracker.cxx +45 -18
  76. data/ext/couchbase/core/impl/error.cxx +22 -2
  77. data/ext/couchbase/core/impl/internal_analytics_stream_result.hxx +111 -0
  78. data/ext/couchbase/core/impl/internal_query_stream_result.hxx +110 -0
  79. data/ext/couchbase/core/impl/invoke_with_node_id.hxx +15 -7
  80. data/ext/couchbase/core/impl/key_value_error_category.cxx +6 -0
  81. data/ext/couchbase/core/impl/lookup_in_replica.cxx +10 -10
  82. data/ext/couchbase/core/impl/lookup_in_replica.hxx +4 -4
  83. data/ext/couchbase/core/impl/node_id.cxx +49 -13
  84. data/ext/couchbase/core/impl/observability_recorder.cxx +12 -2
  85. data/ext/couchbase/core/impl/observe_poll.cxx +63 -23
  86. data/ext/couchbase/core/impl/public_analytics_stream_result.cxx +372 -0
  87. data/ext/couchbase/core/impl/public_bucket.cxx +48 -2
  88. data/ext/couchbase/core/impl/public_cluster.cxx +229 -42
  89. data/ext/couchbase/core/impl/public_query_stream_result.cxx +380 -0
  90. data/ext/couchbase/core/impl/public_transaction_get_multi_replicas_from_preferred_server_group_result.cxx +42 -0
  91. data/ext/couchbase/core/impl/public_transaction_get_multi_result.cxx +42 -0
  92. data/ext/couchbase/core/impl/query.cxx +76 -7
  93. data/ext/couchbase/core/impl/query.hxx +36 -0
  94. data/ext/couchbase/core/impl/query_index_manager.cxx +54 -1
  95. data/ext/couchbase/core/impl/replica_utils.cxx +101 -0
  96. data/ext/couchbase/core/impl/replica_utils.hxx +64 -0
  97. data/ext/couchbase/core/impl/resolve_node_id.hxx +125 -0
  98. data/ext/couchbase/core/impl/scope.cxx +70 -0
  99. data/ext/couchbase/core/impl/search.cxx +31 -1
  100. data/ext/couchbase/core/impl/transactions.cxx +130 -0
  101. data/ext/couchbase/core/impl/wait_until_ready.cxx +439 -0
  102. data/ext/couchbase/core/impl/wait_until_ready.hxx +110 -0
  103. data/ext/couchbase/core/impl/with_bucket_config_or_timeout.hxx +180 -0
  104. data/ext/couchbase/core/impl/with_cancellation.hxx +11 -3
  105. data/ext/couchbase/core/io/configuration_belongs_to_session.hxx +1 -2
  106. data/ext/couchbase/core/io/dns_client.cxx +122 -45
  107. data/ext/couchbase/core/io/dns_codec.hxx +21 -21
  108. data/ext/couchbase/core/io/dns_config.cxx +21 -6
  109. data/ext/couchbase/core/io/http_command.hxx +149 -121
  110. data/ext/couchbase/core/io/http_error.hxx +107 -0
  111. data/ext/couchbase/core/io/http_parser.cxx +4 -0
  112. data/ext/couchbase/core/io/http_session.cxx +606 -154
  113. data/ext/couchbase/core/io/http_session.hxx +147 -30
  114. data/ext/couchbase/core/io/http_session_manager.hxx +329 -382
  115. data/ext/couchbase/core/io/http_streaming_parser.cxx +4 -0
  116. data/ext/couchbase/core/io/http_streaming_response.cxx +328 -43
  117. data/ext/couchbase/core/io/http_streaming_response.hxx +37 -3
  118. data/ext/couchbase/core/io/mcbp_buffer_pool.hxx +122 -0
  119. data/ext/couchbase/core/io/mcbp_command.hxx +150 -51
  120. data/ext/couchbase/core/io/mcbp_command_id.hxx +45 -0
  121. data/ext/couchbase/core/io/mcbp_message.cxx +9 -1
  122. data/ext/couchbase/core/io/mcbp_message.hxx +19 -0
  123. data/ext/couchbase/core/io/mcbp_output_queue.hxx +150 -0
  124. data/ext/couchbase/core/io/mcbp_parser.cxx +24 -7
  125. data/ext/couchbase/core/io/mcbp_session.cxx +309 -301
  126. data/ext/couchbase/core/io/mcbp_session.hxx +27 -18
  127. data/ext/couchbase/core/io/opaque_ring_table.hxx +145 -0
  128. data/ext/couchbase/core/io/retry_orchestrator.hxx +6 -5
  129. data/ext/couchbase/core/io/stream_deadline.hxx +50 -0
  130. data/ext/couchbase/core/io/streams.cxx +151 -21
  131. data/ext/couchbase/core/io/streams.hxx +48 -1
  132. data/ext/couchbase/core/logger/logger.cxx +36 -0
  133. data/ext/couchbase/core/logger/logger.hxx +46 -6
  134. data/ext/couchbase/core/logger/redaction.hxx +503 -0
  135. data/ext/couchbase/core/management/eventing_status.hxx +10 -0
  136. data/ext/couchbase/core/management/eventing_status_json.hxx +4 -0
  137. data/ext/couchbase/core/mcbp/big_endian.cxx +1 -1
  138. data/ext/couchbase/core/mcbp/codec.cxx +27 -18
  139. data/ext/couchbase/core/mcbp/operation_queue.cxx +2 -2
  140. data/ext/couchbase/core/mcbp/packet.hxx +2 -2
  141. data/ext/couchbase/core/mcbp/queue_request.cxx +23 -6
  142. data/ext/couchbase/core/mcbp/queue_request.hxx +21 -0
  143. data/ext/couchbase/core/meta/features.hxx +13 -0
  144. data/ext/couchbase/core/meta/version.cxx +6 -3
  145. data/ext/couchbase/core/metrics/logging_meter.cxx +5 -10
  146. data/ext/couchbase/core/metrics/meter_wrapper.cxx +63 -33
  147. data/ext/couchbase/core/metrics/meter_wrapper.hxx +55 -3
  148. data/ext/couchbase/core/operations/analytics_response_parsing.cxx +177 -0
  149. data/ext/couchbase/core/operations/analytics_response_parsing.hxx +55 -0
  150. data/ext/couchbase/core/operations/document_analytics.cxx +48 -130
  151. data/ext/couchbase/core/operations/document_analytics.hxx +14 -2
  152. data/ext/couchbase/core/operations/document_get_all_replicas.hxx +15 -7
  153. data/ext/couchbase/core/operations/document_get_any_replica.hxx +19 -8
  154. data/ext/couchbase/core/operations/document_get_projected.cxx +1 -1
  155. data/ext/couchbase/core/{impl/get_replica.cxx → operations/document_get_replica.cxx} +21 -3
  156. data/ext/couchbase/core/{impl/get_replica.hxx → operations/document_get_replica.hxx} +31 -4
  157. data/ext/couchbase/core/operations/document_lookup_in.cxx +10 -10
  158. data/ext/couchbase/core/operations/document_lookup_in_all_replicas.hxx +228 -198
  159. data/ext/couchbase/core/operations/document_lookup_in_any_replica.hxx +215 -217
  160. data/ext/couchbase/core/operations/document_query.cxx +108 -221
  161. data/ext/couchbase/core/operations/document_query.hxx +18 -4
  162. data/ext/couchbase/core/operations/document_search.cxx +52 -8
  163. data/ext/couchbase/core/operations/document_search.hxx +3 -0
  164. data/ext/couchbase/core/operations/document_view.cxx +3 -3
  165. data/ext/couchbase/core/operations/management/analytics_dataset_create.cxx +15 -8
  166. data/ext/couchbase/core/operations/management/analytics_dataset_create.hxx +4 -0
  167. data/ext/couchbase/core/operations/management/analytics_dataset_drop.cxx +11 -6
  168. data/ext/couchbase/core/operations/management/analytics_dataset_get_all.cxx +3 -2
  169. data/ext/couchbase/core/operations/management/analytics_dataverse_create.cxx +10 -5
  170. data/ext/couchbase/core/operations/management/analytics_dataverse_drop.cxx +10 -5
  171. data/ext/couchbase/core/operations/management/analytics_get_pending_mutations.cxx +2 -1
  172. data/ext/couchbase/core/operations/management/analytics_index_create.cxx +33 -8
  173. data/ext/couchbase/core/operations/management/analytics_index_drop.cxx +12 -7
  174. data/ext/couchbase/core/operations/management/analytics_index_get_all.cxx +3 -2
  175. data/ext/couchbase/core/operations/management/analytics_link_connect.cxx +11 -6
  176. data/ext/couchbase/core/operations/management/analytics_link_create.cxx +3 -3
  177. data/ext/couchbase/core/operations/management/analytics_link_disconnect.cxx +10 -4
  178. data/ext/couchbase/core/operations/management/analytics_link_drop.cxx +6 -4
  179. data/ext/couchbase/core/operations/management/analytics_link_get_all.cxx +4 -3
  180. data/ext/couchbase/core/operations/management/analytics_link_replace.cxx +3 -3
  181. data/ext/couchbase/core/operations/management/analytics_link_utils.hxx +1 -1
  182. data/ext/couchbase/core/operations/management/change_password.cxx +2 -0
  183. data/ext/couchbase/core/operations/management/collection_drop.cxx +5 -1
  184. data/ext/couchbase/core/operations/management/error_utils.cxx +59 -5
  185. data/ext/couchbase/core/operations/management/error_utils.hxx +29 -1
  186. data/ext/couchbase/core/operations/management/eventing_deploy_function.cxx +9 -3
  187. data/ext/couchbase/core/operations/management/eventing_drop_function.cxx +8 -3
  188. data/ext/couchbase/core/operations/management/eventing_get_all_functions.cxx +4 -2
  189. data/ext/couchbase/core/operations/management/eventing_get_function.cxx +5 -3
  190. data/ext/couchbase/core/operations/management/eventing_get_status.cxx +4 -2
  191. data/ext/couchbase/core/operations/management/eventing_pause_function.cxx +9 -3
  192. data/ext/couchbase/core/operations/management/eventing_resume_function.cxx +9 -3
  193. data/ext/couchbase/core/operations/management/eventing_undeploy_function.cxx +9 -3
  194. data/ext/couchbase/core/operations/management/eventing_upsert_function.cxx +9 -3
  195. data/ext/couchbase/core/operations/management/group_drop.cxx +3 -1
  196. data/ext/couchbase/core/operations/management/group_get.cxx +3 -1
  197. data/ext/couchbase/core/operations/management/group_upsert.cxx +11 -8
  198. data/ext/couchbase/core/operations/management/query_index_build.cxx +5 -2
  199. data/ext/couchbase/core/operations/management/query_index_create.cxx +9 -3
  200. data/ext/couchbase/core/operations/management/query_index_drop.cxx +11 -4
  201. data/ext/couchbase/core/operations/management/query_index_get_all.cxx +1 -1
  202. data/ext/couchbase/core/operations/management/query_index_get_all_deferred.cxx +1 -1
  203. data/ext/couchbase/core/operations/management/scope_drop.cxx +5 -1
  204. data/ext/couchbase/core/operations/management/scope_get_all.cxx +6 -1
  205. data/ext/couchbase/core/operations/management/search_get_stats.cxx +10 -0
  206. data/ext/couchbase/core/operations/management/search_index_analyze_document.cxx +3 -2
  207. data/ext/couchbase/core/operations/management/search_index_control_ingest.cxx +4 -3
  208. data/ext/couchbase/core/operations/management/search_index_control_plan_freeze.cxx +4 -3
  209. data/ext/couchbase/core/operations/management/search_index_control_query.cxx +4 -3
  210. data/ext/couchbase/core/operations/management/search_index_drop.cxx +2 -2
  211. data/ext/couchbase/core/operations/management/search_index_get.cxx +2 -2
  212. data/ext/couchbase/core/operations/management/search_index_get_documents_count.cxx +3 -2
  213. data/ext/couchbase/core/operations/management/search_index_get_stats.cxx +3 -1
  214. data/ext/couchbase/core/operations/management/search_index_upsert.cxx +2 -2
  215. data/ext/couchbase/core/operations/management/user_drop.cxx +3 -1
  216. data/ext/couchbase/core/operations/management/user_get.cxx +3 -1
  217. data/ext/couchbase/core/operations/management/user_upsert.cxx +12 -9
  218. data/ext/couchbase/core/operations/management/view_index_drop.cxx +1 -1
  219. data/ext/couchbase/core/operations/management/view_index_get.cxx +1 -1
  220. data/ext/couchbase/core/operations/management/view_index_upsert.cxx +1 -1
  221. data/ext/couchbase/core/operations/operation_traits.hxx +18 -0
  222. data/ext/couchbase/core/operations/query_response_parsing.cxx +211 -0
  223. data/ext/couchbase/core/operations/query_response_parsing.hxx +60 -0
  224. data/ext/couchbase/core/operations_fwd.hxx +3 -3
  225. data/ext/couchbase/core/origin.cxx +54 -26
  226. data/ext/couchbase/core/origin.hxx +12 -0
  227. data/ext/couchbase/core/orphan_reporter.cxx +2 -1
  228. data/ext/couchbase/core/platform/random.cc +7 -7
  229. data/ext/couchbase/core/protocol/client_request.cxx +2 -2
  230. data/ext/couchbase/core/protocol/client_request.hxx +38 -21
  231. data/ext/couchbase/core/protocol/client_response.cxx +11 -3
  232. data/ext/couchbase/core/protocol/client_response.hxx +27 -6
  233. data/ext/couchbase/core/protocol/cmd_append.cxx +2 -2
  234. data/ext/couchbase/core/protocol/cmd_cluster_map_change_notification.cxx +2 -2
  235. data/ext/couchbase/core/protocol/cmd_decrement.cxx +6 -6
  236. data/ext/couchbase/core/protocol/cmd_get.cxx +1 -1
  237. data/ext/couchbase/core/protocol/cmd_get_and_lock.cxx +2 -2
  238. data/ext/couchbase/core/protocol/cmd_get_and_touch.cxx +2 -2
  239. data/ext/couchbase/core/protocol/cmd_get_cluster_config.cxx +6 -4
  240. data/ext/couchbase/core/protocol/cmd_get_collection_id.cxx +2 -2
  241. data/ext/couchbase/core/protocol/cmd_get_error_map.cxx +1 -1
  242. data/ext/couchbase/core/protocol/cmd_get_meta.cxx +4 -4
  243. data/ext/couchbase/core/protocol/cmd_get_replica.cxx +1 -1
  244. data/ext/couchbase/core/protocol/cmd_hello.cxx +1 -1
  245. data/ext/couchbase/core/protocol/cmd_increment.cxx +6 -6
  246. data/ext/couchbase/core/protocol/cmd_insert.cxx +4 -4
  247. data/ext/couchbase/core/protocol/cmd_lookup_in.cxx +4 -3
  248. data/ext/couchbase/core/protocol/cmd_lookup_in_replica.cxx +4 -3
  249. data/ext/couchbase/core/protocol/cmd_mutate_in.cxx +10 -9
  250. data/ext/couchbase/core/protocol/cmd_mutate_in.hxx +10 -10
  251. data/ext/couchbase/core/protocol/cmd_observe_seqno.cxx +7 -7
  252. data/ext/couchbase/core/protocol/cmd_prepend.cxx +2 -2
  253. data/ext/couchbase/core/protocol/cmd_remove.cxx +2 -2
  254. data/ext/couchbase/core/protocol/cmd_replace.cxx +4 -4
  255. data/ext/couchbase/core/protocol/cmd_touch.cxx +1 -1
  256. data/ext/couchbase/core/protocol/cmd_upsert.cxx +4 -4
  257. data/ext/couchbase/core/protocol/datatype.hxx +118 -1
  258. data/ext/couchbase/core/protocol/frame_info_utils.cxx +1 -1
  259. data/ext/couchbase/core/protocol/magic.hxx +4 -0
  260. data/ext/couchbase/core/protocol/magic_fmt.hxx +3 -0
  261. data/ext/couchbase/core/protocol/server_request.hxx +3 -1
  262. data/ext/couchbase/core/protocol/status.cxx +1 -1
  263. data/ext/couchbase/core/protostellar/analytics_converter.hxx +171 -0
  264. data/ext/couchbase/core/protostellar/bucket_admin_converter.hxx +301 -0
  265. data/ext/couchbase/core/protostellar/collection_admin_converter.hxx +92 -0
  266. data/ext/couchbase/core/protostellar/component.cxx +2445 -0
  267. data/ext/couchbase/core/protostellar/component.hxx +391 -0
  268. data/ext/couchbase/core/{columnar/bootstrap_notification_subscriber.hxx → protostellar/compression_settings.hxx} +11 -10
  269. data/ext/couchbase/core/protostellar/credentials.cxx +233 -0
  270. data/ext/couchbase/core/protostellar/credentials.hxx +88 -0
  271. data/ext/couchbase/core/protostellar/dispatcher.cxx +57 -0
  272. data/ext/couchbase/core/protostellar/dispatcher.hxx +482 -0
  273. data/ext/couchbase/core/protostellar/error_utils.cxx +293 -0
  274. data/ext/couchbase/core/protostellar/error_utils.hxx +97 -0
  275. data/ext/couchbase/core/protostellar/json_payload.hxx +49 -0
  276. data/ext/couchbase/core/protostellar/kv_converter.cxx +70 -0
  277. data/ext/couchbase/core/protostellar/kv_converter.hxx +600 -0
  278. data/ext/couchbase/core/protostellar/query_converter.hxx +265 -0
  279. data/ext/couchbase/core/protostellar/query_index_admin_converter.hxx +291 -0
  280. data/ext/couchbase/core/protostellar/query_proto.hxx +73 -0
  281. data/ext/couchbase/core/protostellar/search_converter.hxx +244 -0
  282. data/ext/couchbase/core/protostellar/search_index_admin_converter.hxx +156 -0
  283. data/ext/couchbase/core/protostellar/view_converter.hxx +158 -0
  284. data/ext/couchbase/core/query_stream.cxx +447 -0
  285. data/ext/couchbase/core/query_stream.hxx +141 -0
  286. data/ext/couchbase/core/query_stream_component.cxx +243 -0
  287. data/ext/couchbase/core/query_stream_component.hxx +68 -0
  288. data/ext/couchbase/core/range_scan_load_balancer.cxx +15 -8
  289. data/ext/couchbase/core/range_scan_orchestrator.cxx +15 -3
  290. data/ext/couchbase/core/response_handler.hxx +41 -4
  291. data/ext/couchbase/core/row_streamer.cxx +332 -46
  292. data/ext/couchbase/core/row_streamer.hxx +31 -1
  293. data/ext/couchbase/core/row_streamer_options.hxx +55 -0
  294. data/ext/couchbase/core/sasl/client.h +3 -0
  295. data/ext/couchbase/core/search_scoring.hxx +66 -0
  296. data/ext/couchbase/core/stream_error_details.hxx +69 -0
  297. data/ext/couchbase/core/timeout_defaults.hxx +0 -1
  298. data/ext/couchbase/core/topology/capabilities.hxx +6 -0
  299. data/ext/couchbase/core/topology/capabilities_fmt.hxx +3 -0
  300. data/ext/couchbase/core/topology/configuration.cxx +21 -6
  301. data/ext/couchbase/core/topology/configuration.hxx +29 -8
  302. data/ext/couchbase/core/topology/configuration_json.hxx +3 -0
  303. data/ext/couchbase/core/topology/error_map_json.hxx +3 -1
  304. data/ext/couchbase/core/tracing/threshold_logging_tracer.cxx +70 -4
  305. data/ext/couchbase/core/tracing/threshold_logging_tracer.hxx +10 -0
  306. data/ext/couchbase/core/transactions/active_transaction_record.cxx +0 -34
  307. data/ext/couchbase/core/transactions/attempt_context_impl.cxx +108 -63
  308. data/ext/couchbase/core/transactions/attempt_context_impl.hxx +19 -2
  309. data/ext/couchbase/core/transactions/error_list.hxx +2 -2
  310. data/ext/couchbase/core/transactions/get_multi_fetch.hxx +160 -0
  311. data/ext/couchbase/core/transactions/get_multi_orchestrator.cxx +326 -125
  312. data/ext/couchbase/core/transactions/get_multi_transaction_id.hxx +62 -0
  313. data/ext/couchbase/core/transactions/internal/atr_entry.hxx +22 -2
  314. data/ext/couchbase/core/transactions/internal/transaction_context.hxx +2 -2
  315. data/ext/couchbase/core/transactions/internal/transactions_cleanup.hxx +23 -1
  316. data/ext/couchbase/core/transactions/internal/utils.hxx +50 -14
  317. data/ext/couchbase/core/transactions/staged_mutation.cxx +23 -18
  318. data/ext/couchbase/core/transactions/staged_mutation.hxx +15 -4
  319. data/ext/couchbase/core/transactions/transaction_context.cxx +55 -40
  320. data/ext/couchbase/core/transactions/transaction_get_result.hxx +16 -0
  321. data/ext/couchbase/core/transactions/transactions.cxx +3 -55
  322. data/ext/couchbase/core/transactions/transactions_cleanup.cxx +165 -72
  323. data/ext/couchbase/core/transactions/transactions_config.cxx +0 -11
  324. data/ext/couchbase/core/transactions/utils.cxx +10 -0
  325. data/ext/couchbase/core/transactions/waitable_op_list.hxx +2 -2
  326. data/ext/couchbase/core/transactions.hxx +9 -9
  327. data/ext/couchbase/core/utils/byteswap.hxx +166 -9
  328. data/ext/couchbase/core/utils/connection_string.cxx +50 -85
  329. data/ext/couchbase/core/utils/connection_string.hxx +15 -0
  330. data/ext/couchbase/core/{columnar/backoff_calculator.hxx → utils/deadline.hxx} +13 -13
  331. data/ext/couchbase/core/utils/duration_parser.cxx +1 -1
  332. data/ext/couchbase/core/utils/json_streaming_lexer.cxx +48 -5
  333. data/ext/couchbase/core/utils/json_streaming_lexer.hxx +4 -1
  334. data/ext/couchbase/core/utils/movable_function.hxx +301 -52
  335. data/ext/couchbase/core/utils/name_codec.hxx +154 -11
  336. data/ext/couchbase/core/{columnar/retry_info.hxx → utils/process_id.hxx} +18 -13
  337. data/ext/couchbase/core/utils/url_codec.cxx +12 -51
  338. data/ext/couchbase/core/websocket_codec.cxx +3 -29
  339. data/ext/couchbase/couchbase/analytics_options.hxx +21 -10
  340. data/ext/couchbase/couchbase/analytics_row.hxx +105 -0
  341. data/ext/couchbase/couchbase/analytics_stream_result.hxx +266 -0
  342. data/ext/couchbase/couchbase/boolean_query.hxx +3 -3
  343. data/ext/couchbase/couchbase/bucket.hxx +57 -0
  344. data/ext/couchbase/couchbase/cluster.hxx +183 -5
  345. data/ext/couchbase/{core/columnar/security_options.hxx → couchbase/cluster_state.hxx} +18 -14
  346. data/ext/couchbase/couchbase/codec/lenient_json_transcoder.hxx +69 -0
  347. data/ext/couchbase/couchbase/collection.hxx +234 -14
  348. data/ext/couchbase/couchbase/common_durability_options.hxx +18 -3
  349. data/ext/couchbase/couchbase/conjunction_query.hxx +1 -1
  350. data/ext/couchbase/couchbase/create_dataset_analytics_options.hxx +6 -1
  351. data/ext/couchbase/couchbase/date_range_query.hxx +2 -2
  352. data/ext/couchbase/couchbase/decrement_options.hxx +1 -1
  353. data/ext/couchbase/couchbase/disjunction_query.hxx +1 -1
  354. data/ext/couchbase/couchbase/error.hxx +32 -0
  355. data/ext/couchbase/couchbase/error_codes.hxx +32 -0
  356. data/ext/couchbase/couchbase/geo_bounding_box_query.hxx +1 -1
  357. data/ext/couchbase/couchbase/geo_distance_query.hxx +1 -1
  358. data/ext/couchbase/couchbase/geo_polygon_query.hxx +1 -1
  359. data/ext/couchbase/couchbase/get_replica_options.hxx +68 -0
  360. data/ext/couchbase/couchbase/get_replica_result.hxx +5 -3
  361. data/ext/couchbase/couchbase/get_replica_strategy.hxx +161 -0
  362. data/ext/couchbase/couchbase/get_result.hxx +1 -0
  363. data/ext/couchbase/couchbase/increment_options.hxx +1 -1
  364. data/ext/couchbase/couchbase/insert_options.hxx +1 -1
  365. data/ext/couchbase/couchbase/match_phrase_query.hxx +1 -1
  366. data/ext/couchbase/couchbase/match_query.hxx +1 -1
  367. data/ext/couchbase/couchbase/mutate_in_options.hxx +3 -3
  368. data/ext/couchbase/couchbase/network_options.hxx +1 -1
  369. data/ext/couchbase/couchbase/node_id.hxx +42 -14
  370. data/ext/couchbase/couchbase/node_id_for_options.hxx +7 -1
  371. data/ext/couchbase/couchbase/node_ids_options.hxx +8 -2
  372. data/ext/couchbase/couchbase/numeric_range_query.hxx +1 -1
  373. data/ext/couchbase/couchbase/phrase_query.hxx +1 -1
  374. data/ext/couchbase/couchbase/prefix_query.hxx +1 -1
  375. data/ext/couchbase/couchbase/query_options.hxx +23 -12
  376. data/ext/couchbase/couchbase/query_row.hxx +111 -0
  377. data/ext/couchbase/couchbase/query_stream_result.hxx +302 -0
  378. data/ext/couchbase/couchbase/query_string_query.hxx +3 -3
  379. data/ext/couchbase/couchbase/regexp_query.hxx +1 -1
  380. data/ext/couchbase/couchbase/replace_options.hxx +3 -3
  381. data/ext/couchbase/couchbase/result.hxx +14 -3
  382. data/ext/couchbase/couchbase/scan_result_item.hxx +1 -0
  383. data/ext/couchbase/couchbase/scope.hxx +85 -2
  384. data/ext/couchbase/couchbase/search_options.hxx +58 -8
  385. data/ext/couchbase/couchbase/search_scoring.hxx +94 -0
  386. data/ext/couchbase/couchbase/search_scoring_none.hxx +51 -0
  387. data/ext/couchbase/couchbase/search_scoring_reciprocal_rank_fusion.hxx +88 -0
  388. data/ext/couchbase/couchbase/search_scoring_relative_score_fusion.hxx +70 -0
  389. data/ext/couchbase/couchbase/term_range_query.hxx +1 -1
  390. data/ext/couchbase/couchbase/tracing/request_span.hxx +46 -0
  391. data/ext/couchbase/couchbase/transactions/transaction_get_multi_replicas_from_preferred_server_group_result.hxx +23 -21
  392. data/ext/couchbase/couchbase/transactions/transaction_get_multi_result.hxx +24 -19
  393. data/ext/couchbase/couchbase/transactions/transaction_get_result.hxx +17 -3
  394. data/ext/couchbase/couchbase/transactions/transactions_config.hxx +4 -2
  395. data/ext/couchbase/couchbase/transactions.hxx +27 -18
  396. data/ext/couchbase/couchbase/upsert_options.hxx +3 -3
  397. data/ext/couchbase/couchbase/vector_query.hxx +1 -1
  398. data/ext/couchbase/couchbase/wait_until_ready_options.hxx +111 -0
  399. data/ext/couchbase/couchbase/wildcard_query.hxx +1 -1
  400. data/ext/extconf.rb +15 -10
  401. data/ext/rcb_analytics.cxx +82 -102
  402. data/ext/rcb_backend.cxx +42 -36
  403. data/ext/rcb_backend.hxx +2 -0
  404. data/ext/rcb_buckets.cxx +47 -59
  405. data/ext/rcb_collections.cxx +42 -52
  406. data/ext/rcb_crud.cxx +345 -224
  407. data/ext/rcb_diagnostics.cxx +117 -27
  408. data/ext/rcb_exceptions.cxx +152 -99
  409. data/ext/rcb_exceptions.hxx +25 -0
  410. data/ext/rcb_extras.cxx +18 -19
  411. data/ext/rcb_hdr_histogram.cxx +19 -4
  412. data/ext/rcb_logger.cxx +202 -27
  413. data/ext/rcb_logger.hxx +12 -0
  414. data/ext/rcb_multi.cxx +40 -40
  415. data/ext/rcb_observability.cxx +7 -5
  416. data/ext/rcb_query.cxx +99 -142
  417. data/ext/rcb_range_scan.cxx +41 -35
  418. data/ext/rcb_search.cxx +98 -99
  419. data/ext/rcb_users.cxx +36 -56
  420. data/ext/rcb_utils.cxx +100 -37
  421. data/ext/rcb_utils.hxx +287 -33
  422. data/ext/rcb_version.cxx +1 -1
  423. data/ext/rcb_views.cxx +55 -51
  424. data/lib/active_support/cache/couchbase_store.rb +77 -12
  425. data/lib/couchbase/bucket.rb +20 -0
  426. data/lib/couchbase/cluster.rb +17 -0
  427. data/lib/couchbase/collection.rb +36 -1
  428. data/lib/couchbase/errors.rb +18 -0
  429. data/lib/couchbase/fork_hooks.rb +16 -7
  430. data/lib/couchbase/get_replica_strategy.rb +89 -0
  431. data/lib/couchbase/logger.rb +1 -1
  432. data/lib/couchbase/management/analytics_index_manager.rb +15 -15
  433. data/lib/couchbase/management/bucket_manager.rb +6 -6
  434. data/lib/couchbase/management/collection_manager.rb +6 -6
  435. data/lib/couchbase/management/query_index_manager.rb +7 -7
  436. data/lib/couchbase/management/search_index_manager.rb +13 -13
  437. data/lib/couchbase/management/user_manager.rb +10 -10
  438. data/lib/couchbase/management/view_index_manager.rb +5 -5
  439. data/lib/couchbase/options.rb +174 -42
  440. data/lib/couchbase/protostellar/bucket.rb +4 -0
  441. data/lib/couchbase/protostellar/cluster.rb +4 -0
  442. data/lib/couchbase/protostellar/collection.rb +4 -0
  443. data/lib/couchbase/protostellar/error_handling.rb +2 -1
  444. data/lib/couchbase/protostellar/request.rb +1 -0
  445. data/lib/couchbase/protostellar/request_generator/kv.rb +16 -2
  446. data/lib/couchbase/protostellar/request_generator/search.rb +17 -1
  447. data/lib/couchbase/protostellar/retry/orchestrator.rb +3 -2
  448. data/lib/couchbase/protostellar/retry/strategies/fail_fast.rb +33 -0
  449. data/lib/couchbase/protostellar/retry/strategies.rb +1 -0
  450. data/lib/couchbase/search_options.rb +95 -6
  451. data/lib/couchbase/version.rb +1 -1
  452. metadata +91 -33
  453. data/ext/0001-fix-build-for-mingw-w64-ucrt-x86_64-toolchain.patch +0 -40
  454. data/ext/couchbase/core/columnar/agent.hxx +0 -71
  455. data/ext/couchbase/core/columnar/agent_config.hxx +0 -59
  456. data/ext/couchbase/core/columnar/background_bootstrap_listener.hxx +0 -42
  457. data/ext/couchbase/core/columnar/backoff_calculator.cxx +0 -62
  458. data/ext/couchbase/core/columnar/columnar_agent.cxx +0 -147
  459. data/ext/couchbase/core/columnar/columnar_agent_config.cxx +0 -48
  460. data/ext/couchbase/core/columnar/columnar_error.cxx +0 -51
  461. data/ext/couchbase/core/columnar/database_management_options.hxx +0 -56
  462. data/ext/couchbase/core/columnar/error.hxx +0 -51
  463. data/ext/couchbase/core/columnar/error_codes.cxx +0 -107
  464. data/ext/couchbase/core/columnar/error_codes.hxx +0 -75
  465. data/ext/couchbase/core/columnar/management_component.cxx +0 -300
  466. data/ext/couchbase/core/columnar/management_component.hxx +0 -56
  467. data/ext/couchbase/core/columnar/query_component.cxx +0 -523
  468. data/ext/couchbase/core/columnar/query_component.hxx +0 -57
  469. data/ext/couchbase/core/columnar/query_options.hxx +0 -59
  470. data/ext/couchbase/core/columnar/query_result.cxx +0 -130
  471. data/ext/couchbase/core/columnar/query_result.hxx +0 -78
  472. data/ext/couchbase/core/io/config_tracker.cxx +0 -687
  473. data/ext/couchbase/core/io/config_tracker.hxx +0 -123
@@ -16,7 +16,6 @@
16
16
  */
17
17
 
18
18
  #include "origin.hxx"
19
- #include <couchbase/build_config.hxx>
20
19
 
21
20
  #include "core/utils/connection_string.hxx"
22
21
  #include "topology/configuration.hxx"
@@ -224,24 +223,6 @@ struct traits<couchbase::transactions::transactions_config::built> {
224
223
  }
225
224
  };
226
225
 
227
- template<>
228
- struct traits<couchbase::core::columnar::security_options> {
229
- template<template<typename...> class Traits>
230
- static void assign(tao::json::basic_value<Traits>& v,
231
- const couchbase::core::columnar::security_options& o)
232
- {
233
- v = {
234
- { "trust_only_capella", o.trust_only_capella },
235
- { "trust_only_pem_file", o.trust_only_pem_file },
236
- { "trust_only_pem_string", o.trust_only_pem_string },
237
- { "trust_only_platform", o.trust_only_platform },
238
- { "trust_only_certificates", o.trust_only_certificates.size() },
239
- // TODO(JC): add if/when we support the cipher_suites option
240
- // { "cipher_suites", utils::join_strings(o.cipher_suites, ":") },
241
- };
242
- }
243
- };
244
-
245
226
  } // namespace tao::json
246
227
 
247
228
  namespace couchbase::core
@@ -267,13 +248,10 @@ origin::to_json() const -> std::string
267
248
  { "config_poll_floor", options_.config_poll_floor },
268
249
  { "user_agent_extra", options_.user_agent_extra },
269
250
  { "dump_configuration", options_.dump_configuration },
251
+ { "log_redaction", options_.log_redaction },
270
252
  { "disable_mozilla_ca_certificates", options_.disable_mozilla_ca_certificates },
271
253
  { "network", options_.network },
272
254
  { "tls_verify", options_.tls_verify },
273
- #ifdef COUCHBASE_CXX_CLIENT_COLUMNAR
274
- { "dispatch_timeout", options_.dispatch_timeout },
275
- { "security_options", options_.security_options },
276
- #else
277
255
  { "key_value_timeout", options_.key_value_timeout },
278
256
  { "key_value_durable_timeout", options_.key_value_durable_timeout },
279
257
  { "view_timeout", options_.view_timeout },
@@ -297,7 +275,6 @@ origin::to_json() const -> std::string
297
275
  { "orphan_reporter_options", options_.orphan_options },
298
276
  { "transactions_options", options_.transactions },
299
277
  { "server_group", options_.server_group },
300
- #endif
301
278
  },
302
279
  },
303
280
  };
@@ -311,6 +288,9 @@ origin::to_json() const -> std::string
311
288
  }
312
289
  json["bootstrap_nodes"] = nodes;
313
290
  }
291
+ // Every value in here is left as it is. The document this returns is annotated as a whole at
292
+ // the log site, because a tag written into one of its string values would be read back as part
293
+ // of that value by anything that parses the line as JSON.
314
294
  return tao::json::to_string(json);
315
295
  }
316
296
 
@@ -319,9 +299,15 @@ origin::to_json() const -> std::string
319
299
  couchbase::core::origin::origin(origin&& other) noexcept
320
300
  : options_(std::move(other.options_))
321
301
  , nodes_(std::move(other.nodes_))
322
- , next_node_(other.next_node_)
302
+ // next_node_ is an iterator into nodes_. Container move construction transfers the buffer, so
303
+ // iterators into the source stay valid and now denote elements of nodes_ -- other.next_node_ can
304
+ // be adopted as-is, preserving the round-robin position. The empty case is guarded separately
305
+ // because that guarantee does not extend to a past-the-end iterator. nodes_ is declared before
306
+ // next_node_, so it is already initialized here.
307
+ , next_node_(nodes_.empty() ? nodes_.begin() : other.next_node_)
323
308
  , exhausted_(other.exhausted_)
324
309
  , connection_string_(std::move(other.connection_string_))
310
+ , uses_protostellar_(other.uses_protostellar_)
325
311
  , credentials_(std::move(other.credentials_))
326
312
  {
327
313
  }
@@ -330,20 +316,38 @@ auto
330
316
  couchbase::core::origin::operator=(origin&& other) noexcept -> origin&
331
317
  {
332
318
  if (this != &other) {
319
+ const auto offset = other.nodes_.empty() ? 0 : other.next_node_ - other.nodes_.begin();
333
320
  options_ = std::move(other.options_);
334
321
  nodes_ = std::move(other.nodes_);
335
- next_node_ = other.next_node_;
322
+ next_node_ = nodes_.begin() + offset;
336
323
  exhausted_ = other.exhausted_;
337
324
  connection_string_ = std::move(other.connection_string_);
325
+ uses_protostellar_ = other.uses_protostellar_;
338
326
  credentials_ = std::move(other.credentials_);
339
327
  }
340
328
  return *this;
341
329
  }
342
330
 
331
+ // A copy is a fresh origin that has not attempted anything, so the rotation cursor is deliberately
332
+ // reset rather than carried. This matters: next_address() marks an origin exhausted as it hands out
333
+ // the *last* node, which on a single-node cluster is the very first call, so a cluster origin is
334
+ // normally exhausted immediately after bootstrap. open_bucket() copies that origin into every
335
+ // bucket and on into every session, and mcbp_session::initiate_bootstrap() tests exhausted()
336
+ // before it ever calls next_address() -- so carrying the flag would send a session that has tried
337
+ // nothing down the "reached the end of the list of bootstrap nodes" path: an unconditional 500 ms
338
+ // backoff.
339
+ //
340
+ // Moving, by contrast, does carry it: a move transfers identity rather than producing an
341
+ // independent origin.
342
+ //
343
+ // connection_string_ and uses_protostellar_ *are* copied. They were being dropped entirely, which
344
+ // left connection_string() returning "" on any copied origin.
343
345
  couchbase::core::origin::origin(const couchbase::core::origin& other)
344
346
  : options_(other.options_)
345
347
  , nodes_(other.nodes_)
346
348
  , next_node_(nodes_.begin())
349
+ , connection_string_(other.connection_string_)
350
+ , uses_protostellar_(other.uses_protostellar_)
347
351
  {
348
352
  update_credentials(other.credentials());
349
353
  }
@@ -378,6 +382,7 @@ couchbase::core::origin::origin(couchbase::core::cluster_credentials auth,
378
382
  const couchbase::core::utils::connection_string& connstr)
379
383
  : options_(connstr.options)
380
384
  , connection_string_(connstr.input)
385
+ , uses_protostellar_(connstr.uses_protostellar())
381
386
  , credentials_(std::move(auth))
382
387
  {
383
388
  nodes_.reserve(connstr.bootstrap_nodes.size());
@@ -396,10 +401,13 @@ couchbase::core::origin::operator=(const couchbase::core::origin& other) -> couc
396
401
  {
397
402
  if (this != &other) {
398
403
  options_ = other.options_;
404
+ connection_string_ = other.connection_string_;
399
405
  update_credentials(other.credentials());
400
406
  nodes_ = other.nodes_;
407
+ // Rotation state is reset, not carried -- see the copy constructor for why.
401
408
  next_node_ = nodes_.begin();
402
409
  exhausted_ = false;
410
+ uses_protostellar_ = other.uses_protostellar_;
403
411
  }
404
412
  return *this;
405
413
  }
@@ -409,6 +417,11 @@ couchbase::core::origin::connection_string() const -> const std::string&
409
417
  return connection_string_;
410
418
  }
411
419
  auto
420
+ couchbase::core::origin::uses_protostellar() const -> bool
421
+ {
422
+ return uses_protostellar_;
423
+ }
424
+ auto
412
425
  couchbase::core::origin::username() const -> std::string
413
426
  {
414
427
  const std::shared_lock lock(credentials_mutex_);
@@ -458,6 +471,16 @@ couchbase::core::origin::get_nodes() const -> std::vector<std::string>
458
471
  }
459
472
  return res;
460
473
  }
474
+ auto
475
+ couchbase::core::origin::get_node_addresses() const -> std::vector<std::string>
476
+ {
477
+ std::vector<std::string> res;
478
+ res.reserve(nodes_.size());
479
+ for (const auto& [hostname, port] : nodes_) {
480
+ res.emplace_back(fmt::format("{}:{}", hostname, port));
481
+ }
482
+ return res;
483
+ }
461
484
 
462
485
  void
463
486
  couchbase::core::origin::shuffle_nodes()
@@ -502,6 +525,11 @@ couchbase::core::origin::set_nodes_from_config(const topology::configuration& co
502
525
  shuffle_nodes();
503
526
  }
504
527
  next_node_ = nodes_.begin();
528
+ // Matches set_nodes(): the node list has just been replaced, so any exhaustion recorded against
529
+ // the previous list is meaningless. Without this an origin that was exhausted stays exhausted
530
+ // across every config update -- cluster.cxx calls this on a long-lived origin that
531
+ // next_address() will have marked exhausted.
532
+ exhausted_ = false;
505
533
  }
506
534
  void
507
535
  couchbase::core::origin::update_credentials(cluster_credentials auth)
@@ -60,6 +60,9 @@ struct origin {
60
60
  auto operator=(const origin& other) -> origin&;
61
61
 
62
62
  [[nodiscard]] auto connection_string() const -> const std::string&;
63
+ // True when built from a couchbase2:// connection string (Protostellar transport). Lets the
64
+ // connect path branch to the gRPC client without re-parsing the connection string.
65
+ [[nodiscard]] auto uses_protostellar() const -> bool;
63
66
  [[nodiscard]] auto username() const -> std::string;
64
67
  [[nodiscard]] auto password() const -> std::string;
65
68
  [[nodiscard]] auto certificate_path() const -> std::string;
@@ -68,6 +71,10 @@ struct origin {
68
71
 
69
72
  [[nodiscard]] auto get_hostnames() const -> std::vector<std::string>;
70
73
  [[nodiscard]] auto get_nodes() const -> std::vector<std::string>;
74
+ // The same addresses as get_nodes(), without the display quotes baked into each entry. Log
75
+ // statements want them bare so that logger::system_data_list() can put a tag inside the quotes it
76
+ // renders; a tag around a pre-quoted entry hashes the punctuation with the value.
77
+ [[nodiscard]] auto get_node_addresses() const -> std::vector<std::string>;
71
78
 
72
79
  void shuffle_nodes();
73
80
  void set_nodes(node_list nodes);
@@ -84,6 +91,10 @@ struct origin {
84
91
  [[nodiscard]] auto options() const -> const couchbase::core::cluster_options&;
85
92
  [[nodiscard]] auto options() -> couchbase::core::cluster_options&;
86
93
  [[nodiscard]] auto credentials() const -> couchbase::core::cluster_credentials;
94
+ // A JSON dump of the whole origin, less the credentials. Its only callers are the log
95
+ // statements in the cluster open paths, and they annotate the whole document: a tag written
96
+ // into one of these values instead would be read back as part of that value by anything that
97
+ // parses the line as JSON. So nothing in here is annotated.
87
98
  [[nodiscard]] auto to_json() const -> std::string;
88
99
 
89
100
  private:
@@ -92,6 +103,7 @@ private:
92
103
  node_list::iterator next_node_{};
93
104
  bool exhausted_{ false };
94
105
  std::string connection_string_{};
106
+ bool uses_protostellar_{ false };
95
107
  cluster_credentials credentials_{};
96
108
  mutable std::shared_mutex credentials_mutex_{};
97
109
  };
@@ -20,6 +20,7 @@
20
20
  #include <couchbase/build_info.hxx>
21
21
 
22
22
  #include "logger/logger.hxx"
23
+ #include "logger/redaction.hxx"
23
24
  #include "utils/concurrent_fixed_priority_queue.hxx"
24
25
  #include "utils/json.hxx"
25
26
 
@@ -120,7 +121,7 @@ private:
120
121
  }
121
122
 
122
123
  if (auto report = self->flush_and_create_output(); report.has_value()) {
123
- CB_LOG_WARNING("Orphan responses observed: {}", report.value());
124
+ CB_LOG_WARNING("Orphan responses observed: {}", logger::system_data(report.value()));
124
125
  }
125
126
 
126
127
  self->rearm();
@@ -25,7 +25,7 @@
25
25
  #include <mutex>
26
26
  #include <system_error>
27
27
 
28
- #ifdef WIN32
28
+ #ifdef _WIN32
29
29
  // We need to include windows.h _before_ wincrypt.h
30
30
  #ifndef WIN32_LEAN_AND_MEAN
31
31
  #define WIN32_LEAN_AND_MEAN
@@ -45,7 +45,7 @@ class RandomGeneratorProvider
45
45
  public:
46
46
  RandomGeneratorProvider()
47
47
  {
48
- #ifdef WIN32
48
+ #ifdef _WIN32
49
49
  if (!CryptAcquireContext(
50
50
  &handle, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
51
51
  throw std::system_error(int(GetLastError()),
@@ -69,7 +69,7 @@ public:
69
69
 
70
70
  virtual ~RandomGeneratorProvider()
71
71
  {
72
- #ifdef WIN32
72
+ #ifdef _WIN32
73
73
  CryptReleaseContext(handle, 0);
74
74
  #else
75
75
  close(handle);
@@ -78,8 +78,8 @@ public:
78
78
 
79
79
  auto getBytes(void* dest, std::size_t size) -> bool
80
80
  {
81
- const std::lock_guard<std::mutex> lock(mutex);
82
- #ifdef WIN32
81
+ const std::scoped_lock<std::mutex> lock(mutex);
82
+ #ifdef _WIN32
83
83
  return CryptGenRandom(handle, (DWORD)size, static_cast<BYTE*>(dest));
84
84
  #else
85
85
  #if defined(__clang__) && defined(__clang_analyzer__)
@@ -92,7 +92,7 @@ public:
92
92
  }
93
93
 
94
94
  private:
95
- #ifdef WIN32
95
+ #ifdef _WIN32
96
96
  HCRYPTPROV handle{};
97
97
  #else
98
98
  int handle = -1;
@@ -107,7 +107,7 @@ RandomGenerator::RandomGenerator()
107
107
  {
108
108
  if (!shared_provider) {
109
109
  // This might be the first one, lets lock and create
110
- const std::lock_guard<std::mutex> guard(shared_provider_lock);
110
+ const std::scoped_lock<std::mutex> guard(shared_provider_lock);
111
111
  if (!shared_provider) { // cppcheck-suppress identicalInnerCondition; DCLP
112
112
  shared_provider = std::make_unique<RandomGeneratorProvider>();
113
113
  }
@@ -23,8 +23,8 @@
23
23
  namespace couchbase::core::protocol
24
24
  {
25
25
  auto
26
- compress_value(const std::vector<std::byte>& value,
27
- std::vector<std::byte>::iterator& output) -> std::pair<bool, std::uint32_t>
26
+ compress_value(const std::vector<std::byte>& value, const std::vector<std::byte>::iterator& output)
27
+ -> std::pair<bool, std::uint32_t>
28
28
  {
29
29
  static const double min_ratio = 0.83;
30
30
 
@@ -23,6 +23,7 @@
23
23
  #include "client_response.hxx"
24
24
  #include "core/utils/binary.hxx"
25
25
  #include "core/utils/byteswap.hxx"
26
+ #include "datatype.hxx"
26
27
  #include "magic.hxx"
27
28
 
28
29
  #include <algorithm>
@@ -32,8 +33,8 @@
32
33
  namespace couchbase::core::protocol
33
34
  {
34
35
  auto
35
- compress_value(const std::vector<std::byte>& value,
36
- std::vector<std::byte>::iterator& output) -> std::pair<bool, std::uint32_t>;
36
+ compress_value(const std::vector<std::byte>& value, const std::vector<std::byte>::iterator& output)
37
+ -> std::pair<bool, std::uint32_t>;
37
38
 
38
39
  template<typename Body>
39
40
  class client_request
@@ -62,7 +63,7 @@ public:
62
63
 
63
64
  void opaque(std::uint32_t val)
64
65
  {
65
- opaque_ = utils::byte_swap(val);
66
+ opaque_ = utils::host_to_network(val);
66
67
  }
67
68
 
68
69
  void datatype(protocol::datatype val)
@@ -72,12 +73,12 @@ public:
72
73
 
73
74
  void cas(couchbase::cas val)
74
75
  {
75
- cas_ = utils::byte_swap(val.value());
76
+ cas_ = utils::host_to_network(val.value());
76
77
  }
77
78
 
78
79
  [[nodiscard]] auto opaque() const -> std::uint32_t
79
80
  {
80
- return utils::byte_swap(opaque_);
81
+ return utils::network_to_host(opaque_);
81
82
  }
82
83
 
83
84
  void opcode(client_opcode val)
@@ -116,23 +117,38 @@ public:
116
117
  private:
117
118
  [[nodiscard]] auto generate_payload(bool try_to_compress) -> std::vector<std::byte>
118
119
  {
120
+ // Bind the body's four wire regions once. Note that value()/extras() on some bodies (e.g.
121
+ // hello, mutate_in) lazily populate their buffers on first access, so this also materialises
122
+ // them before we measure and copy.
123
+ const auto& framing_extras = body_.framing_extras();
124
+ const auto& extras = body_.extras();
125
+ const auto& key = body_.key();
126
+ const auto& value = body_.value();
127
+
128
+ // Size the buffer from the same regions that get copied into it, rather than from the
129
+ // independent body_.size(). body_.size() is defined as exactly this sum for every body type,
130
+ // so the byte layout is unchanged; deriving the length here makes the buffer provably large
131
+ // enough for the copies below. (Without it GCC folds body_.size() to 0 for zero-length bodies
132
+ // such as noop, decides body_itr is one-past-the-end, and emits a bogus -Warray-bounds.)
133
+ const std::size_t body_size_bytes =
134
+ framing_extras.size() + extras.size() + key.size() + value.size();
135
+
119
136
  // SA: for some reason GCC 8.5.0 on CentOS 8 sees here null-pointer dereference
120
137
  // JC: BoringSSL changes, noticed the same when building w/ GCC 11.3.0; TODO: is 12 okay?
121
138
  #if defined(__GNUC__) && __GNUC__ >= 8 && __GNUC__ < 12
122
139
  #pragma GCC diagnostic push
123
140
  #pragma GCC diagnostic ignored "-Wnull-dereference"
124
141
  #endif
125
- std::vector<std::byte> payload(header_size + body_.size(), std::byte{});
142
+ std::vector<std::byte> payload(header_size + body_size_bytes, std::byte{});
126
143
  payload[0] = static_cast<std::byte>(magic_);
127
144
  payload[1] = static_cast<std::byte>(opcode_);
128
145
  #if defined(__GNUC__) && __GNUC__ >= 8 && __GNUC__ < 12
129
146
  #pragma GCC diagnostic pop
130
147
  #endif
131
- const auto& framing_extras = body_.framing_extras();
132
148
 
133
- std::uint16_t key_size = gsl::narrow_cast<std::uint16_t>(body_.key().size());
149
+ std::uint16_t key_size = gsl::narrow_cast<std::uint16_t>(key.size());
134
150
  if (framing_extras.size() == 0) {
135
- key_size = utils::byte_swap(key_size);
151
+ key_size = utils::host_to_network(key_size);
136
152
  memcpy(payload.data() + 2, &key_size, sizeof(key_size));
137
153
  } else {
138
154
  magic_ = protocol::magic::alt_client_request;
@@ -141,15 +157,16 @@ private:
141
157
  payload[3] = gsl::narrow_cast<std::byte>(key_size);
142
158
  }
143
159
 
144
- std::uint8_t ext_size = gsl::narrow_cast<std::uint8_t>(body_.extras().size());
160
+ std::uint8_t ext_size = gsl::narrow_cast<std::uint8_t>(extras.size());
145
161
  memcpy(payload.data() + 4, &ext_size, sizeof(ext_size));
146
162
 
147
163
  payload[5] = static_cast<std::byte>(datatype_);
148
164
 
149
- std::uint16_t vbucket = utils::byte_swap(gsl::narrow_cast<std::uint16_t>(partition_));
165
+ std::uint16_t vbucket = utils::host_to_network(gsl::narrow_cast<std::uint16_t>(partition_));
150
166
  memcpy(payload.data() + 6, &vbucket, sizeof(vbucket));
151
167
 
152
- std::uint32_t body_size = utils::byte_swap(gsl::narrow_cast<std::uint32_t>(body_.size()));
168
+ std::uint32_t body_size =
169
+ utils::host_to_network(gsl::narrow_cast<std::uint32_t>(body_size_bytes));
153
170
  memcpy(payload.data() + 8, &body_size, sizeof(body_size));
154
171
 
155
172
  memcpy(payload.data() + 12, &opaque_, sizeof(opaque_));
@@ -159,24 +176,24 @@ private:
159
176
  if (framing_extras.size() > 0) {
160
177
  body_itr = std::copy(framing_extras.begin(), framing_extras.end(), body_itr);
161
178
  }
162
- body_itr = std::copy(body_.extras().begin(), body_.extras().end(), body_itr);
163
- body_itr = utils::to_binary(body_.key(), body_itr);
179
+ body_itr = std::copy(extras.begin(), extras.end(), body_itr);
180
+ body_itr = utils::to_binary(key, body_itr);
164
181
 
165
182
  if (static const std::size_t min_size_to_compress = 32;
166
- try_to_compress && body_.value().size() > min_size_to_compress) {
167
- if (auto [compressed, new_value_size] = compress_value(body_.value(), body_itr); compressed) {
183
+ try_to_compress && value.size() > min_size_to_compress) {
184
+ if (auto [compressed, new_value_size] = compress_value(value, body_itr); compressed) {
168
185
  /* the compressed value meets requirements and was copied to the payload */
169
- payload[5] |= static_cast<std::byte>(protocol::datatype::snappy);
170
- std::uint32_t new_body_size = utils::byte_swap(body_size) -
171
- gsl::narrow_cast<std::uint32_t>(body_.value().size()) +
186
+ protocol::set_flag(payload[5], protocol::datatype::snappy);
187
+ std::uint32_t new_body_size = utils::network_to_host(body_size) -
188
+ gsl::narrow_cast<std::uint32_t>(value.size()) +
172
189
  new_value_size;
173
190
  payload.resize(header_size + new_body_size);
174
- new_body_size = utils::byte_swap(new_body_size);
191
+ new_body_size = utils::host_to_network(new_body_size);
175
192
  memcpy(payload.data() + 8, &new_body_size, sizeof(new_body_size));
176
193
  return payload;
177
194
  }
178
195
  }
179
- std::copy(body_.value().begin(), body_.value().end(), body_itr);
196
+ std::copy(value.begin(), value.end(), body_itr);
180
197
  return payload;
181
198
  }
182
199
  };
@@ -19,6 +19,7 @@
19
19
 
20
20
  #include "core/utils/json.hxx"
21
21
 
22
+ #include <cstddef>
22
23
  #include <cstring>
23
24
  #include <gsl/assert>
24
25
  #include <tao/json/value.hpp>
@@ -31,8 +32,15 @@ parse_server_duration_us(const io::mcbp_message& msg) -> double
31
32
  if (msg.header.magic != static_cast<std::uint8_t>(magic::alt_client_response)) {
32
33
  return 0;
33
34
  }
34
- auto framing_extras_size = static_cast<std::uint8_t>(msg.header.keylen & 0xfU);
35
- if (framing_extras_size == 0) {
35
+ // Byte 2 of the header, read as a byte. `keylen` holds the wire bytes untouched, so masking it
36
+ // as a native integer reads byte 2 on a little-endian host and byte 3 -- the key length -- on a
37
+ // big-endian one. The mask also truncated the field to its low nibble: four bits is the length
38
+ // of one frame inside the region, not the length of the region, which may exceed 15 bytes.
39
+ const auto framing_extras_size = msg.header.alt_sizes().framing_extras;
40
+ // A region the body cannot hold is a malformed response, not a duration: the loop below walks
41
+ // to framing_extras_size without consulting the body again, and the nibble mask was the only
42
+ // thing that had been keeping it near the front of the buffer.
43
+ if (framing_extras_size == 0 || std::size_t{ framing_extras_size } > msg.body.size()) {
36
44
  return 0;
37
45
  }
38
46
  std::size_t offset = 0;
@@ -44,7 +52,7 @@ parse_server_duration_us(const io::mcbp_message& msg) -> double
44
52
  if (frame_size == 2 && framing_extras_size - offset >= frame_size) {
45
53
  std::uint16_t encoded_duration{};
46
54
  std::memcpy(&encoded_duration, msg.body.data() + offset, sizeof(encoded_duration));
47
- encoded_duration = utils::byte_swap(encoded_duration);
55
+ encoded_duration = utils::network_to_host(encoded_duration);
48
56
  return std::pow(encoded_duration, 1.74) / 2;
49
57
  }
50
58
  }
@@ -23,6 +23,7 @@
23
23
  #include "client_opcode.hxx"
24
24
  #include "client_opcode_fmt.hxx"
25
25
  #include "cmd_info.hxx"
26
+ #include "core/io/mcbp_buffer_pool.hxx"
26
27
  #include "core/io/mcbp_message.hxx"
27
28
  #include "core/utils/byteswap.hxx"
28
29
  #include "datatype.hxx"
@@ -68,6 +69,9 @@ private:
68
69
  std::uint32_t opaque_{};
69
70
  std::uint64_t cas_{};
70
71
  cmd_info info_{};
72
+ // When set, data_ (moved out of the mcbp_message body) is returned to the destroying thread's
73
+ // buffer pool on destruction so its storage can be recycled. See core/io/mcbp_buffer_pool.hxx.
74
+ bool recycle_body_{ false };
71
75
 
72
76
  public:
73
77
  client_response() = default;
@@ -80,11 +84,28 @@ public:
80
84
  : header_(msg.header_data())
81
85
  , data_(std::move(msg.body))
82
86
  , info_(info)
87
+ , recycle_body_(msg.recycle_body)
83
88
  {
84
89
  verify_header();
85
90
  parse_body();
86
91
  }
87
92
 
93
+ client_response(const client_response&) = default;
94
+ auto operator=(const client_response&) -> client_response& = default;
95
+ client_response(client_response&&) = default;
96
+ auto operator=(client_response&&) -> client_response& = default;
97
+
98
+ ~client_response()
99
+ {
100
+ // Recycle the frame buffer to the destroying thread's own pool. The pool is thread-local, so
101
+ // this is safe on whichever IO thread (read loop or a command strand) destroys the response;
102
+ // std::vector value semantics mean no two responses ever share data_, so a buffer is never
103
+ // returned twice.
104
+ if (recycle_body_) {
105
+ io::tls_response_body_pool().release(std::move(data_));
106
+ }
107
+ }
108
+
88
109
  [[nodiscard]] auto opcode() const -> client_opcode
89
110
  {
90
111
  return opcode_;
@@ -131,7 +152,7 @@ public:
131
152
 
132
153
  std::uint16_t status = 0;
133
154
  memcpy(&status, header_.data() + 6, sizeof(status));
134
- status = utils::byte_swap(status);
155
+ status = utils::network_to_host(status);
135
156
  status_ = static_cast<key_value_status_code>(status);
136
157
 
137
158
  extras_size_ = std::to_integer<std::uint8_t>(header_[4]);
@@ -140,19 +161,19 @@ public:
140
161
  key_size_ = std::to_integer<std::uint8_t>(header_[3]);
141
162
  } else {
142
163
  memcpy(&key_size_, header_.data() + 2, sizeof(key_size_));
143
- key_size_ = utils::byte_swap(key_size_);
164
+ key_size_ = utils::network_to_host(key_size_);
144
165
  }
145
166
 
146
167
  std::uint32_t field = 0;
147
168
  memcpy(&field, header_.data() + 8, sizeof(field));
148
- body_size_ = utils::byte_swap(field);
169
+ body_size_ = utils::network_to_host(field);
149
170
  data_.resize(body_size_);
150
171
 
151
172
  memcpy(&opaque_, header_.data() + 12, sizeof(opaque_));
152
- opaque_ = utils::byte_swap(opaque_);
173
+ opaque_ = utils::network_to_host(opaque_);
153
174
 
154
175
  memcpy(&cas_, header_.data() + 16, sizeof(cas_));
155
- cas_ = utils::byte_swap(cas_);
176
+ cas_ = utils::network_to_host(cas_);
156
177
  }
157
178
 
158
179
  [[nodiscard]] auto error_info() const -> std::optional<key_value_extended_error_info>
@@ -200,7 +221,7 @@ public:
200
221
  frame_size == 2 && framing_extras_size_ - offset >= frame_size) {
201
222
  std::uint16_t encoded_duration{};
202
223
  std::memcpy(&encoded_duration, data_.data() + offset, sizeof(encoded_duration));
203
- encoded_duration = utils::byte_swap(encoded_duration);
224
+ encoded_duration = utils::network_to_host(encoded_duration);
204
225
  info_.server_duration_us = std::pow(encoded_duration, 1.74) / 2;
205
226
  }
206
227
  offset += frame_size;
@@ -42,12 +42,12 @@ protocol::append_response_body::parse(key_value_status_code status,
42
42
  if (extras_size == 16) {
43
43
  std::uint64_t partition_uuid{};
44
44
  memcpy(&partition_uuid, body.data() + offset, sizeof(partition_uuid));
45
- partition_uuid = utils::byte_swap(partition_uuid);
45
+ partition_uuid = utils::network_to_host(partition_uuid);
46
46
  offset += 8;
47
47
 
48
48
  std::uint64_t sequence_number{};
49
49
  memcpy(&sequence_number, body.data() + offset, sizeof(sequence_number));
50
- sequence_number = utils::byte_swap(sequence_number);
50
+ sequence_number = utils::network_to_host(sequence_number);
51
51
 
52
52
  token_ = couchbase::utils::build_mutation_token(partition_uuid, sequence_number);
53
53
  return true;
@@ -40,11 +40,11 @@ cluster_map_change_notification_request_body::parse(const header_buffer& header,
40
40
  offset_type offset = ext_size;
41
41
  if (ext_size == 4) {
42
42
  memcpy(&protocol_revision_, body.data(), sizeof(protocol_revision_));
43
- protocol_revision_ = utils::byte_swap(protocol_revision_);
43
+ protocol_revision_ = utils::network_to_host(protocol_revision_);
44
44
  }
45
45
  std::uint16_t key_size = 0;
46
46
  memcpy(&key_size, header.data() + 2, sizeof(key_size));
47
- key_size = utils::byte_swap(key_size);
47
+ key_size = utils::network_to_host(key_size);
48
48
  const auto* data_ptr = reinterpret_cast<const char*>(body.data());
49
49
  bucket_.assign(data_ptr + offset, data_ptr + offset + key_size);
50
50
  offset += key_size;
@@ -42,19 +42,19 @@ decrement_response_body::parse(key_value_status_code status,
42
42
  if (extras_size == 16) {
43
43
  std::uint64_t partition_uuid{};
44
44
  memcpy(&partition_uuid, body.data() + offset, sizeof(partition_uuid));
45
- partition_uuid = utils::byte_swap(partition_uuid);
45
+ partition_uuid = utils::network_to_host(partition_uuid);
46
46
  offset += 8;
47
47
 
48
48
  std::uint64_t sequence_number{};
49
49
  memcpy(&sequence_number, body.data() + offset, sizeof(sequence_number));
50
- sequence_number = utils::byte_swap(sequence_number);
50
+ sequence_number = utils::network_to_host(sequence_number);
51
51
 
52
52
  token_ = couchbase::utils::build_mutation_token(partition_uuid, sequence_number);
53
53
  offset += 8;
54
54
  }
55
55
  offset += key_size;
56
56
  memcpy(&content_, body.data() + offset, sizeof(content_));
57
- content_ = utils::byte_swap(content_);
57
+ content_ = utils::network_to_host(content_);
58
58
  return true;
59
59
  }
60
60
  return false;
@@ -82,15 +82,15 @@ decrement_request_body::fill_extras()
82
82
  using offset_type = std::vector<std::byte>::difference_type;
83
83
  offset_type offset = 0;
84
84
 
85
- std::uint64_t num = utils::byte_swap(delta_);
85
+ std::uint64_t num = utils::host_to_network(delta_);
86
86
  memcpy(extras_.data() + offset, &num, sizeof(num));
87
87
  offset += static_cast<offset_type>(sizeof(delta_));
88
88
 
89
- num = utils::byte_swap(initial_value_);
89
+ num = utils::host_to_network(initial_value_);
90
90
  memcpy(extras_.data() + offset, &num, sizeof(num));
91
91
  offset += static_cast<offset_type>(sizeof(delta_));
92
92
 
93
- std::uint32_t ttl = utils::byte_swap(expiry_);
93
+ std::uint32_t ttl = utils::host_to_network(expiry_);
94
94
  memcpy(extras_.data() + offset, &ttl, sizeof(ttl));
95
95
  }
96
96
  } // namespace couchbase::core::protocol
@@ -39,7 +39,7 @@ get_response_body::parse(key_value_status_code status,
39
39
  std::vector<std::uint8_t>::difference_type offset = framing_extras_size;
40
40
  if (extras_size == 4) {
41
41
  memcpy(&flags_, body.data() + offset, sizeof(flags_));
42
- flags_ = utils::byte_swap(flags_);
42
+ flags_ = utils::network_to_host(flags_);
43
43
  offset += 4;
44
44
  } else {
45
45
  offset += extras_size;
@@ -38,7 +38,7 @@ get_and_lock_response_body::parse(key_value_status_code status,
38
38
  std::vector<std::uint8_t>::difference_type offset = framing_extras_size;
39
39
  if (extras_size == 4) {
40
40
  memcpy(&flags_, body.data() + offset, sizeof(flags_));
41
- flags_ = utils::byte_swap(flags_);
41
+ flags_ = utils::network_to_host(flags_);
42
42
  offset += 4;
43
43
  } else {
44
44
  offset += extras_size;
@@ -60,7 +60,7 @@ void
60
60
  get_and_lock_request_body::fill_extras()
61
61
  {
62
62
  extras_.resize(sizeof(lock_time_));
63
- std::uint32_t field = utils::byte_swap(lock_time_);
63
+ std::uint32_t field = utils::host_to_network(lock_time_);
64
64
  memcpy(extras_.data(), &field, sizeof(field));
65
65
  }
66
66
  } // namespace couchbase::core::protocol