[call-v3] New client channel implementation (#36723)
Closes #36723
COPYBARA_INTEGRATE_REVIEW=https://github.com/grpc/grpc/pull/36723 from ctiller:transport-refs-7 e019b8f5ea
PiperOrigin-RevId: 638424601
This commit is contained in:
parent
ecee02a226
commit
34871fafa3
45
BUILD
45
BUILD
|
|
@ -1797,16 +1797,17 @@ grpc_cc_library(
|
|||
"gpr",
|
||||
"grpc_public_hdrs",
|
||||
"grpc_trace",
|
||||
"orphanable",
|
||||
"ref_counted_ptr",
|
||||
"stats",
|
||||
"//src/core:arena",
|
||||
"//src/core:call_arena_allocator",
|
||||
"//src/core:channel_args",
|
||||
"//src/core:channel_stack_type",
|
||||
"//src/core:compression",
|
||||
"//src/core:connectivity_state",
|
||||
"//src/core:iomgr_fwd",
|
||||
"//src/core:ref_counted",
|
||||
"//src/core:resource_quota",
|
||||
"//src/core:slice",
|
||||
"//src/core:stats_data",
|
||||
"//src/core:time",
|
||||
|
|
@ -1885,6 +1886,7 @@ grpc_cc_library(
|
|||
"config",
|
||||
"gpr",
|
||||
"grpc_base",
|
||||
"grpc_client_channel",
|
||||
"grpc_public_hdrs",
|
||||
"legacy_channel",
|
||||
"ref_counted_ptr",
|
||||
|
|
@ -1892,6 +1894,7 @@ grpc_cc_library(
|
|||
"//src/core:arena",
|
||||
"//src/core:channel_args",
|
||||
"//src/core:channel_stack_type",
|
||||
"//src/core:experiments",
|
||||
"//src/core:iomgr_fwd",
|
||||
"//src/core:ref_counted",
|
||||
"//src/core:slice",
|
||||
|
|
@ -3698,11 +3701,13 @@ grpc_cc_library(
|
|||
grpc_cc_library(
|
||||
name = "grpc_client_channel",
|
||||
srcs = [
|
||||
"//src/core:client_channel/client_channel.cc",
|
||||
"//src/core:client_channel/client_channel_factory.cc",
|
||||
"//src/core:client_channel/client_channel_filter.cc",
|
||||
"//src/core:client_channel/client_channel_plugin.cc",
|
||||
"//src/core:client_channel/dynamic_filters.cc",
|
||||
"//src/core:client_channel/global_subchannel_pool.cc",
|
||||
"//src/core:client_channel/load_balanced_call_destination.cc",
|
||||
"//src/core:client_channel/local_subchannel_pool.cc",
|
||||
"//src/core:client_channel/retry_filter.cc",
|
||||
"//src/core:client_channel/retry_filter_legacy_call_data.cc",
|
||||
|
|
@ -3710,10 +3715,12 @@ grpc_cc_library(
|
|||
"//src/core:client_channel/subchannel_stream_client.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"//src/core:client_channel/client_channel.h",
|
||||
"//src/core:client_channel/client_channel_factory.h",
|
||||
"//src/core:client_channel/client_channel_filter.h",
|
||||
"//src/core:client_channel/dynamic_filters.h",
|
||||
"//src/core:client_channel/global_subchannel_pool.h",
|
||||
"//src/core:client_channel/load_balanced_call_destination.h",
|
||||
"//src/core:client_channel/local_subchannel_pool.h",
|
||||
"//src/core:client_channel/retry_filter.h",
|
||||
"//src/core:client_channel/retry_filter_legacy_call_data.h",
|
||||
|
|
@ -3735,21 +3742,17 @@ grpc_cc_library(
|
|||
"absl/strings:cord",
|
||||
"absl/types:optional",
|
||||
"absl/types:variant",
|
||||
"@com_google_protobuf//upb:base",
|
||||
"@com_google_protobuf//upb:mem",
|
||||
"@com_google_protobuf//upb:message",
|
||||
],
|
||||
language = "c++",
|
||||
visibility = ["@grpc:client_channel"],
|
||||
deps = [
|
||||
"api_trace",
|
||||
"backoff",
|
||||
"call_combiner",
|
||||
"call_tracer",
|
||||
"channel",
|
||||
"channel_arg_names",
|
||||
"channelz",
|
||||
"config",
|
||||
"config_vars",
|
||||
"debug_location",
|
||||
"endpoint_addresses",
|
||||
"exec_ctx",
|
||||
|
|
@ -3760,26 +3763,23 @@ grpc_cc_library(
|
|||
"grpc_security_base",
|
||||
"grpc_service_config_impl",
|
||||
"grpc_trace",
|
||||
"http_connect_handshaker",
|
||||
"iomgr",
|
||||
"iomgr_timer",
|
||||
"lb_child_policy_handler",
|
||||
"legacy_context",
|
||||
"orphanable",
|
||||
"parse_address",
|
||||
"promise",
|
||||
"protobuf_duration_upb",
|
||||
"ref_counted_ptr",
|
||||
"sockaddr_utils",
|
||||
"stats",
|
||||
"uri_parser",
|
||||
"work_serializer",
|
||||
"xds_orca_service_upb",
|
||||
"xds_orca_upb",
|
||||
"//src/core:activity",
|
||||
"//src/core:arena",
|
||||
"//src/core:arena_promise",
|
||||
"//src/core:backend_metric_parser",
|
||||
"//src/core:call_destination",
|
||||
"//src/core:call_filters",
|
||||
"//src/core:call_spine",
|
||||
"//src/core:cancel_callback",
|
||||
"//src/core:channel_args",
|
||||
"//src/core:channel_fwd",
|
||||
|
|
@ -3793,33 +3793,33 @@ grpc_cc_library(
|
|||
"//src/core:connectivity_state",
|
||||
"//src/core:construct_destruct",
|
||||
"//src/core:context",
|
||||
"//src/core:delegating_helper",
|
||||
"//src/core:dual_ref_counted",
|
||||
"//src/core:env",
|
||||
"//src/core:error",
|
||||
"//src/core:error_utils",
|
||||
"//src/core:exec_ctx_wakeup_scheduler",
|
||||
"//src/core:experiments",
|
||||
"//src/core:gpr_atm",
|
||||
"//src/core:gpr_manual_constructor",
|
||||
"//src/core:grpc_backend_metric_data",
|
||||
"//src/core:grpc_message_size_filter",
|
||||
"//src/core:grpc_channel_idle_filter",
|
||||
"//src/core:grpc_service_config",
|
||||
"//src/core:idle_filter_state",
|
||||
"//src/core:init_internally",
|
||||
"//src/core:interception_chain",
|
||||
"//src/core:iomgr_fwd",
|
||||
"//src/core:json",
|
||||
"//src/core:json_args",
|
||||
"//src/core:json_channel_args",
|
||||
"//src/core:json_object_loader",
|
||||
"//src/core:latch",
|
||||
"//src/core:lb_policy",
|
||||
"//src/core:lb_policy_registry",
|
||||
"//src/core:loop",
|
||||
"//src/core:map",
|
||||
"//src/core:memory_quota",
|
||||
"//src/core:metadata",
|
||||
"//src/core:metadata_batch",
|
||||
"//src/core:metrics",
|
||||
"//src/core:observable",
|
||||
"//src/core:pipe",
|
||||
"//src/core:poll",
|
||||
"//src/core:pollset_set",
|
||||
"//src/core:proxy_mapper",
|
||||
"//src/core:proxy_mapper_registry",
|
||||
"//src/core:ref_counted",
|
||||
"//src/core:resolved_address",
|
||||
|
|
@ -3827,11 +3827,13 @@ grpc_cc_library(
|
|||
"//src/core:retry_service_config",
|
||||
"//src/core:retry_throttle",
|
||||
"//src/core:seq",
|
||||
"//src/core:service_config_parser",
|
||||
"//src/core:single_set_ptr",
|
||||
"//src/core:sleep",
|
||||
"//src/core:slice",
|
||||
"//src/core:slice_buffer",
|
||||
"//src/core:slice_refcount",
|
||||
"//src/core:stats_data",
|
||||
"//src/core:status_flag",
|
||||
"//src/core:status_helper",
|
||||
"//src/core:subchannel_connector",
|
||||
"//src/core:subchannel_interface",
|
||||
|
|
@ -3840,7 +3842,6 @@ grpc_cc_library(
|
|||
"//src/core:try_seq",
|
||||
"//src/core:unique_type_name",
|
||||
"//src/core:useful",
|
||||
"//src/core:validation_errors",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -1002,7 +1002,9 @@ if(gRPC_BUILD_TESTS)
|
|||
add_dependencies(buildtests_cxx client_authority_filter_test)
|
||||
add_dependencies(buildtests_cxx client_callback_end2end_test)
|
||||
add_dependencies(buildtests_cxx client_channel_service_config_test)
|
||||
add_dependencies(buildtests_cxx client_channel_test)
|
||||
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
|
||||
add_dependencies(buildtests_cxx client_channel_test)
|
||||
endif()
|
||||
add_dependencies(buildtests_cxx client_context_test_peer_test)
|
||||
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
|
||||
add_dependencies(buildtests_cxx client_fork_test)
|
||||
|
|
@ -1026,6 +1028,9 @@ if(gRPC_BUILD_TESTS)
|
|||
add_dependencies(buildtests_cxx compressed_payload_test)
|
||||
add_dependencies(buildtests_cxx compression_test)
|
||||
add_dependencies(buildtests_cxx concurrent_connectivity_test)
|
||||
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
|
||||
add_dependencies(buildtests_cxx connected_subchannel_test)
|
||||
endif()
|
||||
add_dependencies(buildtests_cxx connection_prefix_bad_client_test)
|
||||
add_dependencies(buildtests_cxx connection_refused_test)
|
||||
add_dependencies(buildtests_cxx connectivity_state_test)
|
||||
|
|
@ -1194,6 +1199,9 @@ if(gRPC_BUILD_TESTS)
|
|||
add_dependencies(buildtests_cxx latch_test)
|
||||
add_dependencies(buildtests_cxx lb_get_cpu_stats_test)
|
||||
add_dependencies(buildtests_cxx lb_load_data_store_test)
|
||||
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
|
||||
add_dependencies(buildtests_cxx load_balanced_call_destination_test)
|
||||
endif()
|
||||
add_dependencies(buildtests_cxx load_config_test)
|
||||
add_dependencies(buildtests_cxx load_file_test)
|
||||
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
|
||||
|
|
@ -1436,6 +1444,7 @@ if(gRPC_BUILD_TESTS)
|
|||
add_dependencies(buildtests_cxx streams_not_seen_test)
|
||||
add_dependencies(buildtests_cxx string_ref_test)
|
||||
add_dependencies(buildtests_cxx string_test)
|
||||
add_dependencies(buildtests_cxx subchannel_args_test)
|
||||
add_dependencies(buildtests_cxx switch_test)
|
||||
add_dependencies(buildtests_cxx sync_test)
|
||||
add_dependencies(buildtests_cxx system_roots_test)
|
||||
|
|
@ -1830,6 +1839,7 @@ add_library(grpc
|
|||
src/core/channelz/channelz.cc
|
||||
src/core/channelz/channelz_registry.cc
|
||||
src/core/client_channel/backup_poller.cc
|
||||
src/core/client_channel/client_channel.cc
|
||||
src/core/client_channel/client_channel_factory.cc
|
||||
src/core/client_channel/client_channel_filter.cc
|
||||
src/core/client_channel/client_channel_plugin.cc
|
||||
|
|
@ -1837,6 +1847,7 @@ add_library(grpc
|
|||
src/core/client_channel/config_selector.cc
|
||||
src/core/client_channel/dynamic_filters.cc
|
||||
src/core/client_channel/global_subchannel_pool.cc
|
||||
src/core/client_channel/load_balanced_call_destination.cc
|
||||
src/core/client_channel/local_subchannel_pool.cc
|
||||
src/core/client_channel/retry_filter.cc
|
||||
src/core/client_channel/retry_filter_legacy_call_data.cc
|
||||
|
|
@ -2292,6 +2303,7 @@ add_library(grpc
|
|||
src/core/lib/event_engine/work_queue/basic_work_queue.cc
|
||||
src/core/lib/experiments/config.cc
|
||||
src/core/lib/experiments/experiments.cc
|
||||
src/core/lib/gprpp/dump_args.cc
|
||||
src/core/lib/gprpp/load_file.cc
|
||||
src/core/lib/gprpp/per_cpu.cc
|
||||
src/core/lib/gprpp/posix/directory_reader.cc
|
||||
|
|
@ -2927,6 +2939,7 @@ add_library(grpc_unsecure
|
|||
src/core/channelz/channelz.cc
|
||||
src/core/channelz/channelz_registry.cc
|
||||
src/core/client_channel/backup_poller.cc
|
||||
src/core/client_channel/client_channel.cc
|
||||
src/core/client_channel/client_channel_factory.cc
|
||||
src/core/client_channel/client_channel_filter.cc
|
||||
src/core/client_channel/client_channel_plugin.cc
|
||||
|
|
@ -2934,6 +2947,7 @@ add_library(grpc_unsecure
|
|||
src/core/client_channel/config_selector.cc
|
||||
src/core/client_channel/dynamic_filters.cc
|
||||
src/core/client_channel/global_subchannel_pool.cc
|
||||
src/core/client_channel/load_balanced_call_destination.cc
|
||||
src/core/client_channel/local_subchannel_pool.cc
|
||||
src/core/client_channel/retry_filter.cc
|
||||
src/core/client_channel/retry_filter_legacy_call_data.cc
|
||||
|
|
@ -3085,6 +3099,7 @@ add_library(grpc_unsecure
|
|||
src/core/lib/event_engine/work_queue/basic_work_queue.cc
|
||||
src/core/lib/experiments/config.cc
|
||||
src/core/lib/experiments/experiments.cc
|
||||
src/core/lib/gprpp/dump_args.cc
|
||||
src/core/lib/gprpp/load_file.cc
|
||||
src/core/lib/gprpp/per_cpu.cc
|
||||
src/core/lib/gprpp/ref_counted_string.cc
|
||||
|
|
@ -5203,6 +5218,7 @@ add_library(grpc_authorization_provider
|
|||
src/core/lib/event_engine/work_queue/basic_work_queue.cc
|
||||
src/core/lib/experiments/config.cc
|
||||
src/core/lib/experiments/experiments.cc
|
||||
src/core/lib/gprpp/dump_args.cc
|
||||
src/core/lib/gprpp/load_file.cc
|
||||
src/core/lib/gprpp/per_cpu.cc
|
||||
src/core/lib/gprpp/ref_counted_string.cc
|
||||
|
|
@ -8506,6 +8522,7 @@ add_executable(call_filters_test
|
|||
src/core/lib/debug/trace.cc
|
||||
src/core/lib/experiments/config.cc
|
||||
src/core/lib/experiments/experiments.cc
|
||||
src/core/lib/gprpp/dump_args.cc
|
||||
src/core/lib/gprpp/ref_counted_string.cc
|
||||
src/core/lib/gprpp/status_helper.cc
|
||||
src/core/lib/gprpp/time.cc
|
||||
|
|
@ -10526,46 +10543,56 @@ target_link_libraries(client_channel_service_config_test
|
|||
|
||||
endif()
|
||||
if(gRPC_BUILD_TESTS)
|
||||
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
|
||||
|
||||
add_executable(client_channel_test
|
||||
test/core/client_channel/client_channel_test.cc
|
||||
)
|
||||
if(WIN32 AND MSVC)
|
||||
if(BUILD_SHARED_LIBS)
|
||||
target_compile_definitions(client_channel_test
|
||||
PRIVATE
|
||||
"GPR_DLL_IMPORTS"
|
||||
"GRPC_DLL_IMPORTS"
|
||||
)
|
||||
add_executable(client_channel_test
|
||||
${_gRPC_PROTO_GENS_DIR}/test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.pb.cc
|
||||
${_gRPC_PROTO_GENS_DIR}/test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.grpc.pb.cc
|
||||
${_gRPC_PROTO_GENS_DIR}/test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.pb.h
|
||||
${_gRPC_PROTO_GENS_DIR}/test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.grpc.pb.h
|
||||
test/core/call/yodel/test_main.cc
|
||||
test/core/call/yodel/yodel_test.cc
|
||||
test/core/client_channel/client_channel_test.cc
|
||||
test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.cc
|
||||
)
|
||||
if(WIN32 AND MSVC)
|
||||
if(BUILD_SHARED_LIBS)
|
||||
target_compile_definitions(client_channel_test
|
||||
PRIVATE
|
||||
"GPR_DLL_IMPORTS"
|
||||
"GRPC_DLL_IMPORTS"
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
target_compile_features(client_channel_test PUBLIC cxx_std_14)
|
||||
target_include_directories(client_channel_test
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
|
||||
${_gRPC_RE2_INCLUDE_DIR}
|
||||
${_gRPC_SSL_INCLUDE_DIR}
|
||||
${_gRPC_UPB_GENERATED_DIR}
|
||||
${_gRPC_UPB_GRPC_GENERATED_DIR}
|
||||
${_gRPC_UPB_INCLUDE_DIR}
|
||||
${_gRPC_XXHASH_INCLUDE_DIR}
|
||||
${_gRPC_ZLIB_INCLUDE_DIR}
|
||||
third_party/googletest/googletest/include
|
||||
third_party/googletest/googletest
|
||||
third_party/googletest/googlemock/include
|
||||
third_party/googletest/googlemock
|
||||
${_gRPC_PROTO_GENS_DIR}
|
||||
)
|
||||
|
||||
target_link_libraries(client_channel_test
|
||||
${_gRPC_ALLTARGETS_LIBRARIES}
|
||||
gtest
|
||||
${_gRPC_PROTOBUF_LIBRARIES}
|
||||
grpc_test_util
|
||||
)
|
||||
|
||||
|
||||
endif()
|
||||
target_compile_features(client_channel_test PUBLIC cxx_std_14)
|
||||
target_include_directories(client_channel_test
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
|
||||
${_gRPC_RE2_INCLUDE_DIR}
|
||||
${_gRPC_SSL_INCLUDE_DIR}
|
||||
${_gRPC_UPB_GENERATED_DIR}
|
||||
${_gRPC_UPB_GRPC_GENERATED_DIR}
|
||||
${_gRPC_UPB_INCLUDE_DIR}
|
||||
${_gRPC_XXHASH_INCLUDE_DIR}
|
||||
${_gRPC_ZLIB_INCLUDE_DIR}
|
||||
third_party/googletest/googletest/include
|
||||
third_party/googletest/googletest
|
||||
third_party/googletest/googlemock/include
|
||||
third_party/googletest/googlemock
|
||||
${_gRPC_PROTO_GENS_DIR}
|
||||
)
|
||||
|
||||
target_link_libraries(client_channel_test
|
||||
${_gRPC_ALLTARGETS_LIBRARIES}
|
||||
gtest
|
||||
grpc_test_util
|
||||
)
|
||||
|
||||
|
||||
endif()
|
||||
if(gRPC_BUILD_TESTS)
|
||||
|
||||
|
|
@ -11340,6 +11367,58 @@ target_link_libraries(concurrent_connectivity_test
|
|||
)
|
||||
|
||||
|
||||
endif()
|
||||
if(gRPC_BUILD_TESTS)
|
||||
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
|
||||
|
||||
add_executable(connected_subchannel_test
|
||||
${_gRPC_PROTO_GENS_DIR}/test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.pb.cc
|
||||
${_gRPC_PROTO_GENS_DIR}/test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.grpc.pb.cc
|
||||
${_gRPC_PROTO_GENS_DIR}/test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.pb.h
|
||||
${_gRPC_PROTO_GENS_DIR}/test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.grpc.pb.h
|
||||
test/core/call/yodel/test_main.cc
|
||||
test/core/call/yodel/yodel_test.cc
|
||||
test/core/client_channel/connected_subchannel_test.cc
|
||||
test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.cc
|
||||
)
|
||||
if(WIN32 AND MSVC)
|
||||
if(BUILD_SHARED_LIBS)
|
||||
target_compile_definitions(connected_subchannel_test
|
||||
PRIVATE
|
||||
"GPR_DLL_IMPORTS"
|
||||
"GRPC_DLL_IMPORTS"
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
target_compile_features(connected_subchannel_test PUBLIC cxx_std_14)
|
||||
target_include_directories(connected_subchannel_test
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
|
||||
${_gRPC_RE2_INCLUDE_DIR}
|
||||
${_gRPC_SSL_INCLUDE_DIR}
|
||||
${_gRPC_UPB_GENERATED_DIR}
|
||||
${_gRPC_UPB_GRPC_GENERATED_DIR}
|
||||
${_gRPC_UPB_INCLUDE_DIR}
|
||||
${_gRPC_XXHASH_INCLUDE_DIR}
|
||||
${_gRPC_ZLIB_INCLUDE_DIR}
|
||||
third_party/googletest/googletest/include
|
||||
third_party/googletest/googletest
|
||||
third_party/googletest/googlemock/include
|
||||
third_party/googletest/googlemock
|
||||
${_gRPC_PROTO_GENS_DIR}
|
||||
)
|
||||
|
||||
target_link_libraries(connected_subchannel_test
|
||||
${_gRPC_ALLTARGETS_LIBRARIES}
|
||||
gtest
|
||||
${_gRPC_PROTOBUF_LIBRARIES}
|
||||
grpc_test_util
|
||||
)
|
||||
|
||||
|
||||
endif()
|
||||
endif()
|
||||
if(gRPC_BUILD_TESTS)
|
||||
|
||||
|
|
@ -17832,6 +17911,7 @@ add_executable(interception_chain_test
|
|||
src/core/lib/event_engine/work_queue/basic_work_queue.cc
|
||||
src/core/lib/experiments/config.cc
|
||||
src/core/lib/experiments/experiments.cc
|
||||
src/core/lib/gprpp/dump_args.cc
|
||||
src/core/lib/gprpp/load_file.cc
|
||||
src/core/lib/gprpp/per_cpu.cc
|
||||
src/core/lib/gprpp/ref_counted_string.cc
|
||||
|
|
@ -18985,6 +19065,58 @@ target_link_libraries(lb_load_data_store_test
|
|||
)
|
||||
|
||||
|
||||
endif()
|
||||
if(gRPC_BUILD_TESTS)
|
||||
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
|
||||
|
||||
add_executable(load_balanced_call_destination_test
|
||||
${_gRPC_PROTO_GENS_DIR}/test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.pb.cc
|
||||
${_gRPC_PROTO_GENS_DIR}/test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.grpc.pb.cc
|
||||
${_gRPC_PROTO_GENS_DIR}/test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.pb.h
|
||||
${_gRPC_PROTO_GENS_DIR}/test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.grpc.pb.h
|
||||
test/core/call/yodel/test_main.cc
|
||||
test/core/call/yodel/yodel_test.cc
|
||||
test/core/client_channel/load_balanced_call_destination_test.cc
|
||||
test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.cc
|
||||
)
|
||||
if(WIN32 AND MSVC)
|
||||
if(BUILD_SHARED_LIBS)
|
||||
target_compile_definitions(load_balanced_call_destination_test
|
||||
PRIVATE
|
||||
"GPR_DLL_IMPORTS"
|
||||
"GRPC_DLL_IMPORTS"
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
target_compile_features(load_balanced_call_destination_test PUBLIC cxx_std_14)
|
||||
target_include_directories(load_balanced_call_destination_test
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
|
||||
${_gRPC_RE2_INCLUDE_DIR}
|
||||
${_gRPC_SSL_INCLUDE_DIR}
|
||||
${_gRPC_UPB_GENERATED_DIR}
|
||||
${_gRPC_UPB_GRPC_GENERATED_DIR}
|
||||
${_gRPC_UPB_INCLUDE_DIR}
|
||||
${_gRPC_XXHASH_INCLUDE_DIR}
|
||||
${_gRPC_ZLIB_INCLUDE_DIR}
|
||||
third_party/googletest/googletest/include
|
||||
third_party/googletest/googletest
|
||||
third_party/googletest/googlemock/include
|
||||
third_party/googletest/googlemock
|
||||
${_gRPC_PROTO_GENS_DIR}
|
||||
)
|
||||
|
||||
target_link_libraries(load_balanced_call_destination_test
|
||||
${_gRPC_ALLTARGETS_LIBRARIES}
|
||||
gtest
|
||||
${_gRPC_PROTOBUF_LIBRARIES}
|
||||
grpc_test_util
|
||||
)
|
||||
|
||||
|
||||
endif()
|
||||
endif()
|
||||
if(gRPC_BUILD_TESTS)
|
||||
|
||||
|
|
@ -29324,6 +29456,48 @@ target_link_libraries(string_test
|
|||
)
|
||||
|
||||
|
||||
endif()
|
||||
if(gRPC_BUILD_TESTS)
|
||||
|
||||
add_executable(subchannel_args_test
|
||||
test/core/client_channel/subchannel_args_test.cc
|
||||
)
|
||||
if(WIN32 AND MSVC)
|
||||
if(BUILD_SHARED_LIBS)
|
||||
target_compile_definitions(subchannel_args_test
|
||||
PRIVATE
|
||||
"GPR_DLL_IMPORTS"
|
||||
"GRPC_DLL_IMPORTS"
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
target_compile_features(subchannel_args_test PUBLIC cxx_std_14)
|
||||
target_include_directories(subchannel_args_test
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
|
||||
${_gRPC_RE2_INCLUDE_DIR}
|
||||
${_gRPC_SSL_INCLUDE_DIR}
|
||||
${_gRPC_UPB_GENERATED_DIR}
|
||||
${_gRPC_UPB_GRPC_GENERATED_DIR}
|
||||
${_gRPC_UPB_INCLUDE_DIR}
|
||||
${_gRPC_XXHASH_INCLUDE_DIR}
|
||||
${_gRPC_ZLIB_INCLUDE_DIR}
|
||||
third_party/googletest/googletest/include
|
||||
third_party/googletest/googletest
|
||||
third_party/googletest/googlemock/include
|
||||
third_party/googletest/googlemock
|
||||
${_gRPC_PROTO_GENS_DIR}
|
||||
)
|
||||
|
||||
target_link_libraries(subchannel_args_test
|
||||
${_gRPC_ALLTARGETS_LIBRARIES}
|
||||
gtest
|
||||
grpc_test_util
|
||||
)
|
||||
|
||||
|
||||
endif()
|
||||
if(gRPC_BUILD_TESTS)
|
||||
|
||||
|
|
|
|||
|
|
@ -670,6 +670,7 @@ LIBGRPC_SRC = \
|
|||
src/core/channelz/channelz.cc \
|
||||
src/core/channelz/channelz_registry.cc \
|
||||
src/core/client_channel/backup_poller.cc \
|
||||
src/core/client_channel/client_channel.cc \
|
||||
src/core/client_channel/client_channel_factory.cc \
|
||||
src/core/client_channel/client_channel_filter.cc \
|
||||
src/core/client_channel/client_channel_plugin.cc \
|
||||
|
|
@ -677,6 +678,7 @@ LIBGRPC_SRC = \
|
|||
src/core/client_channel/config_selector.cc \
|
||||
src/core/client_channel/dynamic_filters.cc \
|
||||
src/core/client_channel/global_subchannel_pool.cc \
|
||||
src/core/client_channel/load_balanced_call_destination.cc \
|
||||
src/core/client_channel/local_subchannel_pool.cc \
|
||||
src/core/client_channel/retry_filter.cc \
|
||||
src/core/client_channel/retry_filter_legacy_call_data.cc \
|
||||
|
|
@ -1137,6 +1139,7 @@ LIBGRPC_SRC = \
|
|||
src/core/lib/experiments/config.cc \
|
||||
src/core/lib/experiments/experiments.cc \
|
||||
src/core/lib/gprpp/crash.cc \
|
||||
src/core/lib/gprpp/dump_args.cc \
|
||||
src/core/lib/gprpp/examine_stack.cc \
|
||||
src/core/lib/gprpp/fork.cc \
|
||||
src/core/lib/gprpp/host_port.cc \
|
||||
|
|
|
|||
|
|
@ -126,6 +126,8 @@ let package = Package(
|
|||
"src/core/channelz/channelz_registry.h",
|
||||
"src/core/client_channel/backup_poller.cc",
|
||||
"src/core/client_channel/backup_poller.h",
|
||||
"src/core/client_channel/client_channel.cc",
|
||||
"src/core/client_channel/client_channel.h",
|
||||
"src/core/client_channel/client_channel_factory.cc",
|
||||
"src/core/client_channel/client_channel_factory.h",
|
||||
"src/core/client_channel/client_channel_filter.cc",
|
||||
|
|
@ -141,6 +143,8 @@ let package = Package(
|
|||
"src/core/client_channel/dynamic_filters.h",
|
||||
"src/core/client_channel/global_subchannel_pool.cc",
|
||||
"src/core/client_channel/global_subchannel_pool.h",
|
||||
"src/core/client_channel/load_balanced_call_destination.cc",
|
||||
"src/core/client_channel/load_balanced_call_destination.h",
|
||||
"src/core/client_channel/local_subchannel_pool.cc",
|
||||
"src/core/client_channel/local_subchannel_pool.h",
|
||||
"src/core/client_channel/retry_filter.cc",
|
||||
|
|
@ -1255,6 +1259,8 @@ let package = Package(
|
|||
"src/core/lib/gprpp/directory_reader.h",
|
||||
"src/core/lib/gprpp/down_cast.h",
|
||||
"src/core/lib/gprpp/dual_ref_counted.h",
|
||||
"src/core/lib/gprpp/dump_args.cc",
|
||||
"src/core/lib/gprpp/dump_args.h",
|
||||
"src/core/lib/gprpp/env.h",
|
||||
"src/core/lib/gprpp/examine_stack.cc",
|
||||
"src/core/lib/gprpp/examine_stack.h",
|
||||
|
|
@ -1480,6 +1486,7 @@ let package = Package(
|
|||
"src/core/lib/promise/latch.h",
|
||||
"src/core/lib/promise/loop.h",
|
||||
"src/core/lib/promise/map.h",
|
||||
"src/core/lib/promise/observable.h",
|
||||
"src/core/lib/promise/party.cc",
|
||||
"src/core/lib/promise/party.h",
|
||||
"src/core/lib/promise/pipe.h",
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@
|
|||
|
||||
EXPERIMENT_ENABLES = {
|
||||
"call_status_override_on_cancellation": "call_status_override_on_cancellation",
|
||||
"call_v3": "call_v3",
|
||||
"canary_client_privacy": "canary_client_privacy",
|
||||
"client_privacy": "client_privacy",
|
||||
"event_engine_client": "event_engine_client",
|
||||
|
|
@ -45,6 +44,7 @@ EXPERIMENT_ENABLES = {
|
|||
"unconstrained_max_quota_buffer_size": "unconstrained_max_quota_buffer_size",
|
||||
"work_serializer_clears_time_cache": "work_serializer_clears_time_cache",
|
||||
"work_serializer_dispatch": "event_engine_client,work_serializer_dispatch",
|
||||
"call_v3": "call_v3,event_engine_client,event_engine_listener,work_serializer_dispatch",
|
||||
}
|
||||
|
||||
EXPERIMENT_POLLERS = [
|
||||
|
|
|
|||
|
|
@ -227,6 +227,7 @@ libs:
|
|||
- src/core/channelz/channelz.h
|
||||
- src/core/channelz/channelz_registry.h
|
||||
- src/core/client_channel/backup_poller.h
|
||||
- src/core/client_channel/client_channel.h
|
||||
- src/core/client_channel/client_channel_factory.h
|
||||
- src/core/client_channel/client_channel_filter.h
|
||||
- src/core/client_channel/client_channel_internal.h
|
||||
|
|
@ -235,6 +236,7 @@ libs:
|
|||
- src/core/client_channel/connector.h
|
||||
- src/core/client_channel/dynamic_filters.h
|
||||
- src/core/client_channel/global_subchannel_pool.h
|
||||
- src/core/client_channel/load_balanced_call_destination.h
|
||||
- src/core/client_channel/local_subchannel_pool.h
|
||||
- src/core/client_channel/retry_filter.h
|
||||
- src/core/client_channel/retry_filter_legacy_call_data.h
|
||||
|
|
@ -883,6 +885,7 @@ libs:
|
|||
- src/core/lib/gprpp/directory_reader.h
|
||||
- src/core/lib/gprpp/down_cast.h
|
||||
- src/core/lib/gprpp/dual_ref_counted.h
|
||||
- src/core/lib/gprpp/dump_args.h
|
||||
- src/core/lib/gprpp/if_list.h
|
||||
- src/core/lib/gprpp/load_file.h
|
||||
- src/core/lib/gprpp/manual_constructor.h
|
||||
|
|
@ -991,6 +994,7 @@ libs:
|
|||
- src/core/lib/promise/latch.h
|
||||
- src/core/lib/promise/loop.h
|
||||
- src/core/lib/promise/map.h
|
||||
- src/core/lib/promise/observable.h
|
||||
- src/core/lib/promise/party.h
|
||||
- src/core/lib/promise/pipe.h
|
||||
- src/core/lib/promise/poll.h
|
||||
|
|
@ -1251,6 +1255,7 @@ libs:
|
|||
- src/core/channelz/channelz.cc
|
||||
- src/core/channelz/channelz_registry.cc
|
||||
- src/core/client_channel/backup_poller.cc
|
||||
- src/core/client_channel/client_channel.cc
|
||||
- src/core/client_channel/client_channel_factory.cc
|
||||
- src/core/client_channel/client_channel_filter.cc
|
||||
- src/core/client_channel/client_channel_plugin.cc
|
||||
|
|
@ -1258,6 +1263,7 @@ libs:
|
|||
- src/core/client_channel/config_selector.cc
|
||||
- src/core/client_channel/dynamic_filters.cc
|
||||
- src/core/client_channel/global_subchannel_pool.cc
|
||||
- src/core/client_channel/load_balanced_call_destination.cc
|
||||
- src/core/client_channel/local_subchannel_pool.cc
|
||||
- src/core/client_channel/retry_filter.cc
|
||||
- src/core/client_channel/retry_filter_legacy_call_data.cc
|
||||
|
|
@ -1713,6 +1719,7 @@ libs:
|
|||
- src/core/lib/event_engine/work_queue/basic_work_queue.cc
|
||||
- src/core/lib/experiments/config.cc
|
||||
- src/core/lib/experiments/experiments.cc
|
||||
- src/core/lib/gprpp/dump_args.cc
|
||||
- src/core/lib/gprpp/load_file.cc
|
||||
- src/core/lib/gprpp/per_cpu.cc
|
||||
- src/core/lib/gprpp/posix/directory_reader.cc
|
||||
|
|
@ -2215,6 +2222,7 @@ libs:
|
|||
- src/core/channelz/channelz.h
|
||||
- src/core/channelz/channelz_registry.h
|
||||
- src/core/client_channel/backup_poller.h
|
||||
- src/core/client_channel/client_channel.h
|
||||
- src/core/client_channel/client_channel_factory.h
|
||||
- src/core/client_channel/client_channel_filter.h
|
||||
- src/core/client_channel/client_channel_internal.h
|
||||
|
|
@ -2223,6 +2231,7 @@ libs:
|
|||
- src/core/client_channel/connector.h
|
||||
- src/core/client_channel/dynamic_filters.h
|
||||
- src/core/client_channel/global_subchannel_pool.h
|
||||
- src/core/client_channel/load_balanced_call_destination.h
|
||||
- src/core/client_channel/local_subchannel_pool.h
|
||||
- src/core/client_channel/retry_filter.h
|
||||
- src/core/client_channel/retry_filter_legacy_call_data.h
|
||||
|
|
@ -2420,6 +2429,7 @@ libs:
|
|||
- src/core/lib/gprpp/cpp_impl_of.h
|
||||
- src/core/lib/gprpp/down_cast.h
|
||||
- src/core/lib/gprpp/dual_ref_counted.h
|
||||
- src/core/lib/gprpp/dump_args.h
|
||||
- src/core/lib/gprpp/if_list.h
|
||||
- src/core/lib/gprpp/load_file.h
|
||||
- src/core/lib/gprpp/manual_constructor.h
|
||||
|
|
@ -2526,6 +2536,7 @@ libs:
|
|||
- src/core/lib/promise/latch.h
|
||||
- src/core/lib/promise/loop.h
|
||||
- src/core/lib/promise/map.h
|
||||
- src/core/lib/promise/observable.h
|
||||
- src/core/lib/promise/party.h
|
||||
- src/core/lib/promise/pipe.h
|
||||
- src/core/lib/promise/poll.h
|
||||
|
|
@ -2708,6 +2719,7 @@ libs:
|
|||
- src/core/channelz/channelz.cc
|
||||
- src/core/channelz/channelz_registry.cc
|
||||
- src/core/client_channel/backup_poller.cc
|
||||
- src/core/client_channel/client_channel.cc
|
||||
- src/core/client_channel/client_channel_factory.cc
|
||||
- src/core/client_channel/client_channel_filter.cc
|
||||
- src/core/client_channel/client_channel_plugin.cc
|
||||
|
|
@ -2715,6 +2727,7 @@ libs:
|
|||
- src/core/client_channel/config_selector.cc
|
||||
- src/core/client_channel/dynamic_filters.cc
|
||||
- src/core/client_channel/global_subchannel_pool.cc
|
||||
- src/core/client_channel/load_balanced_call_destination.cc
|
||||
- src/core/client_channel/local_subchannel_pool.cc
|
||||
- src/core/client_channel/retry_filter.cc
|
||||
- src/core/client_channel/retry_filter_legacy_call_data.cc
|
||||
|
|
@ -2866,6 +2879,7 @@ libs:
|
|||
- src/core/lib/event_engine/work_queue/basic_work_queue.cc
|
||||
- src/core/lib/experiments/config.cc
|
||||
- src/core/lib/experiments/experiments.cc
|
||||
- src/core/lib/gprpp/dump_args.cc
|
||||
- src/core/lib/gprpp/load_file.cc
|
||||
- src/core/lib/gprpp/per_cpu.cc
|
||||
- src/core/lib/gprpp/ref_counted_string.cc
|
||||
|
|
@ -4510,6 +4524,7 @@ libs:
|
|||
- src/core/lib/gprpp/cpp_impl_of.h
|
||||
- src/core/lib/gprpp/down_cast.h
|
||||
- src/core/lib/gprpp/dual_ref_counted.h
|
||||
- src/core/lib/gprpp/dump_args.h
|
||||
- src/core/lib/gprpp/if_list.h
|
||||
- src/core/lib/gprpp/load_file.h
|
||||
- src/core/lib/gprpp/manual_constructor.h
|
||||
|
|
@ -4618,6 +4633,7 @@ libs:
|
|||
- src/core/lib/promise/party.h
|
||||
- src/core/lib/promise/pipe.h
|
||||
- src/core/lib/promise/poll.h
|
||||
- src/core/lib/promise/prioritized_race.h
|
||||
- src/core/lib/promise/promise.h
|
||||
- src/core/lib/promise/race.h
|
||||
- src/core/lib/promise/seq.h
|
||||
|
|
@ -4833,6 +4849,7 @@ libs:
|
|||
- src/core/lib/event_engine/work_queue/basic_work_queue.cc
|
||||
- src/core/lib/experiments/config.cc
|
||||
- src/core/lib/experiments/experiments.cc
|
||||
- src/core/lib/gprpp/dump_args.cc
|
||||
- src/core/lib/gprpp/load_file.cc
|
||||
- src/core/lib/gprpp/per_cpu.cc
|
||||
- src/core/lib/gprpp/ref_counted_string.cc
|
||||
|
|
@ -6378,6 +6395,7 @@ targets:
|
|||
- src/core/lib/gprpp/chunked_vector.h
|
||||
- src/core/lib/gprpp/down_cast.h
|
||||
- src/core/lib/gprpp/dual_ref_counted.h
|
||||
- src/core/lib/gprpp/dump_args.h
|
||||
- src/core/lib/gprpp/if_list.h
|
||||
- src/core/lib/gprpp/manual_constructor.h
|
||||
- src/core/lib/gprpp/orphanable.h
|
||||
|
|
@ -6468,6 +6486,7 @@ targets:
|
|||
- src/core/lib/debug/trace.cc
|
||||
- src/core/lib/experiments/config.cc
|
||||
- src/core/lib/experiments/experiments.cc
|
||||
- src/core/lib/gprpp/dump_args.cc
|
||||
- src/core/lib/gprpp/ref_counted_string.cc
|
||||
- src/core/lib/gprpp/status_helper.cc
|
||||
- src/core/lib/gprpp/time.cc
|
||||
|
|
@ -7869,12 +7888,22 @@ targets:
|
|||
gtest: true
|
||||
build: test
|
||||
language: c++
|
||||
headers: []
|
||||
headers:
|
||||
- test/core/call/yodel/yodel_test.h
|
||||
- test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.h
|
||||
src:
|
||||
- test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.proto
|
||||
- test/core/call/yodel/test_main.cc
|
||||
- test/core/call/yodel/yodel_test.cc
|
||||
- test/core/client_channel/client_channel_test.cc
|
||||
- test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.cc
|
||||
deps:
|
||||
- gtest
|
||||
- protobuf
|
||||
- grpc_test_util
|
||||
platforms:
|
||||
- linux
|
||||
- posix
|
||||
uses_polling: false
|
||||
- name: client_context_test_peer_test
|
||||
gtest: true
|
||||
|
|
@ -8225,6 +8254,27 @@ targets:
|
|||
deps:
|
||||
- gtest
|
||||
- grpc_test_util
|
||||
- name: connected_subchannel_test
|
||||
gtest: true
|
||||
build: test
|
||||
language: c++
|
||||
headers:
|
||||
- test/core/call/yodel/yodel_test.h
|
||||
- test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.h
|
||||
src:
|
||||
- test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.proto
|
||||
- test/core/call/yodel/test_main.cc
|
||||
- test/core/call/yodel/yodel_test.cc
|
||||
- test/core/client_channel/connected_subchannel_test.cc
|
||||
- test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.cc
|
||||
deps:
|
||||
- gtest
|
||||
- protobuf
|
||||
- grpc_test_util
|
||||
platforms:
|
||||
- linux
|
||||
- posix
|
||||
uses_polling: false
|
||||
- name: connection_prefix_bad_client_test
|
||||
gtest: true
|
||||
build: test
|
||||
|
|
@ -11669,6 +11719,7 @@ targets:
|
|||
- src/core/lib/gprpp/cpp_impl_of.h
|
||||
- src/core/lib/gprpp/down_cast.h
|
||||
- src/core/lib/gprpp/dual_ref_counted.h
|
||||
- src/core/lib/gprpp/dump_args.h
|
||||
- src/core/lib/gprpp/if_list.h
|
||||
- src/core/lib/gprpp/load_file.h
|
||||
- src/core/lib/gprpp/manual_constructor.h
|
||||
|
|
@ -11776,6 +11827,7 @@ targets:
|
|||
- src/core/lib/promise/party.h
|
||||
- src/core/lib/promise/pipe.h
|
||||
- src/core/lib/promise/poll.h
|
||||
- src/core/lib/promise/prioritized_race.h
|
||||
- src/core/lib/promise/promise.h
|
||||
- src/core/lib/promise/race.h
|
||||
- src/core/lib/promise/seq.h
|
||||
|
|
@ -11961,6 +12013,7 @@ targets:
|
|||
- src/core/lib/event_engine/work_queue/basic_work_queue.cc
|
||||
- src/core/lib/experiments/config.cc
|
||||
- src/core/lib/experiments/experiments.cc
|
||||
- src/core/lib/gprpp/dump_args.cc
|
||||
- src/core/lib/gprpp/load_file.cc
|
||||
- src/core/lib/gprpp/per_cpu.cc
|
||||
- src/core/lib/gprpp/ref_counted_string.cc
|
||||
|
|
@ -12733,6 +12786,27 @@ targets:
|
|||
- gtest
|
||||
- grpc++
|
||||
- grpc_test_util
|
||||
- name: load_balanced_call_destination_test
|
||||
gtest: true
|
||||
build: test
|
||||
language: c++
|
||||
headers:
|
||||
- test/core/call/yodel/yodel_test.h
|
||||
- test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.h
|
||||
src:
|
||||
- test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.proto
|
||||
- test/core/call/yodel/test_main.cc
|
||||
- test/core/call/yodel/yodel_test.cc
|
||||
- test/core/client_channel/load_balanced_call_destination_test.cc
|
||||
- test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.cc
|
||||
deps:
|
||||
- gtest
|
||||
- protobuf
|
||||
- grpc_test_util
|
||||
platforms:
|
||||
- linux
|
||||
- posix
|
||||
uses_polling: false
|
||||
- name: load_config_test
|
||||
gtest: true
|
||||
build: test
|
||||
|
|
@ -14639,6 +14713,7 @@ targets:
|
|||
- src/core/lib/promise/map.h
|
||||
- src/core/lib/promise/poll.h
|
||||
- src/core/lib/promise/promise.h
|
||||
- test/core/promise/poll_matcher.h
|
||||
src:
|
||||
- test/core/promise/map_test.cc
|
||||
deps:
|
||||
|
|
@ -18993,6 +19068,17 @@ targets:
|
|||
- gtest
|
||||
- grpc_test_util
|
||||
uses_polling: false
|
||||
- name: subchannel_args_test
|
||||
gtest: true
|
||||
build: test
|
||||
language: c++
|
||||
headers: []
|
||||
src:
|
||||
- test/core/client_channel/subchannel_args_test.cc
|
||||
deps:
|
||||
- gtest
|
||||
- grpc_test_util
|
||||
uses_polling: false
|
||||
- name: switch_test
|
||||
gtest: true
|
||||
build: test
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ if test "$PHP_GRPC" != "no"; then
|
|||
src/core/channelz/channelz.cc \
|
||||
src/core/channelz/channelz_registry.cc \
|
||||
src/core/client_channel/backup_poller.cc \
|
||||
src/core/client_channel/client_channel.cc \
|
||||
src/core/client_channel/client_channel_factory.cc \
|
||||
src/core/client_channel/client_channel_filter.cc \
|
||||
src/core/client_channel/client_channel_plugin.cc \
|
||||
|
|
@ -52,6 +53,7 @@ if test "$PHP_GRPC" != "no"; then
|
|||
src/core/client_channel/config_selector.cc \
|
||||
src/core/client_channel/dynamic_filters.cc \
|
||||
src/core/client_channel/global_subchannel_pool.cc \
|
||||
src/core/client_channel/load_balanced_call_destination.cc \
|
||||
src/core/client_channel/local_subchannel_pool.cc \
|
||||
src/core/client_channel/retry_filter.cc \
|
||||
src/core/client_channel/retry_filter_legacy_call_data.cc \
|
||||
|
|
@ -512,6 +514,7 @@ if test "$PHP_GRPC" != "no"; then
|
|||
src/core/lib/experiments/config.cc \
|
||||
src/core/lib/experiments/experiments.cc \
|
||||
src/core/lib/gprpp/crash.cc \
|
||||
src/core/lib/gprpp/dump_args.cc \
|
||||
src/core/lib/gprpp/examine_stack.cc \
|
||||
src/core/lib/gprpp/fork.cc \
|
||||
src/core/lib/gprpp/host_port.cc \
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ if (PHP_GRPC != "no") {
|
|||
"src\\core\\channelz\\channelz.cc " +
|
||||
"src\\core\\channelz\\channelz_registry.cc " +
|
||||
"src\\core\\client_channel\\backup_poller.cc " +
|
||||
"src\\core\\client_channel\\client_channel.cc " +
|
||||
"src\\core\\client_channel\\client_channel_factory.cc " +
|
||||
"src\\core\\client_channel\\client_channel_filter.cc " +
|
||||
"src\\core\\client_channel\\client_channel_plugin.cc " +
|
||||
|
|
@ -17,6 +18,7 @@ if (PHP_GRPC != "no") {
|
|||
"src\\core\\client_channel\\config_selector.cc " +
|
||||
"src\\core\\client_channel\\dynamic_filters.cc " +
|
||||
"src\\core\\client_channel\\global_subchannel_pool.cc " +
|
||||
"src\\core\\client_channel\\load_balanced_call_destination.cc " +
|
||||
"src\\core\\client_channel\\local_subchannel_pool.cc " +
|
||||
"src\\core\\client_channel\\retry_filter.cc " +
|
||||
"src\\core\\client_channel\\retry_filter_legacy_call_data.cc " +
|
||||
|
|
@ -477,6 +479,7 @@ if (PHP_GRPC != "no") {
|
|||
"src\\core\\lib\\experiments\\config.cc " +
|
||||
"src\\core\\lib\\experiments\\experiments.cc " +
|
||||
"src\\core\\lib\\gprpp\\crash.cc " +
|
||||
"src\\core\\lib\\gprpp\\dump_args.cc " +
|
||||
"src\\core\\lib\\gprpp\\examine_stack.cc " +
|
||||
"src\\core\\lib\\gprpp\\fork.cc " +
|
||||
"src\\core\\lib\\gprpp\\host_port.cc " +
|
||||
|
|
|
|||
|
|
@ -268,6 +268,7 @@ Pod::Spec.new do |s|
|
|||
'src/core/channelz/channelz.h',
|
||||
'src/core/channelz/channelz_registry.h',
|
||||
'src/core/client_channel/backup_poller.h',
|
||||
'src/core/client_channel/client_channel.h',
|
||||
'src/core/client_channel/client_channel_factory.h',
|
||||
'src/core/client_channel/client_channel_filter.h',
|
||||
'src/core/client_channel/client_channel_internal.h',
|
||||
|
|
@ -276,6 +277,7 @@ Pod::Spec.new do |s|
|
|||
'src/core/client_channel/connector.h',
|
||||
'src/core/client_channel/dynamic_filters.h',
|
||||
'src/core/client_channel/global_subchannel_pool.h',
|
||||
'src/core/client_channel/load_balanced_call_destination.h',
|
||||
'src/core/client_channel/local_subchannel_pool.h',
|
||||
'src/core/client_channel/retry_filter.h',
|
||||
'src/core/client_channel/retry_filter_legacy_call_data.h',
|
||||
|
|
@ -968,6 +970,7 @@ Pod::Spec.new do |s|
|
|||
'src/core/lib/gprpp/directory_reader.h',
|
||||
'src/core/lib/gprpp/down_cast.h',
|
||||
'src/core/lib/gprpp/dual_ref_counted.h',
|
||||
'src/core/lib/gprpp/dump_args.h',
|
||||
'src/core/lib/gprpp/env.h',
|
||||
'src/core/lib/gprpp/examine_stack.h',
|
||||
'src/core/lib/gprpp/fork.h',
|
||||
|
|
@ -1089,6 +1092,7 @@ Pod::Spec.new do |s|
|
|||
'src/core/lib/promise/latch.h',
|
||||
'src/core/lib/promise/loop.h',
|
||||
'src/core/lib/promise/map.h',
|
||||
'src/core/lib/promise/observable.h',
|
||||
'src/core/lib/promise/party.h',
|
||||
'src/core/lib/promise/pipe.h',
|
||||
'src/core/lib/promise/poll.h',
|
||||
|
|
@ -1557,6 +1561,7 @@ Pod::Spec.new do |s|
|
|||
'src/core/channelz/channelz.h',
|
||||
'src/core/channelz/channelz_registry.h',
|
||||
'src/core/client_channel/backup_poller.h',
|
||||
'src/core/client_channel/client_channel.h',
|
||||
'src/core/client_channel/client_channel_factory.h',
|
||||
'src/core/client_channel/client_channel_filter.h',
|
||||
'src/core/client_channel/client_channel_internal.h',
|
||||
|
|
@ -1565,6 +1570,7 @@ Pod::Spec.new do |s|
|
|||
'src/core/client_channel/connector.h',
|
||||
'src/core/client_channel/dynamic_filters.h',
|
||||
'src/core/client_channel/global_subchannel_pool.h',
|
||||
'src/core/client_channel/load_balanced_call_destination.h',
|
||||
'src/core/client_channel/local_subchannel_pool.h',
|
||||
'src/core/client_channel/retry_filter.h',
|
||||
'src/core/client_channel/retry_filter_legacy_call_data.h',
|
||||
|
|
@ -2239,6 +2245,7 @@ Pod::Spec.new do |s|
|
|||
'src/core/lib/gprpp/directory_reader.h',
|
||||
'src/core/lib/gprpp/down_cast.h',
|
||||
'src/core/lib/gprpp/dual_ref_counted.h',
|
||||
'src/core/lib/gprpp/dump_args.h',
|
||||
'src/core/lib/gprpp/env.h',
|
||||
'src/core/lib/gprpp/examine_stack.h',
|
||||
'src/core/lib/gprpp/fork.h',
|
||||
|
|
@ -2360,6 +2367,7 @@ Pod::Spec.new do |s|
|
|||
'src/core/lib/promise/latch.h',
|
||||
'src/core/lib/promise/loop.h',
|
||||
'src/core/lib/promise/map.h',
|
||||
'src/core/lib/promise/observable.h',
|
||||
'src/core/lib/promise/party.h',
|
||||
'src/core/lib/promise/pipe.h',
|
||||
'src/core/lib/promise/poll.h',
|
||||
|
|
|
|||
|
|
@ -245,6 +245,8 @@ Pod::Spec.new do |s|
|
|||
'src/core/channelz/channelz_registry.h',
|
||||
'src/core/client_channel/backup_poller.cc',
|
||||
'src/core/client_channel/backup_poller.h',
|
||||
'src/core/client_channel/client_channel.cc',
|
||||
'src/core/client_channel/client_channel.h',
|
||||
'src/core/client_channel/client_channel_factory.cc',
|
||||
'src/core/client_channel/client_channel_factory.h',
|
||||
'src/core/client_channel/client_channel_filter.cc',
|
||||
|
|
@ -260,6 +262,8 @@ Pod::Spec.new do |s|
|
|||
'src/core/client_channel/dynamic_filters.h',
|
||||
'src/core/client_channel/global_subchannel_pool.cc',
|
||||
'src/core/client_channel/global_subchannel_pool.h',
|
||||
'src/core/client_channel/load_balanced_call_destination.cc',
|
||||
'src/core/client_channel/load_balanced_call_destination.h',
|
||||
'src/core/client_channel/local_subchannel_pool.cc',
|
||||
'src/core/client_channel/local_subchannel_pool.h',
|
||||
'src/core/client_channel/retry_filter.cc',
|
||||
|
|
@ -1374,6 +1378,8 @@ Pod::Spec.new do |s|
|
|||
'src/core/lib/gprpp/directory_reader.h',
|
||||
'src/core/lib/gprpp/down_cast.h',
|
||||
'src/core/lib/gprpp/dual_ref_counted.h',
|
||||
'src/core/lib/gprpp/dump_args.cc',
|
||||
'src/core/lib/gprpp/dump_args.h',
|
||||
'src/core/lib/gprpp/env.h',
|
||||
'src/core/lib/gprpp/examine_stack.cc',
|
||||
'src/core/lib/gprpp/examine_stack.h',
|
||||
|
|
@ -1599,6 +1605,7 @@ Pod::Spec.new do |s|
|
|||
'src/core/lib/promise/latch.h',
|
||||
'src/core/lib/promise/loop.h',
|
||||
'src/core/lib/promise/map.h',
|
||||
'src/core/lib/promise/observable.h',
|
||||
'src/core/lib/promise/party.cc',
|
||||
'src/core/lib/promise/party.h',
|
||||
'src/core/lib/promise/pipe.h',
|
||||
|
|
@ -2357,6 +2364,7 @@ Pod::Spec.new do |s|
|
|||
'src/core/channelz/channelz.h',
|
||||
'src/core/channelz/channelz_registry.h',
|
||||
'src/core/client_channel/backup_poller.h',
|
||||
'src/core/client_channel/client_channel.h',
|
||||
'src/core/client_channel/client_channel_factory.h',
|
||||
'src/core/client_channel/client_channel_filter.h',
|
||||
'src/core/client_channel/client_channel_internal.h',
|
||||
|
|
@ -2365,6 +2373,7 @@ Pod::Spec.new do |s|
|
|||
'src/core/client_channel/connector.h',
|
||||
'src/core/client_channel/dynamic_filters.h',
|
||||
'src/core/client_channel/global_subchannel_pool.h',
|
||||
'src/core/client_channel/load_balanced_call_destination.h',
|
||||
'src/core/client_channel/local_subchannel_pool.h',
|
||||
'src/core/client_channel/retry_filter.h',
|
||||
'src/core/client_channel/retry_filter_legacy_call_data.h',
|
||||
|
|
@ -3019,6 +3028,7 @@ Pod::Spec.new do |s|
|
|||
'src/core/lib/gprpp/directory_reader.h',
|
||||
'src/core/lib/gprpp/down_cast.h',
|
||||
'src/core/lib/gprpp/dual_ref_counted.h',
|
||||
'src/core/lib/gprpp/dump_args.h',
|
||||
'src/core/lib/gprpp/env.h',
|
||||
'src/core/lib/gprpp/examine_stack.h',
|
||||
'src/core/lib/gprpp/fork.h',
|
||||
|
|
@ -3140,6 +3150,7 @@ Pod::Spec.new do |s|
|
|||
'src/core/lib/promise/latch.h',
|
||||
'src/core/lib/promise/loop.h',
|
||||
'src/core/lib/promise/map.h',
|
||||
'src/core/lib/promise/observable.h',
|
||||
'src/core/lib/promise/party.h',
|
||||
'src/core/lib/promise/pipe.h',
|
||||
'src/core/lib/promise/poll.h',
|
||||
|
|
|
|||
|
|
@ -132,6 +132,8 @@ Gem::Specification.new do |s|
|
|||
s.files += %w( src/core/channelz/channelz_registry.h )
|
||||
s.files += %w( src/core/client_channel/backup_poller.cc )
|
||||
s.files += %w( src/core/client_channel/backup_poller.h )
|
||||
s.files += %w( src/core/client_channel/client_channel.cc )
|
||||
s.files += %w( src/core/client_channel/client_channel.h )
|
||||
s.files += %w( src/core/client_channel/client_channel_factory.cc )
|
||||
s.files += %w( src/core/client_channel/client_channel_factory.h )
|
||||
s.files += %w( src/core/client_channel/client_channel_filter.cc )
|
||||
|
|
@ -147,6 +149,8 @@ Gem::Specification.new do |s|
|
|||
s.files += %w( src/core/client_channel/dynamic_filters.h )
|
||||
s.files += %w( src/core/client_channel/global_subchannel_pool.cc )
|
||||
s.files += %w( src/core/client_channel/global_subchannel_pool.h )
|
||||
s.files += %w( src/core/client_channel/load_balanced_call_destination.cc )
|
||||
s.files += %w( src/core/client_channel/load_balanced_call_destination.h )
|
||||
s.files += %w( src/core/client_channel/local_subchannel_pool.cc )
|
||||
s.files += %w( src/core/client_channel/local_subchannel_pool.h )
|
||||
s.files += %w( src/core/client_channel/retry_filter.cc )
|
||||
|
|
@ -1261,6 +1265,8 @@ Gem::Specification.new do |s|
|
|||
s.files += %w( src/core/lib/gprpp/directory_reader.h )
|
||||
s.files += %w( src/core/lib/gprpp/down_cast.h )
|
||||
s.files += %w( src/core/lib/gprpp/dual_ref_counted.h )
|
||||
s.files += %w( src/core/lib/gprpp/dump_args.cc )
|
||||
s.files += %w( src/core/lib/gprpp/dump_args.h )
|
||||
s.files += %w( src/core/lib/gprpp/env.h )
|
||||
s.files += %w( src/core/lib/gprpp/examine_stack.cc )
|
||||
s.files += %w( src/core/lib/gprpp/examine_stack.h )
|
||||
|
|
@ -1486,6 +1492,7 @@ Gem::Specification.new do |s|
|
|||
s.files += %w( src/core/lib/promise/latch.h )
|
||||
s.files += %w( src/core/lib/promise/loop.h )
|
||||
s.files += %w( src/core/lib/promise/map.h )
|
||||
s.files += %w( src/core/lib/promise/observable.h )
|
||||
s.files += %w( src/core/lib/promise/party.cc )
|
||||
s.files += %w( src/core/lib/promise/party.h )
|
||||
s.files += %w( src/core/lib/promise/pipe.h )
|
||||
|
|
|
|||
|
|
@ -114,6 +114,8 @@
|
|||
<file baseinstalldir="/" name="src/core/channelz/channelz_registry.h" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/client_channel/backup_poller.cc" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/client_channel/backup_poller.h" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/client_channel/client_channel.cc" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/client_channel/client_channel.h" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/client_channel/client_channel_factory.cc" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/client_channel/client_channel_factory.h" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/client_channel/client_channel_filter.cc" role="src" />
|
||||
|
|
@ -129,6 +131,8 @@
|
|||
<file baseinstalldir="/" name="src/core/client_channel/dynamic_filters.h" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/client_channel/global_subchannel_pool.cc" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/client_channel/global_subchannel_pool.h" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/client_channel/load_balanced_call_destination.cc" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/client_channel/load_balanced_call_destination.h" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/client_channel/local_subchannel_pool.cc" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/client_channel/local_subchannel_pool.h" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/client_channel/retry_filter.cc" role="src" />
|
||||
|
|
@ -1243,6 +1247,8 @@
|
|||
<file baseinstalldir="/" name="src/core/lib/gprpp/directory_reader.h" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/lib/gprpp/down_cast.h" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/lib/gprpp/dual_ref_counted.h" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/lib/gprpp/dump_args.cc" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/lib/gprpp/dump_args.h" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/lib/gprpp/env.h" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/lib/gprpp/examine_stack.cc" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/lib/gprpp/examine_stack.h" role="src" />
|
||||
|
|
@ -1468,6 +1474,7 @@
|
|||
<file baseinstalldir="/" name="src/core/lib/promise/latch.h" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/lib/promise/loop.h" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/lib/promise/map.h" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/lib/promise/observable.h" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/lib/promise/party.cc" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/lib/promise/party.h" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/lib/promise/pipe.h" role="src" />
|
||||
|
|
|
|||
|
|
@ -3281,12 +3281,12 @@ grpc_cc_library(
|
|||
language = "c++",
|
||||
deps = [
|
||||
"arena",
|
||||
"call_destination",
|
||||
"grpc_service_config",
|
||||
"lb_policy",
|
||||
"unique_type_name",
|
||||
"//:call_tracer",
|
||||
"//:gpr_public_hdrs",
|
||||
"//:grpc_base",
|
||||
"//:gpr",
|
||||
"//:legacy_context",
|
||||
],
|
||||
)
|
||||
|
|
@ -7509,12 +7509,10 @@ grpc_cc_library(
|
|||
hdrs = [
|
||||
"lib/transport/call_filters.h",
|
||||
],
|
||||
external_deps = [
|
||||
"absl/log:check",
|
||||
"absl/log:log",
|
||||
],
|
||||
external_deps = ["absl/log:check"],
|
||||
deps = [
|
||||
"call_final_info",
|
||||
"dump_args",
|
||||
"latch",
|
||||
"map",
|
||||
"message",
|
||||
|
|
@ -7620,20 +7618,19 @@ grpc_cc_library(
|
|||
hdrs = [
|
||||
"lib/transport/call_spine.h",
|
||||
],
|
||||
external_deps = [
|
||||
"absl/log:check",
|
||||
"absl/log:log",
|
||||
],
|
||||
external_deps = ["absl/log:check"],
|
||||
deps = [
|
||||
"1999",
|
||||
"call_arena_allocator",
|
||||
"call_filters",
|
||||
"dual_ref_counted",
|
||||
"for_each",
|
||||
"if",
|
||||
"latch",
|
||||
"message",
|
||||
"metadata",
|
||||
"pipe",
|
||||
"prioritized_race",
|
||||
"promise_status",
|
||||
"status_flag",
|
||||
"try_seq",
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,245 @@
|
|||
//
|
||||
// Copyright 2015 gRPC authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
#ifndef GRPC_SRC_CORE_CLIENT_CHANNEL_CLIENT_CHANNEL_H
|
||||
#define GRPC_SRC_CORE_CLIENT_CHANNEL_CLIENT_CHANNEL_H
|
||||
|
||||
#include <grpc/support/port_platform.h>
|
||||
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/status/statusor.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
|
||||
#include "src/core/client_channel/client_channel_factory.h"
|
||||
#include "src/core/client_channel/config_selector.h"
|
||||
#include "src/core/client_channel/subchannel.h"
|
||||
#include "src/core/ext/filters/channel_idle/idle_filter_state.h"
|
||||
#include "src/core/lib/gprpp/single_set_ptr.h"
|
||||
#include "src/core/lib/promise/observable.h"
|
||||
#include "src/core/lib/surface/channel.h"
|
||||
#include "src/core/lib/transport/metadata.h"
|
||||
#include "src/core/load_balancing/lb_policy.h"
|
||||
#include "src/core/resolver/resolver.h"
|
||||
#include "src/core/service_config/service_config.h"
|
||||
|
||||
namespace grpc_core {
|
||||
|
||||
class ClientChannel : public Channel {
|
||||
public:
|
||||
using PickerObservable =
|
||||
Observable<RefCountedPtr<LoadBalancingPolicy::SubchannelPicker>>;
|
||||
|
||||
class CallDestinationFactory {
|
||||
public:
|
||||
struct RawPointerChannelArgTag {};
|
||||
|
||||
static absl::string_view ChannelArgName() {
|
||||
return "grpc.internal.client_channel_call_destination";
|
||||
}
|
||||
|
||||
virtual RefCountedPtr<UnstartedCallDestination> CreateCallDestination(
|
||||
PickerObservable) = 0;
|
||||
|
||||
protected:
|
||||
~CallDestinationFactory() = default;
|
||||
};
|
||||
|
||||
static absl::StatusOr<OrphanablePtr<Channel>> Create(
|
||||
std::string target, ChannelArgs channel_args);
|
||||
|
||||
// Do not instantiate directly -- use Create() instead.
|
||||
ClientChannel(std::string target_uri, ChannelArgs args,
|
||||
std::string uri_to_resolve,
|
||||
RefCountedPtr<ServiceConfig> default_service_config,
|
||||
ClientChannelFactory* client_channel_factory,
|
||||
CallDestinationFactory* call_destination_factory);
|
||||
|
||||
~ClientChannel() override;
|
||||
|
||||
void Orphan() override;
|
||||
|
||||
grpc_call* CreateCall(grpc_call* parent_call, uint32_t propagation_mask,
|
||||
grpc_completion_queue* cq,
|
||||
grpc_pollset_set* /*pollset_set_alternative*/,
|
||||
Slice path, absl::optional<Slice> authority,
|
||||
Timestamp deadline, bool registered_method) override;
|
||||
|
||||
CallInitiator CreateCall(ClientMetadataHandle client_initial_metadata);
|
||||
|
||||
grpc_event_engine::experimental::EventEngine* event_engine() const override {
|
||||
return event_engine_.get();
|
||||
}
|
||||
|
||||
// TODO(ctiller): lame channels
|
||||
bool IsLame() const override { return false; }
|
||||
|
||||
bool SupportsConnectivityWatcher() const override { return true; }
|
||||
|
||||
// Returns the current connectivity state. If try_to_connect is true,
|
||||
// triggers a connection attempt if not already connected.
|
||||
grpc_connectivity_state CheckConnectivityState(bool try_to_connect) override;
|
||||
|
||||
void WatchConnectivityState(grpc_connectivity_state last_observed_state,
|
||||
Timestamp deadline, grpc_completion_queue* cq,
|
||||
void* tag) override;
|
||||
|
||||
// Starts and stops a connectivity watch. The watcher will be initially
|
||||
// notified as soon as the state changes from initial_state and then on
|
||||
// every subsequent state change until either the watch is stopped or
|
||||
// it is notified that the state has changed to SHUTDOWN.
|
||||
//
|
||||
// This is intended to be used when starting watches from code inside of
|
||||
// C-core (e.g., for a nested control plane channel for things like xds).
|
||||
void AddConnectivityWatcher(
|
||||
grpc_connectivity_state initial_state,
|
||||
OrphanablePtr<AsyncConnectivityStateWatcherInterface> watcher) override;
|
||||
void RemoveConnectivityWatcher(
|
||||
AsyncConnectivityStateWatcherInterface* watcher) override;
|
||||
|
||||
void GetInfo(const grpc_channel_info* channel_info) override;
|
||||
|
||||
void ResetConnectionBackoff() override;
|
||||
|
||||
void Ping(grpc_completion_queue* cq, void* tag) override;
|
||||
|
||||
// Flag that this object gets stored in channel args as a raw pointer.
|
||||
struct RawPointerChannelArgTag {};
|
||||
static absl::string_view ChannelArgName() {
|
||||
return "grpc.internal.client_channel";
|
||||
}
|
||||
|
||||
private:
|
||||
class ClientChannelControlHelper;
|
||||
class ResolverResultHandler;
|
||||
class SubchannelWrapper;
|
||||
|
||||
void CreateResolverLocked() ABSL_EXCLUSIVE_LOCKS_REQUIRED(*work_serializer_);
|
||||
void DestroyResolverAndLbPolicyLocked()
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(*work_serializer_);
|
||||
|
||||
void TryToConnectLocked() ABSL_EXCLUSIVE_LOCKS_REQUIRED(*work_serializer_);
|
||||
|
||||
void OnResolverResultChangedLocked(Resolver::Result result)
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(*work_serializer_);
|
||||
void OnResolverErrorLocked(absl::Status status)
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(*work_serializer_);
|
||||
|
||||
absl::Status CreateOrUpdateLbPolicyLocked(
|
||||
RefCountedPtr<LoadBalancingPolicy::Config> lb_policy_config,
|
||||
const absl::optional<std::string>& health_check_service_name,
|
||||
Resolver::Result result) ABSL_EXCLUSIVE_LOCKS_REQUIRED(*work_serializer_);
|
||||
OrphanablePtr<LoadBalancingPolicy> CreateLbPolicyLocked(
|
||||
const ChannelArgs& args) ABSL_EXCLUSIVE_LOCKS_REQUIRED(*work_serializer_);
|
||||
|
||||
void UpdateServiceConfigInControlPlaneLocked(
|
||||
RefCountedPtr<ServiceConfig> service_config,
|
||||
RefCountedPtr<ConfigSelector> config_selector, std::string lb_policy_name)
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(*work_serializer_);
|
||||
|
||||
void UpdateServiceConfigInDataPlaneLocked()
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(*work_serializer_);
|
||||
|
||||
void UpdateStateLocked(grpc_connectivity_state state,
|
||||
const absl::Status& status, const char* reason)
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(*work_serializer_);
|
||||
|
||||
void UpdateStateAndPickerLocked(
|
||||
grpc_connectivity_state state, const absl::Status& status,
|
||||
const char* reason,
|
||||
RefCountedPtr<LoadBalancingPolicy::SubchannelPicker> picker)
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(*work_serializer_);
|
||||
|
||||
void StartIdleTimer();
|
||||
|
||||
// Applies service config settings from config_selector to the call.
|
||||
// May modify call context and client_initial_metadata.
|
||||
absl::Status ApplyServiceConfigToCall(
|
||||
ConfigSelector& config_selector,
|
||||
ClientMetadata& client_initial_metadata) const;
|
||||
|
||||
const ChannelArgs channel_args_;
|
||||
const std::shared_ptr<grpc_event_engine::experimental::EventEngine>
|
||||
event_engine_;
|
||||
const std::string uri_to_resolve_;
|
||||
const size_t service_config_parser_index_;
|
||||
const RefCountedPtr<ServiceConfig> default_service_config_;
|
||||
ClientChannelFactory* const client_channel_factory_;
|
||||
const std::string default_authority_;
|
||||
channelz::ChannelNode* const channelz_node_;
|
||||
// TODO(ctiller): unify with Channel
|
||||
const RefCountedPtr<CallArenaAllocator> call_arena_allocator_;
|
||||
GlobalStatsPluginRegistry::StatsPluginGroup stats_plugin_group_;
|
||||
|
||||
//
|
||||
// Idleness state.
|
||||
//
|
||||
const Duration idle_timeout_;
|
||||
IdleFilterState idle_state_{false};
|
||||
SingleSetPtr<Activity, typename ActivityPtr::deleter_type> idle_activity_;
|
||||
|
||||
//
|
||||
// Fields related to name resolution.
|
||||
//
|
||||
struct ResolverDataForCalls {
|
||||
RefCountedPtr<ConfigSelector> config_selector;
|
||||
RefCountedPtr<UnstartedCallDestination> call_destination;
|
||||
};
|
||||
Observable<absl::StatusOr<ResolverDataForCalls>> resolver_data_for_calls_;
|
||||
|
||||
//
|
||||
// Fields related to LB picks.
|
||||
//
|
||||
PickerObservable picker_;
|
||||
const RefCountedPtr<UnstartedCallDestination> call_destination_;
|
||||
|
||||
//
|
||||
// Fields used in the control plane. Guarded by work_serializer.
|
||||
//
|
||||
std::shared_ptr<WorkSerializer> work_serializer_;
|
||||
ConnectivityStateTracker state_tracker_ ABSL_GUARDED_BY(*work_serializer_);
|
||||
OrphanablePtr<Resolver> resolver_ ABSL_GUARDED_BY(*work_serializer_);
|
||||
bool previous_resolution_contained_addresses_
|
||||
ABSL_GUARDED_BY(*work_serializer_) = false;
|
||||
RefCountedPtr<ServiceConfig> saved_service_config_
|
||||
ABSL_GUARDED_BY(*work_serializer_);
|
||||
RefCountedPtr<ConfigSelector> saved_config_selector_
|
||||
ABSL_GUARDED_BY(*work_serializer_);
|
||||
OrphanablePtr<LoadBalancingPolicy> lb_policy_
|
||||
ABSL_GUARDED_BY(*work_serializer_);
|
||||
RefCountedPtr<SubchannelPoolInterface> subchannel_pool_
|
||||
ABSL_GUARDED_BY(*work_serializer_);
|
||||
// The number of SubchannelWrapper instances referencing a given Subchannel.
|
||||
std::map<Subchannel*, int> subchannel_refcount_map_
|
||||
ABSL_GUARDED_BY(*work_serializer_);
|
||||
// The set of SubchannelWrappers that currently exist.
|
||||
// No need to hold a ref, since the set is updated in the control-plane
|
||||
// work_serializer when the SubchannelWrappers are created and destroyed.
|
||||
absl::flat_hash_set<SubchannelWrapper*> subchannel_wrappers_
|
||||
ABSL_GUARDED_BY(*work_serializer_);
|
||||
int keepalive_time_ ABSL_GUARDED_BY(*work_serializer_) = -1;
|
||||
absl::Status disconnect_error_ ABSL_GUARDED_BY(*work_serializer_);
|
||||
|
||||
//
|
||||
// Fields accessed via GetChannelInfo().
|
||||
//
|
||||
Mutex info_mu_;
|
||||
std::string info_lb_policy_name_ ABSL_GUARDED_BY(info_mu_);
|
||||
std::string info_service_config_json_ ABSL_GUARDED_BY(info_mu_);
|
||||
};
|
||||
|
||||
} // namespace grpc_core
|
||||
|
||||
#endif // GRPC_SRC_CORE_CLIENT_CHANNEL_CLIENT_CHANNEL_H
|
||||
|
|
@ -1109,7 +1109,7 @@ class ClientChannelFilter::ClientChannelControlHelper final
|
|||
const ChannelArgs& args) override
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(*chand_->work_serializer_) {
|
||||
if (chand_->resolver_ == nullptr) return nullptr; // Shutting down.
|
||||
ChannelArgs subchannel_args = ClientChannelFilter::MakeSubchannelArgs(
|
||||
ChannelArgs subchannel_args = Subchannel::MakeSubchannelArgs(
|
||||
args, per_address_args, chand_->subchannel_pool_,
|
||||
chand_->default_authority_);
|
||||
// Create subchannel.
|
||||
|
|
@ -1359,31 +1359,6 @@ ClientChannelFilter::CreateLoadBalancedCallPromise(
|
|||
return call_ptr->MakeCallPromise(std::move(call_args), std::move(lb_call));
|
||||
}
|
||||
|
||||
ChannelArgs ClientChannelFilter::MakeSubchannelArgs(
|
||||
const ChannelArgs& channel_args, const ChannelArgs& address_args,
|
||||
const RefCountedPtr<SubchannelPoolInterface>& subchannel_pool,
|
||||
const std::string& channel_default_authority) {
|
||||
// Note that we start with the channel-level args and then apply the
|
||||
// per-address args, so that if a value is present in both, the one
|
||||
// in the channel-level args is used. This is particularly important
|
||||
// for the GRPC_ARG_DEFAULT_AUTHORITY arg, which we want to allow
|
||||
// resolvers to set on a per-address basis only if the application
|
||||
// did not explicitly set it at the channel level.
|
||||
return channel_args.UnionWith(address_args)
|
||||
.SetObject(subchannel_pool)
|
||||
// If we haven't already set the default authority arg (i.e., it
|
||||
// was not explicitly set by the application nor overridden by
|
||||
// the resolver), add it from the channel's default.
|
||||
.SetIfUnset(GRPC_ARG_DEFAULT_AUTHORITY, channel_default_authority)
|
||||
// Remove channel args that should not affect subchannel
|
||||
// uniqueness.
|
||||
.Remove(GRPC_ARG_HEALTH_CHECK_SERVICE_NAME)
|
||||
.Remove(GRPC_ARG_INHIBIT_HEALTH_CHECKING)
|
||||
.Remove(GRPC_ARG_CHANNELZ_CHANNEL_NODE)
|
||||
// Remove all keys with the no-subchannel prefix.
|
||||
.RemoveAllKeysWithPrefix(GRPC_ARG_NO_SUBCHANNEL_PREFIX);
|
||||
}
|
||||
|
||||
void ClientChannelFilter::ReprocessQueuedResolverCalls() {
|
||||
for (CallData* calld : resolver_queued_calls_) {
|
||||
calld->RemoveCallFromResolverQueuedCallsLocked();
|
||||
|
|
|
|||
|
|
@ -86,9 +86,6 @@
|
|||
// Channel arg key for server URI string.
|
||||
#define GRPC_ARG_SERVER_URI "grpc.server_uri"
|
||||
|
||||
// Channel arg containing a pointer to the ClientChannelFilter object.
|
||||
#define GRPC_ARG_CLIENT_CHANNEL "grpc.internal.client_channel_filter"
|
||||
|
||||
// Max number of batches that can be pending on a call at any given
|
||||
// time. This includes one batch for each of the following ops:
|
||||
// recv_initial_metadata
|
||||
|
|
@ -112,7 +109,9 @@ class ClientChannelFilter final {
|
|||
|
||||
// Flag that this object gets stored in channel args as a raw pointer.
|
||||
struct RawPointerChannelArgTag {};
|
||||
static absl::string_view ChannelArgName() { return GRPC_ARG_CLIENT_CHANNEL; }
|
||||
static absl::string_view ChannelArgName() {
|
||||
return "grpc.internal.client_channel_filter";
|
||||
}
|
||||
|
||||
static ArenaPromise<ServerMetadataHandle> MakeCallPromise(
|
||||
grpc_channel_element* elem, CallArgs call_args,
|
||||
|
|
@ -166,12 +165,6 @@ class ClientChannelFilter final {
|
|||
CallArgs call_args, absl::AnyInvocable<void()> on_commit,
|
||||
bool is_transparent_retry);
|
||||
|
||||
// Exposed for testing only.
|
||||
static ChannelArgs MakeSubchannelArgs(
|
||||
const ChannelArgs& channel_args, const ChannelArgs& address_args,
|
||||
const RefCountedPtr<SubchannelPoolInterface>& subchannel_pool,
|
||||
const std::string& channel_default_authority);
|
||||
|
||||
private:
|
||||
class CallData;
|
||||
class FilterBasedCallData;
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include "src/core/lib/channel/context.h"
|
||||
#include "src/core/lib/gprpp/unique_type_name.h"
|
||||
#include "src/core/lib/resource_quota/arena.h"
|
||||
#include "src/core/lib/transport/call_destination.h"
|
||||
#include "src/core/load_balancing/lb_policy.h"
|
||||
#include "src/core/service_config/service_config_call_data.h"
|
||||
#include "src/core/telemetry/call_tracer.h"
|
||||
|
|
@ -75,6 +76,13 @@ class ClientChannelServiceConfigCallData final : public ServiceConfigCallData {
|
|||
absl::AnyInvocable<void()> on_commit_;
|
||||
};
|
||||
|
||||
class SubchannelInterfaceWithCallDestination : public SubchannelInterface {
|
||||
public:
|
||||
using SubchannelInterface::SubchannelInterface;
|
||||
// Obtain the call destination for this subchannel.
|
||||
virtual RefCountedPtr<UnstartedCallDestination> call_destination() = 0;
|
||||
};
|
||||
|
||||
} // namespace grpc_core
|
||||
|
||||
#endif // GRPC_SRC_CORE_CLIENT_CHANNEL_CLIENT_CHANNEL_INTERNAL_H
|
||||
|
|
|
|||
|
|
@ -0,0 +1,335 @@
|
|||
// Copyright 2024 gRPC authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "src/core/client_channel/load_balanced_call_destination.h"
|
||||
|
||||
#include "src/core/client_channel/client_channel.h"
|
||||
#include "src/core/client_channel/client_channel_internal.h"
|
||||
#include "src/core/client_channel/subchannel.h"
|
||||
#include "src/core/lib/channel/status_util.h"
|
||||
#include "src/core/lib/promise/loop.h"
|
||||
#include "src/core/telemetry/call_tracer.h"
|
||||
|
||||
namespace grpc_core {
|
||||
|
||||
// Defined in legacy client channel filter.
|
||||
// TODO(roth): Move these here when we remove the legacy filter.
|
||||
extern TraceFlag grpc_client_channel_trace;
|
||||
extern TraceFlag grpc_client_channel_call_trace;
|
||||
extern TraceFlag grpc_client_channel_lb_call_trace;
|
||||
|
||||
namespace {
|
||||
|
||||
class LbMetadata : public LoadBalancingPolicy::MetadataInterface {
|
||||
public:
|
||||
explicit LbMetadata(grpc_metadata_batch* batch) : batch_(batch) {}
|
||||
|
||||
void Add(absl::string_view key, absl::string_view value) override {
|
||||
if (batch_ == nullptr) return;
|
||||
// Gross, egregious hack to support legacy grpclb behavior.
|
||||
// TODO(ctiller): Use a promise context for this once that plumbing is done.
|
||||
if (key == GrpcLbClientStatsMetadata::key()) {
|
||||
batch_->Set(
|
||||
GrpcLbClientStatsMetadata(),
|
||||
const_cast<GrpcLbClientStats*>(
|
||||
reinterpret_cast<const GrpcLbClientStats*>(value.data())));
|
||||
return;
|
||||
}
|
||||
batch_->Append(key, Slice::FromStaticString(value),
|
||||
[key](absl::string_view error, const Slice& value) {
|
||||
gpr_log(GPR_ERROR, "%s",
|
||||
absl::StrCat(error, " key:", key,
|
||||
" value:", value.as_string_view())
|
||||
.c_str());
|
||||
});
|
||||
}
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> TestOnlyCopyToVector()
|
||||
override {
|
||||
if (batch_ == nullptr) return {};
|
||||
Encoder encoder;
|
||||
batch_->Encode(&encoder);
|
||||
return encoder.Take();
|
||||
}
|
||||
|
||||
absl::optional<absl::string_view> Lookup(absl::string_view key,
|
||||
std::string* buffer) const override {
|
||||
if (batch_ == nullptr) return absl::nullopt;
|
||||
return batch_->GetStringValue(key, buffer);
|
||||
}
|
||||
|
||||
private:
|
||||
class Encoder {
|
||||
public:
|
||||
void Encode(const Slice& key, const Slice& value) {
|
||||
out_.emplace_back(std::string(key.as_string_view()),
|
||||
std::string(value.as_string_view()));
|
||||
}
|
||||
|
||||
template <class Which>
|
||||
void Encode(Which, const typename Which::ValueType& value) {
|
||||
auto value_slice = Which::Encode(value);
|
||||
out_.emplace_back(std::string(Which::key()),
|
||||
std::string(value_slice.as_string_view()));
|
||||
}
|
||||
|
||||
void Encode(GrpcTimeoutMetadata,
|
||||
const typename GrpcTimeoutMetadata::ValueType&) {}
|
||||
void Encode(HttpPathMetadata, const Slice&) {}
|
||||
void Encode(HttpMethodMetadata,
|
||||
const typename HttpMethodMetadata::ValueType&) {}
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> Take() {
|
||||
return std::move(out_);
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::pair<std::string, std::string>> out_;
|
||||
};
|
||||
|
||||
grpc_metadata_batch* batch_;
|
||||
};
|
||||
|
||||
void MaybeCreateCallAttemptTracer(bool is_transparent_retry) {
|
||||
auto* call_tracer = MaybeGetContext<ClientCallTracer>();
|
||||
if (call_tracer == nullptr) return;
|
||||
auto* tracer = call_tracer->StartNewAttempt(is_transparent_retry);
|
||||
SetContext<CallTracerInterface>(tracer);
|
||||
}
|
||||
|
||||
class LbCallState : public ClientChannelLbCallState {
|
||||
public:
|
||||
void* Alloc(size_t size) override { return GetContext<Arena>()->Alloc(size); }
|
||||
|
||||
// Internal API to allow first-party LB policies to access per-call
|
||||
// attributes set by the ConfigSelector.
|
||||
ServiceConfigCallData::CallAttributeInterface* GetCallAttribute(
|
||||
UniqueTypeName type) const override {
|
||||
auto* service_config_call_data = GetContext<ServiceConfigCallData>();
|
||||
return service_config_call_data->GetCallAttribute(type);
|
||||
}
|
||||
|
||||
ClientCallTracer::CallAttemptTracer* GetCallAttemptTracer() const override {
|
||||
auto* legacy_context = GetContext<grpc_call_context_element>();
|
||||
return static_cast<ClientCallTracer::CallAttemptTracer*>(
|
||||
legacy_context[GRPC_CONTEXT_CALL_TRACER].value);
|
||||
}
|
||||
};
|
||||
|
||||
// TODO(roth): Remove this in favor of the gprpp Match() function once
|
||||
// we can do that without breaking lock annotations.
|
||||
template <typename T>
|
||||
T HandlePickResult(
|
||||
LoadBalancingPolicy::PickResult* result,
|
||||
std::function<T(LoadBalancingPolicy::PickResult::Complete*)> complete_func,
|
||||
std::function<T(LoadBalancingPolicy::PickResult::Queue*)> queue_func,
|
||||
std::function<T(LoadBalancingPolicy::PickResult::Fail*)> fail_func,
|
||||
std::function<T(LoadBalancingPolicy::PickResult::Drop*)> drop_func) {
|
||||
auto* complete_pick =
|
||||
absl::get_if<LoadBalancingPolicy::PickResult::Complete>(&result->result);
|
||||
if (complete_pick != nullptr) {
|
||||
return complete_func(complete_pick);
|
||||
}
|
||||
auto* queue_pick =
|
||||
absl::get_if<LoadBalancingPolicy::PickResult::Queue>(&result->result);
|
||||
if (queue_pick != nullptr) {
|
||||
return queue_func(queue_pick);
|
||||
}
|
||||
auto* fail_pick =
|
||||
absl::get_if<LoadBalancingPolicy::PickResult::Fail>(&result->result);
|
||||
if (fail_pick != nullptr) {
|
||||
return fail_func(fail_pick);
|
||||
}
|
||||
auto* drop_pick =
|
||||
absl::get_if<LoadBalancingPolicy::PickResult::Drop>(&result->result);
|
||||
CHECK(drop_pick != nullptr);
|
||||
return drop_func(drop_pick);
|
||||
}
|
||||
|
||||
// Does an LB pick for a call. Returns one of the following things:
|
||||
// - Continue{}, meaning to queue the pick
|
||||
// - a non-OK status, meaning to fail the call
|
||||
// - a call destination, meaning that the pick is complete
|
||||
// When the pick is complete, pushes client_initial_metadata onto
|
||||
// call_initiator. Also adds the subchannel call tracker (if any) to
|
||||
// context.
|
||||
LoopCtl<absl::StatusOr<RefCountedPtr<UnstartedCallDestination>>> PickSubchannel(
|
||||
LoadBalancingPolicy::SubchannelPicker& picker,
|
||||
UnstartedCallHandler& unstarted_handler) {
|
||||
// Perform LB pick.
|
||||
auto& client_initial_metadata =
|
||||
unstarted_handler.UnprocessedClientInitialMetadata();
|
||||
LoadBalancingPolicy::PickArgs pick_args;
|
||||
Slice* path = client_initial_metadata.get_pointer(HttpPathMetadata());
|
||||
CHECK(path != nullptr);
|
||||
pick_args.path = path->as_string_view();
|
||||
LbCallState lb_call_state;
|
||||
pick_args.call_state = &lb_call_state;
|
||||
LbMetadata initial_metadata(&client_initial_metadata);
|
||||
pick_args.initial_metadata = &initial_metadata;
|
||||
auto result = picker.Pick(pick_args);
|
||||
// Handle result.
|
||||
return HandlePickResult<
|
||||
LoopCtl<absl::StatusOr<RefCountedPtr<UnstartedCallDestination>>>>(
|
||||
&result,
|
||||
// CompletePick
|
||||
[&](LoadBalancingPolicy::PickResult::Complete* complete_pick)
|
||||
-> LoopCtl<absl::StatusOr<RefCountedPtr<UnstartedCallDestination>>> {
|
||||
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) {
|
||||
gpr_log(GPR_INFO,
|
||||
"client_channel: %sLB pick succeeded: subchannel=%p",
|
||||
GetContext<Activity>()->DebugTag().c_str(),
|
||||
complete_pick->subchannel.get());
|
||||
}
|
||||
CHECK(complete_pick->subchannel != nullptr);
|
||||
// Grab a ref to the call destination while we're still
|
||||
// holding the data plane mutex.
|
||||
auto call_destination =
|
||||
DownCast<SubchannelInterfaceWithCallDestination*>(
|
||||
complete_pick->subchannel.get())
|
||||
->call_destination();
|
||||
// If the subchannel has no call destination (e.g., if the
|
||||
// subchannel has moved out of state READY but the LB policy hasn't
|
||||
// yet seen that change and given us a new picker), then just
|
||||
// queue the pick. We'll try again as soon as we get a new picker.
|
||||
if (call_destination == nullptr) {
|
||||
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) {
|
||||
gpr_log(GPR_INFO,
|
||||
"client_channel: %ssubchannel returned by LB picker "
|
||||
"has no connected subchannel; queueing pick",
|
||||
GetContext<Activity>()->DebugTag().c_str());
|
||||
}
|
||||
return Continue{};
|
||||
}
|
||||
// If the LB policy returned a call tracker, inform it that the
|
||||
// call is starting and add it to context, so that we can notify
|
||||
// it when the call finishes.
|
||||
if (complete_pick->subchannel_call_tracker != nullptr) {
|
||||
complete_pick->subchannel_call_tracker->Start();
|
||||
SetContext(complete_pick->subchannel_call_tracker.release());
|
||||
}
|
||||
// Return the connected subchannel.
|
||||
return call_destination;
|
||||
},
|
||||
// QueuePick
|
||||
[&](LoadBalancingPolicy::PickResult::Queue* /*queue_pick*/) {
|
||||
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) {
|
||||
gpr_log(GPR_INFO, "client_channel: %sLB pick queued",
|
||||
GetContext<Activity>()->DebugTag().c_str());
|
||||
}
|
||||
return Continue{};
|
||||
},
|
||||
// FailPick
|
||||
[&](LoadBalancingPolicy::PickResult::Fail* fail_pick)
|
||||
-> LoopCtl<absl::StatusOr<RefCountedPtr<UnstartedCallDestination>>> {
|
||||
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) {
|
||||
gpr_log(GPR_INFO, "client_channel: %sLB pick failed: %s",
|
||||
GetContext<Activity>()->DebugTag().c_str(),
|
||||
fail_pick->status.ToString().c_str());
|
||||
}
|
||||
// If wait_for_ready is false, then the error indicates the RPC
|
||||
// attempt's final status.
|
||||
if (!unstarted_handler.UnprocessedClientInitialMetadata()
|
||||
.GetOrCreatePointer(WaitForReady())
|
||||
->value) {
|
||||
return MaybeRewriteIllegalStatusCode(std::move(fail_pick->status),
|
||||
"LB pick");
|
||||
}
|
||||
// If wait_for_ready is true, then queue to retry when we get a new
|
||||
// picker.
|
||||
return Continue{};
|
||||
},
|
||||
// DropPick
|
||||
[&](LoadBalancingPolicy::PickResult::Drop* drop_pick)
|
||||
-> LoopCtl<absl::StatusOr<RefCountedPtr<UnstartedCallDestination>>> {
|
||||
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) {
|
||||
gpr_log(GPR_INFO, "client_channel: %sLB pick dropped: %s",
|
||||
GetContext<Activity>()->DebugTag().c_str(),
|
||||
drop_pick->status.ToString().c_str());
|
||||
}
|
||||
return grpc_error_set_int(MaybeRewriteIllegalStatusCode(
|
||||
std::move(drop_pick->status), "LB drop"),
|
||||
StatusIntProperty::kLbPolicyDrop, 1);
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void LoadBalancedCallDestination::StartCall(
|
||||
UnstartedCallHandler unstarted_handler) {
|
||||
// If there is a call tracer, create a call attempt tracer.
|
||||
bool* is_transparent_retry_metadata =
|
||||
unstarted_handler.UnprocessedClientInitialMetadata().get_pointer(
|
||||
IsTransparentRetry());
|
||||
bool is_transparent_retry = is_transparent_retry_metadata != nullptr
|
||||
? *is_transparent_retry_metadata
|
||||
: false;
|
||||
MaybeCreateCallAttemptTracer(is_transparent_retry);
|
||||
// Spawn a promise to do the LB pick.
|
||||
// This will eventually start the call.
|
||||
unstarted_handler.SpawnGuardedUntilCallCompletes(
|
||||
"lb_pick", [unstarted_handler, picker = picker_]() mutable {
|
||||
return Map(
|
||||
// Wait for the LB picker.
|
||||
CheckDelayed(Loop(
|
||||
[last_picker =
|
||||
RefCountedPtr<LoadBalancingPolicy::SubchannelPicker>(),
|
||||
unstarted_handler, picker]() mutable {
|
||||
return Map(
|
||||
picker.Next(last_picker),
|
||||
[unstarted_handler, &last_picker](
|
||||
RefCountedPtr<LoadBalancingPolicy::SubchannelPicker>
|
||||
picker) mutable {
|
||||
last_picker = std::move(picker);
|
||||
// Returns 3 possible things:
|
||||
// - Continue to queue the pick
|
||||
// - non-OK status to fail the pick
|
||||
// - a connected subchannel to complete the pick
|
||||
return PickSubchannel(*last_picker, unstarted_handler);
|
||||
});
|
||||
})),
|
||||
// Create call stack on the connected subchannel.
|
||||
[unstarted_handler](
|
||||
std::tuple<
|
||||
absl::StatusOr<RefCountedPtr<UnstartedCallDestination>>,
|
||||
bool>
|
||||
pick_result) {
|
||||
auto& call_destination = std::get<0>(pick_result);
|
||||
const bool was_queued = std::get<1>(pick_result);
|
||||
if (!call_destination.ok()) {
|
||||
return call_destination.status();
|
||||
}
|
||||
// LB pick is done, so indicate that we've committed.
|
||||
auto* on_commit = MaybeGetContext<LbOnCommit>();
|
||||
if (on_commit != nullptr && *on_commit != nullptr) {
|
||||
(*on_commit)();
|
||||
}
|
||||
// If it was queued, add a trace annotation.
|
||||
if (was_queued) {
|
||||
auto* tracer =
|
||||
MaybeGetContext<ClientCallTracer::CallAttemptTracer>();
|
||||
if (tracer != nullptr) {
|
||||
tracer->RecordAnnotation("Delayed LB pick complete.");
|
||||
}
|
||||
}
|
||||
// Delegate to connected subchannel.
|
||||
// TODO(ctiller): need to insert LbCallTracingFilter at the top of
|
||||
// the stack
|
||||
(*call_destination)->StartCall(unstarted_handler);
|
||||
return absl::OkStatus();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace grpc_core
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
// Copyright 2024 gRPC authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef GRPC_SRC_CORE_CLIENT_CHANNEL_LOAD_BALANCED_CALL_DESTINATION_H
|
||||
#define GRPC_SRC_CORE_CLIENT_CHANNEL_LOAD_BALANCED_CALL_DESTINATION_H
|
||||
|
||||
#include "absl/functional/any_invocable.h"
|
||||
|
||||
#include "src/core/client_channel/client_channel.h"
|
||||
#include "src/core/lib/promise/context.h"
|
||||
#include "src/core/lib/transport/call_destination.h"
|
||||
#include "src/core/load_balancing/lb_policy.h"
|
||||
|
||||
namespace grpc_core {
|
||||
|
||||
// Context type for LB on_commit callback.
|
||||
// TODO(ctiller): make this a struct, so we don't accidentally alias context
|
||||
// types
|
||||
using LbOnCommit = absl::AnyInvocable<void()>;
|
||||
template <>
|
||||
struct ContextType<LbOnCommit> {};
|
||||
|
||||
class LoadBalancedCallDestination final : public UnstartedCallDestination {
|
||||
public:
|
||||
explicit LoadBalancedCallDestination(ClientChannel::PickerObservable picker)
|
||||
: picker_(std::move(picker)) {}
|
||||
|
||||
void Orphaned() override {}
|
||||
|
||||
void StartCall(UnstartedCallHandler unstarted_handler) override;
|
||||
|
||||
private:
|
||||
ClientChannel::PickerObservable picker_;
|
||||
};
|
||||
|
||||
} // namespace grpc_core
|
||||
|
||||
#endif // GRPC_SRC_CORE_CLIENT_CHANNEL_LOAD_BALANCED_CALL_DESTINATION_H
|
||||
|
|
@ -41,6 +41,7 @@
|
|||
|
||||
#include "src/core/channelz/channel_trace.h"
|
||||
#include "src/core/channelz/channelz.h"
|
||||
#include "src/core/client_channel/client_channel_internal.h"
|
||||
#include "src/core/client_channel/subchannel_pool_interface.h"
|
||||
#include "src/core/handshaker/proxy_mapper_registry.h"
|
||||
#include "src/core/lib/address_utils/sockaddr_utils.h"
|
||||
|
|
@ -50,7 +51,10 @@
|
|||
#include "src/core/lib/channel/channel_stack_builder_impl.h"
|
||||
#include "src/core/lib/config/core_configuration.h"
|
||||
#include "src/core/lib/debug/trace.h"
|
||||
#include "src/core/lib/experiments/experiments.h"
|
||||
#include "src/core/lib/gprpp/debug_location.h"
|
||||
#include "src/core/lib/gprpp/orphanable.h"
|
||||
#include "src/core/lib/gprpp/ref_counted.h"
|
||||
#include "src/core/lib/gprpp/ref_counted_ptr.h"
|
||||
#include "src/core/lib/gprpp/status_helper.h"
|
||||
#include "src/core/lib/gprpp/sync.h"
|
||||
|
|
@ -64,6 +68,7 @@
|
|||
#include "src/core/lib/surface/init_internally.h"
|
||||
#include "src/core/lib/transport/connectivity_state.h"
|
||||
#include "src/core/lib/transport/error_utils.h"
|
||||
#include "src/core/lib/transport/interception_chain.h"
|
||||
#include "src/core/lib/transport/transport.h"
|
||||
#include "src/core/telemetry/stats.h"
|
||||
#include "src/core/telemetry/stats_data.h"
|
||||
|
|
@ -97,75 +102,168 @@ DebugOnlyTraceFlag grpc_trace_subchannel_refcount(false, "subchannel_refcount");
|
|||
//
|
||||
|
||||
ConnectedSubchannel::ConnectedSubchannel(
|
||||
grpc_channel_stack* channel_stack, const ChannelArgs& args,
|
||||
const ChannelArgs& args,
|
||||
RefCountedPtr<channelz::SubchannelNode> channelz_subchannel)
|
||||
: RefCounted<ConnectedSubchannel>(
|
||||
GRPC_TRACE_FLAG_ENABLED(grpc_trace_subchannel_refcount)
|
||||
? "ConnectedSubchannel"
|
||||
: nullptr),
|
||||
channel_stack_(channel_stack),
|
||||
args_(args),
|
||||
channelz_subchannel_(std::move(channelz_subchannel)) {}
|
||||
|
||||
ConnectedSubchannel::~ConnectedSubchannel() {
|
||||
GRPC_CHANNEL_STACK_UNREF(channel_stack_, "connected_subchannel_dtor");
|
||||
}
|
||||
//
|
||||
// LegacyConnectedSubchannel
|
||||
//
|
||||
|
||||
void ConnectedSubchannel::StartWatch(
|
||||
grpc_pollset_set* interested_parties,
|
||||
OrphanablePtr<ConnectivityStateWatcherInterface> watcher) {
|
||||
grpc_transport_op* op = grpc_make_transport_op(nullptr);
|
||||
op->start_connectivity_watch = std::move(watcher);
|
||||
op->start_connectivity_watch_state = GRPC_CHANNEL_READY;
|
||||
op->bind_pollset_set = interested_parties;
|
||||
grpc_channel_element* elem = grpc_channel_stack_element(channel_stack_, 0);
|
||||
elem->filter->start_transport_op(elem, op);
|
||||
}
|
||||
class LegacyConnectedSubchannel : public ConnectedSubchannel {
|
||||
public:
|
||||
LegacyConnectedSubchannel(
|
||||
RefCountedPtr<grpc_channel_stack> channel_stack, const ChannelArgs& args,
|
||||
RefCountedPtr<channelz::SubchannelNode> channelz_subchannel)
|
||||
: ConnectedSubchannel(args, std::move(channelz_subchannel)),
|
||||
channel_stack_(std::move(channel_stack)) {}
|
||||
|
||||
void ConnectedSubchannel::Ping(grpc_closure* on_initiate,
|
||||
grpc_closure* on_ack) {
|
||||
grpc_transport_op* op = grpc_make_transport_op(nullptr);
|
||||
grpc_channel_element* elem;
|
||||
op->send_ping.on_initiate = on_initiate;
|
||||
op->send_ping.on_ack = on_ack;
|
||||
elem = grpc_channel_stack_element(channel_stack_, 0);
|
||||
elem->filter->start_transport_op(elem, op);
|
||||
}
|
||||
|
||||
size_t ConnectedSubchannel::GetInitialCallSizeEstimate() const {
|
||||
return GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(SubchannelCall)) +
|
||||
channel_stack_->call_stack_size;
|
||||
}
|
||||
|
||||
ArenaPromise<ServerMetadataHandle> ConnectedSubchannel::MakeCallPromise(
|
||||
CallArgs call_args) {
|
||||
// If not using channelz, we just need to call the channel stack.
|
||||
if (channelz_subchannel() == nullptr) {
|
||||
return channel_stack_->MakeClientCallPromise(std::move(call_args));
|
||||
~LegacyConnectedSubchannel() override {
|
||||
channel_stack_.reset(DEBUG_LOCATION, "ConnectedSubchannel");
|
||||
}
|
||||
// Otherwise, we need to wrap the channel stack promise with code that
|
||||
// handles the channelz updates.
|
||||
return OnCancel(
|
||||
Seq(channel_stack_->MakeClientCallPromise(std::move(call_args)),
|
||||
[self = Ref()](ServerMetadataHandle metadata) {
|
||||
channelz::SubchannelNode* channelz_subchannel =
|
||||
self->channelz_subchannel();
|
||||
CHECK_NE(channelz_subchannel, nullptr);
|
||||
if (metadata->get(GrpcStatusMetadata())
|
||||
.value_or(GRPC_STATUS_UNKNOWN) != GRPC_STATUS_OK) {
|
||||
channelz_subchannel->RecordCallFailed();
|
||||
} else {
|
||||
channelz_subchannel->RecordCallSucceeded();
|
||||
}
|
||||
return metadata;
|
||||
}),
|
||||
[self = Ref()]() {
|
||||
channelz::SubchannelNode* channelz_subchannel =
|
||||
self->channelz_subchannel();
|
||||
CHECK_NE(channelz_subchannel, nullptr);
|
||||
channelz_subchannel->RecordCallFailed();
|
||||
});
|
||||
}
|
||||
|
||||
void StartWatch(
|
||||
grpc_pollset_set* interested_parties,
|
||||
OrphanablePtr<ConnectivityStateWatcherInterface> watcher) override {
|
||||
grpc_transport_op* op = grpc_make_transport_op(nullptr);
|
||||
op->start_connectivity_watch = std::move(watcher);
|
||||
op->start_connectivity_watch_state = GRPC_CHANNEL_READY;
|
||||
op->bind_pollset_set = interested_parties;
|
||||
grpc_channel_element* elem =
|
||||
grpc_channel_stack_element(channel_stack_.get(), 0);
|
||||
elem->filter->start_transport_op(elem, op);
|
||||
}
|
||||
|
||||
void Ping(absl::AnyInvocable<void(absl::Status)>) override {
|
||||
Crash("call v3 ping method called in legacy impl");
|
||||
}
|
||||
|
||||
RefCountedPtr<UnstartedCallDestination> unstarted_call_destination()
|
||||
const override {
|
||||
Crash("call v3 unstarted_call_destination method called in legacy impl");
|
||||
}
|
||||
|
||||
grpc_channel_stack* channel_stack() const override {
|
||||
return channel_stack_.get();
|
||||
}
|
||||
|
||||
size_t GetInitialCallSizeEstimate() const override {
|
||||
return GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(SubchannelCall)) +
|
||||
channel_stack_->call_stack_size;
|
||||
}
|
||||
|
||||
ArenaPromise<ServerMetadataHandle> MakeCallPromise(
|
||||
CallArgs call_args) override {
|
||||
// If not using channelz, we just need to call the channel stack.
|
||||
if (channelz_subchannel() == nullptr) {
|
||||
return channel_stack_->MakeClientCallPromise(std::move(call_args));
|
||||
}
|
||||
// Otherwise, we need to wrap the channel stack promise with code that
|
||||
// handles the channelz updates.
|
||||
return OnCancel(
|
||||
Seq(channel_stack_->MakeClientCallPromise(std::move(call_args)),
|
||||
[self = Ref()](ServerMetadataHandle metadata) {
|
||||
channelz::SubchannelNode* channelz_subchannel =
|
||||
self->channelz_subchannel();
|
||||
CHECK(channelz_subchannel != nullptr);
|
||||
if (metadata->get(GrpcStatusMetadata())
|
||||
.value_or(GRPC_STATUS_UNKNOWN) != GRPC_STATUS_OK) {
|
||||
channelz_subchannel->RecordCallFailed();
|
||||
} else {
|
||||
channelz_subchannel->RecordCallSucceeded();
|
||||
}
|
||||
return metadata;
|
||||
}),
|
||||
[self = Ref()]() {
|
||||
channelz::SubchannelNode* channelz_subchannel =
|
||||
self->channelz_subchannel();
|
||||
CHECK(channelz_subchannel != nullptr);
|
||||
channelz_subchannel->RecordCallFailed();
|
||||
});
|
||||
}
|
||||
|
||||
void Ping(grpc_closure* on_initiate, grpc_closure* on_ack) override {
|
||||
grpc_transport_op* op = grpc_make_transport_op(nullptr);
|
||||
op->send_ping.on_initiate = on_initiate;
|
||||
op->send_ping.on_ack = on_ack;
|
||||
grpc_channel_element* elem =
|
||||
grpc_channel_stack_element(channel_stack_.get(), 0);
|
||||
elem->filter->start_transport_op(elem, op);
|
||||
}
|
||||
|
||||
private:
|
||||
RefCountedPtr<grpc_channel_stack> channel_stack_;
|
||||
};
|
||||
|
||||
//
|
||||
// NewConnectedSubchannel
|
||||
//
|
||||
|
||||
class NewConnectedSubchannel : public ConnectedSubchannel {
|
||||
public:
|
||||
class TransportCallDestination final : public CallDestination {
|
||||
public:
|
||||
explicit TransportCallDestination(OrphanablePtr<ClientTransport> transport)
|
||||
: transport_(std::move(transport)) {}
|
||||
|
||||
ClientTransport* transport() { return transport_.get(); }
|
||||
|
||||
void HandleCall(CallHandler handler) override {
|
||||
transport_->StartCall(std::move(handler));
|
||||
}
|
||||
|
||||
void Orphaned() override { transport_.reset(); }
|
||||
|
||||
private:
|
||||
OrphanablePtr<ClientTransport> transport_;
|
||||
};
|
||||
|
||||
NewConnectedSubchannel(
|
||||
RefCountedPtr<UnstartedCallDestination> call_destination,
|
||||
RefCountedPtr<TransportCallDestination> transport,
|
||||
const ChannelArgs& args,
|
||||
RefCountedPtr<channelz::SubchannelNode> channelz_subchannel)
|
||||
: ConnectedSubchannel(args, std::move(channelz_subchannel)),
|
||||
call_destination_(std::move(call_destination)),
|
||||
transport_(std::move(transport)) {}
|
||||
|
||||
void StartWatch(
|
||||
grpc_pollset_set*,
|
||||
OrphanablePtr<ConnectivityStateWatcherInterface> watcher) override {
|
||||
transport_->transport()->StartConnectivityWatch(std::move(watcher));
|
||||
}
|
||||
|
||||
void Ping(absl::AnyInvocable<void(absl::Status)>) override {
|
||||
// TODO(ctiller): add new transport API for this in v3 stack
|
||||
Crash("not implemented");
|
||||
}
|
||||
|
||||
RefCountedPtr<UnstartedCallDestination> unstarted_call_destination()
|
||||
const override {
|
||||
return call_destination_;
|
||||
}
|
||||
|
||||
grpc_channel_stack* channel_stack() const override { return nullptr; }
|
||||
|
||||
size_t GetInitialCallSizeEstimate() const override { return 0; }
|
||||
|
||||
ArenaPromise<ServerMetadataHandle> MakeCallPromise(CallArgs) override {
|
||||
Crash("legacy MakeCallPromise() method called in call v3 impl");
|
||||
}
|
||||
|
||||
void Ping(grpc_closure*, grpc_closure*) override {
|
||||
Crash("legacy ping method called in call v3 impl");
|
||||
}
|
||||
|
||||
private:
|
||||
RefCountedPtr<UnstartedCallDestination> call_destination_;
|
||||
RefCountedPtr<TransportCallDestination> transport_;
|
||||
};
|
||||
|
||||
//
|
||||
// SubchannelCall
|
||||
|
|
@ -255,8 +353,8 @@ void SubchannelCall::Destroy(void* arg, grpc_error_handle /*error*/) {
|
|||
// Destroy the subchannel call.
|
||||
self->~SubchannelCall();
|
||||
// Destroy the call stack. This should be after destroying the subchannel
|
||||
// call, because call->after_call_stack_destroy(), if not null, will free the
|
||||
// call arena.
|
||||
// call, because call->after_call_stack_destroy(), if not null, will free
|
||||
// the call arena.
|
||||
grpc_call_stack_destroy(SUBCHANNEL_CALL_TO_CALL_STACK(self), nullptr,
|
||||
after_call_stack_destroy);
|
||||
// Automatically reset connected_subchannel. This should be after destroying
|
||||
|
|
@ -474,8 +572,8 @@ Subchannel::Subchannel(SubchannelKey key,
|
|||
// result the subchannel destruction happens asynchronously to channel
|
||||
// destruction. If the last channel destruction triggers a grpc_shutdown
|
||||
// before the last subchannel destruction, then there maybe race conditions
|
||||
// triggering segmentation faults. To prevent this issue, we call a grpc_init
|
||||
// here and a grpc_shutdown in the subchannel destructor.
|
||||
// triggering segmentation faults. To prevent this issue, we call a
|
||||
// grpc_init here and a grpc_shutdown in the subchannel destructor.
|
||||
InitInternally();
|
||||
global_stats().IncrementClientSubchannelsCreated();
|
||||
GRPC_CLOSURE_INIT(&on_connecting_finished_, OnConnectingFinished, this,
|
||||
|
|
@ -587,7 +685,8 @@ void Subchannel::CancelConnectivityStateWatch(
|
|||
watcher_list_.RemoveWatcherLocked(watcher);
|
||||
}
|
||||
// Drain any connectivity state notifications after releasing the mutex.
|
||||
// (Shouldn't actually be necessary in this case, but better safe than sorry.)
|
||||
// (Shouldn't actually be necessary in this case, but better safe than
|
||||
// sorry.)
|
||||
work_serializer_.DrainQueue();
|
||||
}
|
||||
|
||||
|
|
@ -758,11 +857,11 @@ void Subchannel::OnConnectingFinishedLocked(grpc_error_handle error) {
|
|||
ExecCtx exec_ctx;
|
||||
self->OnRetryTimer();
|
||||
// Subchannel deletion might require an active ExecCtx. So if
|
||||
// self.reset() is not called here, the WeakRefCountedPtr destructor
|
||||
// may run after the ExecCtx declared in the callback is destroyed.
|
||||
// Since subchannel may get destroyed when the WeakRefCountedPtr
|
||||
// destructor runs, it may not have an active ExecCtx - thus leading
|
||||
// to crashes.
|
||||
// self.reset() is not called here, the WeakRefCountedPtr
|
||||
// destructor may run after the ExecCtx declared in the callback
|
||||
// is destroyed. Since subchannel may get destroyed when the
|
||||
// WeakRefCountedPtr destructor runs, it may not have an active
|
||||
// ExecCtx - thus leading to crashes.
|
||||
self.reset();
|
||||
}
|
||||
});
|
||||
|
|
@ -770,37 +869,60 @@ void Subchannel::OnConnectingFinishedLocked(grpc_error_handle error) {
|
|||
}
|
||||
|
||||
bool Subchannel::PublishTransportLocked() {
|
||||
// Construct channel stack.
|
||||
// Builder takes ownership of transport.
|
||||
ChannelStackBuilderImpl builder(
|
||||
"subchannel", GRPC_CLIENT_SUBCHANNEL,
|
||||
connecting_result_.channel_args.SetObject(
|
||||
std::exchange(connecting_result_.transport, nullptr)));
|
||||
if (!CoreConfiguration::Get().channel_init().CreateStack(&builder)) {
|
||||
return false;
|
||||
auto socket_node = std::move(connecting_result_.socket_node);
|
||||
if (connecting_result_.transport->filter_stack_transport() != nullptr ||
|
||||
IsChaoticGoodEnabled()) {
|
||||
// Construct channel stack.
|
||||
// Builder takes ownership of transport.
|
||||
ChannelStackBuilderImpl builder(
|
||||
"subchannel", GRPC_CLIENT_SUBCHANNEL,
|
||||
connecting_result_.channel_args.SetObject(
|
||||
std::exchange(connecting_result_.transport, nullptr)));
|
||||
if (!CoreConfiguration::Get().channel_init().CreateStack(&builder)) {
|
||||
return false;
|
||||
}
|
||||
absl::StatusOr<RefCountedPtr<grpc_channel_stack>> stack = builder.Build();
|
||||
if (!stack.ok()) {
|
||||
connecting_result_.Reset();
|
||||
gpr_log(GPR_ERROR,
|
||||
"subchannel %p %s: error initializing subchannel stack: %s", this,
|
||||
key_.ToString().c_str(), stack.status().ToString().c_str());
|
||||
return false;
|
||||
}
|
||||
connected_subchannel_ = MakeRefCounted<LegacyConnectedSubchannel>(
|
||||
std::move(*stack), args_, channelz_node_);
|
||||
} else {
|
||||
OrphanablePtr<ClientTransport> transport(
|
||||
std::exchange(connecting_result_.transport, nullptr)
|
||||
->client_transport());
|
||||
InterceptionChainBuilder builder(
|
||||
connecting_result_.channel_args.SetObject(transport.get()));
|
||||
CoreConfiguration::Get().channel_init().AddToInterceptionChainBuilder(
|
||||
GRPC_CLIENT_SUBCHANNEL, builder);
|
||||
auto transport_destination =
|
||||
MakeRefCounted<NewConnectedSubchannel::TransportCallDestination>(
|
||||
std::move(transport));
|
||||
auto call_destination = builder.Build(transport_destination);
|
||||
if (!call_destination.ok()) {
|
||||
connecting_result_.Reset();
|
||||
gpr_log(GPR_ERROR,
|
||||
"subchannel %p %s: error initializing subchannel stack: %s", this,
|
||||
key_.ToString().c_str(),
|
||||
call_destination.status().ToString().c_str());
|
||||
return false;
|
||||
}
|
||||
connected_subchannel_ = MakeRefCounted<NewConnectedSubchannel>(
|
||||
std::move(*call_destination), std::move(transport_destination), args_,
|
||||
channelz_node_);
|
||||
}
|
||||
absl::StatusOr<RefCountedPtr<grpc_channel_stack>> stk = builder.Build();
|
||||
if (!stk.ok()) {
|
||||
auto error = absl_status_to_grpc_error(stk.status());
|
||||
connecting_result_.Reset();
|
||||
gpr_log(GPR_ERROR,
|
||||
"subchannel %p %s: error initializing subchannel stack: %s", this,
|
||||
key_.ToString().c_str(), StatusToString(error).c_str());
|
||||
return false;
|
||||
}
|
||||
RefCountedPtr<channelz::SocketNode> socket =
|
||||
std::move(connecting_result_.socket_node);
|
||||
connecting_result_.Reset();
|
||||
if (shutdown_) return false;
|
||||
// Publish.
|
||||
connected_subchannel_.reset(
|
||||
new ConnectedSubchannel(stk->release(), args_, channelz_node_));
|
||||
if (GRPC_TRACE_FLAG_ENABLED(grpc_trace_subchannel)) {
|
||||
gpr_log(GPR_INFO, "subchannel %p %s: new connected subchannel at %p", this,
|
||||
key_.ToString().c_str(), connected_subchannel_.get());
|
||||
}
|
||||
if (channelz_node_ != nullptr) {
|
||||
channelz_node_->SetChildSocket(std::move(socket));
|
||||
channelz_node_->SetChildSocket(std::move(socket_node));
|
||||
}
|
||||
// Start watching connected subchannel.
|
||||
connected_subchannel_->StartWatch(
|
||||
|
|
@ -811,4 +933,29 @@ bool Subchannel::PublishTransportLocked() {
|
|||
return true;
|
||||
}
|
||||
|
||||
ChannelArgs Subchannel::MakeSubchannelArgs(
|
||||
const ChannelArgs& channel_args, const ChannelArgs& address_args,
|
||||
const RefCountedPtr<SubchannelPoolInterface>& subchannel_pool,
|
||||
const std::string& channel_default_authority) {
|
||||
// Note that we start with the channel-level args and then apply the
|
||||
// per-address args, so that if a value is present in both, the one
|
||||
// in the channel-level args is used. This is particularly important
|
||||
// for the GRPC_ARG_DEFAULT_AUTHORITY arg, which we want to allow
|
||||
// resolvers to set on a per-address basis only if the application
|
||||
// did not explicitly set it at the channel level.
|
||||
return channel_args.UnionWith(address_args)
|
||||
.SetObject(subchannel_pool)
|
||||
// If we haven't already set the default authority arg (i.e., it
|
||||
// was not explicitly set by the application nor overridden by
|
||||
// the resolver), add it from the channel's default.
|
||||
.SetIfUnset(GRPC_ARG_DEFAULT_AUTHORITY, channel_default_authority)
|
||||
// Remove channel args that should not affect subchannel
|
||||
// uniqueness.
|
||||
.Remove(GRPC_ARG_HEALTH_CHECK_SERVICE_NAME)
|
||||
.Remove(GRPC_ARG_INHIBIT_HEALTH_CHECKING)
|
||||
.Remove(GRPC_ARG_CHANNELZ_CHANNEL_NODE)
|
||||
// Remove all keys with the no-subchannel prefix.
|
||||
.RemoveAllKeysWithPrefix(GRPC_ARG_NO_SUBCHANNEL_PREFIX);
|
||||
}
|
||||
|
||||
} // namespace grpc_core
|
||||
|
|
|
|||
|
|
@ -64,30 +64,35 @@ namespace grpc_core {
|
|||
|
||||
class SubchannelCall;
|
||||
|
||||
class ConnectedSubchannel final : public RefCounted<ConnectedSubchannel> {
|
||||
class ConnectedSubchannel : public RefCounted<ConnectedSubchannel> {
|
||||
public:
|
||||
ConnectedSubchannel(
|
||||
grpc_channel_stack* channel_stack, const ChannelArgs& args,
|
||||
RefCountedPtr<channelz::SubchannelNode> channelz_subchannel);
|
||||
~ConnectedSubchannel() override;
|
||||
|
||||
void StartWatch(grpc_pollset_set* interested_parties,
|
||||
OrphanablePtr<ConnectivityStateWatcherInterface> watcher);
|
||||
|
||||
void Ping(grpc_closure* on_initiate, grpc_closure* on_ack);
|
||||
|
||||
grpc_channel_stack* channel_stack() const { return channel_stack_; }
|
||||
const ChannelArgs& args() const { return args_; }
|
||||
channelz::SubchannelNode* channelz_subchannel() const {
|
||||
return channelz_subchannel_.get();
|
||||
}
|
||||
|
||||
size_t GetInitialCallSizeEstimate() const;
|
||||
virtual void StartWatch(
|
||||
grpc_pollset_set* interested_parties,
|
||||
OrphanablePtr<ConnectivityStateWatcherInterface> watcher) = 0;
|
||||
|
||||
ArenaPromise<ServerMetadataHandle> MakeCallPromise(CallArgs call_args);
|
||||
// Methods for v3 stack.
|
||||
virtual void Ping(absl::AnyInvocable<void(absl::Status)> on_ack) = 0;
|
||||
virtual RefCountedPtr<UnstartedCallDestination> unstarted_call_destination()
|
||||
const = 0;
|
||||
|
||||
// Methods for legacy stack.
|
||||
virtual grpc_channel_stack* channel_stack() const = 0;
|
||||
virtual size_t GetInitialCallSizeEstimate() const = 0;
|
||||
virtual ArenaPromise<ServerMetadataHandle> MakeCallPromise(
|
||||
CallArgs call_args) = 0;
|
||||
virtual void Ping(grpc_closure* on_initiate, grpc_closure* on_ack) = 0;
|
||||
|
||||
protected:
|
||||
ConnectedSubchannel(
|
||||
const ChannelArgs& args,
|
||||
RefCountedPtr<channelz::SubchannelNode> channelz_subchannel);
|
||||
|
||||
private:
|
||||
grpc_channel_stack* channel_stack_;
|
||||
ChannelArgs args_;
|
||||
// ref counted pointer to the channelz node in this connected subchannel's
|
||||
// owning subchannel.
|
||||
|
|
@ -243,6 +248,12 @@ class Subchannel final : public DualRefCounted<Subchannel> {
|
|||
return connected_subchannel_;
|
||||
}
|
||||
|
||||
RefCountedPtr<UnstartedCallDestination> call_destination() {
|
||||
MutexLock lock(&mu_);
|
||||
if (connected_subchannel_ == nullptr) return nullptr;
|
||||
return connected_subchannel_->unstarted_call_destination();
|
||||
}
|
||||
|
||||
// Attempt to connect to the backend. Has no effect if already connected.
|
||||
void RequestConnection() ABSL_LOCKS_EXCLUDED(mu_);
|
||||
|
||||
|
|
@ -272,6 +283,12 @@ class Subchannel final : public DualRefCounted<Subchannel> {
|
|||
return event_engine_;
|
||||
}
|
||||
|
||||
// Exposed for testing purposes only.
|
||||
static ChannelArgs MakeSubchannelArgs(
|
||||
const ChannelArgs& channel_args, const ChannelArgs& address_args,
|
||||
const RefCountedPtr<SubchannelPoolInterface>& subchannel_pool,
|
||||
const std::string& channel_default_authority);
|
||||
|
||||
private:
|
||||
// Tears down any existing connection, and arranges for destruction
|
||||
void Orphaned() override ABSL_LOCKS_EXCLUDED(mu_);
|
||||
|
|
|
|||
|
|
@ -78,15 +78,11 @@ TraceFlag grpc_trace_client_idle_filter(false, "client_idle_filter");
|
|||
} \
|
||||
} while (0)
|
||||
|
||||
namespace {
|
||||
|
||||
Duration GetClientIdleTimeout(const ChannelArgs& args) {
|
||||
return args.GetDurationFromIntMillis(GRPC_ARG_CLIENT_IDLE_TIMEOUT_MS)
|
||||
.value_or(kDefaultIdleTimeout);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
struct LegacyMaxAgeFilter::Config {
|
||||
Duration max_connection_age;
|
||||
Duration max_connection_idle;
|
||||
|
|
|
|||
|
|
@ -40,6 +40,8 @@
|
|||
|
||||
namespace grpc_core {
|
||||
|
||||
Duration GetClientIdleTimeout(const ChannelArgs& args);
|
||||
|
||||
class LegacyChannelIdleFilter : public ChannelFilter {
|
||||
public:
|
||||
LegacyChannelIdleFilter(grpc_channel_stack* channel_stack,
|
||||
|
|
|
|||
|
|
@ -83,6 +83,16 @@ inline int PointerCompare(void* a_ptr, const grpc_arg_pointer_vtable* a_vtable,
|
|||
// before the crt refcount base class.
|
||||
template <typename T>
|
||||
using RefType = absl::remove_cvref_t<decltype(*std::declval<T>().Ref())>;
|
||||
|
||||
template <typename T, typename Ignored = void /* for SFINAE */>
|
||||
struct IsRawPointerTagged {
|
||||
static constexpr bool kValue = false;
|
||||
};
|
||||
template <typename T>
|
||||
struct IsRawPointerTagged<T,
|
||||
absl::void_t<typename T::RawPointerChannelArgTag>> {
|
||||
static constexpr bool kValue = true;
|
||||
};
|
||||
} // namespace channel_args_detail
|
||||
|
||||
// Specialization for ref-counted pointers.
|
||||
|
|
@ -91,13 +101,14 @@ using RefType = absl::remove_cvref_t<decltype(*std::declval<T>().Ref())>;
|
|||
template <typename T>
|
||||
struct ChannelArgTypeTraits<
|
||||
T, absl::enable_if_t<
|
||||
std::is_base_of<RefCounted<channel_args_detail::RefType<T>>,
|
||||
channel_args_detail::RefType<T>>::value ||
|
||||
std::is_base_of<RefCounted<channel_args_detail::RefType<T>,
|
||||
NonPolymorphicRefCount>,
|
||||
channel_args_detail::RefType<T>>::value ||
|
||||
std::is_base_of<DualRefCounted<channel_args_detail::RefType<T>>,
|
||||
channel_args_detail::RefType<T>>::value,
|
||||
!channel_args_detail::IsRawPointerTagged<T>::kValue &&
|
||||
(std::is_base_of<RefCounted<channel_args_detail::RefType<T>>,
|
||||
channel_args_detail::RefType<T>>::value ||
|
||||
std::is_base_of<RefCounted<channel_args_detail::RefType<T>,
|
||||
NonPolymorphicRefCount>,
|
||||
channel_args_detail::RefType<T>>::value ||
|
||||
std::is_base_of<DualRefCounted<channel_args_detail::RefType<T>>,
|
||||
channel_args_detail::RefType<T>>::value),
|
||||
void>> {
|
||||
static const grpc_arg_pointer_vtable* VTable() {
|
||||
static const grpc_arg_pointer_vtable tbl = {
|
||||
|
|
|
|||
|
|
@ -230,6 +230,7 @@ struct grpc_channel_stack {
|
|||
// full C++-ification for now.
|
||||
void IncrementRefCount();
|
||||
void Unref();
|
||||
void Unref(const grpc_core::DebugLocation& location, const char* reason);
|
||||
grpc_core::RefCountedPtr<grpc_channel_stack> Ref() {
|
||||
IncrementRefCount();
|
||||
return grpc_core::RefCountedPtr<grpc_channel_stack>(this);
|
||||
|
|
@ -345,6 +346,11 @@ inline void grpc_channel_stack::Unref() {
|
|||
GRPC_CHANNEL_STACK_UNREF(this, "smart_pointer");
|
||||
}
|
||||
|
||||
inline void grpc_channel_stack::Unref(const grpc_core::DebugLocation&,
|
||||
const char* reason) {
|
||||
GRPC_CHANNEL_STACK_UNREF(this, reason);
|
||||
}
|
||||
|
||||
inline void grpc_call_stack::IncrementRefCount() {
|
||||
GRPC_CALL_STACK_REF(this, "smart_pointer");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,6 +59,9 @@ typedef enum {
|
|||
/// the server.
|
||||
GRPC_CONTEXT_BACKEND_METRIC_PROVIDER,
|
||||
|
||||
/// A LoadBalancingPolicy::SubchannelCallTrackerInterface
|
||||
GRPC_SUBCHANNEL_CALL_TRACKER_INTERFACE,
|
||||
|
||||
/// Special Google context
|
||||
GRPC_CONTEXT_GOOGLE,
|
||||
|
||||
|
|
@ -73,6 +76,8 @@ struct grpc_call_context_element {
|
|||
namespace grpc_core {
|
||||
class Call;
|
||||
class CallTracerAnnotationInterface;
|
||||
class CallTracerInterface;
|
||||
class ServiceConfigCallData;
|
||||
|
||||
// Bind the legacy context array into the new style structure
|
||||
// TODO(ctiller): remove as we migrate these contexts to the new system.
|
||||
|
|
@ -96,6 +101,17 @@ struct OldStyleContext<CallTracerAnnotationInterface> {
|
|||
GRPC_CONTEXT_CALL_TRACER_ANNOTATION_INTERFACE;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct OldStyleContext<CallTracerInterface> {
|
||||
static constexpr grpc_context_index kIndex = GRPC_CONTEXT_CALL_TRACER;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct OldStyleContext<ServiceConfigCallData> {
|
||||
static constexpr grpc_context_index kIndex =
|
||||
GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class Context<T, absl::void_t<decltype(OldStyleContext<T>::kIndex)>> {
|
||||
public:
|
||||
|
|
@ -104,6 +120,15 @@ class Context<T, absl::void_t<decltype(OldStyleContext<T>::kIndex)>> {
|
|||
GetContext<grpc_call_context_element>()[OldStyleContext<T>::kIndex]
|
||||
.value);
|
||||
}
|
||||
static void set(T* value) {
|
||||
auto& elem =
|
||||
GetContext<grpc_call_context_element>()[OldStyleContext<T>::kIndex];
|
||||
if (elem.destroy != nullptr) {
|
||||
elem.destroy(elem.value);
|
||||
elem.destroy = nullptr;
|
||||
}
|
||||
elem.value = value;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace promise_detail
|
||||
|
|
|
|||
|
|
@ -29,8 +29,6 @@ const char* const description_call_status_override_on_cancellation =
|
|||
"with cancellation.";
|
||||
const char* const additional_constraints_call_status_override_on_cancellation =
|
||||
"{}";
|
||||
const char* const description_call_v3 = "Promise-based call version 3.";
|
||||
const char* const additional_constraints_call_v3 = "{}";
|
||||
const char* const description_canary_client_privacy =
|
||||
"If set, canary client privacy";
|
||||
const char* const additional_constraints_canary_client_privacy = "{}";
|
||||
|
|
@ -133,6 +131,12 @@ const char* const description_work_serializer_dispatch =
|
|||
const char* const additional_constraints_work_serializer_dispatch = "{}";
|
||||
const uint8_t required_experiments_work_serializer_dispatch[] = {
|
||||
static_cast<uint8_t>(grpc_core::kExperimentIdEventEngineClient)};
|
||||
const char* const description_call_v3 = "Promise-based call version 3.";
|
||||
const char* const additional_constraints_call_v3 = "{}";
|
||||
const uint8_t required_experiments_call_v3[] = {
|
||||
static_cast<uint8_t>(grpc_core::kExperimentIdEventEngineClient),
|
||||
static_cast<uint8_t>(grpc_core::kExperimentIdEventEngineListener),
|
||||
static_cast<uint8_t>(grpc_core::kExperimentIdWorkSerializerDispatch)};
|
||||
} // namespace
|
||||
|
||||
namespace grpc_core {
|
||||
|
|
@ -142,8 +146,6 @@ const ExperimentMetadata g_experiment_metadata[] = {
|
|||
description_call_status_override_on_cancellation,
|
||||
additional_constraints_call_status_override_on_cancellation, nullptr, 0,
|
||||
true, true},
|
||||
{"call_v3", description_call_v3, additional_constraints_call_v3, nullptr, 0,
|
||||
false, true},
|
||||
{"canary_client_privacy", description_canary_client_privacy,
|
||||
additional_constraints_canary_client_privacy, nullptr, 0, false, false},
|
||||
{"client_privacy", description_client_privacy,
|
||||
|
|
@ -208,6 +210,8 @@ const ExperimentMetadata g_experiment_metadata[] = {
|
|||
{"work_serializer_dispatch", description_work_serializer_dispatch,
|
||||
additional_constraints_work_serializer_dispatch,
|
||||
required_experiments_work_serializer_dispatch, 1, false, true},
|
||||
{"call_v3", description_call_v3, additional_constraints_call_v3,
|
||||
required_experiments_call_v3, 3, false, false},
|
||||
};
|
||||
|
||||
} // namespace grpc_core
|
||||
|
|
@ -219,8 +223,6 @@ const char* const description_call_status_override_on_cancellation =
|
|||
"with cancellation.";
|
||||
const char* const additional_constraints_call_status_override_on_cancellation =
|
||||
"{}";
|
||||
const char* const description_call_v3 = "Promise-based call version 3.";
|
||||
const char* const additional_constraints_call_v3 = "{}";
|
||||
const char* const description_canary_client_privacy =
|
||||
"If set, canary client privacy";
|
||||
const char* const additional_constraints_canary_client_privacy = "{}";
|
||||
|
|
@ -323,6 +325,12 @@ const char* const description_work_serializer_dispatch =
|
|||
const char* const additional_constraints_work_serializer_dispatch = "{}";
|
||||
const uint8_t required_experiments_work_serializer_dispatch[] = {
|
||||
static_cast<uint8_t>(grpc_core::kExperimentIdEventEngineClient)};
|
||||
const char* const description_call_v3 = "Promise-based call version 3.";
|
||||
const char* const additional_constraints_call_v3 = "{}";
|
||||
const uint8_t required_experiments_call_v3[] = {
|
||||
static_cast<uint8_t>(grpc_core::kExperimentIdEventEngineClient),
|
||||
static_cast<uint8_t>(grpc_core::kExperimentIdEventEngineListener),
|
||||
static_cast<uint8_t>(grpc_core::kExperimentIdWorkSerializerDispatch)};
|
||||
} // namespace
|
||||
|
||||
namespace grpc_core {
|
||||
|
|
@ -332,8 +340,6 @@ const ExperimentMetadata g_experiment_metadata[] = {
|
|||
description_call_status_override_on_cancellation,
|
||||
additional_constraints_call_status_override_on_cancellation, nullptr, 0,
|
||||
true, true},
|
||||
{"call_v3", description_call_v3, additional_constraints_call_v3, nullptr, 0,
|
||||
false, true},
|
||||
{"canary_client_privacy", description_canary_client_privacy,
|
||||
additional_constraints_canary_client_privacy, nullptr, 0, false, false},
|
||||
{"client_privacy", description_client_privacy,
|
||||
|
|
@ -398,6 +404,8 @@ const ExperimentMetadata g_experiment_metadata[] = {
|
|||
{"work_serializer_dispatch", description_work_serializer_dispatch,
|
||||
additional_constraints_work_serializer_dispatch,
|
||||
required_experiments_work_serializer_dispatch, 1, false, true},
|
||||
{"call_v3", description_call_v3, additional_constraints_call_v3,
|
||||
required_experiments_call_v3, 3, false, false},
|
||||
};
|
||||
|
||||
} // namespace grpc_core
|
||||
|
|
@ -409,8 +417,6 @@ const char* const description_call_status_override_on_cancellation =
|
|||
"with cancellation.";
|
||||
const char* const additional_constraints_call_status_override_on_cancellation =
|
||||
"{}";
|
||||
const char* const description_call_v3 = "Promise-based call version 3.";
|
||||
const char* const additional_constraints_call_v3 = "{}";
|
||||
const char* const description_canary_client_privacy =
|
||||
"If set, canary client privacy";
|
||||
const char* const additional_constraints_canary_client_privacy = "{}";
|
||||
|
|
@ -513,6 +519,12 @@ const char* const description_work_serializer_dispatch =
|
|||
const char* const additional_constraints_work_serializer_dispatch = "{}";
|
||||
const uint8_t required_experiments_work_serializer_dispatch[] = {
|
||||
static_cast<uint8_t>(grpc_core::kExperimentIdEventEngineClient)};
|
||||
const char* const description_call_v3 = "Promise-based call version 3.";
|
||||
const char* const additional_constraints_call_v3 = "{}";
|
||||
const uint8_t required_experiments_call_v3[] = {
|
||||
static_cast<uint8_t>(grpc_core::kExperimentIdEventEngineClient),
|
||||
static_cast<uint8_t>(grpc_core::kExperimentIdEventEngineListener),
|
||||
static_cast<uint8_t>(grpc_core::kExperimentIdWorkSerializerDispatch)};
|
||||
} // namespace
|
||||
|
||||
namespace grpc_core {
|
||||
|
|
@ -522,8 +534,6 @@ const ExperimentMetadata g_experiment_metadata[] = {
|
|||
description_call_status_override_on_cancellation,
|
||||
additional_constraints_call_status_override_on_cancellation, nullptr, 0,
|
||||
true, true},
|
||||
{"call_v3", description_call_v3, additional_constraints_call_v3, nullptr, 0,
|
||||
false, true},
|
||||
{"canary_client_privacy", description_canary_client_privacy,
|
||||
additional_constraints_canary_client_privacy, nullptr, 0, false, false},
|
||||
{"client_privacy", description_client_privacy,
|
||||
|
|
@ -588,6 +598,8 @@ const ExperimentMetadata g_experiment_metadata[] = {
|
|||
{"work_serializer_dispatch", description_work_serializer_dispatch,
|
||||
additional_constraints_work_serializer_dispatch,
|
||||
required_experiments_work_serializer_dispatch, 1, true, true},
|
||||
{"call_v3", description_call_v3, additional_constraints_call_v3,
|
||||
required_experiments_call_v3, 3, false, false},
|
||||
};
|
||||
|
||||
} // namespace grpc_core
|
||||
|
|
|
|||
|
|
@ -59,7 +59,6 @@ namespace grpc_core {
|
|||
#if defined(GRPC_CFSTREAM)
|
||||
#define GRPC_EXPERIMENT_IS_INCLUDED_CALL_STATUS_OVERRIDE_ON_CANCELLATION
|
||||
inline bool IsCallStatusOverrideOnCancellationEnabled() { return true; }
|
||||
inline bool IsCallV3Enabled() { return false; }
|
||||
inline bool IsCanaryClientPrivacyEnabled() { return false; }
|
||||
inline bool IsClientPrivacyEnabled() { return false; }
|
||||
inline bool IsEventEngineClientEnabled() { return false; }
|
||||
|
|
@ -91,11 +90,11 @@ inline bool IsUnconstrainedMaxQuotaBufferSizeEnabled() { return false; }
|
|||
#define GRPC_EXPERIMENT_IS_INCLUDED_WORK_SERIALIZER_CLEARS_TIME_CACHE
|
||||
inline bool IsWorkSerializerClearsTimeCacheEnabled() { return true; }
|
||||
inline bool IsWorkSerializerDispatchEnabled() { return false; }
|
||||
inline bool IsCallV3Enabled() { return false; }
|
||||
|
||||
#elif defined(GPR_WINDOWS)
|
||||
#define GRPC_EXPERIMENT_IS_INCLUDED_CALL_STATUS_OVERRIDE_ON_CANCELLATION
|
||||
inline bool IsCallStatusOverrideOnCancellationEnabled() { return true; }
|
||||
inline bool IsCallV3Enabled() { return false; }
|
||||
inline bool IsCanaryClientPrivacyEnabled() { return false; }
|
||||
inline bool IsClientPrivacyEnabled() { return false; }
|
||||
inline bool IsEventEngineClientEnabled() { return false; }
|
||||
|
|
@ -129,11 +128,11 @@ inline bool IsUnconstrainedMaxQuotaBufferSizeEnabled() { return false; }
|
|||
#define GRPC_EXPERIMENT_IS_INCLUDED_WORK_SERIALIZER_CLEARS_TIME_CACHE
|
||||
inline bool IsWorkSerializerClearsTimeCacheEnabled() { return true; }
|
||||
inline bool IsWorkSerializerDispatchEnabled() { return false; }
|
||||
inline bool IsCallV3Enabled() { return false; }
|
||||
|
||||
#else
|
||||
#define GRPC_EXPERIMENT_IS_INCLUDED_CALL_STATUS_OVERRIDE_ON_CANCELLATION
|
||||
inline bool IsCallStatusOverrideOnCancellationEnabled() { return true; }
|
||||
inline bool IsCallV3Enabled() { return false; }
|
||||
inline bool IsCanaryClientPrivacyEnabled() { return false; }
|
||||
inline bool IsClientPrivacyEnabled() { return false; }
|
||||
inline bool IsEventEngineClientEnabled() { return false; }
|
||||
|
|
@ -168,12 +167,12 @@ inline bool IsUnconstrainedMaxQuotaBufferSizeEnabled() { return false; }
|
|||
inline bool IsWorkSerializerClearsTimeCacheEnabled() { return true; }
|
||||
#define GRPC_EXPERIMENT_IS_INCLUDED_WORK_SERIALIZER_DISPATCH
|
||||
inline bool IsWorkSerializerDispatchEnabled() { return true; }
|
||||
inline bool IsCallV3Enabled() { return false; }
|
||||
#endif
|
||||
|
||||
#else
|
||||
enum ExperimentIds {
|
||||
kExperimentIdCallStatusOverrideOnCancellation,
|
||||
kExperimentIdCallV3,
|
||||
kExperimentIdCanaryClientPrivacy,
|
||||
kExperimentIdClientPrivacy,
|
||||
kExperimentIdEventEngineClient,
|
||||
|
|
@ -200,16 +199,13 @@ enum ExperimentIds {
|
|||
kExperimentIdUnconstrainedMaxQuotaBufferSize,
|
||||
kExperimentIdWorkSerializerClearsTimeCache,
|
||||
kExperimentIdWorkSerializerDispatch,
|
||||
kExperimentIdCallV3,
|
||||
kNumExperiments
|
||||
};
|
||||
#define GRPC_EXPERIMENT_IS_INCLUDED_CALL_STATUS_OVERRIDE_ON_CANCELLATION
|
||||
inline bool IsCallStatusOverrideOnCancellationEnabled() {
|
||||
return IsExperimentEnabled(kExperimentIdCallStatusOverrideOnCancellation);
|
||||
}
|
||||
#define GRPC_EXPERIMENT_IS_INCLUDED_CALL_V3
|
||||
inline bool IsCallV3Enabled() {
|
||||
return IsExperimentEnabled(kExperimentIdCallV3);
|
||||
}
|
||||
#define GRPC_EXPERIMENT_IS_INCLUDED_CANARY_CLIENT_PRIVACY
|
||||
inline bool IsCanaryClientPrivacyEnabled() {
|
||||
return IsExperimentEnabled(kExperimentIdCanaryClientPrivacy);
|
||||
|
|
@ -314,6 +310,10 @@ inline bool IsWorkSerializerClearsTimeCacheEnabled() {
|
|||
inline bool IsWorkSerializerDispatchEnabled() {
|
||||
return IsExperimentEnabled(kExperimentIdWorkSerializerDispatch);
|
||||
}
|
||||
#define GRPC_EXPERIMENT_IS_INCLUDED_CALL_V3
|
||||
inline bool IsCallV3Enabled() {
|
||||
return IsExperimentEnabled(kExperimentIdCallV3);
|
||||
}
|
||||
|
||||
extern const ExperimentMetadata g_experiment_metadata[kNumExperiments];
|
||||
|
||||
|
|
|
|||
|
|
@ -52,6 +52,8 @@
|
|||
expiry: 2024/06/01
|
||||
owner: ctiller@google.com
|
||||
test_tags: []
|
||||
requires: ["work_serializer_dispatch", "event_engine_listener", "event_engine_client"]
|
||||
allow_in_fuzzing_config: false
|
||||
- name: canary_client_privacy
|
||||
description:
|
||||
If set, canary client privacy
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include "absl/base/thread_annotations.h"
|
||||
#include "absl/log/check.h"
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "absl/types/optional.h"
|
||||
|
||||
#include <grpc/support/log.h>
|
||||
|
|
@ -121,6 +122,11 @@ class Waker {
|
|||
return wakeable_and_arg_.ActivityDebugTag();
|
||||
}
|
||||
|
||||
std::string DebugString() {
|
||||
return absl::StrFormat("Waker{%p, %d}", wakeable_and_arg_.wakeable,
|
||||
wakeable_and_arg_.wakeup_mask);
|
||||
}
|
||||
|
||||
// This is for tests to assert that a waker is occupied or not.
|
||||
bool is_unwakeable() const {
|
||||
return wakeable_and_arg_.wakeable == promise_detail::unwakeable();
|
||||
|
|
|
|||
|
|
@ -125,6 +125,11 @@ T* MaybeGetContext() {
|
|||
return promise_detail::Context<T>::get();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void SetContext(T* p) {
|
||||
promise_detail::Context<T>::set(p);
|
||||
}
|
||||
|
||||
// Given a promise and a context, return a promise that has that context set.
|
||||
template <typename T, typename F>
|
||||
promise_detail::WithContext<T, F> WithContext(F f, T* context) {
|
||||
|
|
|
|||
|
|
@ -72,6 +72,23 @@ promise_detail::Map<Promise, Fn> Map(Promise promise, Fn fn) {
|
|||
return promise_detail::Map<Promise, Fn>(std::move(promise), std::move(fn));
|
||||
}
|
||||
|
||||
// Maps a promise to a new promise that returns a tuple of the original result
|
||||
// and a bool indicating whether there was ever a Pending{} value observed from
|
||||
// polling.
|
||||
template <typename Promise>
|
||||
auto CheckDelayed(Promise promise) {
|
||||
using P = promise_detail::PromiseLike<Promise>;
|
||||
return [delayed = false, promise = P(std::move(promise))]() mutable
|
||||
-> Poll<std::tuple<typename P::Result, bool>> {
|
||||
auto r = promise();
|
||||
if (r.pending()) {
|
||||
delayed = true;
|
||||
return Pending{};
|
||||
}
|
||||
return std::make_tuple(r.value(), delayed);
|
||||
};
|
||||
}
|
||||
|
||||
// Callable that takes a tuple and returns one element
|
||||
template <size_t kElem>
|
||||
struct JustElem {
|
||||
|
|
|
|||
|
|
@ -125,6 +125,7 @@ class Observable {
|
|||
Observer& operator=(const Observer&) = delete;
|
||||
Observer(Observer&& other) noexcept : state_(std::move(other.state_)) {
|
||||
CHECK(other.waker_.is_unwakeable());
|
||||
DCHECK(waker_.is_unwakeable());
|
||||
CHECK(!other.saw_pending_);
|
||||
}
|
||||
Observer& operator=(Observer&& other) noexcept = delete;
|
||||
|
|
|
|||
|
|
@ -308,8 +308,10 @@ void Party::AddParticipants(Participant** participants, size_t count) {
|
|||
for (size_t i = 0; i < count; i++) {
|
||||
if (grpc_trace_party_state.enabled()) {
|
||||
gpr_log(GPR_INFO,
|
||||
"Party %p AddParticipant: %s @ %" PRIdPTR,
|
||||
&sync_, std::string(participants[i]->name()).c_str(), slots[i]);
|
||||
"Party %p AddParticipant: %s @ %" PRIdPTR
|
||||
" [participant=%p]",
|
||||
&sync_, std::string(participants[i]->name()).c_str(), slots[i],
|
||||
participants[i]);
|
||||
}
|
||||
participants_[slots[i]].store(participants[i], std::memory_order_release);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -379,6 +379,11 @@ class Party : public Activity, private Wakeable {
|
|||
// The on_complete callback will be called with the result of the promise if
|
||||
// it completes.
|
||||
// A maximum of sixteen promises can be spawned onto a party.
|
||||
// promise_factory called to create the promise with the party lock taken;
|
||||
// after the promise is created the factory is destroyed.
|
||||
// This means that pointers or references to factory members will be
|
||||
// invalidated after the promise is created - so the promise should not retain
|
||||
// any of these.
|
||||
template <typename Factory, typename OnComplete>
|
||||
void Spawn(absl::string_view name, Factory promise_factory,
|
||||
OnComplete on_complete);
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
#include <type_traits>
|
||||
|
||||
#include "absl/functional/any_invocable.h"
|
||||
#include "absl/log/log.h"
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/types/optional.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -130,6 +130,8 @@ class Call : public CppImplOf<Call, grpc_call>,
|
|||
// Implementation of EventEngine::Closure, called when deadline expires
|
||||
void Run() final;
|
||||
|
||||
gpr_cycle_counter start_time() const { return start_time_; }
|
||||
|
||||
protected:
|
||||
// The maximum number of concurrent batches possible.
|
||||
// Based upon the maximum number of individually queueable ops in the batch
|
||||
|
|
@ -209,8 +211,6 @@ class Call : public CppImplOf<Call, grpc_call>,
|
|||
void HandleCompressionAlgorithmNotAccepted(
|
||||
grpc_compression_algorithm compression_algorithm) GPR_ATTRIBUTE_NOINLINE;
|
||||
|
||||
gpr_cycle_counter start_time() const { return start_time_; }
|
||||
|
||||
virtual grpc_compression_options compression_options() = 0;
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -65,7 +65,22 @@ Channel::RegisteredCall::~RegisteredCall() {}
|
|||
Channel::Channel(std::string target, const ChannelArgs& channel_args)
|
||||
: target_(std::move(target)),
|
||||
channelz_node_(channel_args.GetObjectRef<channelz::ChannelNode>()),
|
||||
compression_options_(CompressionOptionsFromChannelArgs(channel_args)) {}
|
||||
compression_options_(CompressionOptionsFromChannelArgs(channel_args)),
|
||||
call_size_estimator_(1024),
|
||||
allocator_(channel_args.GetObject<ResourceQuota>()
|
||||
->memory_quota()
|
||||
->CreateMemoryOwner()) {}
|
||||
|
||||
Arena* Channel::CreateArena() {
|
||||
const size_t initial_size = call_size_estimator_.CallSizeEstimate();
|
||||
global_stats().IncrementCallInitialSize(initial_size);
|
||||
return Arena::Create(initial_size, &allocator_);
|
||||
}
|
||||
|
||||
void Channel::DestroyArena(Arena* arena) {
|
||||
call_size_estimator_.UpdateCallSizeEstimate(arena->TotalUsedBytes());
|
||||
arena->Destroy();
|
||||
}
|
||||
|
||||
Channel::RegisteredCall* Channel::RegisterCall(const char* method,
|
||||
const char* host) {
|
||||
|
|
|
|||
|
|
@ -40,8 +40,10 @@
|
|||
#include "src/core/lib/gprpp/time.h"
|
||||
#include "src/core/lib/iomgr/iomgr_fwd.h"
|
||||
#include "src/core/lib/resource_quota/arena.h"
|
||||
#include "src/core/lib/resource_quota/resource_quota.h"
|
||||
#include "src/core/lib/slice/slice.h"
|
||||
#include "src/core/lib/surface/channel_stack_type.h"
|
||||
#include "src/core/lib/transport/call_arena_allocator.h"
|
||||
#include "src/core/lib/transport/connectivity_state.h"
|
||||
|
||||
// Forward declaration to avoid dependency loop.
|
||||
|
|
@ -52,7 +54,7 @@ namespace grpc_core {
|
|||
// Forward declaration to avoid dependency loop.
|
||||
class Transport;
|
||||
|
||||
class Channel : public RefCounted<Channel>,
|
||||
class Channel : public InternallyRefCounted<Channel>,
|
||||
public CppImplOf<Channel, grpc_channel> {
|
||||
public:
|
||||
struct RegisteredCall {
|
||||
|
|
@ -66,10 +68,17 @@ class Channel : public RefCounted<Channel>,
|
|||
~RegisteredCall();
|
||||
};
|
||||
|
||||
virtual void Orphan() = 0;
|
||||
|
||||
virtual Arena* CreateArena() = 0;
|
||||
virtual void DestroyArena(Arena* arena) = 0;
|
||||
// Though internally ref counted channels expose their "Ref" method to
|
||||
// create a RefCountedPtr to themselves. The OrphanablePtr owner is the
|
||||
// singleton decision maker on whether the channel should be destroyed or
|
||||
// not.
|
||||
// TODO(ctiller): in a future change (I have it written) these will be removed
|
||||
// and substituted with DualRefCounted<Channel> as a base.
|
||||
RefCountedPtr<Channel> Ref() { return InternallyRefCounted<Channel>::Ref(); }
|
||||
template <typename T>
|
||||
RefCountedPtr<T> RefAsSubclass() {
|
||||
return InternallyRefCounted<Channel>::RefAsSubclass<T>();
|
||||
}
|
||||
|
||||
virtual bool IsLame() const = 0;
|
||||
|
||||
|
|
@ -125,6 +134,8 @@ class Channel : public RefCounted<Channel>,
|
|||
virtual void Ping(grpc_completion_queue* cq, void* tag) = 0;
|
||||
|
||||
// TODO(roth): Remove these methods when LegacyChannel goes away.
|
||||
Arena* CreateArena();
|
||||
void DestroyArena(Arena* arena);
|
||||
virtual grpc_channel_stack* channel_stack() const { return nullptr; }
|
||||
virtual bool is_client() const { return true; }
|
||||
virtual bool is_promising() const { return true; }
|
||||
|
|
@ -137,6 +148,10 @@ class Channel : public RefCounted<Channel>,
|
|||
const RefCountedPtr<channelz::ChannelNode> channelz_node_;
|
||||
const grpc_compression_options compression_options_;
|
||||
|
||||
// TODO(ctiller): move to use CallArenaAllocator
|
||||
CallSizeEstimator call_size_estimator_;
|
||||
MemoryAllocator allocator_;
|
||||
|
||||
Mutex mu_;
|
||||
// The map key needs to be owned strings rather than unowned char*'s to
|
||||
// guarantee that it outlives calls on the core channel (which may outlast
|
||||
|
|
|
|||
|
|
@ -22,8 +22,10 @@
|
|||
#include <grpc/support/port_platform.h>
|
||||
|
||||
#include "src/core/channelz/channelz.h"
|
||||
#include "src/core/client_channel/client_channel.h"
|
||||
#include "src/core/lib/channel/channel_args.h"
|
||||
#include "src/core/lib/config/core_configuration.h"
|
||||
#include "src/core/lib/experiments/experiments.h"
|
||||
#include "src/core/lib/surface/channel.h"
|
||||
#include "src/core/lib/surface/lame_client.h"
|
||||
#include "src/core/lib/surface/legacy_channel.h"
|
||||
|
|
@ -77,9 +79,13 @@ absl::StatusOr<OrphanablePtr<Channel>> ChannelCreate(
|
|||
if (optional_transport != nullptr) {
|
||||
args = args.SetObject(optional_transport);
|
||||
}
|
||||
// Delegate to legacy channel impl.
|
||||
return LegacyChannel::Create(std::move(target), std::move(args),
|
||||
channel_stack_type);
|
||||
// Delegate to appropriate channel impl.
|
||||
if (!IsCallV3Enabled()) {
|
||||
return LegacyChannel::Create(std::move(target), std::move(args),
|
||||
channel_stack_type);
|
||||
}
|
||||
CHECK_EQ(channel_stack_type, GRPC_CLIENT_CHANNEL);
|
||||
return ClientChannel::Create(std::move(target), std::move(args));
|
||||
}
|
||||
|
||||
} // namespace grpc_core
|
||||
|
|
|
|||
|
|
@ -113,10 +113,7 @@ LegacyChannel::LegacyChannel(bool is_client, bool is_promising,
|
|||
: Channel(std::move(target), channel_args),
|
||||
is_client_(is_client),
|
||||
is_promising_(is_promising),
|
||||
channel_stack_(std::move(channel_stack)),
|
||||
allocator_(channel_args.GetObject<ResourceQuota>()
|
||||
->memory_quota()
|
||||
->CreateMemoryOwner()) {
|
||||
channel_stack_(std::move(channel_stack)) {
|
||||
// We need to make sure that grpc_shutdown() does not shut things down
|
||||
// until after the channel is destroyed. However, the channel may not
|
||||
// actually be destroyed by the time grpc_channel_destroy() returns,
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
#include "src/core/lib/surface/channel.h"
|
||||
#include "src/core/lib/surface/channel_stack_type.h"
|
||||
#include "src/core/lib/transport/call_arena_allocator.h"
|
||||
#include "src/core/lib/transport/transport.h"
|
||||
#include "src/core/telemetry/stats.h"
|
||||
|
||||
namespace grpc_core {
|
||||
|
|
@ -56,16 +57,6 @@ class LegacyChannel final : public Channel {
|
|||
|
||||
void Orphan() override;
|
||||
|
||||
Arena* CreateArena() override {
|
||||
const size_t initial_size = call_size_estimator_.CallSizeEstimate();
|
||||
global_stats().IncrementCallInitialSize(initial_size);
|
||||
return Arena::Create(initial_size, &allocator_);
|
||||
}
|
||||
void DestroyArena(Arena* arena) override {
|
||||
call_size_estimator_.UpdateCallSizeEstimate(arena->TotalUsedBytes());
|
||||
arena->Destroy();
|
||||
}
|
||||
|
||||
bool IsLame() const override;
|
||||
|
||||
grpc_call* CreateCall(grpc_call* parent_call, uint32_t propagation_mask,
|
||||
|
|
@ -114,8 +105,6 @@ class LegacyChannel final : public Channel {
|
|||
const bool is_client_;
|
||||
const bool is_promising_;
|
||||
RefCountedPtr<grpc_channel_stack> channel_stack_;
|
||||
CallSizeEstimator call_size_estimator_{1024};
|
||||
grpc_event_engine::experimental::MemoryAllocator allocator_;
|
||||
};
|
||||
|
||||
} // namespace grpc_core
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@ namespace grpc_core {
|
|||
class UnstartedCallDestination
|
||||
: public DualRefCounted<UnstartedCallDestination> {
|
||||
public:
|
||||
using DualRefCounted::DualRefCounted;
|
||||
|
||||
~UnstartedCallDestination() override = default;
|
||||
// Start a call. The UnstartedCallHandler will be consumed by the Destination
|
||||
// and started.
|
||||
|
|
|
|||
|
|
@ -170,8 +170,15 @@ Poll<T> InfallibleOperationExecutor<T>::ContinueStep(void* call_data) {
|
|||
template class OperationExecutor<ClientMetadataHandle>;
|
||||
template class OperationExecutor<MessageHandle>;
|
||||
template class InfallibleOperationExecutor<ServerMetadataHandle>;
|
||||
|
||||
} // namespace filters_detail
|
||||
|
||||
namespace {
|
||||
// Call data for those calls that don't have any call data
|
||||
// (we form pointers to this that aren't allowed to be nullptr)
|
||||
char g_empty_call_data;
|
||||
} // namespace
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CallFilters
|
||||
|
||||
|
|
@ -181,7 +188,7 @@ CallFilters::CallFilters(ClientMetadataHandle client_initial_metadata)
|
|||
client_initial_metadata_(std::move(client_initial_metadata)) {}
|
||||
|
||||
CallFilters::~CallFilters() {
|
||||
if (call_data_ != nullptr) {
|
||||
if (call_data_ != nullptr && call_data_ != &g_empty_call_data) {
|
||||
for (const auto& destructor : stack_->data_.filter_destructor) {
|
||||
destructor.call_destroy(Offset(call_data_, destructor.call_offset));
|
||||
}
|
||||
|
|
@ -192,8 +199,12 @@ CallFilters::~CallFilters() {
|
|||
void CallFilters::SetStack(RefCountedPtr<Stack> stack) {
|
||||
CHECK_EQ(call_data_, nullptr);
|
||||
stack_ = std::move(stack);
|
||||
call_data_ = gpr_malloc_aligned(stack_->data_.call_data_size,
|
||||
stack_->data_.call_data_alignment);
|
||||
if (stack_->data_.call_data_size != 0) {
|
||||
call_data_ = gpr_malloc_aligned(stack_->data_.call_data_size,
|
||||
stack_->data_.call_data_alignment);
|
||||
} else {
|
||||
call_data_ = &g_empty_call_data;
|
||||
}
|
||||
for (const auto& constructor : stack_->data_.filter_constructor) {
|
||||
constructor.call_init(Offset(call_data_, constructor.call_offset),
|
||||
constructor.channel_data);
|
||||
|
|
@ -232,7 +243,8 @@ void CallFilters::PushServerTrailingMetadata(ServerMetadataHandle md) {
|
|||
md->DebugString().c_str(), DebugString().c_str());
|
||||
}
|
||||
CHECK(md != nullptr);
|
||||
if (server_trailing_metadata_ != nullptr) return;
|
||||
if (cancelled_.is_set()) return;
|
||||
cancelled_.Set(md->get(GrpcCallWasCancelled()).value_or(false));
|
||||
server_trailing_metadata_ = std::move(md);
|
||||
client_initial_metadata_state_.CloseWithError();
|
||||
server_initial_metadata_state_.CloseSending();
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include <grpc/support/port_platform.h>
|
||||
|
||||
#include "src/core/lib/gprpp/dump_args.h"
|
||||
#include "src/core/lib/gprpp/ref_counted.h"
|
||||
#include "src/core/lib/gprpp/ref_counted_ptr.h"
|
||||
#include "src/core/lib/promise/latch.h"
|
||||
|
|
@ -1944,11 +1945,7 @@ inline auto CallFilters::PullServerToClientMessage() {
|
|||
}
|
||||
|
||||
inline auto CallFilters::PullServerTrailingMetadata() {
|
||||
return Map(PullServerTrailingMetadataPromise(this),
|
||||
[this](ServerMetadataHandle h) {
|
||||
cancelled_.Set(h->get(GrpcCallWasCancelled()).value_or(false));
|
||||
return h;
|
||||
});
|
||||
return PullServerTrailingMetadataPromise(this);
|
||||
}
|
||||
|
||||
inline auto CallFilters::WasCancelled() { return cancelled_.Wait(); }
|
||||
|
|
|
|||
|
|
@ -21,13 +21,16 @@
|
|||
#include <grpc/support/port_platform.h>
|
||||
|
||||
#include "src/core/lib/channel/context.h"
|
||||
#include "src/core/lib/gprpp/dual_ref_counted.h"
|
||||
#include "src/core/lib/promise/detail/status.h"
|
||||
#include "src/core/lib/promise/if.h"
|
||||
#include "src/core/lib/promise/latch.h"
|
||||
#include "src/core/lib/promise/party.h"
|
||||
#include "src/core/lib/promise/pipe.h"
|
||||
#include "src/core/lib/promise/prioritized_race.h"
|
||||
#include "src/core/lib/promise/promise.h"
|
||||
#include "src/core/lib/promise/status_flag.h"
|
||||
#include "src/core/lib/promise/try_seq.h"
|
||||
#include "src/core/lib/transport/call_arena_allocator.h"
|
||||
#include "src/core/lib/transport/call_filters.h"
|
||||
#include "src/core/lib/transport/message.h"
|
||||
|
|
@ -135,6 +138,23 @@ class CallSpineInterface {
|
|||
});
|
||||
}
|
||||
|
||||
// Wrap a promise so that if the call completes that promise is cancelled.
|
||||
template <typename Promise>
|
||||
auto UntilCallCompletes(Promise promise) {
|
||||
using Result = PromiseResult<Promise>;
|
||||
return PrioritizedRace(std::move(promise), Map(WasCancelled(), [](bool) {
|
||||
return FailureStatusCast<Result>(Failure{});
|
||||
}));
|
||||
}
|
||||
|
||||
template <typename PromiseFactory>
|
||||
void SpawnGuardedUntilCallCompletes(absl::string_view name,
|
||||
PromiseFactory promise_factory) {
|
||||
SpawnGuarded(name, [this, promise_factory]() mutable {
|
||||
return UntilCallCompletes(promise_factory());
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
absl::AnyInvocable<void()> on_done_{nullptr};
|
||||
};
|
||||
|
|
@ -272,7 +292,7 @@ class CallSpine final : public CallSpineInterface, public Party {
|
|||
if (legacy_context_is_owned_) {
|
||||
for (size_t i = 0; i < GRPC_CONTEXT_COUNT; i++) {
|
||||
grpc_call_context_element& elem = legacy_context_[i];
|
||||
if (elem.destroy != nullptr) elem.destroy(&elem);
|
||||
if (elem.destroy != nullptr) elem.destroy(elem.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -472,6 +492,12 @@ class CallInitiator {
|
|||
spine_->SpawnGuarded(name, std::move(promise_factory));
|
||||
}
|
||||
|
||||
template <typename PromiseFactory>
|
||||
void SpawnGuardedUntilCallCompletes(absl::string_view name,
|
||||
PromiseFactory promise_factory) {
|
||||
spine_->SpawnGuardedUntilCallCompletes(name, std::move(promise_factory));
|
||||
}
|
||||
|
||||
template <typename PromiseFactory>
|
||||
void SpawnInfallible(absl::string_view name, PromiseFactory promise_factory) {
|
||||
spine_->SpawnInfallible(name, std::move(promise_factory));
|
||||
|
|
@ -526,6 +552,12 @@ class CallHandler {
|
|||
spine_->SpawnGuarded(name, std::move(promise_factory), whence);
|
||||
}
|
||||
|
||||
template <typename PromiseFactory>
|
||||
void SpawnGuardedUntilCallCompletes(absl::string_view name,
|
||||
PromiseFactory promise_factory) {
|
||||
spine_->SpawnGuardedUntilCallCompletes(name, std::move(promise_factory));
|
||||
}
|
||||
|
||||
template <typename PromiseFactory>
|
||||
void SpawnInfallible(absl::string_view name, PromiseFactory promise_factory) {
|
||||
spine_->SpawnInfallible(name, std::move(promise_factory));
|
||||
|
|
@ -577,6 +609,12 @@ class UnstartedCallHandler {
|
|||
spine_->SpawnGuarded(name, std::move(promise_factory), whence);
|
||||
}
|
||||
|
||||
template <typename PromiseFactory>
|
||||
void SpawnGuardedUntilCallCompletes(absl::string_view name,
|
||||
PromiseFactory promise_factory) {
|
||||
spine_->SpawnGuardedUntilCallCompletes(name, std::move(promise_factory));
|
||||
}
|
||||
|
||||
template <typename PromiseFactory>
|
||||
void SpawnInfallible(absl::string_view name, PromiseFactory promise_factory) {
|
||||
spine_->SpawnInfallible(name, std::move(promise_factory));
|
||||
|
|
|
|||
|
|
@ -528,6 +528,14 @@ struct WaitForReady {
|
|||
static std::string DisplayValue(ValueType x);
|
||||
};
|
||||
|
||||
// Annotation added by retry code to indicate a transparent retry.
|
||||
struct IsTransparentRetry {
|
||||
static absl::string_view DebugKey() { return "IsTransparentRetry"; }
|
||||
static constexpr bool kRepeatable = false;
|
||||
using ValueType = bool;
|
||||
static std::string DisplayValue(ValueType x) { return x ? "true" : "false"; }
|
||||
};
|
||||
|
||||
// Annotation added by a transport to note that server trailing metadata
|
||||
// is a Trailers-Only response.
|
||||
struct GrpcTrailersOnly {
|
||||
|
|
@ -1536,7 +1544,8 @@ using grpc_metadata_batch_base = grpc_core::MetadataMap<
|
|||
grpc_core::GrpcStreamNetworkState, grpc_core::PeerString,
|
||||
grpc_core::GrpcStatusContext, grpc_core::GrpcStatusFromWire,
|
||||
grpc_core::GrpcCallWasCancelled, grpc_core::WaitForReady,
|
||||
grpc_core::GrpcTrailersOnly, grpc_core::GrpcTarPit,
|
||||
grpc_core::IsTransparentRetry, grpc_core::GrpcTrailersOnly,
|
||||
grpc_core::GrpcTarPit,
|
||||
grpc_core::GrpcRegisteredMethod GRPC_CUSTOM_CLIENT_METADATA
|
||||
GRPC_CUSTOM_SERVER_METADATA>;
|
||||
|
||||
|
|
|
|||
|
|
@ -484,6 +484,16 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
|
|||
ChannelArgs channel_args_;
|
||||
};
|
||||
|
||||
namespace promise_detail {
|
||||
|
||||
template <>
|
||||
struct OldStyleContext<LoadBalancingPolicy::SubchannelCallTrackerInterface> {
|
||||
static constexpr grpc_context_index kIndex =
|
||||
GRPC_SUBCHANNEL_CALL_TRACKER_INTERFACE;
|
||||
};
|
||||
|
||||
} // namespace promise_detail
|
||||
|
||||
} // namespace grpc_core
|
||||
|
||||
#endif // GRPC_SRC_CORE_LOAD_BALANCING_LB_POLICY_H
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#include "src/core/lib/channel/context.h"
|
||||
#include "src/core/lib/gprpp/ref_counted_string.h"
|
||||
#include "src/core/lib/iomgr/error.h"
|
||||
#include "src/core/lib/promise/context.h"
|
||||
#include "src/core/lib/resource_quota/arena.h"
|
||||
#include "src/core/lib/slice/slice_buffer.h"
|
||||
#include "src/core/lib/transport/call_final_info.h"
|
||||
|
|
@ -221,6 +222,21 @@ void AddClientCallTracerToContext(grpc_call_context_element* call_context,
|
|||
void AddServerCallTracerToContext(grpc_call_context_element* call_context,
|
||||
ServerCallTracer* tracer);
|
||||
|
||||
template <>
|
||||
struct ContextSubclass<ClientCallTracer::CallAttemptTracer> {
|
||||
using Base = CallTracerInterface;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ContextSubclass<ServerCallTracer> {
|
||||
using Base = CallTracerInterface;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ContextSubclass<ClientCallTracer> {
|
||||
using Base = CallTracerAnnotationInterface;
|
||||
};
|
||||
|
||||
} // namespace grpc_core
|
||||
|
||||
#endif // GRPC_SRC_CORE_TELEMETRY_CALL_TRACER_H
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ CORE_SOURCE_FILES = [
|
|||
'src/core/channelz/channelz.cc',
|
||||
'src/core/channelz/channelz_registry.cc',
|
||||
'src/core/client_channel/backup_poller.cc',
|
||||
'src/core/client_channel/client_channel.cc',
|
||||
'src/core/client_channel/client_channel_factory.cc',
|
||||
'src/core/client_channel/client_channel_filter.cc',
|
||||
'src/core/client_channel/client_channel_plugin.cc',
|
||||
|
|
@ -26,6 +27,7 @@ CORE_SOURCE_FILES = [
|
|||
'src/core/client_channel/config_selector.cc',
|
||||
'src/core/client_channel/dynamic_filters.cc',
|
||||
'src/core/client_channel/global_subchannel_pool.cc',
|
||||
'src/core/client_channel/load_balanced_call_destination.cc',
|
||||
'src/core/client_channel/local_subchannel_pool.cc',
|
||||
'src/core/client_channel/retry_filter.cc',
|
||||
'src/core/client_channel/retry_filter_legacy_call_data.cc',
|
||||
|
|
@ -486,6 +488,7 @@ CORE_SOURCE_FILES = [
|
|||
'src/core/lib/experiments/config.cc',
|
||||
'src/core/lib/experiments/experiments.cc',
|
||||
'src/core/lib/gprpp/crash.cc',
|
||||
'src/core/lib/gprpp/dump_args.cc',
|
||||
'src/core/lib/gprpp/examine_stack.cc',
|
||||
'src/core/lib/gprpp/fork.cc',
|
||||
'src/core/lib/gprpp/host_port.cc',
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
Generate one transport test & associated fuzzer
|
||||
"""
|
||||
|
||||
load("//bazel:grpc_build_system.bzl", "grpc_cc_test")
|
||||
load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test")
|
||||
load("//test/core/test_util:grpc_fuzzer.bzl", "grpc_proto_fuzzer")
|
||||
|
||||
def grpc_yodel_test(name, deps):
|
||||
|
|
@ -57,3 +57,12 @@ def grpc_yodel_test(name, deps):
|
|||
corpus = "corpus/%s" % name,
|
||||
proto = None,
|
||||
)
|
||||
|
||||
def grpc_yodel_simple_test(name, **kwargs):
|
||||
grpc_cc_library(
|
||||
name = "%s_test_lib" % name,
|
||||
testonly = True,
|
||||
alwayslink = 1,
|
||||
**kwargs
|
||||
)
|
||||
grpc_yodel_test(name, deps = ["%s_test_lib" % name])
|
||||
|
|
|
|||
|
|
@ -14,8 +14,12 @@
|
|||
|
||||
#include "test/core/call/yodel/yodel_test.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "absl/random/random.h"
|
||||
|
||||
#include "src/core/lib/config/core_configuration.h"
|
||||
#include "src/core/lib/iomgr/exec_ctx.h"
|
||||
#include "src/core/lib/iomgr/timer_manager.h"
|
||||
#include "src/core/lib/resource_quota/resource_quota.h"
|
||||
|
||||
|
|
@ -117,13 +121,13 @@ void SimpleTestRegistry::ContributeTests(std::vector<Test>& tests) {
|
|||
class YodelTest::WatchDog {
|
||||
public:
|
||||
explicit WatchDog(YodelTest* test) : test_(test) {}
|
||||
~WatchDog() { test_->event_engine_->Cancel(timer_); }
|
||||
~WatchDog() { test_->state_->event_engine->Cancel(timer_); }
|
||||
|
||||
private:
|
||||
YodelTest* const test_;
|
||||
grpc_event_engine::experimental::EventEngine::TaskHandle const timer_{
|
||||
test_->event_engine_->RunAfter(Duration::Minutes(5),
|
||||
[this]() { test_->Timeout(); })};
|
||||
test_->state_->event_engine->RunAfter(Duration::Minutes(5),
|
||||
[this]() { test_->Timeout(); })};
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -131,36 +135,46 @@ class YodelTest::WatchDog {
|
|||
|
||||
YodelTest::YodelTest(const fuzzing_event_engine::Actions& actions,
|
||||
absl::BitGenRef rng)
|
||||
: rng_(rng),
|
||||
event_engine_{
|
||||
std::make_shared<grpc_event_engine::experimental::FuzzingEventEngine>(
|
||||
[]() {
|
||||
grpc_timer_manager_set_threading(false);
|
||||
grpc_event_engine::experimental::FuzzingEventEngine::Options
|
||||
options;
|
||||
return options;
|
||||
}(),
|
||||
actions)},
|
||||
call_arena_allocator_{MakeRefCounted<CallArenaAllocator>(
|
||||
MakeResourceQuota("test-quota")
|
||||
->memory_quota()
|
||||
->CreateMemoryAllocator("test-allocator"),
|
||||
1024)} {}
|
||||
: rng_(rng), actions_(actions) {}
|
||||
|
||||
void YodelTest::RunTest() {
|
||||
TestImpl();
|
||||
CoreConfiguration::Reset();
|
||||
InitCoreConfiguration();
|
||||
state_ = std::make_unique<State>();
|
||||
state_->event_engine =
|
||||
std::make_shared<grpc_event_engine::experimental::FuzzingEventEngine>(
|
||||
[]() {
|
||||
grpc_timer_manager_set_threading(false);
|
||||
grpc_event_engine::experimental::FuzzingEventEngine::Options
|
||||
options;
|
||||
return options;
|
||||
}(),
|
||||
actions_);
|
||||
state_->call_arena_allocator = MakeRefCounted<CallArenaAllocator>(
|
||||
ResourceQuota::Default()->memory_quota()->CreateMemoryAllocator(
|
||||
"test-allocator"),
|
||||
1024);
|
||||
{
|
||||
ExecCtx exec_ctx;
|
||||
InitTest();
|
||||
}
|
||||
{
|
||||
ExecCtx exec_ctx;
|
||||
TestImpl();
|
||||
}
|
||||
EXPECT_EQ(pending_actions_.size(), 0)
|
||||
<< "There are still pending actions: did you forget to call "
|
||||
"WaitForAllPendingWork()?";
|
||||
Shutdown();
|
||||
event_engine_->TickUntilIdle();
|
||||
event_engine_->UnsetGlobalHooks();
|
||||
state_->event_engine->TickUntilIdle();
|
||||
state_->event_engine->UnsetGlobalHooks();
|
||||
}
|
||||
|
||||
void YodelTest::TickUntilTrue(absl::FunctionRef<bool()> poll) {
|
||||
WatchDog watchdog(this);
|
||||
while (!poll()) {
|
||||
event_engine_->Tick();
|
||||
ExecCtx exec_ctx;
|
||||
state_->event_engine->Tick();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -171,7 +185,7 @@ void YodelTest::WaitForAllPendingWork() {
|
|||
pending_actions_.pop();
|
||||
continue;
|
||||
}
|
||||
event_engine_->Tick();
|
||||
state_->event_engine->Tick();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -350,7 +350,7 @@ class YodelTest : public ::testing::Test {
|
|||
yodel_detail::SequenceSpawner(
|
||||
name_and_location,
|
||||
yodel_detail::SpawnerForContext(std::move(context),
|
||||
event_engine_.get()),
|
||||
state_->event_engine.get()),
|
||||
[this](yodel_detail::NameAndLocation name_and_location, int step) {
|
||||
auto action = std::make_shared<yodel_detail::ActionState>(
|
||||
name_and_location, step);
|
||||
|
|
@ -361,9 +361,10 @@ class YodelTest : public ::testing::Test {
|
|||
}
|
||||
|
||||
auto MakeCall(ClientMetadataHandle client_initial_metadata) {
|
||||
auto* arena = call_arena_allocator_->MakeArena();
|
||||
return MakeCallPair(std::move(client_initial_metadata), event_engine_.get(),
|
||||
arena, call_arena_allocator_, nullptr);
|
||||
auto* arena = state_->call_arena_allocator->MakeArena();
|
||||
return MakeCallPair(std::move(client_initial_metadata),
|
||||
state_->event_engine.get(), arena,
|
||||
state_->call_arena_allocator, nullptr);
|
||||
}
|
||||
|
||||
void WaitForAllPendingWork();
|
||||
|
|
@ -384,25 +385,35 @@ class YodelTest : public ::testing::Test {
|
|||
|
||||
const std::shared_ptr<grpc_event_engine::experimental::FuzzingEventEngine>&
|
||||
event_engine() {
|
||||
return event_engine_;
|
||||
return state_->event_engine;
|
||||
}
|
||||
|
||||
private:
|
||||
class WatchDog;
|
||||
struct State {
|
||||
grpc::testing::TestGrpcScope grpc_scope;
|
||||
std::shared_ptr<grpc_event_engine::experimental::FuzzingEventEngine>
|
||||
event_engine;
|
||||
RefCountedPtr<CallArenaAllocator> call_arena_allocator;
|
||||
};
|
||||
|
||||
virtual void TestImpl() = 0;
|
||||
|
||||
void Timeout();
|
||||
void TickUntilTrue(absl::FunctionRef<bool()> poll);
|
||||
|
||||
// Called before the test runs, after core configuration has been reset
|
||||
// and before the event engine is started.
|
||||
// This is a good time to register any custom core configuration builders.
|
||||
virtual void InitCoreConfiguration() {}
|
||||
// Called after the event engine has been started, but before the test runs.
|
||||
virtual void InitTest() {}
|
||||
// Called after the test has run, but before the event engine is shut down.
|
||||
virtual void Shutdown() {}
|
||||
|
||||
grpc::testing::TestGrpcScope grpc_scope_;
|
||||
absl::BitGenRef rng_;
|
||||
const std::shared_ptr<grpc_event_engine::experimental::FuzzingEventEngine>
|
||||
event_engine_;
|
||||
const RefCountedPtr<CallArenaAllocator> call_arena_allocator_;
|
||||
fuzzing_event_engine::Actions actions_;
|
||||
std::unique_ptr<State> state_;
|
||||
std::queue<std::shared_ptr<yodel_detail::ActionState>> pending_actions_;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -13,14 +13,15 @@
|
|||
# limitations under the License.
|
||||
|
||||
load("//bazel:grpc_build_system.bzl", "grpc_cc_test", "grpc_package")
|
||||
load("//test/core/call/yodel:grpc_yodel_test.bzl", "grpc_yodel_simple_test")
|
||||
|
||||
grpc_package(name = "test/core/client_channel")
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
grpc_cc_test(
|
||||
name = "client_channel_test",
|
||||
srcs = ["client_channel_test.cc"],
|
||||
name = "subchannel_args_test",
|
||||
srcs = ["subchannel_args_test.cc"],
|
||||
external_deps = ["gtest"],
|
||||
language = "C++",
|
||||
uses_event_engine = False,
|
||||
|
|
@ -33,6 +34,36 @@ grpc_cc_test(
|
|||
],
|
||||
)
|
||||
|
||||
grpc_yodel_simple_test(
|
||||
name = "client_channel",
|
||||
srcs = ["client_channel_test.cc"],
|
||||
external_deps = ["gtest"],
|
||||
deps = [
|
||||
"//:grpc_client_channel",
|
||||
"//test/core/call/yodel:yodel_test",
|
||||
],
|
||||
)
|
||||
|
||||
grpc_yodel_simple_test(
|
||||
name = "connected_subchannel",
|
||||
srcs = ["connected_subchannel_test.cc"],
|
||||
external_deps = ["gtest"],
|
||||
deps = [
|
||||
"//:grpc_client_channel",
|
||||
"//test/core/call/yodel:yodel_test",
|
||||
],
|
||||
)
|
||||
|
||||
grpc_yodel_simple_test(
|
||||
name = "load_balanced_call_destination",
|
||||
srcs = ["load_balanced_call_destination_test.cc"],
|
||||
external_deps = ["gtest"],
|
||||
deps = [
|
||||
"//:grpc_client_channel",
|
||||
"//test/core/call/yodel:yodel_test",
|
||||
],
|
||||
)
|
||||
|
||||
grpc_cc_test(
|
||||
name = "retry_throttle_test",
|
||||
srcs = ["retry_throttle_test.cc"],
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
//
|
||||
// Copyright 2022 gRPC authors.
|
||||
// Copyright 2024 gRPC authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
|
@ -12,79 +11,272 @@
|
|||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
#include "src/core/client_channel/client_channel.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <grpc/impl/channel_arg_names.h>
|
||||
#include <grpc/support/port_platform.h>
|
||||
#include <grpc/grpc.h>
|
||||
|
||||
#include "src/core/client_channel/client_channel_filter.h"
|
||||
#include "src/core/client_channel/subchannel_pool_interface.h"
|
||||
#include "src/core/lib/channel/channel_args.h"
|
||||
#include "src/core/resolver/endpoint_addresses.h"
|
||||
#include "test/core/test_util/test_config.h"
|
||||
#include "src/core/lib/address_utils/parse_address.h"
|
||||
#include "src/core/lib/config/core_configuration.h"
|
||||
#include "test/core/call/yodel/yodel_test.h"
|
||||
|
||||
namespace grpc_core {
|
||||
namespace testing {
|
||||
|
||||
using EventEngine = grpc_event_engine::experimental::EventEngine;
|
||||
|
||||
namespace {
|
||||
|
||||
TEST(MakeSubchannelArgs, UsesChannelDefaultAuthorityByDefault) {
|
||||
ChannelArgs args = ClientChannelFilter::MakeSubchannelArgs(
|
||||
ChannelArgs(), ChannelArgs(), nullptr, "foo.example.com");
|
||||
EXPECT_EQ(args.GetString(GRPC_ARG_DEFAULT_AUTHORITY), "foo.example.com");
|
||||
const absl::string_view kTestScheme = "test";
|
||||
const absl::string_view kTestTarget = "/target";
|
||||
const absl::string_view kTestPath = "/test_method";
|
||||
std::string TestTarget() {
|
||||
return absl::StrCat(kTestScheme, "://", kTestTarget);
|
||||
}
|
||||
|
||||
TEST(MakeSubchannelArgs, DefaultAuthorityFromChannelArgs) {
|
||||
ChannelArgs args = ClientChannelFilter::MakeSubchannelArgs(
|
||||
ChannelArgs().Set(GRPC_ARG_DEFAULT_AUTHORITY, "bar.example.com"),
|
||||
ChannelArgs(), nullptr, "foo.example.com");
|
||||
EXPECT_EQ(args.GetString(GRPC_ARG_DEFAULT_AUTHORITY), "bar.example.com");
|
||||
}
|
||||
|
||||
TEST(MakeSubchannelArgs, DefaultAuthorityFromResolver) {
|
||||
ChannelArgs args = ClientChannelFilter::MakeSubchannelArgs(
|
||||
ChannelArgs(),
|
||||
ChannelArgs().Set(GRPC_ARG_DEFAULT_AUTHORITY, "bar.example.com"), nullptr,
|
||||
"foo.example.com");
|
||||
EXPECT_EQ(args.GetString(GRPC_ARG_DEFAULT_AUTHORITY), "bar.example.com");
|
||||
}
|
||||
|
||||
TEST(MakeSubchannelArgs,
|
||||
DefaultAuthorityFromChannelArgsOverridesValueFromResolver) {
|
||||
ChannelArgs args = ClientChannelFilter::MakeSubchannelArgs(
|
||||
ChannelArgs().Set(GRPC_ARG_DEFAULT_AUTHORITY, "bar.example.com"),
|
||||
ChannelArgs().Set(GRPC_ARG_DEFAULT_AUTHORITY, "baz.example.com"), nullptr,
|
||||
"foo.example.com");
|
||||
EXPECT_EQ(args.GetString(GRPC_ARG_DEFAULT_AUTHORITY), "bar.example.com");
|
||||
}
|
||||
|
||||
TEST(MakeSubchannelArgs, ArgsFromChannelTrumpPerAddressArgs) {
|
||||
ChannelArgs args = ClientChannelFilter::MakeSubchannelArgs(
|
||||
ChannelArgs().Set("foo", 1), ChannelArgs().Set("foo", 2), nullptr,
|
||||
"foo.example.com");
|
||||
EXPECT_EQ(args.GetInt("foo"), 1);
|
||||
}
|
||||
|
||||
TEST(MakeSubchannelArgs, StripsOutNoSubchannelArgs) {
|
||||
ChannelArgs args = ClientChannelFilter::MakeSubchannelArgs(
|
||||
ChannelArgs().Set(GRPC_ARG_NO_SUBCHANNEL_PREFIX "foo", 1),
|
||||
ChannelArgs().Set(GRPC_ARG_NO_SUBCHANNEL_PREFIX "bar", 1), nullptr,
|
||||
"foo.example.com");
|
||||
EXPECT_EQ(args.GetString(GRPC_ARG_NO_SUBCHANNEL_PREFIX "foo"), absl::nullopt);
|
||||
EXPECT_EQ(args.GetString(GRPC_ARG_NO_SUBCHANNEL_PREFIX "bar"), absl::nullopt);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace testing
|
||||
} // namespace grpc_core
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
grpc::testing::TestEnvironment env(&argc, argv);
|
||||
auto result = RUN_ALL_TESTS();
|
||||
return result;
|
||||
class ClientChannelTest : public YodelTest {
|
||||
protected:
|
||||
using YodelTest::YodelTest;
|
||||
|
||||
ClientChannel& InitChannel(const ChannelArgs& args) {
|
||||
auto channel = ClientChannel::Create(TestTarget(), CompleteArgs(args));
|
||||
CHECK_OK(channel);
|
||||
channel_ = OrphanablePtr<ClientChannel>(
|
||||
DownCast<ClientChannel*>(channel->release()));
|
||||
return *channel_;
|
||||
}
|
||||
|
||||
ClientChannel& channel() { return *channel_; }
|
||||
|
||||
ClientMetadataHandle MakeClientInitialMetadata() {
|
||||
auto client_initial_metadata = Arena::MakePooled<ClientMetadata>();
|
||||
client_initial_metadata->Set(HttpPathMetadata(),
|
||||
Slice::FromCopiedString(kTestPath));
|
||||
return client_initial_metadata;
|
||||
}
|
||||
|
||||
CallHandler TickUntilCallStarted() {
|
||||
return TickUntil<CallHandler>([this]() -> Poll<CallHandler> {
|
||||
auto handler = call_destination_->PopHandler();
|
||||
if (handler.has_value()) return std::move(*handler);
|
||||
return Pending();
|
||||
});
|
||||
}
|
||||
|
||||
void QueueNameResolutionResult(Resolver::Result result) {
|
||||
if (resolver_ != nullptr) {
|
||||
resolver_->QueueNameResolutionResult(std::move(result));
|
||||
} else {
|
||||
early_resolver_results_.push(std::move(result));
|
||||
}
|
||||
}
|
||||
|
||||
Resolver::Result MakeSuccessfulResolutionResult(
|
||||
absl::string_view endpoint_address) {
|
||||
Resolver::Result result;
|
||||
grpc_resolved_address address;
|
||||
CHECK(grpc_parse_uri(URI::Parse(endpoint_address).value(), &address));
|
||||
result.addresses = EndpointAddressesList({EndpointAddresses{address, {}}});
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
class TestConnector final : public SubchannelConnector {
|
||||
public:
|
||||
void Connect(const Args&, Result*, grpc_closure* notify) override {
|
||||
CHECK_EQ(notify_, nullptr);
|
||||
notify_ = notify;
|
||||
}
|
||||
|
||||
void Shutdown(grpc_error_handle error) override {
|
||||
if (notify_ != nullptr) ExecCtx::Run(DEBUG_LOCATION, notify_, error);
|
||||
}
|
||||
|
||||
private:
|
||||
grpc_closure* notify_ = nullptr;
|
||||
};
|
||||
|
||||
class TestClientChannelFactory final : public ClientChannelFactory {
|
||||
public:
|
||||
RefCountedPtr<Subchannel> CreateSubchannel(
|
||||
const grpc_resolved_address& address,
|
||||
const ChannelArgs& args) override {
|
||||
gpr_log(GPR_INFO, "CreateSubchannel: args=%s", args.ToString().c_str());
|
||||
return Subchannel::Create(MakeOrphanable<TestConnector>(), address, args);
|
||||
}
|
||||
};
|
||||
|
||||
class TestCallDestination final : public UnstartedCallDestination {
|
||||
public:
|
||||
void StartCall(UnstartedCallHandler unstarted_call_handler) override {
|
||||
handlers_.push(
|
||||
unstarted_call_handler.V2HackToStartCallWithoutACallFilterStack());
|
||||
}
|
||||
|
||||
absl::optional<CallHandler> PopHandler() {
|
||||
if (handlers_.empty()) return absl::nullopt;
|
||||
auto handler = std::move(handlers_.front());
|
||||
handlers_.pop();
|
||||
return handler;
|
||||
}
|
||||
|
||||
void Orphaned() override {}
|
||||
|
||||
private:
|
||||
std::queue<CallHandler> handlers_;
|
||||
};
|
||||
|
||||
class TestCallDestinationFactory final
|
||||
: public ClientChannel::CallDestinationFactory {
|
||||
public:
|
||||
explicit TestCallDestinationFactory(ClientChannelTest* test)
|
||||
: test_(test) {}
|
||||
|
||||
RefCountedPtr<UnstartedCallDestination> CreateCallDestination(
|
||||
ClientChannel::PickerObservable picker) override {
|
||||
CHECK(!test_->picker_.has_value());
|
||||
test_->picker_ = std::move(picker);
|
||||
return test_->call_destination_;
|
||||
}
|
||||
|
||||
private:
|
||||
ClientChannelTest* const test_;
|
||||
};
|
||||
|
||||
class TestResolver final : public Resolver {
|
||||
public:
|
||||
explicit TestResolver(
|
||||
ClientChannelTest* test, ChannelArgs args,
|
||||
std::unique_ptr<Resolver::ResultHandler> result_handler,
|
||||
std::shared_ptr<WorkSerializer> work_serializer)
|
||||
: test_(test),
|
||||
args_(std::move(args)),
|
||||
result_handler_(std::move(result_handler)),
|
||||
work_serializer_(std::move(work_serializer)) {
|
||||
CHECK(test_->resolver_ == nullptr);
|
||||
test_->resolver_ = this;
|
||||
}
|
||||
|
||||
~TestResolver() override {
|
||||
CHECK_EQ(test_->resolver_, this);
|
||||
test_->resolver_ = nullptr;
|
||||
}
|
||||
|
||||
void StartLocked() override {
|
||||
while (!test_->early_resolver_results_.empty()) {
|
||||
QueueNameResolutionResult(
|
||||
std::move(test_->early_resolver_results_.front()));
|
||||
test_->early_resolver_results_.pop();
|
||||
}
|
||||
}
|
||||
void ShutdownLocked() override {}
|
||||
|
||||
void QueueNameResolutionResult(Resolver::Result result) {
|
||||
result.args = result.args.UnionWith(args_);
|
||||
work_serializer_->Run(
|
||||
[self = RefAsSubclass<TestResolver>(),
|
||||
result = std::move(result)]() mutable {
|
||||
self->result_handler_->ReportResult(std::move(result));
|
||||
},
|
||||
DEBUG_LOCATION);
|
||||
}
|
||||
|
||||
private:
|
||||
ClientChannelTest* const test_;
|
||||
const ChannelArgs args_;
|
||||
const std::unique_ptr<Resolver::ResultHandler> result_handler_;
|
||||
const std::shared_ptr<WorkSerializer> work_serializer_;
|
||||
};
|
||||
|
||||
class TestResolverFactory final : public ResolverFactory {
|
||||
public:
|
||||
explicit TestResolverFactory(ClientChannelTest* test) : test_(test) {}
|
||||
|
||||
OrphanablePtr<Resolver> CreateResolver(ResolverArgs args) const override {
|
||||
CHECK_EQ(args.uri.scheme(), kTestScheme);
|
||||
CHECK_EQ(args.uri.path(), kTestTarget);
|
||||
return MakeOrphanable<TestResolver>(test_, std::move(args.args),
|
||||
std::move(args.result_handler),
|
||||
std::move(args.work_serializer));
|
||||
}
|
||||
|
||||
absl::string_view scheme() const override { return "test"; }
|
||||
bool IsValidUri(const URI&) const override { return true; }
|
||||
|
||||
private:
|
||||
ClientChannelTest* const test_;
|
||||
};
|
||||
|
||||
ChannelArgs CompleteArgs(const ChannelArgs& args) {
|
||||
return args.SetObject(&call_destination_factory_)
|
||||
.SetObject(&client_channel_factory_)
|
||||
.SetObject(ResourceQuota::Default())
|
||||
.SetObject(std::static_pointer_cast<EventEngine>(event_engine()))
|
||||
// TODO(ctiller): remove once v3 supports retries?
|
||||
.SetIfUnset(GRPC_ARG_ENABLE_RETRIES, 0);
|
||||
}
|
||||
|
||||
void InitCoreConfiguration() override {
|
||||
CoreConfiguration::RegisterBuilder(
|
||||
[this](CoreConfiguration::Builder* builder) {
|
||||
builder->resolver_registry()->RegisterResolverFactory(
|
||||
std::make_unique<TestResolverFactory>(this));
|
||||
});
|
||||
}
|
||||
|
||||
void Shutdown() override {
|
||||
ExecCtx exec_ctx;
|
||||
channel_.reset();
|
||||
picker_.reset();
|
||||
}
|
||||
|
||||
OrphanablePtr<ClientChannel> channel_;
|
||||
absl::optional<ClientChannel::PickerObservable> picker_;
|
||||
TestCallDestinationFactory call_destination_factory_{this};
|
||||
TestClientChannelFactory client_channel_factory_;
|
||||
RefCountedPtr<TestCallDestination> call_destination_ =
|
||||
MakeRefCounted<TestCallDestination>();
|
||||
// Resolver results that have been reported before the resolver has been
|
||||
// instantiated.
|
||||
std::queue<Resolver::Result> early_resolver_results_;
|
||||
TestResolver* resolver_ = nullptr;
|
||||
};
|
||||
|
||||
#define CLIENT_CHANNEL_TEST(name) YODEL_TEST(ClientChannelTest, name)
|
||||
|
||||
CLIENT_CHANNEL_TEST(NoOp) { InitChannel(ChannelArgs()); }
|
||||
|
||||
CLIENT_CHANNEL_TEST(CreateCall) {
|
||||
auto& channel = InitChannel(ChannelArgs());
|
||||
auto call_initiator = channel.CreateCall(MakeClientInitialMetadata());
|
||||
SpawnTestSeq(call_initiator, "cancel", [call_initiator]() mutable {
|
||||
call_initiator.Cancel();
|
||||
return Empty{};
|
||||
});
|
||||
WaitForAllPendingWork();
|
||||
}
|
||||
|
||||
CLIENT_CHANNEL_TEST(StartCall) {
|
||||
auto& channel = InitChannel(ChannelArgs());
|
||||
auto call_initiator = channel.CreateCall(MakeClientInitialMetadata());
|
||||
QueueNameResolutionResult(
|
||||
MakeSuccessfulResolutionResult("ipv4:127.0.0.1:1234"));
|
||||
auto call_handler = TickUntilCallStarted();
|
||||
SpawnTestSeq(call_initiator, "cancel", [call_initiator]() mutable {
|
||||
call_initiator.Cancel();
|
||||
return Empty{};
|
||||
});
|
||||
WaitForAllPendingWork();
|
||||
}
|
||||
|
||||
// TODO(ctiller, roth): MANY more test cases
|
||||
// - Resolver returns an error for the initial result, then returns a valid
|
||||
// result.
|
||||
// - Resolver returns a service config (various permutations).
|
||||
|
||||
} // namespace grpc_core
|
||||
|
|
|
|||
|
|
@ -0,0 +1,178 @@
|
|||
// Copyright 2024 gRPC authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <grpc/grpc.h>
|
||||
|
||||
#include "src/core/client_channel/client_channel.h"
|
||||
#include "src/core/client_channel/local_subchannel_pool.h"
|
||||
#include "src/core/lib/address_utils/parse_address.h"
|
||||
#include "src/core/lib/config/core_configuration.h"
|
||||
#include "test/core/call/yodel/yodel_test.h"
|
||||
|
||||
namespace grpc_core {
|
||||
|
||||
using EventEngine = grpc_event_engine::experimental::EventEngine;
|
||||
|
||||
namespace {
|
||||
const absl::string_view kTestPath = "/test_method";
|
||||
const absl::string_view kTestAddress = "ipv4:127.0.0.1:1234";
|
||||
const absl::string_view kDefaultAuthority = "test-authority";
|
||||
} // namespace
|
||||
|
||||
class ConnectedSubchannelTest : public YodelTest {
|
||||
protected:
|
||||
using YodelTest::YodelTest;
|
||||
|
||||
RefCountedPtr<ConnectedSubchannel> InitChannel(const ChannelArgs& args) {
|
||||
grpc_resolved_address addr;
|
||||
CHECK(grpc_parse_uri(URI::Parse(kTestAddress).value(), &addr));
|
||||
auto subchannel = Subchannel::Create(MakeOrphanable<TestConnector>(this),
|
||||
addr, CompleteArgs(args));
|
||||
{
|
||||
ExecCtx exec_ctx;
|
||||
subchannel->RequestConnection();
|
||||
}
|
||||
return TickUntil<RefCountedPtr<ConnectedSubchannel>>(
|
||||
[subchannel]() -> Poll<RefCountedPtr<ConnectedSubchannel>> {
|
||||
auto connected_subchannel = subchannel->connected_subchannel();
|
||||
if (connected_subchannel != nullptr) return connected_subchannel;
|
||||
return Pending();
|
||||
});
|
||||
}
|
||||
|
||||
ClientMetadataHandle MakeClientInitialMetadata() {
|
||||
auto client_initial_metadata = Arena::MakePooled<ClientMetadata>();
|
||||
client_initial_metadata->Set(HttpPathMetadata(),
|
||||
Slice::FromCopiedString(kTestPath));
|
||||
return client_initial_metadata;
|
||||
}
|
||||
|
||||
CallInitiatorAndHandler MakeCall(
|
||||
ClientMetadataHandle client_initial_metadata) {
|
||||
return MakeCallPair(
|
||||
std::move(client_initial_metadata), event_engine().get(),
|
||||
call_arena_allocator_->MakeArena(), call_arena_allocator_, nullptr);
|
||||
}
|
||||
|
||||
CallHandler TickUntilCallStarted() {
|
||||
return TickUntil<CallHandler>([this]() -> Poll<CallHandler> {
|
||||
auto handler = PopHandler();
|
||||
if (handler.has_value()) return std::move(*handler);
|
||||
return Pending();
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
class TestTransport final : public ClientTransport {
|
||||
public:
|
||||
explicit TestTransport(ConnectedSubchannelTest* test) : test_(test) {}
|
||||
|
||||
void Orphan() override {
|
||||
state_tracker_.SetState(GRPC_CHANNEL_SHUTDOWN, absl::OkStatus(),
|
||||
"transport-orphaned");
|
||||
Unref();
|
||||
}
|
||||
|
||||
FilterStackTransport* filter_stack_transport() override { return nullptr; }
|
||||
ClientTransport* client_transport() override { return this; }
|
||||
ServerTransport* server_transport() override { return nullptr; }
|
||||
absl::string_view GetTransportName() const override { return "test"; }
|
||||
void SetPollset(grpc_stream*, grpc_pollset*) override {}
|
||||
void SetPollsetSet(grpc_stream*, grpc_pollset_set*) override {}
|
||||
void PerformOp(grpc_transport_op* op) override {
|
||||
LOG(INFO) << "PerformOp: " << grpc_transport_op_string(op);
|
||||
if (op->start_connectivity_watch != nullptr) {
|
||||
state_tracker_.AddWatcher(op->start_connectivity_watch_state,
|
||||
std::move(op->start_connectivity_watch));
|
||||
}
|
||||
ExecCtx::Run(DEBUG_LOCATION, op->on_consumed, absl::OkStatus());
|
||||
}
|
||||
|
||||
void StartCall(CallHandler call_handler) override {
|
||||
test_->handlers_.push(std::move(call_handler));
|
||||
}
|
||||
|
||||
private:
|
||||
ConnectedSubchannelTest* const test_;
|
||||
ConnectivityStateTracker state_tracker_{"test-transport"};
|
||||
};
|
||||
|
||||
class TestConnector final : public SubchannelConnector {
|
||||
public:
|
||||
explicit TestConnector(ConnectedSubchannelTest* test) : test_(test) {}
|
||||
|
||||
void Connect(const Args& args, Result* result,
|
||||
grpc_closure* notify) override {
|
||||
result->channel_args = args.channel_args;
|
||||
result->transport = MakeOrphanable<TestTransport>(test_).release();
|
||||
ExecCtx::Run(DEBUG_LOCATION, notify, absl::OkStatus());
|
||||
}
|
||||
|
||||
void Shutdown(grpc_error_handle) override {}
|
||||
|
||||
private:
|
||||
ConnectedSubchannelTest* const test_;
|
||||
};
|
||||
|
||||
ChannelArgs CompleteArgs(const ChannelArgs& args) {
|
||||
return args.SetObject(ResourceQuota::Default())
|
||||
.SetObject(std::static_pointer_cast<EventEngine>(event_engine()))
|
||||
.SetObject(MakeRefCounted<LocalSubchannelPool>())
|
||||
.Set(GRPC_ARG_DEFAULT_AUTHORITY, kDefaultAuthority);
|
||||
}
|
||||
|
||||
void InitCoreConfiguration() override {}
|
||||
|
||||
void Shutdown() override {}
|
||||
|
||||
absl::optional<CallHandler> PopHandler() {
|
||||
if (handlers_.empty()) return absl::nullopt;
|
||||
auto handler = std::move(handlers_.front());
|
||||
handlers_.pop();
|
||||
return handler;
|
||||
}
|
||||
|
||||
std::queue<CallHandler> handlers_;
|
||||
RefCountedPtr<CallArenaAllocator> call_arena_allocator_ =
|
||||
MakeRefCounted<CallArenaAllocator>(
|
||||
ResourceQuota::Default()->memory_quota()->CreateMemoryAllocator(
|
||||
"test"),
|
||||
1024);
|
||||
};
|
||||
|
||||
#define CONNECTED_SUBCHANNEL_CHANNEL_TEST(name) \
|
||||
YODEL_TEST(ConnectedSubchannelTest, name)
|
||||
|
||||
CONNECTED_SUBCHANNEL_CHANNEL_TEST(NoOp) { InitChannel(ChannelArgs()); }
|
||||
|
||||
CONNECTED_SUBCHANNEL_CHANNEL_TEST(StartCall) {
|
||||
auto channel = InitChannel(ChannelArgs());
|
||||
auto call = MakeCall(MakeClientInitialMetadata());
|
||||
SpawnTestSeq(
|
||||
call.handler, "start-call", [channel, handler = call.handler]() mutable {
|
||||
channel->unstarted_call_destination()->StartCall(std::move(handler));
|
||||
return Empty{};
|
||||
});
|
||||
auto handler = TickUntilCallStarted();
|
||||
WaitForAllPendingWork();
|
||||
}
|
||||
|
||||
} // namespace grpc_core
|
||||
|
|
@ -0,0 +1 @@
|
|||
|
||||
|
|
@ -0,0 +1 @@
|
|||
|
||||
|
|
@ -0,0 +1 @@
|
|||
|
||||
|
|
@ -0,0 +1,202 @@
|
|||
// Copyright 2024 gRPC authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "src/core/client_channel/load_balanced_call_destination.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <queue>
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <grpc/grpc.h>
|
||||
|
||||
#include "test/core/call/yodel/yodel_test.h"
|
||||
|
||||
using testing::StrictMock;
|
||||
|
||||
namespace grpc_core {
|
||||
|
||||
using EventEngine = grpc_event_engine::experimental::EventEngine;
|
||||
|
||||
namespace {
|
||||
const absl::string_view kTestPath = "/test_method";
|
||||
} // namespace
|
||||
|
||||
class LoadBalancedCallDestinationTest : public YodelTest {
|
||||
protected:
|
||||
using YodelTest::YodelTest;
|
||||
|
||||
ClientMetadataHandle MakeClientInitialMetadata() {
|
||||
auto client_initial_metadata = Arena::MakePooled<ClientMetadata>();
|
||||
client_initial_metadata->Set(HttpPathMetadata(),
|
||||
Slice::FromCopiedString(kTestPath));
|
||||
return client_initial_metadata;
|
||||
}
|
||||
|
||||
CallInitiatorAndHandler MakeCall(
|
||||
ClientMetadataHandle client_initial_metadata) {
|
||||
return MakeCallPair(
|
||||
std::move(client_initial_metadata), event_engine().get(),
|
||||
call_arena_allocator_->MakeArena(), call_arena_allocator_, nullptr);
|
||||
}
|
||||
|
||||
CallHandler TickUntilCallStarted() {
|
||||
auto poll = [this]() -> Poll<CallHandler> {
|
||||
auto handler = call_destination_->PopHandler();
|
||||
if (handler.has_value()) return std::move(*handler);
|
||||
return Pending();
|
||||
};
|
||||
return TickUntil(absl::FunctionRef<Poll<CallHandler>()>(poll));
|
||||
}
|
||||
|
||||
LoadBalancedCallDestination& destination_under_test() {
|
||||
return *destination_under_test_;
|
||||
}
|
||||
|
||||
ClientChannel::PickerObservable& picker() { return picker_; }
|
||||
|
||||
RefCountedPtr<SubchannelInterface> subchannel() { return subchannel_; }
|
||||
|
||||
private:
|
||||
class TestCallDestination final : public UnstartedCallDestination {
|
||||
public:
|
||||
void StartCall(UnstartedCallHandler unstarted_call_handler) override {
|
||||
handlers_.push(
|
||||
unstarted_call_handler.V2HackToStartCallWithoutACallFilterStack());
|
||||
}
|
||||
|
||||
absl::optional<CallHandler> PopHandler() {
|
||||
if (handlers_.empty()) return absl::nullopt;
|
||||
auto handler = std::move(handlers_.front());
|
||||
handlers_.pop();
|
||||
return handler;
|
||||
}
|
||||
|
||||
void Orphaned() override {}
|
||||
|
||||
private:
|
||||
std::queue<CallHandler> handlers_;
|
||||
};
|
||||
|
||||
class TestSubchannel : public SubchannelInterfaceWithCallDestination {
|
||||
public:
|
||||
explicit TestSubchannel(
|
||||
RefCountedPtr<UnstartedCallDestination> call_destination)
|
||||
: call_destination_(std::move(call_destination)) {}
|
||||
|
||||
void WatchConnectivityState(
|
||||
std::unique_ptr<ConnectivityStateWatcherInterface>) override {
|
||||
Crash("not implemented");
|
||||
}
|
||||
void CancelConnectivityStateWatch(
|
||||
ConnectivityStateWatcherInterface*) override {
|
||||
Crash("not implemented");
|
||||
}
|
||||
void RequestConnection() override { Crash("not implemented"); }
|
||||
void ResetBackoff() override { Crash("not implemented"); }
|
||||
void AddDataWatcher(std::unique_ptr<DataWatcherInterface>) override {
|
||||
Crash("not implemented");
|
||||
}
|
||||
void CancelDataWatcher(DataWatcherInterface*) override {
|
||||
Crash("not implemented");
|
||||
}
|
||||
RefCountedPtr<UnstartedCallDestination> call_destination() override {
|
||||
return call_destination_;
|
||||
}
|
||||
|
||||
private:
|
||||
const RefCountedPtr<UnstartedCallDestination> call_destination_;
|
||||
};
|
||||
|
||||
void InitCoreConfiguration() override {}
|
||||
|
||||
void Shutdown() override {
|
||||
channel_.reset();
|
||||
picker_ = ClientChannel::PickerObservable(nullptr);
|
||||
call_destination_.reset();
|
||||
destination_under_test_.reset();
|
||||
call_arena_allocator_.reset();
|
||||
subchannel_.reset();
|
||||
}
|
||||
|
||||
OrphanablePtr<ClientChannel> channel_;
|
||||
ClientChannel::PickerObservable picker_{nullptr};
|
||||
RefCountedPtr<TestCallDestination> call_destination_ =
|
||||
MakeRefCounted<TestCallDestination>();
|
||||
RefCountedPtr<LoadBalancedCallDestination> destination_under_test_ =
|
||||
MakeRefCounted<LoadBalancedCallDestination>(picker_);
|
||||
RefCountedPtr<CallArenaAllocator> call_arena_allocator_ =
|
||||
MakeRefCounted<CallArenaAllocator>(
|
||||
ResourceQuota::Default()->memory_quota()->CreateMemoryAllocator(
|
||||
"test"),
|
||||
1024);
|
||||
RefCountedPtr<TestSubchannel> subchannel_ =
|
||||
MakeRefCounted<TestSubchannel>(call_destination_);
|
||||
};
|
||||
|
||||
#define LOAD_BALANCED_CALL_DESTINATION_TEST(name) \
|
||||
YODEL_TEST(LoadBalancedCallDestinationTest, name)
|
||||
|
||||
class MockPicker : public LoadBalancingPolicy::SubchannelPicker {
|
||||
public:
|
||||
MOCK_METHOD(LoadBalancingPolicy::PickResult, Pick,
|
||||
(LoadBalancingPolicy::PickArgs));
|
||||
};
|
||||
|
||||
LOAD_BALANCED_CALL_DESTINATION_TEST(NoOp) {}
|
||||
|
||||
LOAD_BALANCED_CALL_DESTINATION_TEST(CreateCall) {
|
||||
auto call = MakeCall(MakeClientInitialMetadata());
|
||||
SpawnTestSeq(
|
||||
call.initiator, "initiator",
|
||||
[this, handler = std::move(call.handler)]() {
|
||||
destination_under_test().StartCall(handler);
|
||||
return Empty{};
|
||||
},
|
||||
[call_initiator = call.initiator]() mutable {
|
||||
call_initiator.Cancel();
|
||||
return Empty{};
|
||||
});
|
||||
WaitForAllPendingWork();
|
||||
}
|
||||
|
||||
LOAD_BALANCED_CALL_DESTINATION_TEST(StartCall) {
|
||||
auto call = MakeCall(MakeClientInitialMetadata());
|
||||
SpawnTestSeq(call.initiator, "initiator",
|
||||
[this, handler = std::move(call.handler)]() {
|
||||
destination_under_test().StartCall(handler);
|
||||
return Empty{};
|
||||
});
|
||||
auto mock_picker = MakeRefCounted<StrictMock<MockPicker>>();
|
||||
EXPECT_CALL(*mock_picker, Pick)
|
||||
.WillOnce([this](LoadBalancingPolicy::PickArgs) {
|
||||
return LoadBalancingPolicy::PickResult::Complete{subchannel()};
|
||||
});
|
||||
picker().Set(mock_picker);
|
||||
auto handler = TickUntilCallStarted();
|
||||
SpawnTestSeq(call.initiator, "cancel",
|
||||
[call_initiator = call.initiator]() mutable {
|
||||
call_initiator.Cancel();
|
||||
return Empty{};
|
||||
});
|
||||
WaitForAllPendingWork();
|
||||
}
|
||||
|
||||
// TODO(roth, ctiller): more tests
|
||||
// - tests for the picker returning queue, fail, and drop results.
|
||||
|
||||
} // namespace grpc_core
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
//
|
||||
// Copyright 2022 gRPC authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <grpc/impl/channel_arg_names.h>
|
||||
#include <grpc/support/port_platform.h>
|
||||
|
||||
#include "src/core/client_channel/subchannel.h"
|
||||
#include "src/core/client_channel/subchannel_pool_interface.h"
|
||||
#include "src/core/lib/channel/channel_args.h"
|
||||
#include "src/core/resolver/endpoint_addresses.h"
|
||||
#include "test/core/test_util/test_config.h"
|
||||
|
||||
namespace grpc_core {
|
||||
namespace testing {
|
||||
namespace {
|
||||
|
||||
TEST(MakeSubchannelArgs, UsesChannelDefaultAuthorityByDefault) {
|
||||
ChannelArgs args = Subchannel::MakeSubchannelArgs(
|
||||
ChannelArgs(), ChannelArgs(), nullptr, "foo.example.com");
|
||||
EXPECT_EQ(args.GetString(GRPC_ARG_DEFAULT_AUTHORITY), "foo.example.com");
|
||||
}
|
||||
|
||||
TEST(MakeSubchannelArgs, DefaultAuthorityFromChannelArgs) {
|
||||
ChannelArgs args = Subchannel::MakeSubchannelArgs(
|
||||
ChannelArgs().Set(GRPC_ARG_DEFAULT_AUTHORITY, "bar.example.com"),
|
||||
ChannelArgs(), nullptr, "foo.example.com");
|
||||
EXPECT_EQ(args.GetString(GRPC_ARG_DEFAULT_AUTHORITY), "bar.example.com");
|
||||
}
|
||||
|
||||
TEST(MakeSubchannelArgs, DefaultAuthorityFromResolver) {
|
||||
ChannelArgs args = Subchannel::MakeSubchannelArgs(
|
||||
ChannelArgs(),
|
||||
ChannelArgs().Set(GRPC_ARG_DEFAULT_AUTHORITY, "bar.example.com"), nullptr,
|
||||
"foo.example.com");
|
||||
EXPECT_EQ(args.GetString(GRPC_ARG_DEFAULT_AUTHORITY), "bar.example.com");
|
||||
}
|
||||
|
||||
TEST(MakeSubchannelArgs,
|
||||
DefaultAuthorityFromChannelArgsOverridesValueFromResolver) {
|
||||
ChannelArgs args = Subchannel::MakeSubchannelArgs(
|
||||
ChannelArgs().Set(GRPC_ARG_DEFAULT_AUTHORITY, "bar.example.com"),
|
||||
ChannelArgs().Set(GRPC_ARG_DEFAULT_AUTHORITY, "baz.example.com"), nullptr,
|
||||
"foo.example.com");
|
||||
EXPECT_EQ(args.GetString(GRPC_ARG_DEFAULT_AUTHORITY), "bar.example.com");
|
||||
}
|
||||
|
||||
TEST(MakeSubchannelArgs, ArgsFromChannelTrumpPerAddressArgs) {
|
||||
ChannelArgs args = Subchannel::MakeSubchannelArgs(ChannelArgs().Set("foo", 1),
|
||||
ChannelArgs().Set("foo", 2),
|
||||
nullptr, "foo.example.com");
|
||||
EXPECT_EQ(args.GetInt("foo"), 1);
|
||||
}
|
||||
|
||||
TEST(MakeSubchannelArgs, StripsOutNoSubchannelArgs) {
|
||||
ChannelArgs args = Subchannel::MakeSubchannelArgs(
|
||||
ChannelArgs().Set(GRPC_ARG_NO_SUBCHANNEL_PREFIX "foo", 1),
|
||||
ChannelArgs().Set(GRPC_ARG_NO_SUBCHANNEL_PREFIX "bar", 1), nullptr,
|
||||
"foo.example.com");
|
||||
EXPECT_EQ(args.GetString(GRPC_ARG_NO_SUBCHANNEL_PREFIX "foo"), absl::nullopt);
|
||||
EXPECT_EQ(args.GetString(GRPC_ARG_NO_SUBCHANNEL_PREFIX "bar"), absl::nullopt);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace testing
|
||||
} // namespace grpc_core
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
grpc::testing::TestEnvironment env(&argc, argv);
|
||||
auto result = RUN_ALL_TESTS();
|
||||
return result;
|
||||
}
|
||||
|
|
@ -145,6 +145,7 @@ grpc_cc_test(
|
|||
uses_event_engine = False,
|
||||
uses_polling = False,
|
||||
deps = [
|
||||
"poll_matcher",
|
||||
"//:promise",
|
||||
"//src/core:map",
|
||||
],
|
||||
|
|
|
|||
|
|
@ -20,12 +20,13 @@
|
|||
#include "gtest/gtest.h"
|
||||
|
||||
#include "src/core/lib/promise/promise.h"
|
||||
#include "test/core/promise/poll_matcher.h"
|
||||
|
||||
namespace grpc_core {
|
||||
|
||||
TEST(MapTest, Works) {
|
||||
Promise<int> x = Map([]() { return 42; }, [](int i) { return i / 2; });
|
||||
EXPECT_EQ(x(), Poll<int>(21));
|
||||
EXPECT_THAT(x(), IsReady(21));
|
||||
}
|
||||
|
||||
TEST(MapTest, JustElem) {
|
||||
|
|
@ -34,6 +35,21 @@ TEST(MapTest, JustElem) {
|
|||
EXPECT_EQ(JustElem<0>()(t), 1);
|
||||
}
|
||||
|
||||
TEST(CheckDelayedTest, SeesImmediate) {
|
||||
auto x = CheckDelayed([]() { return 42; });
|
||||
EXPECT_THAT(x(), IsReady(std::make_tuple(42, false)));
|
||||
}
|
||||
|
||||
TEST(CheckDelayedTest, SeesDelayed) {
|
||||
auto x = CheckDelayed([n = 1]() mutable -> Poll<int> {
|
||||
if (n == 0) return 42;
|
||||
--n;
|
||||
return Pending{};
|
||||
});
|
||||
EXPECT_THAT(x(), IsPending());
|
||||
EXPECT_THAT(x(), IsReady(std::make_tuple(42, true)));
|
||||
}
|
||||
|
||||
} // namespace grpc_core
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
|
|
|||
|
|
@ -140,6 +140,16 @@ TEST(ObservableTest, MultipleActivitiesWakeUp) {
|
|||
EXPECT_THAT(next2(), IsReady(2));
|
||||
}
|
||||
|
||||
TEST(ObservableTest, NoDeadlockOnDestruction) {
|
||||
StrictMock<MockActivity> activity;
|
||||
Observable<int> observable(1);
|
||||
activity.Activate();
|
||||
{
|
||||
auto next = observable.Next(1);
|
||||
EXPECT_THAT(next(), IsPending());
|
||||
}
|
||||
}
|
||||
|
||||
class ThreadWakeupScheduler {
|
||||
public:
|
||||
template <typename ActivityType>
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ void test_unknown_scheme_target(void) {
|
|||
grpc_core::Channel::FromC(chan)->channel_stack(), 0);
|
||||
ASSERT_STREQ(elem->filter->name, "lame-client");
|
||||
grpc_core::ExecCtx exec_ctx;
|
||||
grpc_core::Channel::FromC(chan)->Unref();
|
||||
grpc_core::Channel::FromC(chan)->Orphan();
|
||||
creds->Unref();
|
||||
}
|
||||
|
||||
|
|
@ -53,7 +53,7 @@ void test_security_connector_already_in_arg(void) {
|
|||
grpc_core::Channel::FromC(chan)->channel_stack(), 0);
|
||||
ASSERT_STREQ(elem->filter->name, "lame-client");
|
||||
grpc_core::ExecCtx exec_ctx;
|
||||
grpc_core::Channel::FromC(chan)->Unref();
|
||||
grpc_core::Channel::FromC(chan)->Orphan();
|
||||
}
|
||||
|
||||
void test_null_creds(void) {
|
||||
|
|
@ -62,7 +62,7 @@ void test_null_creds(void) {
|
|||
grpc_core::Channel::FromC(chan)->channel_stack(), 0);
|
||||
ASSERT_STREQ(elem->filter->name, "lame-client");
|
||||
grpc_core::ExecCtx exec_ctx;
|
||||
grpc_core::Channel::FromC(chan)->Unref();
|
||||
grpc_core::Channel::FromC(chan)->Orphan();
|
||||
}
|
||||
|
||||
TEST(SecureChannelCreateTest, MainTest) {
|
||||
|
|
|
|||
|
|
@ -58,12 +58,10 @@ void TransportTest::ServerCallDestination::StartCall(
|
|||
}
|
||||
|
||||
absl::optional<CallHandler> TransportTest::ServerCallDestination::PopHandler() {
|
||||
if (!handlers_.empty()) {
|
||||
auto handler = std::move(handlers_.front());
|
||||
handlers_.pop();
|
||||
return handler;
|
||||
}
|
||||
return absl::nullopt;
|
||||
if (handlers_.empty()) return absl::nullopt;
|
||||
auto handler = std::move(handlers_.front());
|
||||
handlers_.pop();
|
||||
return handler;
|
||||
}
|
||||
|
||||
} // namespace grpc_core
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ class TransportTest : public YodelTest {
|
|||
TransportTest(const TransportFixture& fixture,
|
||||
const fuzzing_event_engine::Actions& actions,
|
||||
absl::BitGenRef rng)
|
||||
: YodelTest(actions, rng), transport_pair_(fixture(event_engine())) {}
|
||||
: YodelTest(actions, rng), fixture_(std::move(fixture)) {}
|
||||
|
||||
void SetServerCallDestination();
|
||||
CallInitiator CreateCall(ClientMetadataHandle client_initial_metadata);
|
||||
|
|
@ -60,6 +60,8 @@ class TransportTest : public YodelTest {
|
|||
std::queue<CallHandler> handlers_;
|
||||
};
|
||||
|
||||
void InitTest() override { transport_pair_ = fixture_(event_engine()); }
|
||||
|
||||
void Shutdown() override {
|
||||
transport_pair_.client.reset();
|
||||
transport_pair_.server.reset();
|
||||
|
|
@ -67,6 +69,7 @@ class TransportTest : public YodelTest {
|
|||
|
||||
RefCountedPtr<ServerCallDestination> server_call_destination_ =
|
||||
MakeRefCounted<ServerCallDestination>();
|
||||
const TransportFixture& fixture_;
|
||||
ClientAndServerTransportPair transport_pair_;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -400,6 +400,7 @@ for dirname in [
|
|||
"src/cpp/ext/otel",
|
||||
"test/core/backoff",
|
||||
"test/core/call/yodel",
|
||||
"test/core/client_channel",
|
||||
"test/core/experiments",
|
||||
"test/core/uri",
|
||||
"test/core/test_util",
|
||||
|
|
@ -430,7 +431,10 @@ for dirname in [
|
|||
"grpc_cc_library": grpc_cc_library,
|
||||
"grpc_cc_test": grpc_cc_library,
|
||||
"grpc_core_end2end_test": lambda **kwargs: None,
|
||||
"grpc_filegroup": lambda **kwargs: None,
|
||||
"grpc_transport_test": lambda **kwargs: None,
|
||||
"grpc_yodel_test": lambda **kwargs: None,
|
||||
"grpc_yodel_simple_test": lambda **kwargs: None,
|
||||
"grpc_fuzzer": grpc_cc_library,
|
||||
"grpc_fuzz_test": grpc_cc_library,
|
||||
"grpc_proto_fuzzer": grpc_cc_library,
|
||||
|
|
|
|||
|
|
@ -1093,6 +1093,8 @@ src/core/channelz/channelz_registry.cc \
|
|||
src/core/channelz/channelz_registry.h \
|
||||
src/core/client_channel/backup_poller.cc \
|
||||
src/core/client_channel/backup_poller.h \
|
||||
src/core/client_channel/client_channel.cc \
|
||||
src/core/client_channel/client_channel.h \
|
||||
src/core/client_channel/client_channel_factory.cc \
|
||||
src/core/client_channel/client_channel_factory.h \
|
||||
src/core/client_channel/client_channel_filter.cc \
|
||||
|
|
@ -1108,6 +1110,8 @@ src/core/client_channel/dynamic_filters.cc \
|
|||
src/core/client_channel/dynamic_filters.h \
|
||||
src/core/client_channel/global_subchannel_pool.cc \
|
||||
src/core/client_channel/global_subchannel_pool.h \
|
||||
src/core/client_channel/load_balanced_call_destination.cc \
|
||||
src/core/client_channel/load_balanced_call_destination.h \
|
||||
src/core/client_channel/local_subchannel_pool.cc \
|
||||
src/core/client_channel/local_subchannel_pool.h \
|
||||
src/core/client_channel/retry_filter.cc \
|
||||
|
|
@ -2260,6 +2264,8 @@ src/core/lib/gprpp/debug_location.h \
|
|||
src/core/lib/gprpp/directory_reader.h \
|
||||
src/core/lib/gprpp/down_cast.h \
|
||||
src/core/lib/gprpp/dual_ref_counted.h \
|
||||
src/core/lib/gprpp/dump_args.cc \
|
||||
src/core/lib/gprpp/dump_args.h \
|
||||
src/core/lib/gprpp/env.h \
|
||||
src/core/lib/gprpp/examine_stack.cc \
|
||||
src/core/lib/gprpp/examine_stack.h \
|
||||
|
|
@ -2485,6 +2491,7 @@ src/core/lib/promise/interceptor_list.h \
|
|||
src/core/lib/promise/latch.h \
|
||||
src/core/lib/promise/loop.h \
|
||||
src/core/lib/promise/map.h \
|
||||
src/core/lib/promise/observable.h \
|
||||
src/core/lib/promise/party.cc \
|
||||
src/core/lib/promise/party.h \
|
||||
src/core/lib/promise/pipe.h \
|
||||
|
|
|
|||
|
|
@ -896,6 +896,8 @@ src/core/channelz/channelz_registry.h \
|
|||
src/core/client_channel/README.md \
|
||||
src/core/client_channel/backup_poller.cc \
|
||||
src/core/client_channel/backup_poller.h \
|
||||
src/core/client_channel/client_channel.cc \
|
||||
src/core/client_channel/client_channel.h \
|
||||
src/core/client_channel/client_channel_factory.cc \
|
||||
src/core/client_channel/client_channel_factory.h \
|
||||
src/core/client_channel/client_channel_filter.cc \
|
||||
|
|
@ -911,6 +913,8 @@ src/core/client_channel/dynamic_filters.cc \
|
|||
src/core/client_channel/dynamic_filters.h \
|
||||
src/core/client_channel/global_subchannel_pool.cc \
|
||||
src/core/client_channel/global_subchannel_pool.h \
|
||||
src/core/client_channel/load_balanced_call_destination.cc \
|
||||
src/core/client_channel/load_balanced_call_destination.h \
|
||||
src/core/client_channel/local_subchannel_pool.cc \
|
||||
src/core/client_channel/local_subchannel_pool.h \
|
||||
src/core/client_channel/retry_filter.cc \
|
||||
|
|
@ -2033,6 +2037,8 @@ src/core/lib/gprpp/debug_location.h \
|
|||
src/core/lib/gprpp/directory_reader.h \
|
||||
src/core/lib/gprpp/down_cast.h \
|
||||
src/core/lib/gprpp/dual_ref_counted.h \
|
||||
src/core/lib/gprpp/dump_args.cc \
|
||||
src/core/lib/gprpp/dump_args.h \
|
||||
src/core/lib/gprpp/env.h \
|
||||
src/core/lib/gprpp/examine_stack.cc \
|
||||
src/core/lib/gprpp/examine_stack.h \
|
||||
|
|
@ -2259,6 +2265,7 @@ src/core/lib/promise/interceptor_list.h \
|
|||
src/core/lib/promise/latch.h \
|
||||
src/core/lib/promise/loop.h \
|
||||
src/core/lib/promise/map.h \
|
||||
src/core/lib/promise/observable.h \
|
||||
src/core/lib/promise/party.cc \
|
||||
src/core/lib/promise/party.h \
|
||||
src/core/lib/promise/pipe.h \
|
||||
|
|
|
|||
|
|
@ -2118,9 +2118,7 @@
|
|||
"benchmark": false,
|
||||
"ci_platforms": [
|
||||
"linux",
|
||||
"mac",
|
||||
"posix",
|
||||
"windows"
|
||||
"posix"
|
||||
],
|
||||
"cpu_cost": 1.0,
|
||||
"exclude_configs": [],
|
||||
|
|
@ -2131,9 +2129,7 @@
|
|||
"name": "client_channel_test",
|
||||
"platforms": [
|
||||
"linux",
|
||||
"mac",
|
||||
"posix",
|
||||
"windows"
|
||||
"posix"
|
||||
],
|
||||
"uses_polling": false
|
||||
},
|
||||
|
|
@ -2445,6 +2441,26 @@
|
|||
],
|
||||
"uses_polling": true
|
||||
},
|
||||
{
|
||||
"args": [],
|
||||
"benchmark": false,
|
||||
"ci_platforms": [
|
||||
"linux",
|
||||
"posix"
|
||||
],
|
||||
"cpu_cost": 1.0,
|
||||
"exclude_configs": [],
|
||||
"exclude_iomgrs": [],
|
||||
"flaky": false,
|
||||
"gtest": true,
|
||||
"language": "c++",
|
||||
"name": "connected_subchannel_test",
|
||||
"platforms": [
|
||||
"linux",
|
||||
"posix"
|
||||
],
|
||||
"uses_polling": false
|
||||
},
|
||||
{
|
||||
"args": [],
|
||||
"benchmark": false,
|
||||
|
|
@ -5533,6 +5549,26 @@
|
|||
],
|
||||
"uses_polling": true
|
||||
},
|
||||
{
|
||||
"args": [],
|
||||
"benchmark": false,
|
||||
"ci_platforms": [
|
||||
"linux",
|
||||
"posix"
|
||||
],
|
||||
"cpu_cost": 1.0,
|
||||
"exclude_configs": [],
|
||||
"exclude_iomgrs": [],
|
||||
"flaky": false,
|
||||
"gtest": true,
|
||||
"language": "c++",
|
||||
"name": "load_balanced_call_destination_test",
|
||||
"platforms": [
|
||||
"linux",
|
||||
"posix"
|
||||
],
|
||||
"uses_polling": false
|
||||
},
|
||||
{
|
||||
"args": [],
|
||||
"benchmark": false,
|
||||
|
|
@ -10065,6 +10101,30 @@
|
|||
],
|
||||
"uses_polling": false
|
||||
},
|
||||
{
|
||||
"args": [],
|
||||
"benchmark": false,
|
||||
"ci_platforms": [
|
||||
"linux",
|
||||
"mac",
|
||||
"posix",
|
||||
"windows"
|
||||
],
|
||||
"cpu_cost": 1.0,
|
||||
"exclude_configs": [],
|
||||
"exclude_iomgrs": [],
|
||||
"flaky": false,
|
||||
"gtest": true,
|
||||
"language": "c++",
|
||||
"name": "subchannel_args_test",
|
||||
"platforms": [
|
||||
"linux",
|
||||
"mac",
|
||||
"posix",
|
||||
"windows"
|
||||
],
|
||||
"uses_polling": false
|
||||
},
|
||||
{
|
||||
"args": [],
|
||||
"benchmark": false,
|
||||
|
|
|
|||
Loading…
Reference in New Issue