couchbase 3.8.2 → 3.9.1

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 +136 -23
  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 +82 -7
  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 +1551 -397
  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 +60 -6
  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 +13 -37
  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 +33 -1
  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
@@ -0,0 +1,481 @@
1
+ # Find or build gRPC and Protobuf for the gRPC-based components (the couchbase2:// transport and the
2
+ # FIT performer).
3
+ #
4
+ # COUCHBASE_CXX_CLIENT_SYSTEM_GRPC selects where they come from:
5
+ #
6
+ # AUTO link the platform's packages where they exist, build from source where they do not
7
+ # ON require the platform's packages; a build that cannot use them is an error
8
+ # OFF always build from source
9
+ #
10
+ # AUTO chooses on presence, not on suitability: a platform gRPC that is present but unusable is an
11
+ # error under AUTO too, for the reason given at the protobuf floor below.
12
+ #
13
+ # The packages need OFF, which COUCHBASE_CXX_CLIENT_PACKAGE_BUILD selects: the platform's gRPC is
14
+ # linked against the platform's OpenSSL, while this project links BoringSSL statically
15
+ # (COUCHBASE_CXX_CLIENT_STATIC_BORINGSSL), so shipping it would put two TLS stacks in one address
16
+ # space. A source build also decouples the artefact from the distribution's protobuf version: the
17
+ # .proto schemas use proto3 "optional", whose has_*() accessors protobuf only emits from 3.15.
18
+ #
19
+ # Everything else defaults to AUTO, because a source build of gRPC and its transitive dependencies
20
+ # costs far more than the rest of this project put together, and neither reason above applies to a
21
+ # build that is not going to be redistributed.
22
+ #
23
+ # This module MUST be included before OpenTelemetry so OTel's protobuf.cmake detects the
24
+ # already-available protobuf targets and reuses them rather than resolving a second copy.
25
+
26
+ include(FetchContent)
27
+
28
+ if(COUCHBASE_CXX_CLIENT_PACKAGE_BUILD)
29
+ set(_couchbase_cxx_client_system_grpc_default "OFF")
30
+ else()
31
+ set(_couchbase_cxx_client_system_grpc_default "AUTO")
32
+ endif()
33
+ set(COUCHBASE_CXX_CLIENT_SYSTEM_GRPC
34
+ "${_couchbase_cxx_client_system_grpc_default}"
35
+ CACHE STRING "Where gRPC/Protobuf come from: AUTO (platform packages where they exist), ON
36
+ (require them), OFF (always build from source)")
37
+ set_property(CACHE COUCHBASE_CXX_CLIENT_SYSTEM_GRPC PROPERTY STRINGS AUTO ON OFF)
38
+
39
+ # Normalise the value, and reject anything that is not one of the three.
40
+ #
41
+ # The STRINGS property above only fills the GUI drop-down; it rejects nothing. Every string CMake
42
+ # reads as true takes the ON branch below, so an unrecognised value -- a misspelt AUTO among them --
43
+ # would silently select the platform's TLS stack for a binary meant to ship its own. Boolean
44
+ # spellings are folded onto ON and OFF rather than refused, because two of the three values are
45
+ # already booleans and a caller who writes TRUE means ON.
46
+ string(TOUPPER "${COUCHBASE_CXX_CLIENT_SYSTEM_GRPC}" _couchbase_cxx_client_system_grpc)
47
+ if(_couchbase_cxx_client_system_grpc MATCHES "^(ON|TRUE|YES|Y|1)$")
48
+ set(_couchbase_cxx_client_system_grpc "ON")
49
+ elseif(_couchbase_cxx_client_system_grpc MATCHES "^(OFF|FALSE|NO|N|0)$")
50
+ set(_couchbase_cxx_client_system_grpc "OFF")
51
+ elseif(NOT _couchbase_cxx_client_system_grpc STREQUAL "AUTO")
52
+ message(FATAL_ERROR "COUCHBASE_CXX_CLIENT_SYSTEM_GRPC must be AUTO, ON or OFF, not "
53
+ "'${COUCHBASE_CXX_CLIENT_SYSTEM_GRPC}'.")
54
+ endif()
55
+ set(COUCHBASE_CXX_CLIENT_SYSTEM_GRPC
56
+ "${_couchbase_cxx_client_system_grpc}"
57
+ CACHE STRING "Where gRPC/Protobuf come from: AUTO (platform packages where they exist), ON
58
+ (require them), OFF (always build from source)" FORCE)
59
+
60
+ # The platform's packages are built against libstdc++, so a libc++ build cannot link them: the ABI
61
+ # mismatch surfaces as unresolved std:: symbols at link time.
62
+ set(_couchbase_cxx_client_libcxx FALSE)
63
+ if(CMAKE_CXX_FLAGS MATCHES "-stdlib=libc\\+\\+")
64
+ set(_couchbase_cxx_client_libcxx TRUE)
65
+ endif()
66
+
67
+ # AUTO is a string, and if() treats any string that is not a false constant as true, so it must be
68
+ # matched before the boolean branch rather than after it.
69
+ if(COUCHBASE_CXX_CLIENT_SYSTEM_GRPC STREQUAL "AUTO")
70
+ if(_couchbase_cxx_client_libcxx)
71
+ message(STATUS "Using libc++; skipping system gRPC to avoid an ABI mismatch")
72
+ else()
73
+ find_package(gRPC CONFIG QUIET)
74
+ endif()
75
+ elseif(COUCHBASE_CXX_CLIENT_SYSTEM_GRPC)
76
+ # Asked for explicitly: report what stops it rather than quietly building from source, which would
77
+ # ignore what the caller asked for.
78
+ if(_couchbase_cxx_client_libcxx)
79
+ message(
80
+ FATAL_ERROR
81
+ "COUCHBASE_CXX_CLIENT_SYSTEM_GRPC is ON, but this build uses -stdlib=libc++ and the platform's "
82
+ "gRPC is built against libstdc++. Set it to OFF to build gRPC from source.")
83
+ endif()
84
+ find_package(gRPC CONFIG QUIET)
85
+ if(NOT gRPC_FOUND)
86
+ message(
87
+ FATAL_ERROR
88
+ "COUCHBASE_CXX_CLIENT_SYSTEM_GRPC is ON but no gRPC package was found. Install grpc-devel and "
89
+ "grpc-plugins (protobuf >= 3.15), or set it to OFF to build gRPC from source.")
90
+ endif()
91
+ endif()
92
+
93
+ # The schemas use proto3 "optional", whose has_*() accessors protobuf emits only from 3.15. Applied
94
+ # as a floor here, an older platform package is named at configure time; accepted, it fails much
95
+ # later inside the generated code with nothing pointing at the version.
96
+ #
97
+ # Too old is an error under AUTO as well, rather than a fall back to the source build. gRPCConfig
98
+ # resolves Protobuf as a dependency, so the platform's protobuf::libprotobuf and protobuf::libprotoc
99
+ # exist from the moment gRPC is found, and an imported target cannot be withdrawn. A source build
100
+ # after that point dies in protobuf's own CMakeLists with "add_library cannot create ALIAS target
101
+ # protobuf::libprotobuf because another target with the same name already exists". Probing the
102
+ # version before looking for gRPC does not avoid it either: find_package(Protobuf) imports the same
103
+ # targets, which moves the collision onto every host carrying protobuf without gRPC.
104
+ if(gRPC_FOUND)
105
+ message(STATUS "Found system gRPC: ${gRPC_VERSION}")
106
+ set(protobuf_MODULE_COMPATIBLE ON CACHE BOOL "")
107
+ find_package(Protobuf 3.15 CONFIG QUIET)
108
+ if(NOT Protobuf_FOUND)
109
+ find_package(Protobuf 3.15 MODULE QUIET)
110
+ endif()
111
+ if(NOT Protobuf_FOUND)
112
+ message(
113
+ FATAL_ERROR
114
+ "The platform's gRPC ${gRPC_VERSION} was found, but its protobuf is older than 3.15 and does "
115
+ "not emit the has_*() accessors the schemas need. Set COUCHBASE_CXX_CLIENT_SYSTEM_GRPC=OFF "
116
+ "to build gRPC and protobuf from source.")
117
+ endif()
118
+
119
+ # Libraries are not enough: cmake/gRPC_Generate.cmake runs protoc with the gRPC C++ plugin, and
120
+ # distributions ship those compilers in their own packages (protobuf-compiler,
121
+ # protobuf-compiler-grpc / grpc-plugins) separate from the -dev packages that satisfy the
122
+ # find_package calls above. Without this check a build configures cleanly and then fails in code
123
+ # generation, where the missing package is much harder to recognise.
124
+ # Both generators name the TARGETS unconditionally -- cmake/gRPC_Generate.cmake runs
125
+ # "COMMAND protobuf::protoc" and lists both in DEPENDS -- so finding the executables is not enough
126
+ # on its own. Where only a program is found, it is wrapped in the imported target the generators
127
+ # expect; where neither exists, the build is refused here.
128
+ set(_missing_codegen)
129
+ if(NOT TARGET protobuf::protoc)
130
+ find_program(Protobuf_PROTOC_EXECUTABLE protoc)
131
+ if(Protobuf_PROTOC_EXECUTABLE)
132
+ add_executable(protobuf::protoc IMPORTED GLOBAL)
133
+ set_target_properties(protobuf::protoc PROPERTIES IMPORTED_LOCATION "${Protobuf_PROTOC_EXECUTABLE}")
134
+ else()
135
+ list(APPEND _missing_codegen "protoc")
136
+ endif()
137
+ endif()
138
+ if(NOT TARGET gRPC::grpc_cpp_plugin)
139
+ find_program(_grpc_cpp_plugin grpc_cpp_plugin)
140
+ if(_grpc_cpp_plugin)
141
+ add_executable(gRPC::grpc_cpp_plugin IMPORTED GLOBAL)
142
+ set_target_properties(gRPC::grpc_cpp_plugin PROPERTIES IMPORTED_LOCATION "${_grpc_cpp_plugin}")
143
+ else()
144
+ list(APPEND _missing_codegen "grpc_cpp_plugin")
145
+ endif()
146
+ endif()
147
+ if(_missing_codegen)
148
+ message(
149
+ FATAL_ERROR
150
+ "The platform's gRPC ${gRPC_VERSION} was found, but the code generator(s) it needs are not "
151
+ "installed: ${_missing_codegen}. Install the distribution's protobuf-compiler and gRPC "
152
+ "plugin packages, or set COUCHBASE_CXX_CLIENT_SYSTEM_GRPC=OFF to build them from source.")
153
+ endif()
154
+ endif()
155
+
156
+ if(NOT gRPC_FOUND)
157
+ message(STATUS "Building gRPC and protobuf from source")
158
+
159
+ # CMake 4.x removed compatibility with cmake_minimum_required < 3.5.
160
+ # Several gRPC submodules (c-ares, protobuf/utf8_range) have old minimum
161
+ # versions that would cause hard errors without this policy escape hatch.
162
+ if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.27")
163
+ set(CMAKE_POLICY_VERSION_MINIMUM 3.5 CACHE STRING "" FORCE)
164
+ endif()
165
+
166
+ # Determine which submodules gRPC needs.
167
+ #
168
+ # The list is part of CPM's cache key: a different submodule set produces a different hash and
169
+ # therefore a different third_party_cache directory, so it must be IDENTICAL on every platform
170
+ # that should hit the cache the source tarball ships. That is why third_party/zlib is fetched
171
+ # unconditionally even though only Windows *uses* it (gRPC_ZLIB_PROVIDER below stays "package"
172
+ # elsewhere -- fetching is cheap, the provider switch decides whether it is built). gRPC's bundled
173
+ # zlib has an fdopen macro in zutil.h that conflicts with newer macOS SDK headers, hence system
174
+ # zlib everywhere it exists.
175
+ # Hiding gRPC, protobuf, abseil, re2 and c-ares keeps them out of libcouchbase_cxx_client's
176
+ # dynamic symbol table, where an application linking its own protobuf or gRPC would otherwise
177
+ # interpose on ours at load time. That is what a shipped library needs, so it follows
178
+ # COUCHBASE_CXX_CLIENT_PACKAGE_BUILD.
179
+ #
180
+ # It must NOT be the default, for the same reason the generated stubs are not hidden by default.
181
+ # Hidden symbols cannot be preempted, so an executable linking BOTH the shared client and anything
182
+ # that pulls in gRPC -- every CNG test does, through couchbase_cxx_protostellar -- ends up with a
183
+ # second gRPC beside the one inside the .so. Two ExecCtx thread-locals and two closure lists in one
184
+ # process crash in grpc_closure_list_append, which is what the tsan leg showed across ten tests:
185
+ # it is the only leg that builds gRPC from source, so the only one where the duplicate is real.
186
+ if(COUCHBASE_CXX_CLIENT_PACKAGE_BUILD)
187
+ set(_grpc_visibility_options "CMAKE_C_VISIBILITY_PRESET hidden" "CMAKE_CXX_VISIBILITY_PRESET hidden")
188
+ else()
189
+ set(_grpc_visibility_options)
190
+ endif()
191
+
192
+ set(_GRPC_SUBMODULES
193
+ "third_party/re2"
194
+ "third_party/abseil-cpp"
195
+ "third_party/protobuf"
196
+ "third_party/cares/cares"
197
+ "third_party/zlib"
198
+ )
199
+
200
+ # If the project already has BoringSSL targets (from cmake/OpenSSL.cmake),
201
+ # reuse them instead of letting gRPC build a second copy.
202
+ if(TARGET ssl AND TARGET crypto)
203
+ # Pre-set gRPC's internal SSL variables so ssl.cmake can be skipped
204
+ set(_gRPC_SSL_LIBRARIES ssl crypto CACHE INTERNAL "")
205
+ get_target_property(_boring_include ssl INTERFACE_INCLUDE_DIRECTORIES)
206
+ if(_boring_include)
207
+ set(_gRPC_SSL_INCLUDE_DIR "${_boring_include}" CACHE INTERNAL "")
208
+ else()
209
+ set(_gRPC_SSL_INCLUDE_DIR "" CACHE INTERNAL "")
210
+ endif()
211
+ set(gRPC_SSL_PROVIDER "" CACHE STRING "" FORCE)
212
+ elseif(TARGET PkgConfig::PKG_CONFIG_OPENSSL)
213
+ # OpenSSL was found via pkg-config (when CMake's find_package(OpenSSL) returned an unusable setup).
214
+ # Reuse PkgConfig::PKG_CONFIG_OPENSSL directly so gRPC links the exact same OpenSSL library.
215
+ set(_gRPC_SSL_LIBRARIES PkgConfig::PKG_CONFIG_OPENSSL CACHE INTERNAL "")
216
+ set(gRPC_SSL_PROVIDER "" CACHE STRING "" FORCE)
217
+ else()
218
+ # No project-provided BoringSSL or pkg-config OpenSSL; point gRPC at the OpenSSL package.
219
+ find_package(OpenSSL REQUIRED)
220
+ set(gRPC_SSL_PROVIDER "package" CACHE STRING "" FORCE)
221
+ endif()
222
+
223
+ set(gRPC_INSTALL OFF CACHE BOOL "" FORCE)
224
+ # gRPC emits install() rules that gRPC_INSTALL does not gate -- etc/roots.pem, its headers, its
225
+ # pkg-config files. Vendored, those stage into our install tree, where they are files no package
226
+ # owns: rpmbuild fails the build over them, and a DEB would ship gRPC's headers next to ours.
227
+ # Point every gRPC install destination at one throwaway prefix instead, which the RPM and DEB
228
+ # install steps delete in a single line. The alternative -- deleting each path -- silently grows a
229
+ # new leak every time gRPC adds a rule.
230
+ foreach(_grpc_install_dir BINDIR LIBDIR INCLUDEDIR CMAKEDIR SHAREDIR)
231
+ set(gRPC_INSTALL_${_grpc_install_dir}
232
+ "${COUCHBASE_CXX_CLIENT_VENDORED_INSTALL_JUNK_DIR}/${_grpc_install_dir}"
233
+ CACHE STRING "" FORCE)
234
+ endforeach()
235
+ set(gRPC_BUILD_TESTS OFF CACHE BOOL "" FORCE)
236
+ # gRPC's CMakeLists downloads xds/envoy-api/googleapis/opencensus-proto archives from the
237
+ # grpc-bazel-mirror at configure time when their third_party/ directories do not exist. None of
238
+ # the gRPC targets built here need them: a fresh git clone leaves empty submodule-placeholder
239
+ # directories that suppress the download, but a source tarball carries files only, so the
240
+ # placeholders vanish and the download fires. Disabling it keeps from-tarball builds offline.
241
+ set(gRPC_DOWNLOAD_ARCHIVES OFF CACHE BOOL "" FORCE)
242
+ # gRPC's systemd support defaults to AUTO, which links libsystemd whenever the build host happens
243
+ # to have systemd-devel installed. That makes the artefact's dependencies a property of the build
244
+ # machine rather than of the source, and it breaks executables linking the static client, which do
245
+ # not inherit the -lsystemd that the shared library records. It provides only socket activation
246
+ # (sd_listen_fds) for gRPC servers, which nothing here uses.
247
+ set(gRPC_USE_SYSTEMD "OFF" CACHE STRING "" FORCE)
248
+ set(gRPC_BUILD_GRPC_CPP_PLUGIN ON CACHE BOOL "" FORCE)
249
+ set(gRPC_BUILD_GRPC_CSHARP_PLUGIN OFF CACHE BOOL "" FORCE)
250
+ set(gRPC_BUILD_GRPC_OBJECTIVE_C_PLUGIN OFF CACHE BOOL "" FORCE)
251
+ set(gRPC_BUILD_GRPC_PHP_PLUGIN OFF CACHE BOOL "" FORCE)
252
+ set(gRPC_BUILD_GRPC_NODE_PLUGIN OFF CACHE BOOL "" FORCE)
253
+ set(gRPC_BUILD_GRPC_PYTHON_PLUGIN OFF CACHE BOOL "" FORCE)
254
+ set(gRPC_BUILD_GRPC_RUBY_PLUGIN OFF CACHE BOOL "" FORCE)
255
+ if(WIN32)
256
+ set(gRPC_ZLIB_PROVIDER "module" CACHE STRING "" FORCE)
257
+ else()
258
+ set(gRPC_ZLIB_PROVIDER "package" CACHE STRING "" FORCE)
259
+ endif()
260
+ set(gRPC_RE2_PROVIDER "module" CACHE STRING "" FORCE)
261
+ set(RE2_BUILD_TESTING OFF CACHE BOOL "" FORCE)
262
+ set(gRPC_PROTOBUF_PROVIDER "module" CACHE STRING "" FORCE)
263
+ set(gRPC_PROTOBUF_PACKAGE_TYPE "CONFIG" CACHE STRING "" FORCE)
264
+ set(gRPC_ABSL_PROVIDER "module" CACHE STRING "" FORCE)
265
+ set(gRPC_CARES_PROVIDER "module" CACHE STRING "" FORCE)
266
+ set(protobuf_INSTALL OFF CACHE BOOL "" FORCE)
267
+ set(protobuf_BUILD_TESTS OFF CACHE BOOL "" FORCE)
268
+ set(protobuf_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
269
+ set(protobuf_MSVC_STATIC_RUNTIME OFF CACHE BOOL "" FORCE)
270
+
271
+ # Fetched via CPM, NOT raw FetchContent, so the source-tarball machinery captures it: packaging
272
+ # configures with CPM_DOWNLOAD_ALL + CPM_USE_NAMED_CACHE_DIRECTORIES and harvests
273
+ # CPM_SOURCE_CACHE into the tarball's third_party_cache/, and from-tarball builds
274
+ # (cmake/TarballRelease.cmake) point CPM back at it. FetchContent populates into the build tree
275
+ # instead, which packaging deletes -- so gRPC would be re-cloned from github.com on every
276
+ # from-tarball build, and an offline build would simply fail. CPM forwards the GIT_* arguments to
277
+ # FetchContent underneath, so fetch semantics are unchanged; only the source location differs.
278
+ #
279
+ # gRPC v1.65.x is the last series that ships protobuf 3.x which is compatible with the protobuf
280
+ # version opentelemetry-cpp 1.23 expects.
281
+ # https://github.com/grpc/grpc/releases
282
+ cpmaddpackage(
283
+ NAME
284
+ grpc
285
+ VERSION
286
+ 1.65.5
287
+ GIT_REPOSITORY
288
+ "https://github.com/grpc/grpc.git"
289
+ GIT_TAG
290
+ v1.65.5
291
+ GIT_SHALLOW
292
+ TRUE
293
+ GIT_SUBMODULES
294
+ ${_GRPC_SUBMODULES}
295
+ OPTIONS
296
+ # Send every install rule these projects declare into a throwaway prefix. gRPC's own rules are
297
+ # not gated by gRPC_INSTALL, and re2's are not gated at all -- it installs its headers, its
298
+ # archive and its CMake package unconditionally -- while c-ares additionally installs adig,
299
+ # ahost and acountry into bindir. Left alone they land in our install tree as files no package
300
+ # owns, which fails rpmbuild outright and would put gRPC's headers in the DEB beside ours.
301
+ # Redirecting the GNUInstallDirs variables catches all of them at once, including submodules
302
+ # added later; CPM applies OPTIONS as ordinary variables scoped to this package, so the
303
+ # project's own install destinations are unaffected.
304
+ "CMAKE_INSTALL_BINDIR ${COUCHBASE_CXX_CLIENT_VENDORED_INSTALL_JUNK_DIR}/bin"
305
+ "CMAKE_INSTALL_LIBDIR ${COUCHBASE_CXX_CLIENT_VENDORED_INSTALL_JUNK_DIR}/lib"
306
+ "CMAKE_INSTALL_INCLUDEDIR ${COUCHBASE_CXX_CLIENT_VENDORED_INSTALL_JUNK_DIR}/include"
307
+ "CMAKE_INSTALL_DATADIR ${COUCHBASE_CXX_CLIENT_VENDORED_INSTALL_JUNK_DIR}/share"
308
+ "CMAKE_INSTALL_DATAROOTDIR ${COUCHBASE_CXX_CLIENT_VENDORED_INSTALL_JUNK_DIR}/share"
309
+ # c-ares builds three command line tools that nothing here uses and that only exist to be
310
+ # installed into bindir.
311
+ "CARES_BUILD_TOOLS OFF"
312
+ ${_grpc_visibility_options}
313
+ "CMAKE_POSITION_INDEPENDENT_CODE ON")
314
+
315
+ # Compile all fetched gRPC, Protobuf, Abseil, upb, re2 targets with the project's sanitizer
316
+ # flags so that all translation units agree on struct layouts, member definitions, and TSan
317
+ # instrumentation (mirroring commit be6fb44f9 / CXXCBC-917 for couchbase_cxx_protostellar).
318
+ if(LIST_OF_SANITIZERS AND NOT "${LIST_OF_SANITIZERS}" STREQUAL "")
319
+ function(couchbase_get_targets_recursively out_var dir)
320
+ get_property(_targets DIRECTORY "${dir}" PROPERTY BUILDSYSTEM_TARGETS)
321
+ get_property(_subdirs DIRECTORY "${dir}" PROPERTY SUBDIRECTORIES)
322
+ foreach(_subdir IN LISTS _subdirs)
323
+ couchbase_get_targets_recursively(_sub_targets "${_subdir}")
324
+ list(APPEND _targets ${_sub_targets})
325
+ endforeach()
326
+ set(${out_var} "${_targets}" PARENT_SCOPE)
327
+ endfunction()
328
+
329
+ couchbase_get_targets_recursively(_fetched_targets "${grpc_SOURCE_DIR}")
330
+ foreach(_fetched_target IN LISTS _fetched_targets)
331
+ get_target_property(_target_type ${_fetched_target} TYPE)
332
+ if(_target_type STREQUAL "STATIC_LIBRARY"
333
+ OR _target_type STREQUAL "SHARED_LIBRARY"
334
+ OR _target_type STREQUAL "OBJECT_LIBRARY"
335
+ OR _target_type STREQUAL "EXECUTABLE")
336
+ target_compile_options(${_fetched_target} PRIVATE -fsanitize=${LIST_OF_SANITIZERS})
337
+ target_link_options(${_fetched_target} PRIVATE -fsanitize=${LIST_OF_SANITIZERS})
338
+ if("thread" IN_LIST SANITIZERS
339
+ AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU"
340
+ AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "14.0.0")
341
+ target_compile_options(${_fetched_target} PRIVATE -Wno-error=tsan)
342
+ endif()
343
+ endif()
344
+ endforeach()
345
+ endif()
346
+
347
+ # Abseil-cpp bundled with gRPC v1.65.5 has a bug in its randen HWAES compile
348
+ # options on Apple ARM64: CMake's option deduplication strips the second
349
+ # -Xarch_x86_64 prefix, leaving -msse4.1 unscoped, which causes a hard error
350
+ # on newer AppleClang (16+). Fix by replacing the incorrectly deduped flags
351
+ # with properly SHELL:-prefixed versions on the affected targets.
352
+ # See https://github.com/abseil/abseil-cpp/pull/1710
353
+ #
354
+ # After CMake deduplication the compile options are stored as individual list
355
+ # elements (e.g. "-Xarch_x86_64;-maes;-msse4.1;...") rather than as
356
+ # space-joined pairs, so we must remove them one by one.
357
+ # Both absl_random_internal_randen_hwaes and absl_random_internal_randen_hwaes_impl
358
+ # use ABSL_RANDOM_RANDEN_COPTS and need this fix.
359
+ if(APPLE)
360
+ foreach(_randen_target absl_random_internal_randen_hwaes absl_random_internal_randen_hwaes_impl)
361
+ if(TARGET ${_randen_target})
362
+ get_target_property(_randen_opts ${_randen_target} COMPILE_OPTIONS)
363
+ if(_randen_opts)
364
+ list(REMOVE_ITEM _randen_opts
365
+ "-Xarch_x86_64"
366
+ "-maes"
367
+ "-msse4.1"
368
+ "-Xarch_arm64"
369
+ "-march=armv8-a+crypto"
370
+ "-Wno-unused-command-line-argument"
371
+ )
372
+ list(APPEND _randen_opts
373
+ "SHELL:-Xarch_x86_64 -maes"
374
+ "SHELL:-Xarch_x86_64 -msse4.1"
375
+ "SHELL:-Xarch_arm64 -march=armv8-a+crypto"
376
+ "-Wno-unused-command-line-argument"
377
+ )
378
+ set_target_properties(${_randen_target} PROPERTIES COMPILE_OPTIONS "${_randen_opts}")
379
+ endif()
380
+ endif()
381
+ endforeach()
382
+ endif()
383
+
384
+ # OpenTelemetry's cmake/protobuf.cmake checks gRPC_PROVIDER to detect
385
+ # whether gRPC fetched protobuf as a submodule. When that variable is set
386
+ # (and != "find_package") and TARGET libprotobuf exists, OTel reuses the
387
+ # existing protobuf instead of fetching its own copy via FetchContent.
388
+ # Also ensure grpc_SOURCE_DIR is visible: OTel's cmake/protobuf.cmake reads the protobuf version
389
+ # from ${grpc_SOURCE_DIR}/third_party/protobuf/version.json. gRPC has no version.json of its own.
390
+ if(TARGET protobuf::libprotobuf)
391
+ set(Protobuf_FOUND TRUE CACHE BOOL "" FORCE)
392
+ set(gRPC_PROVIDER "fetch_content" CACHE STRING "" FORCE)
393
+ FetchContent_GetProperties(grpc)
394
+
395
+ # When protobuf is built from source, protoc has no built-in path to
396
+ # well-known .proto files (google/protobuf/timestamp.proto etc.).
397
+ # Set PROTOBUF_IMPORT_DIRS so protobuf_Generate.cmake and gRPC_Generate.cmake
398
+ # add the necessary -I flag when invoking protoc.
399
+ set(PROTOBUF_IMPORT_DIRS "${grpc_SOURCE_DIR}/third_party/protobuf/src" CACHE STRING "" FORCE)
400
+
401
+ # With WITH_OTLP_GRPC, OTel's cmake/grpc.cmake finds this gRPC through the grpc-config.cmake
402
+ # redirect and sets gRPC_PROVIDER to "find_package", so its protobuf.cmake runs
403
+ # find_package(Protobuf) instead. That resolves a platform protobuf where one is installed, or
404
+ # fetches a second copy whose targets collide with these. This empty package config makes the
405
+ # CONFIG search succeed on the targets that already exist. ThirdPartyDependencies.cmake passes
406
+ # it to OpenTelemetry alone, as a package option, so no other find_package(Protobuf) sees it.
407
+ set(COUCHBASE_CXX_CLIENT_BUNDLED_PROTOBUF_DIR "${CMAKE_BINARY_DIR}/cmake/protobuf-from-grpc")
408
+ file(WRITE "${COUCHBASE_CXX_CLIENT_BUNDLED_PROTOBUF_DIR}/protobuf-config.cmake"
409
+ "# protobuf::libprotobuf and protobuf::protoc are defined by gRPC's bundled protobuf.\n")
410
+ endif()
411
+
412
+ if(TARGET grpc++ AND NOT TARGET gRPC::grpc++)
413
+ add_library(gRPC::grpc++ ALIAS grpc++)
414
+ endif()
415
+ if(TARGET grpc_cpp_plugin AND NOT TARGET gRPC::grpc_cpp_plugin)
416
+ add_executable(gRPC::grpc_cpp_plugin ALIAS grpc_cpp_plugin)
417
+ endif()
418
+
419
+ foreach(_target grpc++ grpc_cpp_plugin)
420
+ if(TARGET ${_target})
421
+ set_target_properties(${_target} PROPERTIES
422
+ POSITION_INDEPENDENT_CODE ON
423
+ CXX_CLANG_TIDY ""
424
+ CXX_INCLUDE_WHAT_YOU_USE "")
425
+ endif()
426
+ endforeach()
427
+
428
+ if(TARGET libprotobuf)
429
+ set_target_properties(libprotobuf PROPERTIES
430
+ POSITION_INDEPENDENT_CODE ON
431
+ CXX_CLANG_TIDY ""
432
+ CXX_INCLUDE_WHAT_YOU_USE "")
433
+ endif()
434
+
435
+ # gRPC unconditionally defines several library targets we do not link
436
+ # against (the couchbase2 transport and the fit_performer tool consume only
437
+ # gRPC::grpc++ and gRPC::grpc_cpp_plugin). Because gRPC's CMakeLists has no
438
+ # per-library opt-out and the subdirectory is added without
439
+ # EXCLUDE_FROM_ALL, every target ends up in the Visual Studio ALL_BUILD
440
+ # and gets compiled on Windows. grpc_unsecure alone is a ~300-source
441
+ # near-duplicate of gRPC without TLS; combined with the admin/auth
442
+ # extras below this is ~15 minutes of pointless compile per Windows
443
+ # build. Marking each EXCLUDE_FROM_ALL removes them from ALL_BUILD
444
+ # while leaving the targets defined, so anything that does
445
+ # transitively need one is still pulled in by CMake on demand.
446
+ foreach(_unused_grpc_target
447
+ grpc_unsecure
448
+ grpc++_unsecure
449
+ grpc++_alts
450
+ grpc++_reflection
451
+ grpcpp_channelz
452
+ grpc_authorization_provider)
453
+ if(TARGET ${_unused_grpc_target})
454
+ set_target_properties(${_unused_grpc_target} PROPERTIES EXCLUDE_FROM_ALL TRUE)
455
+ endif()
456
+ endforeach()
457
+ endif()
458
+
459
+ # gRPC's headers are not clean under this project's warning set: <grpcpp/...> trips
460
+ # -Wold-style-cast, -Wsign-conversion and -Wgcc-compat, and with -Werror that is a hard failure in
461
+ # any translation unit including them.
462
+ #
463
+ # It bites on the built-from-source path: the include directories are ordinary -I entries, so every
464
+ # warning applies. Platform packages instead put the headers under a system prefix, where the
465
+ # compiler treats them as system headers for free.
466
+ #
467
+ # fit_performer sidesteps this by turning its own warnings off wholesale (/W0 or -w plus
468
+ # COMPILE_WARNING_AS_ERROR OFF). That is not an option for couchbase_cxx_client, which compiles
469
+ # core/protostellar/*.cxx and must keep full warnings on its own code, so the fix belongs on the
470
+ # dependency: mark the interface include directories SYSTEM, exactly as is done for spdlog.
471
+ #
472
+ # Marking gRPC::grpc++ is sufficient and abseil/protobuf/boringssl need no separate handling --
473
+ # both clang and gcc propagate system-ness down the include stack, so a header reached from a system
474
+ # header is itself treated as one. Verified: with grpc-src/include as -I, <grpcpp/grpcpp.h> emits 26
475
+ # errors across grpcpp and abseil-cpp; with it as -isystem and every other third-party directory
476
+ # left as -I, zero.
477
+ foreach(_grpc_system_target gRPC::grpc++ gRPC::grpc protobuf::libprotobuf)
478
+ if(TARGET ${_grpc_system_target})
479
+ declare_system_library(${_grpc_system_target})
480
+ endif()
481
+ endforeach()
@@ -1,4 +1,11 @@
1
1
  option(COUCHBASE_CXX_CLIENT_POST_LINKED_OPENSSL "Rely on application to link OpenSSL library" FALSE)
2
+
3
+ # The pkg-config module both fallbacks below ask for, named once because cmake/Packaging.cmake has to
4
+ # request the same one in the installed package config: a consumer that resolves a different module
5
+ # than the archive was built against gets a different TLS installation, quietly.
6
+ set(COUCHBASE_CXX_CLIENT_OPENSSL_PKGCONFIG_MODULE
7
+ "openssl11"
8
+ CACHE STRING "pkg-config module used when find_package(OpenSSL) is unusable")
2
9
  option(COUCHBASE_CXX_CLIENT_USE_HOMEBREW_TO_DETECT_OPENSSL "Use homebrew to determine OpenSSL root directory" TRUE)
3
10
  option(COUCHBASE_CXX_CLIENT_USE_SCOOP_TO_DETECT_OPENSSL "Use scoop to determine OpenSSL root directory" TRUE)
4
11
  option(COUCHBASE_CXX_CLIENT_STATIC_BORINGSSL "Build and statically link BoringSSL library" FALSE)
@@ -115,7 +122,7 @@ else()
115
122
  REQUIRED
116
123
  IMPORTED_TARGET
117
124
  GLOBAL
118
- openssl11)
125
+ ${COUCHBASE_CXX_CLIENT_OPENSSL_PKGCONFIG_MODULE})
119
126
  if(PKG_CONFIG_OPENSSL_FOUND)
120
127
  message(STATUS "PKG_CONFIG_OPENSSL_VERSION: ${PKG_CONFIG_OPENSSL_VERSION}")
121
128
  message(STATUS "PKG_CONFIG_OPENSSL_INCLUDE_DIRS: ${PKG_CONFIG_OPENSSL_INCLUDE_DIRS}")
@@ -134,7 +141,7 @@ else()
134
141
  REQUIRED
135
142
  IMPORTED_TARGET
136
143
  GLOBAL
137
- openssl11)
144
+ ${COUCHBASE_CXX_CLIENT_OPENSSL_PKGCONFIG_MODULE})
138
145
  if(PKG_CONFIG_OPENSSL_FOUND)
