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.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/ext/CMakeLists.txt +16 -1
- data/ext/cache/cpm/{CPM_0.42.0.cmake → CPM_0.43.1.cmake} +18 -2
- data/ext/cache/extconf_include.rb +6 -6
- data/ext/cache/mozilla-ca-bundle.crt +121 -55
- data/ext/cache/mozilla-ca-bundle.sha256 +1 -1
- data/ext/couchbase/CMakeLists.txt +130 -21
- data/ext/couchbase/cmake/APKBUILD.in +25 -4
- data/ext/couchbase/cmake/Bundler.cmake +143 -34
- data/ext/couchbase/cmake/CPM.cmake +126 -12
- data/ext/couchbase/cmake/Cache.cmake +7 -1
- data/ext/couchbase/cmake/CompilerOptions.cmake +1 -1
- data/ext/couchbase/cmake/CompilerWarnings.cmake +17 -6
- data/ext/couchbase/cmake/GrpcProtobuf.cmake +481 -0
- data/ext/couchbase/cmake/OpenSSL.cmake +10 -3
- data/ext/couchbase/cmake/Packaging.cmake +519 -65
- data/ext/couchbase/cmake/Protostellar.cmake +250 -0
- data/ext/couchbase/cmake/Sanitizers.cmake +61 -50
- data/ext/couchbase/cmake/StaticAnalyzers.cmake +16 -5
- data/ext/couchbase/cmake/TestFramework.cmake +283 -0
- data/ext/couchbase/cmake/TestFrameworkAddTests.cmake +51 -0
- data/ext/couchbase/cmake/Testing.cmake +27 -9
- data/ext/couchbase/cmake/ThirdPartyDependencies.cmake +141 -8
- data/ext/couchbase/cmake/VersionInfo.cmake +50 -0
- data/ext/couchbase/cmake/build_config.hxx.in +2 -1
- data/ext/couchbase/cmake/couchbase-cxx-client.spec.in +101 -23
- data/ext/couchbase/cmake/couchbase_cxx_client_static-config.cmake.in +7 -0
- data/ext/couchbase/cmake/couchbase_cxx_client_static.pc.in +2 -0
- data/ext/couchbase/cmake/gRPC_Generate.cmake +58 -0
- data/ext/couchbase/cmake/protobuf_Generate.cmake +69 -0
- data/ext/couchbase/cmake/require-git-checkout.cmake +25 -0
- data/ext/couchbase/cmake/tarball_glob.txt +49 -0
- data/ext/couchbase/core/agent_group.cxx +0 -8
- data/ext/couchbase/core/agent_group.hxx +0 -4
- data/ext/couchbase/core/analytics_stream.cxx +314 -0
- data/ext/couchbase/core/analytics_stream.hxx +129 -0
- data/ext/couchbase/core/analytics_stream_component.cxx +245 -0
- data/ext/couchbase/core/analytics_stream_component.hxx +67 -0
- data/ext/couchbase/core/app_telemetry_meter.cxx +25 -3
- data/ext/couchbase/core/app_telemetry_meter.hxx +77 -0
- data/ext/couchbase/core/app_telemetry_reporter.cxx +7 -6
- data/ext/couchbase/core/bucket.cxx +381 -87
- data/ext/couchbase/core/bucket.hxx +105 -25
- data/ext/couchbase/core/bucket_unit_test_api.hxx +57 -0
- data/ext/couchbase/core/capella.hxx +91 -0
- data/ext/couchbase/core/cluster.cxx +1554 -398
- data/ext/couchbase/core/cluster.hxx +39 -8
- data/ext/couchbase/core/cluster_agent.cxx +0 -8
- data/ext/couchbase/core/cluster_agent.hxx +0 -4
- data/ext/couchbase/core/cluster_options.hxx +26 -3
- data/ext/couchbase/core/collections_component.cxx +39 -15
- data/ext/couchbase/core/config_profiles.cxx +1 -1
- data/ext/couchbase/core/crud_component.cxx +2 -2
- data/ext/couchbase/core/crud_options.hxx +34 -0
- data/ext/couchbase/core/crypto/cbcrypto.cc +18 -13
- data/ext/couchbase/core/document_id_redaction.hxx +81 -0
- data/ext/couchbase/core/error_context/base_error_context.hxx +7 -6
- data/ext/couchbase/core/error_context/key_value.cxx +25 -2
- data/ext/couchbase/core/error_context/key_value.hxx +60 -33
- data/ext/couchbase/core/error_context/key_value_error_context.hxx +16 -15
- data/ext/couchbase/core/error_context/search.hxx +5 -0
- data/ext/couchbase/core/error_context/search_json.hxx +3 -0
- data/ext/couchbase/core/error_context/subdocument_error_context.hxx +19 -18
- data/ext/couchbase/core/error_context/view.hxx +5 -0
- data/ext/couchbase/core/free_form_http_request.cxx +237 -4
- data/ext/couchbase/core/free_form_http_request.hxx +41 -8
- data/ext/couchbase/core/http_component.cxx +300 -284
- data/ext/couchbase/core/http_component.hxx +0 -4
- data/ext/couchbase/core/impl/analytics.cxx +38 -5
- data/ext/couchbase/core/impl/analytics.hxx +34 -0
- data/ext/couchbase/core/impl/bootstrap_error.hxx +0 -3
- data/ext/couchbase/core/impl/collection.cxx +215 -202
- data/ext/couchbase/core/impl/collection_manager.cxx +1 -1
- data/ext/couchbase/core/impl/dns_srv_tracker.cxx +45 -18
- data/ext/couchbase/core/impl/error.cxx +22 -2
- data/ext/couchbase/core/impl/internal_analytics_stream_result.hxx +111 -0
- data/ext/couchbase/core/impl/internal_query_stream_result.hxx +110 -0
- data/ext/couchbase/core/impl/invoke_with_node_id.hxx +15 -7
- data/ext/couchbase/core/impl/key_value_error_category.cxx +6 -0
- data/ext/couchbase/core/impl/lookup_in_replica.cxx +10 -10
- data/ext/couchbase/core/impl/lookup_in_replica.hxx +4 -4
- data/ext/couchbase/core/impl/node_id.cxx +49 -13
- data/ext/couchbase/core/impl/observability_recorder.cxx +12 -2
- data/ext/couchbase/core/impl/observe_poll.cxx +63 -23
- data/ext/couchbase/core/impl/public_analytics_stream_result.cxx +372 -0
- data/ext/couchbase/core/impl/public_bucket.cxx +48 -2
- data/ext/couchbase/core/impl/public_cluster.cxx +229 -42
- data/ext/couchbase/core/impl/public_query_stream_result.cxx +380 -0
- data/ext/couchbase/core/impl/public_transaction_get_multi_replicas_from_preferred_server_group_result.cxx +42 -0
- data/ext/couchbase/core/impl/public_transaction_get_multi_result.cxx +42 -0
- data/ext/couchbase/core/impl/query.cxx +76 -7
- data/ext/couchbase/core/impl/query.hxx +36 -0
- data/ext/couchbase/core/impl/query_index_manager.cxx +54 -1
- data/ext/couchbase/core/impl/replica_utils.cxx +101 -0
- data/ext/couchbase/core/impl/replica_utils.hxx +64 -0
- data/ext/couchbase/core/impl/resolve_node_id.hxx +125 -0
- data/ext/couchbase/core/impl/scope.cxx +70 -0
- data/ext/couchbase/core/impl/search.cxx +31 -1
- data/ext/couchbase/core/impl/transactions.cxx +130 -0
- data/ext/couchbase/core/impl/wait_until_ready.cxx +439 -0
- data/ext/couchbase/core/impl/wait_until_ready.hxx +110 -0
- data/ext/couchbase/core/impl/with_bucket_config_or_timeout.hxx +180 -0
- data/ext/couchbase/core/impl/with_cancellation.hxx +11 -3
- data/ext/couchbase/core/io/configuration_belongs_to_session.hxx +1 -2
- data/ext/couchbase/core/io/dns_client.cxx +122 -45
- data/ext/couchbase/core/io/dns_codec.hxx +21 -21
- data/ext/couchbase/core/io/dns_config.cxx +21 -6
- data/ext/couchbase/core/io/http_command.hxx +149 -121
- data/ext/couchbase/core/io/http_error.hxx +107 -0
- data/ext/couchbase/core/io/http_parser.cxx +4 -0
- data/ext/couchbase/core/io/http_session.cxx +606 -154
- data/ext/couchbase/core/io/http_session.hxx +147 -30
- data/ext/couchbase/core/io/http_session_manager.hxx +329 -382
- data/ext/couchbase/core/io/http_streaming_parser.cxx +4 -0
- data/ext/couchbase/core/io/http_streaming_response.cxx +328 -43
- data/ext/couchbase/core/io/http_streaming_response.hxx +37 -3
- data/ext/couchbase/core/io/mcbp_buffer_pool.hxx +122 -0
- data/ext/couchbase/core/io/mcbp_command.hxx +150 -51
- data/ext/couchbase/core/io/mcbp_command_id.hxx +45 -0
- data/ext/couchbase/core/io/mcbp_message.cxx +9 -1
- data/ext/couchbase/core/io/mcbp_message.hxx +19 -0
- data/ext/couchbase/core/io/mcbp_output_queue.hxx +150 -0
- data/ext/couchbase/core/io/mcbp_parser.cxx +24 -7
- data/ext/couchbase/core/io/mcbp_session.cxx +309 -301
- data/ext/couchbase/core/io/mcbp_session.hxx +27 -18
- data/ext/couchbase/core/io/opaque_ring_table.hxx +145 -0
- data/ext/couchbase/core/io/retry_orchestrator.hxx +6 -5
- data/ext/couchbase/core/io/stream_deadline.hxx +50 -0
- data/ext/couchbase/core/io/streams.cxx +151 -21
- data/ext/couchbase/core/io/streams.hxx +48 -1
- data/ext/couchbase/core/logger/logger.cxx +36 -0
- data/ext/couchbase/core/logger/logger.hxx +46 -6
- data/ext/couchbase/core/logger/redaction.hxx +503 -0
- data/ext/couchbase/core/management/eventing_status.hxx +10 -0
- data/ext/couchbase/core/management/eventing_status_json.hxx +4 -0
- data/ext/couchbase/core/mcbp/big_endian.cxx +1 -1
- data/ext/couchbase/core/mcbp/codec.cxx +27 -18
- data/ext/couchbase/core/mcbp/operation_queue.cxx +2 -2
- data/ext/couchbase/core/mcbp/packet.hxx +2 -2
- data/ext/couchbase/core/mcbp/queue_request.cxx +23 -6
- data/ext/couchbase/core/mcbp/queue_request.hxx +21 -0
- data/ext/couchbase/core/meta/features.hxx +13 -0
- data/ext/couchbase/core/meta/version.cxx +6 -3
- data/ext/couchbase/core/metrics/logging_meter.cxx +5 -10
- data/ext/couchbase/core/metrics/meter_wrapper.cxx +63 -33
- data/ext/couchbase/core/metrics/meter_wrapper.hxx +55 -3
- data/ext/couchbase/core/operations/analytics_response_parsing.cxx +177 -0
- data/ext/couchbase/core/operations/analytics_response_parsing.hxx +55 -0
- data/ext/couchbase/core/operations/document_analytics.cxx +48 -130
- data/ext/couchbase/core/operations/document_analytics.hxx +14 -2
- data/ext/couchbase/core/operations/document_get_all_replicas.hxx +15 -7
- data/ext/couchbase/core/operations/document_get_any_replica.hxx +19 -8
- data/ext/couchbase/core/operations/document_get_projected.cxx +1 -1
- data/ext/couchbase/core/{impl/get_replica.cxx → operations/document_get_replica.cxx} +21 -3
- data/ext/couchbase/core/{impl/get_replica.hxx → operations/document_get_replica.hxx} +31 -4
- data/ext/couchbase/core/operations/document_lookup_in.cxx +10 -10
- data/ext/couchbase/core/operations/document_lookup_in_all_replicas.hxx +228 -198
- data/ext/couchbase/core/operations/document_lookup_in_any_replica.hxx +215 -217
- data/ext/couchbase/core/operations/document_query.cxx +108 -221
- data/ext/couchbase/core/operations/document_query.hxx +18 -4
- data/ext/couchbase/core/operations/document_search.cxx +52 -8
- data/ext/couchbase/core/operations/document_search.hxx +3 -0
- data/ext/couchbase/core/operations/document_view.cxx +3 -3
- data/ext/couchbase/core/operations/management/analytics_dataset_create.cxx +15 -8
- data/ext/couchbase/core/operations/management/analytics_dataset_create.hxx +4 -0
- data/ext/couchbase/core/operations/management/analytics_dataset_drop.cxx +11 -6
- data/ext/couchbase/core/operations/management/analytics_dataset_get_all.cxx +3 -2
- data/ext/couchbase/core/operations/management/analytics_dataverse_create.cxx +10 -5
- data/ext/couchbase/core/operations/management/analytics_dataverse_drop.cxx +10 -5
- data/ext/couchbase/core/operations/management/analytics_get_pending_mutations.cxx +2 -1
- data/ext/couchbase/core/operations/management/analytics_index_create.cxx +33 -8
- data/ext/couchbase/core/operations/management/analytics_index_drop.cxx +12 -7
- data/ext/couchbase/core/operations/management/analytics_index_get_all.cxx +3 -2
- data/ext/couchbase/core/operations/management/analytics_link_connect.cxx +11 -6
- data/ext/couchbase/core/operations/management/analytics_link_create.cxx +3 -3
- data/ext/couchbase/core/operations/management/analytics_link_disconnect.cxx +10 -4
- data/ext/couchbase/core/operations/management/analytics_link_drop.cxx +6 -4
- data/ext/couchbase/core/operations/management/analytics_link_get_all.cxx +4 -3
- data/ext/couchbase/core/operations/management/analytics_link_replace.cxx +3 -3
- data/ext/couchbase/core/operations/management/analytics_link_utils.hxx +1 -1
- data/ext/couchbase/core/operations/management/change_password.cxx +2 -0
- data/ext/couchbase/core/operations/management/collection_drop.cxx +5 -1
- data/ext/couchbase/core/operations/management/error_utils.cxx +59 -5
- data/ext/couchbase/core/operations/management/error_utils.hxx +29 -1
- data/ext/couchbase/core/operations/management/eventing_deploy_function.cxx +9 -3
- data/ext/couchbase/core/operations/management/eventing_drop_function.cxx +8 -3
- data/ext/couchbase/core/operations/management/eventing_get_all_functions.cxx +4 -2
- data/ext/couchbase/core/operations/management/eventing_get_function.cxx +5 -3
- data/ext/couchbase/core/operations/management/eventing_get_status.cxx +4 -2
- data/ext/couchbase/core/operations/management/eventing_pause_function.cxx +9 -3
- data/ext/couchbase/core/operations/management/eventing_resume_function.cxx +9 -3
- data/ext/couchbase/core/operations/management/eventing_undeploy_function.cxx +9 -3
- data/ext/couchbase/core/operations/management/eventing_upsert_function.cxx +9 -3
- data/ext/couchbase/core/operations/management/group_drop.cxx +3 -1
- data/ext/couchbase/core/operations/management/group_get.cxx +3 -1
- data/ext/couchbase/core/operations/management/group_upsert.cxx +11 -8
- data/ext/couchbase/core/operations/management/query_index_build.cxx +5 -2
- data/ext/couchbase/core/operations/management/query_index_create.cxx +9 -3
- data/ext/couchbase/core/operations/management/query_index_drop.cxx +11 -4
- data/ext/couchbase/core/operations/management/query_index_get_all.cxx +1 -1
- data/ext/couchbase/core/operations/management/query_index_get_all_deferred.cxx +1 -1
- data/ext/couchbase/core/operations/management/scope_drop.cxx +5 -1
- data/ext/couchbase/core/operations/management/scope_get_all.cxx +6 -1
- data/ext/couchbase/core/operations/management/search_get_stats.cxx +10 -0
- data/ext/couchbase/core/operations/management/search_index_analyze_document.cxx +3 -2
- data/ext/couchbase/core/operations/management/search_index_control_ingest.cxx +4 -3
- data/ext/couchbase/core/operations/management/search_index_control_plan_freeze.cxx +4 -3
- data/ext/couchbase/core/operations/management/search_index_control_query.cxx +4 -3
- data/ext/couchbase/core/operations/management/search_index_drop.cxx +2 -2
- data/ext/couchbase/core/operations/management/search_index_get.cxx +2 -2
- data/ext/couchbase/core/operations/management/search_index_get_documents_count.cxx +3 -2
- data/ext/couchbase/core/operations/management/search_index_get_stats.cxx +3 -1
- data/ext/couchbase/core/operations/management/search_index_upsert.cxx +2 -2
- data/ext/couchbase/core/operations/management/user_drop.cxx +3 -1
- data/ext/couchbase/core/operations/management/user_get.cxx +3 -1
- data/ext/couchbase/core/operations/management/user_upsert.cxx +12 -9
- data/ext/couchbase/core/operations/management/view_index_drop.cxx +1 -1
- data/ext/couchbase/core/operations/management/view_index_get.cxx +1 -1
- data/ext/couchbase/core/operations/management/view_index_upsert.cxx +1 -1
- data/ext/couchbase/core/operations/operation_traits.hxx +18 -0
- data/ext/couchbase/core/operations/query_response_parsing.cxx +211 -0
- data/ext/couchbase/core/operations/query_response_parsing.hxx +60 -0
- data/ext/couchbase/core/operations_fwd.hxx +3 -3
- data/ext/couchbase/core/origin.cxx +54 -26
- data/ext/couchbase/core/origin.hxx +12 -0
- data/ext/couchbase/core/orphan_reporter.cxx +2 -1
- data/ext/couchbase/core/platform/random.cc +7 -7
- data/ext/couchbase/core/protocol/client_request.cxx +2 -2
- data/ext/couchbase/core/protocol/client_request.hxx +38 -21
- data/ext/couchbase/core/protocol/client_response.cxx +11 -3
- data/ext/couchbase/core/protocol/client_response.hxx +27 -6
- data/ext/couchbase/core/protocol/cmd_append.cxx +2 -2
- data/ext/couchbase/core/protocol/cmd_cluster_map_change_notification.cxx +2 -2
- data/ext/couchbase/core/protocol/cmd_decrement.cxx +6 -6
- data/ext/couchbase/core/protocol/cmd_get.cxx +1 -1
- data/ext/couchbase/core/protocol/cmd_get_and_lock.cxx +2 -2
- data/ext/couchbase/core/protocol/cmd_get_and_touch.cxx +2 -2
- data/ext/couchbase/core/protocol/cmd_get_cluster_config.cxx +6 -4
- data/ext/couchbase/core/protocol/cmd_get_collection_id.cxx +2 -2
- data/ext/couchbase/core/protocol/cmd_get_error_map.cxx +1 -1
- data/ext/couchbase/core/protocol/cmd_get_meta.cxx +4 -4
- data/ext/couchbase/core/protocol/cmd_get_replica.cxx +1 -1
- data/ext/couchbase/core/protocol/cmd_hello.cxx +1 -1
- data/ext/couchbase/core/protocol/cmd_increment.cxx +6 -6
- data/ext/couchbase/core/protocol/cmd_insert.cxx +4 -4
- data/ext/couchbase/core/protocol/cmd_lookup_in.cxx +4 -3
- data/ext/couchbase/core/protocol/cmd_lookup_in_replica.cxx +4 -3
- data/ext/couchbase/core/protocol/cmd_mutate_in.cxx +10 -9
- data/ext/couchbase/core/protocol/cmd_mutate_in.hxx +10 -10
- data/ext/couchbase/core/protocol/cmd_observe_seqno.cxx +7 -7
- data/ext/couchbase/core/protocol/cmd_prepend.cxx +2 -2
- data/ext/couchbase/core/protocol/cmd_remove.cxx +2 -2
- data/ext/couchbase/core/protocol/cmd_replace.cxx +4 -4
- data/ext/couchbase/core/protocol/cmd_touch.cxx +1 -1
- data/ext/couchbase/core/protocol/cmd_upsert.cxx +4 -4
- data/ext/couchbase/core/protocol/datatype.hxx +118 -1
- data/ext/couchbase/core/protocol/frame_info_utils.cxx +1 -1
- data/ext/couchbase/core/protocol/magic.hxx +4 -0
- data/ext/couchbase/core/protocol/magic_fmt.hxx +3 -0
- data/ext/couchbase/core/protocol/server_request.hxx +3 -1
- data/ext/couchbase/core/protocol/status.cxx +1 -1
- data/ext/couchbase/core/protostellar/analytics_converter.hxx +171 -0
- data/ext/couchbase/core/protostellar/bucket_admin_converter.hxx +301 -0
- data/ext/couchbase/core/protostellar/collection_admin_converter.hxx +92 -0
- data/ext/couchbase/core/protostellar/component.cxx +2445 -0
- data/ext/couchbase/core/protostellar/component.hxx +391 -0
- data/ext/couchbase/core/{columnar/bootstrap_notification_subscriber.hxx → protostellar/compression_settings.hxx} +11 -10
- data/ext/couchbase/core/protostellar/credentials.cxx +233 -0
- data/ext/couchbase/core/protostellar/credentials.hxx +88 -0
- data/ext/couchbase/core/protostellar/dispatcher.cxx +57 -0
- data/ext/couchbase/core/protostellar/dispatcher.hxx +482 -0
- data/ext/couchbase/core/protostellar/error_utils.cxx +293 -0
- data/ext/couchbase/core/protostellar/error_utils.hxx +97 -0
- data/ext/couchbase/core/protostellar/json_payload.hxx +49 -0
- data/ext/couchbase/core/protostellar/kv_converter.cxx +70 -0
- data/ext/couchbase/core/protostellar/kv_converter.hxx +600 -0
- data/ext/couchbase/core/protostellar/query_converter.hxx +265 -0
- data/ext/couchbase/core/protostellar/query_index_admin_converter.hxx +291 -0
- data/ext/couchbase/core/protostellar/query_proto.hxx +73 -0
- data/ext/couchbase/core/protostellar/search_converter.hxx +244 -0
- data/ext/couchbase/core/protostellar/search_index_admin_converter.hxx +156 -0
- data/ext/couchbase/core/protostellar/view_converter.hxx +158 -0
- data/ext/couchbase/core/query_stream.cxx +447 -0
- data/ext/couchbase/core/query_stream.hxx +141 -0
- data/ext/couchbase/core/query_stream_component.cxx +243 -0
- data/ext/couchbase/core/query_stream_component.hxx +68 -0
- data/ext/couchbase/core/range_scan_load_balancer.cxx +15 -8
- data/ext/couchbase/core/range_scan_orchestrator.cxx +15 -3
- data/ext/couchbase/core/response_handler.hxx +41 -4
- data/ext/couchbase/core/row_streamer.cxx +332 -46
- data/ext/couchbase/core/row_streamer.hxx +31 -1
- data/ext/couchbase/core/row_streamer_options.hxx +55 -0
- data/ext/couchbase/core/sasl/client.h +3 -0
- data/ext/couchbase/core/search_scoring.hxx +66 -0
- data/ext/couchbase/core/stream_error_details.hxx +69 -0
- data/ext/couchbase/core/timeout_defaults.hxx +0 -1
- data/ext/couchbase/core/topology/capabilities.hxx +6 -0
- data/ext/couchbase/core/topology/capabilities_fmt.hxx +3 -0
- data/ext/couchbase/core/topology/configuration.cxx +21 -6
- data/ext/couchbase/core/topology/configuration.hxx +29 -8
- data/ext/couchbase/core/topology/configuration_json.hxx +3 -0
- data/ext/couchbase/core/topology/error_map_json.hxx +3 -1
- data/ext/couchbase/core/tracing/threshold_logging_tracer.cxx +70 -4
- data/ext/couchbase/core/tracing/threshold_logging_tracer.hxx +10 -0
- data/ext/couchbase/core/transactions/active_transaction_record.cxx +0 -34
- data/ext/couchbase/core/transactions/attempt_context_impl.cxx +108 -63
- data/ext/couchbase/core/transactions/attempt_context_impl.hxx +19 -2
- data/ext/couchbase/core/transactions/error_list.hxx +2 -2
- data/ext/couchbase/core/transactions/get_multi_fetch.hxx +160 -0
- data/ext/couchbase/core/transactions/get_multi_orchestrator.cxx +326 -125
- data/ext/couchbase/core/transactions/get_multi_transaction_id.hxx +62 -0
- data/ext/couchbase/core/transactions/internal/atr_entry.hxx +22 -2
- data/ext/couchbase/core/transactions/internal/transaction_context.hxx +2 -2
- data/ext/couchbase/core/transactions/internal/transactions_cleanup.hxx +23 -1
- data/ext/couchbase/core/transactions/internal/utils.hxx +50 -14
- data/ext/couchbase/core/transactions/staged_mutation.cxx +23 -18
- data/ext/couchbase/core/transactions/staged_mutation.hxx +15 -4
- data/ext/couchbase/core/transactions/transaction_context.cxx +55 -40
- data/ext/couchbase/core/transactions/transaction_get_result.hxx +16 -0
- data/ext/couchbase/core/transactions/transactions.cxx +3 -55
- data/ext/couchbase/core/transactions/transactions_cleanup.cxx +165 -72
- data/ext/couchbase/core/transactions/transactions_config.cxx +0 -11
- data/ext/couchbase/core/transactions/utils.cxx +10 -0
- data/ext/couchbase/core/transactions/waitable_op_list.hxx +2 -2
- data/ext/couchbase/core/transactions.hxx +9 -9
- data/ext/couchbase/core/utils/byteswap.hxx +166 -9
- data/ext/couchbase/core/utils/connection_string.cxx +50 -85
- data/ext/couchbase/core/utils/connection_string.hxx +15 -0
- data/ext/couchbase/core/{columnar/backoff_calculator.hxx → utils/deadline.hxx} +13 -13
- data/ext/couchbase/core/utils/duration_parser.cxx +1 -1
- data/ext/couchbase/core/utils/json_streaming_lexer.cxx +48 -5
- data/ext/couchbase/core/utils/json_streaming_lexer.hxx +4 -1
- data/ext/couchbase/core/utils/movable_function.hxx +301 -52
- data/ext/couchbase/core/utils/name_codec.hxx +154 -11
- data/ext/couchbase/core/{columnar/retry_info.hxx → utils/process_id.hxx} +18 -13
- data/ext/couchbase/core/utils/url_codec.cxx +12 -51
- data/ext/couchbase/core/websocket_codec.cxx +3 -29
- data/ext/couchbase/couchbase/analytics_options.hxx +21 -10
- data/ext/couchbase/couchbase/analytics_row.hxx +105 -0
- data/ext/couchbase/couchbase/analytics_stream_result.hxx +266 -0
- data/ext/couchbase/couchbase/boolean_query.hxx +3 -3
- data/ext/couchbase/couchbase/bucket.hxx +57 -0
- data/ext/couchbase/couchbase/cluster.hxx +183 -5
- data/ext/couchbase/{core/columnar/security_options.hxx → couchbase/cluster_state.hxx} +18 -14
- data/ext/couchbase/couchbase/codec/lenient_json_transcoder.hxx +69 -0
- data/ext/couchbase/couchbase/collection.hxx +234 -14
- data/ext/couchbase/couchbase/common_durability_options.hxx +18 -3
- data/ext/couchbase/couchbase/conjunction_query.hxx +1 -1
- data/ext/couchbase/couchbase/create_dataset_analytics_options.hxx +6 -1
- data/ext/couchbase/couchbase/date_range_query.hxx +2 -2
- data/ext/couchbase/couchbase/decrement_options.hxx +1 -1
- data/ext/couchbase/couchbase/disjunction_query.hxx +1 -1
- data/ext/couchbase/couchbase/error.hxx +32 -0
- data/ext/couchbase/couchbase/error_codes.hxx +32 -0
- data/ext/couchbase/couchbase/geo_bounding_box_query.hxx +1 -1
- data/ext/couchbase/couchbase/geo_distance_query.hxx +1 -1
- data/ext/couchbase/couchbase/geo_polygon_query.hxx +1 -1
- data/ext/couchbase/couchbase/get_replica_options.hxx +68 -0
- data/ext/couchbase/couchbase/get_replica_result.hxx +5 -3
- data/ext/couchbase/couchbase/get_replica_strategy.hxx +161 -0
- data/ext/couchbase/couchbase/get_result.hxx +1 -0
- data/ext/couchbase/couchbase/increment_options.hxx +1 -1
- data/ext/couchbase/couchbase/insert_options.hxx +1 -1
- data/ext/couchbase/couchbase/match_phrase_query.hxx +1 -1
- data/ext/couchbase/couchbase/match_query.hxx +1 -1
- data/ext/couchbase/couchbase/mutate_in_options.hxx +3 -3
- data/ext/couchbase/couchbase/network_options.hxx +1 -1
- data/ext/couchbase/couchbase/node_id.hxx +42 -14
- data/ext/couchbase/couchbase/node_id_for_options.hxx +7 -1
- data/ext/couchbase/couchbase/node_ids_options.hxx +8 -2
- data/ext/couchbase/couchbase/numeric_range_query.hxx +1 -1
- data/ext/couchbase/couchbase/phrase_query.hxx +1 -1
- data/ext/couchbase/couchbase/prefix_query.hxx +1 -1
- data/ext/couchbase/couchbase/query_options.hxx +23 -12
- data/ext/couchbase/couchbase/query_row.hxx +111 -0
- data/ext/couchbase/couchbase/query_stream_result.hxx +302 -0
- data/ext/couchbase/couchbase/query_string_query.hxx +3 -3
- data/ext/couchbase/couchbase/regexp_query.hxx +1 -1
- data/ext/couchbase/couchbase/replace_options.hxx +3 -3
- data/ext/couchbase/couchbase/result.hxx +14 -3
- data/ext/couchbase/couchbase/scan_result_item.hxx +1 -0
- data/ext/couchbase/couchbase/scope.hxx +85 -2
- data/ext/couchbase/couchbase/search_options.hxx +58 -8
- data/ext/couchbase/couchbase/search_scoring.hxx +94 -0
- data/ext/couchbase/couchbase/search_scoring_none.hxx +51 -0
- data/ext/couchbase/couchbase/search_scoring_reciprocal_rank_fusion.hxx +88 -0
- data/ext/couchbase/couchbase/search_scoring_relative_score_fusion.hxx +70 -0
- data/ext/couchbase/couchbase/term_range_query.hxx +1 -1
- data/ext/couchbase/couchbase/tracing/request_span.hxx +46 -0
- data/ext/couchbase/couchbase/transactions/transaction_get_multi_replicas_from_preferred_server_group_result.hxx +23 -21
- data/ext/couchbase/couchbase/transactions/transaction_get_multi_result.hxx +24 -19
- data/ext/couchbase/couchbase/transactions/transaction_get_result.hxx +17 -3
- data/ext/couchbase/couchbase/transactions/transactions_config.hxx +4 -2
- data/ext/couchbase/couchbase/transactions.hxx +27 -18
- data/ext/couchbase/couchbase/upsert_options.hxx +3 -3
- data/ext/couchbase/couchbase/vector_query.hxx +1 -1
- data/ext/couchbase/couchbase/wait_until_ready_options.hxx +111 -0
- data/ext/couchbase/couchbase/wildcard_query.hxx +1 -1
- data/ext/extconf.rb +15 -10
- data/ext/rcb_analytics.cxx +82 -102
- data/ext/rcb_backend.cxx +42 -36
- data/ext/rcb_backend.hxx +2 -0
- data/ext/rcb_buckets.cxx +47 -59
- data/ext/rcb_collections.cxx +42 -52
- data/ext/rcb_crud.cxx +345 -224
- data/ext/rcb_diagnostics.cxx +117 -27
- data/ext/rcb_exceptions.cxx +152 -99
- data/ext/rcb_exceptions.hxx +25 -0
- data/ext/rcb_extras.cxx +18 -19
- data/ext/rcb_hdr_histogram.cxx +19 -4
- data/ext/rcb_logger.cxx +202 -27
- data/ext/rcb_logger.hxx +12 -0
- data/ext/rcb_multi.cxx +40 -40
- data/ext/rcb_observability.cxx +7 -5
- data/ext/rcb_query.cxx +99 -142
- data/ext/rcb_range_scan.cxx +41 -35
- data/ext/rcb_search.cxx +98 -99
- data/ext/rcb_users.cxx +36 -56
- data/ext/rcb_utils.cxx +100 -37
- data/ext/rcb_utils.hxx +287 -33
- data/ext/rcb_version.cxx +1 -1
- data/ext/rcb_views.cxx +55 -51
- data/lib/active_support/cache/couchbase_store.rb +77 -12
- data/lib/couchbase/bucket.rb +20 -0
- data/lib/couchbase/cluster.rb +17 -0
- data/lib/couchbase/collection.rb +36 -1
- data/lib/couchbase/errors.rb +18 -0
- data/lib/couchbase/fork_hooks.rb +16 -7
- data/lib/couchbase/get_replica_strategy.rb +89 -0
- data/lib/couchbase/logger.rb +1 -1
- data/lib/couchbase/management/analytics_index_manager.rb +15 -15
- data/lib/couchbase/management/bucket_manager.rb +6 -6
- data/lib/couchbase/management/collection_manager.rb +6 -6
- data/lib/couchbase/management/query_index_manager.rb +7 -7
- data/lib/couchbase/management/search_index_manager.rb +13 -13
- data/lib/couchbase/management/user_manager.rb +10 -10
- data/lib/couchbase/management/view_index_manager.rb +5 -5
- data/lib/couchbase/options.rb +174 -42
- data/lib/couchbase/protostellar/bucket.rb +4 -0
- data/lib/couchbase/protostellar/cluster.rb +4 -0
- data/lib/couchbase/protostellar/collection.rb +4 -0
- data/lib/couchbase/protostellar/error_handling.rb +2 -1
- data/lib/couchbase/protostellar/request.rb +1 -0
- data/lib/couchbase/protostellar/request_generator/kv.rb +16 -2
- data/lib/couchbase/protostellar/request_generator/search.rb +17 -1
- data/lib/couchbase/protostellar/retry/orchestrator.rb +3 -2
- data/lib/couchbase/protostellar/retry/strategies/fail_fast.rb +33 -0
- data/lib/couchbase/protostellar/retry/strategies.rb +1 -0
- data/lib/couchbase/search_options.rb +95 -6
- data/lib/couchbase/version.rb +1 -1
- metadata +91 -33
- data/ext/0001-fix-build-for-mingw-w64-ucrt-x86_64-toolchain.patch +0 -40
- data/ext/couchbase/core/columnar/agent.hxx +0 -71
- data/ext/couchbase/core/columnar/agent_config.hxx +0 -59
- data/ext/couchbase/core/columnar/background_bootstrap_listener.hxx +0 -42
- data/ext/couchbase/core/columnar/backoff_calculator.cxx +0 -62
- data/ext/couchbase/core/columnar/columnar_agent.cxx +0 -147
- data/ext/couchbase/core/columnar/columnar_agent_config.cxx +0 -48
- data/ext/couchbase/core/columnar/columnar_error.cxx +0 -51
- data/ext/couchbase/core/columnar/database_management_options.hxx +0 -56
- data/ext/couchbase/core/columnar/error.hxx +0 -51
- data/ext/couchbase/core/columnar/error_codes.cxx +0 -107
- data/ext/couchbase/core/columnar/error_codes.hxx +0 -75
- data/ext/couchbase/core/columnar/management_component.cxx +0 -300
- data/ext/couchbase/core/columnar/management_component.hxx +0 -56
- data/ext/couchbase/core/columnar/query_component.cxx +0 -523
- data/ext/couchbase/core/columnar/query_component.hxx +0 -57
- data/ext/couchbase/core/columnar/query_options.hxx +0 -59
- data/ext/couchbase/core/columnar/query_result.cxx +0 -130
- data/ext/couchbase/core/columnar/query_result.hxx +0 -78
- data/ext/couchbase/core/io/config_tracker.cxx +0 -687
- data/ext/couchbase/core/io/config_tracker.hxx +0 -123
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
2
|
+
/*
|
|
3
|
+
* Copyright 2026-Present Couchbase, Inc.
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
#pragma once
|
|
19
|
+
|
|
20
|
+
#include "core/cluster.hxx"
|
|
21
|
+
#include "core/topology/configuration.hxx"
|
|
22
|
+
|
|
23
|
+
#include <couchbase/error.hxx>
|
|
24
|
+
#include <couchbase/error_codes.hxx>
|
|
25
|
+
|
|
26
|
+
#include <asio/error.hpp>
|
|
27
|
+
#include <asio/io_context.hpp>
|
|
28
|
+
#include <asio/post.hpp>
|
|
29
|
+
#include <asio/steady_timer.hpp>
|
|
30
|
+
|
|
31
|
+
#include <atomic>
|
|
32
|
+
#include <chrono>
|
|
33
|
+
#include <memory>
|
|
34
|
+
#include <string>
|
|
35
|
+
#include <system_error>
|
|
36
|
+
#include <utility>
|
|
37
|
+
|
|
38
|
+
namespace couchbase::core::impl
|
|
39
|
+
{
|
|
40
|
+
/**
|
|
41
|
+
* Async scaffold shared between @c collection_impl::node_id_for and
|
|
42
|
+
* @c collection_impl::node_ids — and any future client-side API that needs
|
|
43
|
+
* to wait for a bucket configuration with a hard timeout.
|
|
44
|
+
*
|
|
45
|
+
* The scaffold owns the atomic-done guard, the timer, and the asio::post
|
|
46
|
+
* back to the io_context. Callers supply a resolver that maps a topology
|
|
47
|
+
* snapshot to a (error_code, payload) pair; the user handler is invoked
|
|
48
|
+
* with (error, payload) exactly once — including on io_context shutdown,
|
|
49
|
+
* where a fail-closed destructor backstop completes the handler with
|
|
50
|
+
* @c errc::network::cluster_closed rather than leaking a dropped completion
|
|
51
|
+
* (which would surface as a broken_promise to a std::future caller or a
|
|
52
|
+
* permanent hang to a callback caller).
|
|
53
|
+
*
|
|
54
|
+
* Thread-safety: the SDK's core io_context is single-threaded for KV work
|
|
55
|
+
* in the current release. The timer and atomic-done dance are safe under
|
|
56
|
+
* that assumption. If the io_context is ever multi-threaded, both
|
|
57
|
+
* @c timer.cancel() and the handler dispatch must be wrapped in a strand
|
|
58
|
+
* because @c asio::steady_timer is not thread-safe.
|
|
59
|
+
*
|
|
60
|
+
* @tparam Payload The success-path payload type (e.g. @c node_id or
|
|
61
|
+
* @c std::vector<node_id>). Must be default-
|
|
62
|
+
* constructible (used for the timeout / error branches)
|
|
63
|
+
* and move-constructible.
|
|
64
|
+
* @tparam Handler Callable accepting @c (couchbase::error, Payload).
|
|
65
|
+
* @tparam Resolver Callable accepting
|
|
66
|
+
* @c const std::shared_ptr<topology::configuration>&
|
|
67
|
+
* and returning @c std::pair<std::error_code, Payload>.
|
|
68
|
+
* Invoked at most once, on the config-callback path
|
|
69
|
+
* when @c ec is falsy.
|
|
70
|
+
*/
|
|
71
|
+
template<typename Payload, typename Handler, typename Resolver>
|
|
72
|
+
void
|
|
73
|
+
with_bucket_config_or_timeout(const couchbase::core::cluster& core,
|
|
74
|
+
const std::string& bucket_name,
|
|
75
|
+
std::chrono::milliseconds timeout,
|
|
76
|
+
Handler handler,
|
|
77
|
+
Resolver resolver)
|
|
78
|
+
{
|
|
79
|
+
struct state {
|
|
80
|
+
std::atomic<bool> done{ false };
|
|
81
|
+
std::atomic<bool> delivered{ false };
|
|
82
|
+
asio::steady_timer timer;
|
|
83
|
+
Handler handler;
|
|
84
|
+
|
|
85
|
+
state(asio::io_context& ioc, Handler&& h)
|
|
86
|
+
: timer{ ioc }
|
|
87
|
+
, handler{ std::move(h) }
|
|
88
|
+
{
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Invoke the user handler at most once. The `done` flag arbitrates the
|
|
92
|
+
// timer-vs-config race; `delivered` guards the handler call itself so the
|
|
93
|
+
// destructor can fail closed (below) without ever risking a double call.
|
|
94
|
+
void deliver(couchbase::error err, Payload payload)
|
|
95
|
+
{
|
|
96
|
+
if (!delivered.exchange(true, std::memory_order_acq_rel)) {
|
|
97
|
+
handler(std::move(err), std::move(payload));
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Fail-closed backstop. If every async continuation is torn down without
|
|
102
|
+
// the handler having run — io_context stopped on shutdown drops both the
|
|
103
|
+
// pending timer wait and any deferred asio::post — complete here so a
|
|
104
|
+
// std::future caller never observes broken_promise and a callback caller
|
|
105
|
+
// never hangs. By the time the destructor runs the last shared_ptr
|
|
106
|
+
// reference is gone, so no other thread can be in deliver() concurrently.
|
|
107
|
+
// The handler is user code; a destructor must not let an exception escape.
|
|
108
|
+
~state()
|
|
109
|
+
{
|
|
110
|
+
try {
|
|
111
|
+
deliver(couchbase::error{ errc::network::cluster_closed }, Payload{});
|
|
112
|
+
} catch (...) { // NOLINT(bugprone-empty-catch)
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
auto shared = std::make_shared<state>(core.io_context(), std::move(handler));
|
|
118
|
+
// Capture the io_context by pointer value (not by reference to a local
|
|
119
|
+
// reference variable): core and its io_context outlive this operation, so
|
|
120
|
+
// the pointer stays valid even though the bucket-config callback may run
|
|
121
|
+
// after this function has returned.
|
|
122
|
+
auto* io_context = &core.io_context();
|
|
123
|
+
|
|
124
|
+
shared->timer.expires_after(timeout);
|
|
125
|
+
shared->timer.async_wait([shared](std::error_code timer_ec) -> void {
|
|
126
|
+
if (timer_ec == asio::error::operation_aborted) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
// acq_rel matches the other writer (config callback): the only thing
|
|
130
|
+
// we synchronise on is whether we won the race to fire the handler.
|
|
131
|
+
if (shared->done.exchange(true, std::memory_order_acq_rel)) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
shared->deliver(couchbase::error{ errc::common::unambiguous_timeout }, Payload{});
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
core.with_bucket_configuration(
|
|
138
|
+
bucket_name,
|
|
139
|
+
// Capture a weak_ptr, not a strong one. with_bucket_configuration() queues
|
|
140
|
+
// this callback in the bucket's deferred-commands list until a config
|
|
141
|
+
// arrives; if the timeout fires first and a config never arrives, a strong
|
|
142
|
+
// capture would pin the user handler, promise and timer in that queue
|
|
143
|
+
// indefinitely. The pending timer owns the state while we wait, so a config
|
|
144
|
+
// that arrives before the timeout still locks successfully; once the
|
|
145
|
+
// timeout has fired the state is released and this callback is a no-op.
|
|
146
|
+
[weak = std::weak_ptr<state>(shared), io_context, resolver = std::move(resolver)](
|
|
147
|
+
std::error_code ec,
|
|
148
|
+
const std::shared_ptr<core::topology::configuration>& config) mutable -> void {
|
|
149
|
+
auto shared = weak.lock();
|
|
150
|
+
if (!shared || shared->done.exchange(true, std::memory_order_acq_rel)) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
std::error_code result_ec = ec;
|
|
155
|
+
Payload payload{};
|
|
156
|
+
if (!ec) {
|
|
157
|
+
std::tie(result_ec, payload) = resolver(config);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Hop back onto the io_context before touching the timer or invoking
|
|
161
|
+
// the user handler. with_bucket_configuration() invokes its callback
|
|
162
|
+
// synchronously on the caller's thread when the bucket configuration
|
|
163
|
+
// is already cached (see bucket.cxx). Two things must therefore not
|
|
164
|
+
// happen inline here:
|
|
165
|
+
// 1. timer.cancel() — asio::steady_timer is not thread-safe and is
|
|
166
|
+
// bound to core.io_context(); cancelling it from an arbitrary
|
|
167
|
+
// application thread races with the io_context processing the
|
|
168
|
+
// pending async_wait. It must run on the timer's executor.
|
|
169
|
+
// 2. the user handler — it reasonably expects an async hop and may
|
|
170
|
+
// itself re-enter the SDK.
|
|
171
|
+
// The done flag above is atomic, so the race is already decided; the
|
|
172
|
+
// deferred cancel() is a harmless no-op if the timer has since fired
|
|
173
|
+
// (its handler short-circuits on operation_aborted / done).
|
|
174
|
+
asio::post(*io_context, [shared, result_ec, payload = std::move(payload)]() mutable {
|
|
175
|
+
shared->timer.cancel();
|
|
176
|
+
shared->deliver(couchbase::error{ result_ec }, std::move(payload));
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
} // namespace couchbase::core::impl
|
|
@@ -17,9 +17,9 @@
|
|
|
17
17
|
|
|
18
18
|
#pragma once
|
|
19
19
|
|
|
20
|
-
#include "core/impl/get_replica.hxx"
|
|
21
20
|
#include "core/impl/lookup_in_replica.hxx"
|
|
22
21
|
#include "core/operations/document_get.hxx"
|
|
22
|
+
#include "core/operations/document_get_replica.hxx"
|
|
23
23
|
#include "core/operations/document_lookup_in.hxx"
|
|
24
24
|
#include "core/operations/operation_traits.hxx"
|
|
25
25
|
#include "core/utils/movable_function.hxx"
|
|
@@ -35,7 +35,7 @@ class cancellation_token
|
|
|
35
35
|
public:
|
|
36
36
|
void setup(utils::movable_function<void()> cancel_fn)
|
|
37
37
|
{
|
|
38
|
-
const std::
|
|
38
|
+
const std::scoped_lock lock(mutex_);
|
|
39
39
|
if (cancelled_) {
|
|
40
40
|
cancel_fn();
|
|
41
41
|
return;
|
|
@@ -47,7 +47,7 @@ public:
|
|
|
47
47
|
{
|
|
48
48
|
utils::movable_function<void()> fn{};
|
|
49
49
|
{
|
|
50
|
-
const std::
|
|
50
|
+
const std::scoped_lock lock(mutex_);
|
|
51
51
|
cancelled_ = true;
|
|
52
52
|
fn = std::move(cancel_fn_);
|
|
53
53
|
}
|
|
@@ -72,4 +72,12 @@ template<typename kv_operation>
|
|
|
72
72
|
struct operations::is_cancellable_operation<impl::with_cancellation<kv_operation>>
|
|
73
73
|
: public std::true_type {
|
|
74
74
|
};
|
|
75
|
+
|
|
76
|
+
// Wrapping must not change how a request is routed: the wrapper inherits the
|
|
77
|
+
// operation, so a trait left behind here would silently drop the wrapped
|
|
78
|
+
// request back onto plain vbucket-map routing.
|
|
79
|
+
template<typename kv_operation>
|
|
80
|
+
struct operations::resolves_own_route<impl::with_cancellation<kv_operation>>
|
|
81
|
+
: public operations::resolves_own_route<kv_operation> {
|
|
82
|
+
};
|
|
75
83
|
} // namespace couchbase::core
|
|
@@ -60,8 +60,7 @@ configuration_belongs_to_session(const std::optional<std::string>& config_bucket
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
// Stage 3 — both sides name a bucket: accept only if it is the *same* bucket.
|
|
63
|
-
// Reaching here guarantees both optionals are engaged, so value() is safe.
|
|
64
63
|
// Guards against applying another bucket's map to this session.
|
|
65
|
-
return config_bucket
|
|
64
|
+
return config_bucket == session_bucket;
|
|
66
65
|
}
|
|
67
66
|
} // namespace couchbase::core::io
|
|
@@ -17,8 +17,11 @@
|
|
|
17
17
|
|
|
18
18
|
#include "dns_client.hxx"
|
|
19
19
|
|
|
20
|
+
#include "core/io/streams.hxx"
|
|
20
21
|
#include "core/logger/logger.hxx"
|
|
22
|
+
#include "core/logger/redaction.hxx"
|
|
21
23
|
#include "core/utils/join_strings.hxx"
|
|
24
|
+
#include "core/utils/process_id.hxx"
|
|
22
25
|
#include "dns_codec.hxx"
|
|
23
26
|
#include "dns_config.hxx"
|
|
24
27
|
|
|
@@ -37,6 +40,29 @@
|
|
|
37
40
|
|
|
38
41
|
namespace couchbase::core::io::dns
|
|
39
42
|
{
|
|
43
|
+
namespace
|
|
44
|
+
{
|
|
45
|
+
auto
|
|
46
|
+
rcode_description(response_code rcode) -> const char*
|
|
47
|
+
{
|
|
48
|
+
switch (rcode) {
|
|
49
|
+
case response_code::no_error:
|
|
50
|
+
return "NOERROR";
|
|
51
|
+
case response_code::format_error:
|
|
52
|
+
return "FORMERR (server could not interpret the query)";
|
|
53
|
+
case response_code::server_failure:
|
|
54
|
+
return "SERVFAIL (server failure — DNS resolver may not support SRV queries)";
|
|
55
|
+
case response_code::name_error:
|
|
56
|
+
return "NXDOMAIN (name does not exist — no SRV record registered for this hostname)";
|
|
57
|
+
case response_code::not_implemented:
|
|
58
|
+
return "NOTIMP (query type not implemented by the server)";
|
|
59
|
+
case response_code::refused:
|
|
60
|
+
return "REFUSED (server refused the query — policy restriction)";
|
|
61
|
+
}
|
|
62
|
+
return "UNKNOWN";
|
|
63
|
+
}
|
|
64
|
+
} // namespace
|
|
65
|
+
|
|
40
66
|
class dns_srv_command : public std::enable_shared_from_this<dns_srv_command>
|
|
41
67
|
{
|
|
42
68
|
public:
|
|
@@ -47,7 +73,8 @@ public:
|
|
|
47
73
|
asio::ip::address address,
|
|
48
74
|
std::uint16_t port,
|
|
49
75
|
utils::movable_function<void(couchbase::core::io::dns::dns_srv_response&& resp)> handler)
|
|
50
|
-
:
|
|
76
|
+
: ctx_(ctx)
|
|
77
|
+
, deadline_(ctx)
|
|
51
78
|
, udp_deadline_(ctx)
|
|
52
79
|
, udp_(ctx)
|
|
53
80
|
, tcp_(ctx)
|
|
@@ -73,13 +100,19 @@ public:
|
|
|
73
100
|
|
|
74
101
|
void execute(std::chrono::milliseconds total_timeout, std::chrono::milliseconds udp_timeout)
|
|
75
102
|
{
|
|
76
|
-
CB_LOG_TRACE("Query DNS-SRV (UDP) address=\"{}
|
|
77
|
-
|
|
78
|
-
port_,
|
|
103
|
+
CB_LOG_TRACE("Query DNS-SRV (UDP) address=\"{}\", udp_timeout={}, total_timeout={}",
|
|
104
|
+
logger::system_data(nameserver_address()),
|
|
79
105
|
udp_timeout,
|
|
80
106
|
total_timeout);
|
|
81
107
|
const asio::ip::udp::endpoint endpoint(address_, port_);
|
|
82
108
|
udp_.open(endpoint.protocol());
|
|
109
|
+
// A process forked while this lookup is pending inherits both sockets. Registering them lets
|
|
110
|
+
// the forked process's fixup release them, so it cannot read the response this process is
|
|
111
|
+
// waiting for.
|
|
112
|
+
register_inherited_socket(ctx_,
|
|
113
|
+
std::shared_ptr<asio::ip::udp::socket>(shared_from_this(), &udp_));
|
|
114
|
+
register_inherited_socket(ctx_,
|
|
115
|
+
std::shared_ptr<asio::ip::tcp::socket>(shared_from_this(), &tcp_));
|
|
83
116
|
CB_LOG_PROTOCOL("[DNS, UDP, OUT] host=\"{}\", port={}, buffer_size={}{:a}",
|
|
84
117
|
address_.to_string(),
|
|
85
118
|
port_,
|
|
@@ -100,9 +133,8 @@ public:
|
|
|
100
133
|
return;
|
|
101
134
|
}
|
|
102
135
|
CB_LOG_DEBUG(
|
|
103
|
-
"DNS UDP write operation has got error, retrying with TCP, address=\"{}
|
|
104
|
-
self->
|
|
105
|
-
self->port_,
|
|
136
|
+
"DNS UDP write operation has got error, retrying with TCP, address=\"{}\", ec={}",
|
|
137
|
+
logger::system_data(self->nameserver_address()),
|
|
106
138
|
ec1.message());
|
|
107
139
|
return self->retry_with_tcp();
|
|
108
140
|
}
|
|
@@ -126,20 +158,26 @@ public:
|
|
|
126
158
|
return;
|
|
127
159
|
}
|
|
128
160
|
CB_LOG_DEBUG(
|
|
129
|
-
"DNS UDP read operation has got error, retrying with TCP, address=\"{}
|
|
130
|
-
self->
|
|
131
|
-
self->port_,
|
|
161
|
+
"DNS UDP read operation has got error, retrying with TCP, address=\"{}\", ec={}",
|
|
162
|
+
logger::system_data(self->nameserver_address()),
|
|
132
163
|
ec2.message());
|
|
133
164
|
return self->retry_with_tcp();
|
|
134
165
|
}
|
|
135
166
|
self->recv_buf_.resize(bytes_transferred);
|
|
136
167
|
const dns_message message = dns_codec::decode(self->recv_buf_);
|
|
137
168
|
if (message.header.flags.tc == truncation::yes) {
|
|
138
|
-
|
|
169
|
+
std::error_code ignored{};
|
|
170
|
+
self->udp_.close(ignored);
|
|
139
171
|
CB_LOG_DEBUG("DNS UDP read operation returned truncated response, retrying with TCP");
|
|
140
172
|
return self->retry_with_tcp();
|
|
141
173
|
}
|
|
142
174
|
self->deadline_.cancel();
|
|
175
|
+
if (message.header.flags.rcode != response_code::no_error) {
|
|
176
|
+
CB_LOG_WARNING("DNS UDP response for \"{}\" returned non-zero RCODE: {} ({})",
|
|
177
|
+
logger::system_data(self->nameserver_address()),
|
|
178
|
+
static_cast<int>(message.header.flags.rcode),
|
|
179
|
+
rcode_description(message.header.flags.rcode));
|
|
180
|
+
}
|
|
143
181
|
dns_srv_response resp{ ec2 };
|
|
144
182
|
resp.targets.reserve(message.answers.size());
|
|
145
183
|
for (const auto& answer : message.answers) {
|
|
@@ -147,7 +185,7 @@ public:
|
|
|
147
185
|
utils::join_strings(answer.target.labels, "."), answer.port });
|
|
148
186
|
}
|
|
149
187
|
CB_LOG_DEBUG("DNS UDP returned {} records", resp.targets.size());
|
|
150
|
-
return self->
|
|
188
|
+
return self->complete(std::move(resp));
|
|
151
189
|
});
|
|
152
190
|
});
|
|
153
191
|
udp_deadline_.expires_after(udp_timeout);
|
|
@@ -155,11 +193,11 @@ public:
|
|
|
155
193
|
if (ec == asio::error::operation_aborted) {
|
|
156
194
|
return;
|
|
157
195
|
}
|
|
158
|
-
|
|
196
|
+
std::error_code ignored{};
|
|
197
|
+
self->udp_.cancel(ignored);
|
|
159
198
|
CB_LOG_DEBUG("DNS UDP deadline has been reached, cancelling UDP operation and fall back to "
|
|
160
|
-
"TCP, address=\"{}
|
|
161
|
-
self->
|
|
162
|
-
self->port_);
|
|
199
|
+
"TCP, address=\"{}\"",
|
|
200
|
+
logger::system_data(self->nameserver_address()));
|
|
163
201
|
return self->retry_with_tcp();
|
|
164
202
|
});
|
|
165
203
|
|
|
@@ -169,29 +207,52 @@ public:
|
|
|
169
207
|
return;
|
|
170
208
|
}
|
|
171
209
|
CB_LOG_DEBUG("DNS deadline has been reached, cancelling in-flight operations "
|
|
172
|
-
"(tcp.is_open={}, address=\"{}
|
|
210
|
+
"(tcp.is_open={}, address=\"{}\")",
|
|
173
211
|
self->tcp_.is_open(),
|
|
174
|
-
self->
|
|
175
|
-
|
|
176
|
-
self->udp_.cancel();
|
|
212
|
+
logger::system_data(self->nameserver_address()));
|
|
213
|
+
std::error_code ignored{};
|
|
214
|
+
self->udp_.cancel(ignored);
|
|
177
215
|
if (self->tcp_.is_open()) {
|
|
178
|
-
self->tcp_.cancel();
|
|
216
|
+
self->tcp_.cancel(ignored);
|
|
179
217
|
}
|
|
180
|
-
return self->
|
|
218
|
+
return self->complete({ errc::common::unambiguous_timeout });
|
|
181
219
|
});
|
|
182
220
|
}
|
|
183
221
|
|
|
184
222
|
private:
|
|
223
|
+
// A lookup that a forked process inherited belongs to the process that started it. The child
|
|
224
|
+
// fixup releases its sockets, which fails their pending operations; neither those failures nor
|
|
225
|
+
// its timers may retry or complete the lookup in that process.
|
|
226
|
+
[[nodiscard]] auto inherited() const -> bool
|
|
227
|
+
{
|
|
228
|
+
return owner_pid_ != utils::current_process_id();
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
void complete(dns_srv_response&& resp)
|
|
232
|
+
{
|
|
233
|
+
if (inherited()) {
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
handler_(std::move(resp));
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
[[nodiscard]] auto nameserver_address() const -> std::string
|
|
240
|
+
{
|
|
241
|
+
return fmt::format("{}:{}", address_.to_string(), port_);
|
|
242
|
+
}
|
|
243
|
+
|
|
185
244
|
void retry_with_tcp()
|
|
186
245
|
{
|
|
246
|
+
if (inherited()) {
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
187
249
|
if (bool expected_state{ false };
|
|
188
250
|
!retrying_with_tcp_.compare_exchange_strong(expected_state, true)) {
|
|
189
251
|
return;
|
|
190
252
|
}
|
|
191
253
|
|
|
192
|
-
CB_LOG_TRACE("Query DNS-SRV (TCP) address=\"{}
|
|
193
|
-
|
|
194
|
-
port_,
|
|
254
|
+
CB_LOG_TRACE("Query DNS-SRV (TCP) address=\"{}\", time_left={}",
|
|
255
|
+
logger::system_data(nameserver_address()),
|
|
195
256
|
std::chrono::duration_cast<std::chrono::milliseconds>(
|
|
196
257
|
deadline_.expiry() - std::chrono::steady_clock::now()));
|
|
197
258
|
|
|
@@ -205,11 +266,10 @@ private:
|
|
|
205
266
|
return;
|
|
206
267
|
}
|
|
207
268
|
self->deadline_.cancel();
|
|
208
|
-
CB_LOG_DEBUG("DNS TCP connection has been aborted, address=\"{}
|
|
209
|
-
self->
|
|
210
|
-
self->port_,
|
|
269
|
+
CB_LOG_DEBUG("DNS TCP connection has been aborted, address=\"{}\", ec={}",
|
|
270
|
+
logger::system_data(self->nameserver_address()),
|
|
211
271
|
ec1.message());
|
|
212
|
-
return self->
|
|
272
|
+
return self->complete({ ec1 });
|
|
213
273
|
}
|
|
214
274
|
auto send_size = static_cast<std::uint16_t>(self->send_buf_.size());
|
|
215
275
|
self->send_buf_.insert(self->send_buf_.begin(), static_cast<std::uint8_t>(send_size & 0xffU));
|
|
@@ -232,12 +292,11 @@ private:
|
|
|
232
292
|
if (ec2 == asio::error::operation_aborted) {
|
|
233
293
|
return;
|
|
234
294
|
}
|
|
235
|
-
CB_LOG_DEBUG("DNS TCP write operation has been aborted, address=\"{}
|
|
236
|
-
self->
|
|
237
|
-
self->port_,
|
|
295
|
+
CB_LOG_DEBUG("DNS TCP write operation has been aborted, address=\"{}\", ec={}",
|
|
296
|
+
logger::system_data(self->nameserver_address()),
|
|
238
297
|
ec2.message());
|
|
239
298
|
self->deadline_.cancel();
|
|
240
|
-
return self->
|
|
299
|
+
return self->complete({ ec2 });
|
|
241
300
|
}
|
|
242
301
|
asio::async_read(
|
|
243
302
|
self->tcp_,
|
|
@@ -257,14 +316,13 @@ private:
|
|
|
257
316
|
return;
|
|
258
317
|
}
|
|
259
318
|
CB_LOG_DEBUG(
|
|
260
|
-
"DNS TCP buf size read operation has been aborted, address=\"{}
|
|
261
|
-
self->
|
|
262
|
-
self->port_,
|
|
319
|
+
"DNS TCP buf size read operation has been aborted, address=\"{}\", ec={}",
|
|
320
|
+
logger::system_data(self->nameserver_address()),
|
|
263
321
|
ec3.message());
|
|
264
322
|
self->deadline_.cancel();
|
|
265
|
-
return self->
|
|
323
|
+
return self->complete({ ec3 });
|
|
266
324
|
}
|
|
267
|
-
self->recv_buf_size_ = utils::
|
|
325
|
+
self->recv_buf_size_ = utils::network_to_host(self->recv_buf_size_);
|
|
268
326
|
self->recv_buf_.resize(self->recv_buf_size_);
|
|
269
327
|
CB_LOG_DEBUG("DNS TCP schedule read of {} bytes", self->recv_buf_size_);
|
|
270
328
|
asio::async_read(
|
|
@@ -285,15 +343,19 @@ private:
|
|
|
285
343
|
}
|
|
286
344
|
self->deadline_.cancel();
|
|
287
345
|
if (ec4) {
|
|
288
|
-
CB_LOG_DEBUG(
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
ec4.message());
|
|
293
|
-
return self->handler_({ ec4 });
|
|
346
|
+
CB_LOG_DEBUG("DNS TCP read operation has been aborted, address=\"{}\", ec={}",
|
|
347
|
+
logger::system_data(self->nameserver_address()),
|
|
348
|
+
ec4.message());
|
|
349
|
+
return self->complete({ ec4 });
|
|
294
350
|
}
|
|
295
351
|
self->recv_buf_.resize(bytes_transferred4);
|
|
296
352
|
const dns_message message = dns_codec::decode(self->recv_buf_);
|
|
353
|
+
if (message.header.flags.rcode != response_code::no_error) {
|
|
354
|
+
CB_LOG_WARNING("DNS TCP response for \"{}\" returned non-zero RCODE: {} ({})",
|
|
355
|
+
logger::system_data(self->nameserver_address()),
|
|
356
|
+
static_cast<int>(message.header.flags.rcode),
|
|
357
|
+
rcode_description(message.header.flags.rcode));
|
|
358
|
+
}
|
|
297
359
|
dns_srv_response resp{ ec4 };
|
|
298
360
|
resp.targets.reserve(message.answers.size());
|
|
299
361
|
for (const auto& answer : message.answers) {
|
|
@@ -301,13 +363,14 @@ private:
|
|
|
301
363
|
utils::join_strings(answer.target.labels, "."), answer.port });
|
|
302
364
|
}
|
|
303
365
|
CB_LOG_DEBUG("DNS TCP returned {} records", resp.targets.size());
|
|
304
|
-
return self->
|
|
366
|
+
return self->complete(std::move(resp));
|
|
305
367
|
});
|
|
306
368
|
});
|
|
307
369
|
});
|
|
308
370
|
});
|
|
309
371
|
}
|
|
310
372
|
|
|
373
|
+
asio::io_context& ctx_;
|
|
311
374
|
asio::steady_timer deadline_;
|
|
312
375
|
asio::steady_timer udp_deadline_;
|
|
313
376
|
asio::ip::udp::socket udp_;
|
|
@@ -323,6 +386,7 @@ private:
|
|
|
323
386
|
std::vector<std::uint8_t> recv_buf_{};
|
|
324
387
|
|
|
325
388
|
std::atomic_bool retrying_with_tcp_{ false };
|
|
389
|
+
std::int64_t owner_pid_{ utils::current_process_id() };
|
|
326
390
|
};
|
|
327
391
|
|
|
328
392
|
void
|
|
@@ -332,12 +396,25 @@ dns_client::query_srv(const std::string& name,
|
|
|
332
396
|
utils::movable_function<void(dns_srv_response&&)>&& handler)
|
|
333
397
|
{
|
|
334
398
|
if (config.nameserver().empty()) {
|
|
399
|
+
CB_LOG_WARNING(
|
|
400
|
+
"DNS-SRV query for \"{}/{}\" skipped: no nameserver configured (DNS-SRV bootstrap is "
|
|
401
|
+
"disabled). Check that /etc/resolv.conf contains a valid IP address on a \"nameserver\" "
|
|
402
|
+
"line, or set the nameserver explicitly in the cluster options.",
|
|
403
|
+
logger::system_data(name),
|
|
404
|
+
service);
|
|
335
405
|
return handler({ {} });
|
|
336
406
|
}
|
|
337
407
|
|
|
338
408
|
std::error_code ec;
|
|
339
409
|
auto address = asio::ip::make_address(config.nameserver(), ec);
|
|
340
410
|
if (ec) {
|
|
411
|
+
CB_LOG_WARNING(
|
|
412
|
+
"DNS-SRV query for \"{}/{}\" skipped: configured nameserver \"{}\" could not be parsed as "
|
|
413
|
+
"an IP address ({}). Only numeric IP addresses are supported as nameserver values.",
|
|
414
|
+
logger::system_data(name),
|
|
415
|
+
service,
|
|
416
|
+
logger::system_data(config.nameserver()),
|
|
417
|
+
ec.message());
|
|
341
418
|
return handler({ ec });
|
|
342
419
|
}
|
|
343
420
|
auto cmd = std::make_shared<dns_srv_command>(
|