139
146
  message(STATUS "PKG_CONFIG_OPENSSL_VERSION: ${PKG_CONFIG_OPENSSL_VERSION}")
140
147
  message(STATUS "PKG_CONFIG_OPENSSL_INCLUDE_DIRS: ${PKG_CONFIG_OPENSSL_INCLUDE_DIRS}")
@@ -231,15 +238,29 @@ set(CA_BUNDLE_CPP_FILE "${CMAKE_CURRENT_BINARY_DIR}/generated/mozilla_ca_bundle.
231
238
  # seems to be cross-platform and fast.
232
239
  string(
233
240
  REGEX MATCHALL
234
- "[^=#]+=+\n-----BEGIN CERTIFICATE-----[^-]+-----END CERTIFICATE-----"
241
+ "[^\n]+\n=+\n(#[^\n]*\n)*-----BEGIN CERTIFICATE-----[^-]+-----END CERTIFICATE-----"
235
242
  CERTIFICATES
236
243
  "${CA_BUNDLE_CONTENT}")
237
244
  list(LENGTH CERTIFICATES NUMBER_OF_CERTIFICATES)
245
+ if(COUCHBASE_CXX_CLIENT_EMBED_MOZILLA_CA_BUNDLE)
246
+ # A bundle layout that the certificate expressions do not recognise fails configure. Otherwise the
247
+ # library builds with fewer default roots than the bundle carries, or none.
248
+ string(REGEX MATCHALL "-----BEGIN CERTIFICATE-----" PEM_BLOCKS "${CA_BUNDLE_CONTENT}")
249
+ list(LENGTH PEM_BLOCKS NUMBER_OF_PEM_BLOCKS)
250
+ if(NUMBER_OF_CERTIFICATES EQUAL 0 OR NOT NUMBER_OF_CERTIFICATES EQUAL NUMBER_OF_PEM_BLOCKS)
251
+ message(
252
+ FATAL_ERROR
253
+ "Extracted ${NUMBER_OF_CERTIFICATES} of ${NUMBER_OF_PEM_BLOCKS} certificates from "
254
+ "${COUCHBASE_CXX_CLIENT_EMBED_MOZILLA_CA_BUNDLE_ROOT}/mozilla-ca-bundle.crt")
255
+ endif()
256
+ endif()
238
257
  file(
239
258
  WRITE ${CA_BUNDLE_CPP_FILE}
240
259
  "
241
260
  #include \"core/mozilla_ca_bundle.hxx\"
242
261
 
262
+ #include <couchbase/build_config.hxx>
263
+
243
264
  #include <gsl/span>
244
265
 
245
266
  #include <array>
@@ -249,23 +270,77 @@ namespace couchbase::core::default_ca
249
270
  {
250
271
  constexpr inline std::array<certificate, ${NUMBER_OF_CERTIFICATES}> certificates{
251
272
  ")
273
+ set(CERTIFICATE_BODIES "")
252
274
  foreach(CERTIFICATE ${CERTIFICATES})
253
275
  string(
254
276
  REGEX MATCH
255
- "[ \t\r\n]*([^=\n]+)[ \t\r\n]*=+\n(-----BEGIN CERTIFICATE-----[^-]+-----END CERTIFICATE-----)"
277
+ "^([^\n]+)\n=+\n(#[^\n]*\n)*(-----BEGIN CERTIFICATE-----[^-]+-----END CERTIFICATE-----)$"
256
278
  PARTS
257
- ${CERTIFICATE})
279
+ "${CERTIFICATE}")
280
+ if(NOT PARTS)
281
+ message(FATAL_ERROR "Unable to split CA bundle entry into name and certificate:\n${CERTIFICATE}")
282
+ endif()
283
+ set(CERTIFICATE_NAME "${CMAKE_MATCH_1}")
284
+ set(CERTIFICATE_BODY "${CMAKE_MATCH_3}")
285
+ if(NOT CERTIFICATE_BODY MATCHES "^-----BEGIN CERTIFICATE-----\n([A-Za-z0-9+/=]+\n)+-----END CERTIFICATE-----$")
286
+ message(FATAL_ERROR "CA bundle entry \"${CERTIFICATE_NAME}\" is not a PEM certificate:\n${CERTIFICATE_BODY}")
287
+ endif()
288
+ # The name is emitted as an R"(...)" literal, which ends at the first )" it contains. The body
289
+ # cannot contain one: the PEM check above admits no ')'.
290
+ string(FIND "${CERTIFICATE_NAME}" ")\"" CLOSING_DELIMITER)
291
+ if(NOT CLOSING_DELIMITER EQUAL -1)
292
+ message(FATAL_ERROR "CA bundle entry name cannot be embedded as a raw string: ${CERTIFICATE_NAME}")
293
+ endif()
294
+ list(APPEND CERTIFICATE_BODIES "${CERTIFICATE_BODY}")
258
295
  file(APPEND ${CA_BUNDLE_CPP_FILE}
259
- " certificate{ R\"(${CMAKE_MATCH_1})\",
260
- R\"(${CMAKE_MATCH_2})\" },
296
+ " certificate{ R\"(${CERTIFICATE_NAME})\",
297
+ R\"(${CERTIFICATE_BODY})\", },
261
298
 
262
299
  ")
263
300
  endforeach()
301
+ set(UNIQUE_CERTIFICATE_BODIES ${CERTIFICATE_BODIES})
302
+ list(REMOVE_DUPLICATES UNIQUE_CERTIFICATE_BODIES)
303
+ list(LENGTH UNIQUE_CERTIFICATE_BODIES NUMBER_OF_UNIQUE_CERTIFICATES)
304
+ if(NOT NUMBER_OF_UNIQUE_CERTIFICATES EQUAL NUMBER_OF_CERTIFICATES)
305
+ message(FATAL_ERROR "CA bundle carries ${NUMBER_OF_CERTIFICATES} certificates, but only "
306
+ "${NUMBER_OF_UNIQUE_CERTIFICATES} are distinct")
307
+ endif()
264
308
 
265
309
  file(
266
310
  APPEND ${CA_BUNDLE_CPP_FILE}
267
311
  "};
268
312
 
313
+ namespace
314
+ {
315
+ constexpr auto
316
+ is_pem_certificate(std::string_view body) -> bool
317
+ {
318
+ constexpr std::string_view header{ \"-----BEGIN CERTIFICATE-----\\n\" };
319
+ constexpr std::string_view footer{ \"\\n-----END CERTIFICATE-----\" };
320
+ return body.size() > header.size() + footer.size() && body.substr(0, header.size()) == header &&
321
+ body.substr(body.size() - footer.size()) == footer;
322
+ }
323
+
324
+ constexpr auto
325
+ every_entry_is_named_certificate() -> bool
326
+ {
327
+ for (const auto& entry : certificates) {
328
+ if (entry.authority.empty() || !is_pem_certificate(entry.body)) {
329
+ return false;
330
+ }
331
+ }
332
+ return true;
333
+ }
334
+ } // namespace
335
+
336
+ // An array sized larger than its initialiser list value-initialises the remaining entries.
337
+ static_assert(every_entry_is_named_certificate(),
338
+ \"every embedded CA bundle entry carries a name and a PEM certificate\");
339
+ #if defined(COUCHBASE_CXX_CLIENT_EMBED_MOZILLA_CA_BUNDLE)
340
+ static_assert(!certificates.empty(),
341
+ \"COUCHBASE_CXX_CLIENT_EMBED_MOZILLA_CA_BUNDLE is enabled, but no certificates were embedded\");
342
+ #endif
343
+
269
344
  auto
270
345
  mozilla_ca_certs() -> gsl::span<const certificate>
271
346
  {