[promises] Promise based grpc_call (#29598)
* Automated change: Fix sanity tests * fix * fixes * fixup allocator story - we should require a context * fixes * doodling * context scribbles * [arena] Add ManagedNew(), gtest-ify test Add a ManagedNew() method to Arena that calls the relevant destructor at Arena destruction time. There are some cases coming up in the promise based call work where this becomes super convenient, and I expect it's likely that there are other places that's true too. * Automated change: Fix sanity tests * progress * lalalal * progress * x * Automated change: Fix sanity tests * fixes * fix * fix * fix * fix * Automated change: Fix sanity tests * fix * Automated change: Fix sanity tests * fixes * fixes * fixes * Automated change: Fix sanity tests * progress * fix client streaming * handle invalid flags * Automated change: Fix sanity tests * no logging * progress * progress * channelz * tentative fix * fix * lalala * Automated change: Fix sanity tests * more readable trace * logging improvements, leading to bug fix in connected channel * fix * improve debuggability * fix * progress to better refcounting * progress * Automated change: Fix sanity tests * Automated change: Fix sanity tests * fix * fix * fix * threading * Automated change: Fix sanity tests * fix * fix * improve debuggability * fix * fix * Automated change: Fix sanity tests * fix * make promises runtime configurable * Automated change: Fix sanity tests * fix * fix build * fix broken test * clean up api * deal with stats better * peer string! * introduce fragments * Automated change: Fix sanity tests * use fragments * stuff * [promises] Add AtomicWaker type * Automated change: Fix sanity tests * fix * fix write path * fix * polling-entity-hell * review feedback * fix * fix * fix * fix * make an experiment * [experiments] Make output more diffable/readable * Automated change: Fix sanity tests * buildifier sized indentations * fix * fix * Automated change: Fix sanity tests * fix? * fix promise * prototype * progress * implement new api * Revert "fix promise" This reverts commitded85e7d19. * Revert "Revert "fix promise"" This reverts commitc2acef1958. * progress * done * Automated change: Fix sanity tests * fix * fix * fix * Automated change: Fix sanity tests * updates * review feedback * first pass feedback * Automated change: Fix sanity tests * review feedback * naming * better-logs * fix test * Automated change: Fix sanity tests * comments * fix * progress * validation * iwyu * fix * ugh this needs to be any * fix flakiness in asan * call tracing * cleanup unused args * fix windows * fix build * ugh * fix tsan race * threading-fix * bloat1 * bloat2 * bloat3 * fix * unused-args * sanity * iwyu * fix * fix * this is ok * iwyu, exchange * fix * Automated change: Fix sanity tests * fix ee lifetime issue * fix * review feedback * Automated change: Fix sanity tests * comment * x * fix tsan race * iwyu * Automated change: Fix sanity tests Co-authored-by: ctiller <ctiller@users.noreply.github.com>
This commit is contained in:
parent
e1e1f6181f
commit
beb5bdca62
9
BUILD
9
BUILD
|
|
@ -1659,6 +1659,7 @@ grpc_cc_library(
|
|||
external_deps = [
|
||||
"absl/base:core_headers",
|
||||
"absl/status",
|
||||
"absl/strings:str_format",
|
||||
"absl/types:optional",
|
||||
"absl/types:variant",
|
||||
"absl/utility",
|
||||
|
|
@ -2820,7 +2821,6 @@ grpc_cc_library(
|
|||
"absl/strings",
|
||||
"absl/strings:str_format",
|
||||
"absl/types:optional",
|
||||
"absl/utility",
|
||||
],
|
||||
deps = [
|
||||
"event_engine_base_hdrs",
|
||||
|
|
@ -3234,6 +3234,7 @@ grpc_cc_library(
|
|||
"src/core/lib/surface/call.cc",
|
||||
"src/core/lib/surface/call_details.cc",
|
||||
"src/core/lib/surface/call_log_batch.cc",
|
||||
"src/core/lib/surface/call_trace.cc",
|
||||
"src/core/lib/surface/channel.cc",
|
||||
"src/core/lib/surface/channel_ping.cc",
|
||||
"src/core/lib/surface/completion_queue.cc",
|
||||
|
|
@ -3244,6 +3245,7 @@ grpc_cc_library(
|
|||
"src/core/lib/surface/server.cc",
|
||||
"src/core/lib/surface/validate_metadata.cc",
|
||||
"src/core/lib/surface/version.cc",
|
||||
"src/core/lib/transport/call_fragments.cc",
|
||||
"src/core/lib/transport/connectivity_state.cc",
|
||||
"src/core/lib/transport/error_utils.cc",
|
||||
"src/core/lib/transport/metadata_batch.cc",
|
||||
|
|
@ -3324,6 +3326,7 @@ grpc_cc_library(
|
|||
"src/core/lib/surface/builtins.h",
|
||||
"src/core/lib/surface/call.h",
|
||||
"src/core/lib/surface/call_test_only.h",
|
||||
"src/core/lib/surface/call_trace.h",
|
||||
"src/core/lib/surface/channel.h",
|
||||
"src/core/lib/surface/completion_queue.h",
|
||||
"src/core/lib/surface/completion_queue_factory.h",
|
||||
|
|
@ -3334,6 +3337,7 @@ grpc_cc_library(
|
|||
"src/core/lib/surface/validate_metadata.h",
|
||||
"src/core/lib/transport/connectivity_state.h",
|
||||
"src/core/lib/transport/metadata_batch.h",
|
||||
"src/core/lib/transport/call_fragments.h",
|
||||
"src/core/lib/transport/parsed_metadata.h",
|
||||
"src/core/lib/transport/status_conversion.h",
|
||||
"src/core/lib/transport/timeout_encoding.h",
|
||||
|
|
@ -3359,6 +3363,7 @@ grpc_cc_library(
|
|||
],
|
||||
external_deps = [
|
||||
"absl/base:core_headers",
|
||||
"absl/cleanup",
|
||||
"absl/container:flat_hash_map",
|
||||
"absl/container:inlined_vector",
|
||||
"absl/functional:any_invocable",
|
||||
|
|
@ -3417,11 +3422,13 @@ grpc_cc_library(
|
|||
"iomgr_timer",
|
||||
"json",
|
||||
"latch",
|
||||
"match",
|
||||
"memory_quota",
|
||||
"no_destruct",
|
||||
"notification",
|
||||
"orphanable",
|
||||
"packed_table",
|
||||
"pipe",
|
||||
"poll",
|
||||
"pollset_set",
|
||||
"promise",
|
||||
|
|
|
|||
|
|
@ -865,6 +865,7 @@ if(gRPC_BUILD_TESTS)
|
|||
add_dependencies(buildtests_cxx byte_buffer_test)
|
||||
add_dependencies(buildtests_cxx c_slice_buffer_test)
|
||||
add_dependencies(buildtests_cxx call_finalization_test)
|
||||
add_dependencies(buildtests_cxx call_fragments_test)
|
||||
add_dependencies(buildtests_cxx call_push_pull_test)
|
||||
add_dependencies(buildtests_cxx cancel_ares_query_test)
|
||||
add_dependencies(buildtests_cxx cel_authorization_engine_test)
|
||||
|
|
@ -2309,6 +2310,7 @@ add_library(grpc
|
|||
src/core/lib/surface/call.cc
|
||||
src/core/lib/surface/call_details.cc
|
||||
src/core/lib/surface/call_log_batch.cc
|
||||
src/core/lib/surface/call_trace.cc
|
||||
src/core/lib/surface/channel.cc
|
||||
src/core/lib/surface/channel_init.cc
|
||||
src/core/lib/surface/channel_ping.cc
|
||||
|
|
@ -2324,6 +2326,7 @@ add_library(grpc
|
|||
src/core/lib/surface/validate_metadata.cc
|
||||
src/core/lib/surface/version.cc
|
||||
src/core/lib/transport/bdp_estimator.cc
|
||||
src/core/lib/transport/call_fragments.cc
|
||||
src/core/lib/transport/connectivity_state.cc
|
||||
src/core/lib/transport/error_utils.cc
|
||||
src/core/lib/transport/handshaker.cc
|
||||
|
|
@ -2407,6 +2410,7 @@ target_link_libraries(grpc
|
|||
${_gRPC_RE2_LIBRARIES}
|
||||
${_gRPC_UPB_LIBRARIES}
|
||||
${_gRPC_ALLTARGETS_LIBRARIES}
|
||||
absl::cleanup
|
||||
absl::flat_hash_map
|
||||
absl::flat_hash_set
|
||||
absl::inlined_vector
|
||||
|
|
@ -2877,6 +2881,7 @@ add_library(grpc_unsecure
|
|||
src/core/lib/surface/call.cc
|
||||
src/core/lib/surface/call_details.cc
|
||||
src/core/lib/surface/call_log_batch.cc
|
||||
src/core/lib/surface/call_trace.cc
|
||||
src/core/lib/surface/channel.cc
|
||||
src/core/lib/surface/channel_init.cc
|
||||
src/core/lib/surface/channel_ping.cc
|
||||
|
|
@ -2892,6 +2897,7 @@ add_library(grpc_unsecure
|
|||
src/core/lib/surface/validate_metadata.cc
|
||||
src/core/lib/surface/version.cc
|
||||
src/core/lib/transport/bdp_estimator.cc
|
||||
src/core/lib/transport/call_fragments.cc
|
||||
src/core/lib/transport/connectivity_state.cc
|
||||
src/core/lib/transport/error_utils.cc
|
||||
src/core/lib/transport/handshaker.cc
|
||||
|
|
@ -2951,6 +2957,7 @@ target_link_libraries(grpc_unsecure
|
|||
${_gRPC_RE2_LIBRARIES}
|
||||
${_gRPC_UPB_LIBRARIES}
|
||||
${_gRPC_ALLTARGETS_LIBRARIES}
|
||||
absl::cleanup
|
||||
absl::flat_hash_map
|
||||
absl::flat_hash_set
|
||||
absl::inlined_vector
|
||||
|
|
@ -3207,7 +3214,6 @@ target_link_libraries(grpc++
|
|||
${_gRPC_BASELIB_LIBRARIES}
|
||||
${_gRPC_PROTOBUF_LIBRARIES}
|
||||
${_gRPC_ALLTARGETS_LIBRARIES}
|
||||
absl::cleanup
|
||||
grpc
|
||||
)
|
||||
|
||||
|
|
@ -6528,7 +6534,6 @@ target_include_directories(binder_transport_test
|
|||
target_link_libraries(binder_transport_test
|
||||
${_gRPC_PROTOBUF_LIBRARIES}
|
||||
${_gRPC_ALLTARGETS_LIBRARIES}
|
||||
absl::cleanup
|
||||
grpc_test_util
|
||||
)
|
||||
|
||||
|
|
@ -6721,6 +6726,41 @@ target_link_libraries(call_finalization_test
|
|||
)
|
||||
|
||||
|
||||
endif()
|
||||
if(gRPC_BUILD_TESTS)
|
||||
|
||||
add_executable(call_fragments_test
|
||||
test/core/transport/call_fragments_test.cc
|
||||
third_party/googletest/googletest/src/gtest-all.cc
|
||||
third_party/googletest/googlemock/src/gmock-all.cc
|
||||
)
|
||||
|
||||
target_include_directories(call_fragments_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(call_fragments_test
|
||||
${_gRPC_PROTOBUF_LIBRARIES}
|
||||
${_gRPC_ALLTARGETS_LIBRARIES}
|
||||
grpc_test_util
|
||||
)
|
||||
|
||||
|
||||
endif()
|
||||
if(gRPC_BUILD_TESTS)
|
||||
|
||||
|
|
@ -9139,7 +9179,6 @@ target_include_directories(endpoint_binder_pool_test
|
|||
target_link_libraries(endpoint_binder_pool_test
|
||||
${_gRPC_PROTOBUF_LIBRARIES}
|
||||
${_gRPC_ALLTARGETS_LIBRARIES}
|
||||
absl::cleanup
|
||||
grpc_test_util
|
||||
)
|
||||
|
||||
|
|
@ -9774,7 +9813,6 @@ target_include_directories(fake_binder_test
|
|||
target_link_libraries(fake_binder_test
|
||||
${_gRPC_PROTOBUF_LIBRARIES}
|
||||
${_gRPC_ALLTARGETS_LIBRARIES}
|
||||
absl::cleanup
|
||||
grpc_test_util
|
||||
)
|
||||
|
||||
|
|
@ -17775,7 +17813,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
|
|||
target_link_libraries(tcp_posix_socket_utils_test
|
||||
${_gRPC_PROTOBUF_LIBRARIES}
|
||||
${_gRPC_ALLTARGETS_LIBRARIES}
|
||||
absl::cleanup
|
||||
grpc_test_util
|
||||
)
|
||||
|
||||
|
|
@ -18027,7 +18064,6 @@ target_include_directories(test_core_gprpp_load_file_test
|
|||
target_link_libraries(test_core_gprpp_load_file_test
|
||||
${_gRPC_PROTOBUF_LIBRARIES}
|
||||
${_gRPC_ALLTARGETS_LIBRARIES}
|
||||
absl::cleanup
|
||||
grpc_test_util
|
||||
)
|
||||
|
||||
|
|
@ -19198,7 +19234,6 @@ target_include_directories(transport_stream_receiver_test
|
|||
target_link_libraries(transport_stream_receiver_test
|
||||
${_gRPC_PROTOBUF_LIBRARIES}
|
||||
${_gRPC_ALLTARGETS_LIBRARIES}
|
||||
absl::cleanup
|
||||
grpc_test_util
|
||||
)
|
||||
|
||||
|
|
@ -19745,7 +19780,6 @@ target_include_directories(wire_reader_test
|
|||
target_link_libraries(wire_reader_test
|
||||
${_gRPC_PROTOBUF_LIBRARIES}
|
||||
${_gRPC_ALLTARGETS_LIBRARIES}
|
||||
absl::cleanup
|
||||
grpc_test_util
|
||||
)
|
||||
|
||||
|
|
@ -19848,7 +19882,6 @@ target_include_directories(wire_writer_test
|
|||
target_link_libraries(wire_writer_test
|
||||
${_gRPC_PROTOBUF_LIBRARIES}
|
||||
${_gRPC_ALLTARGETS_LIBRARIES}
|
||||
absl::cleanup
|
||||
grpc_test_util
|
||||
)
|
||||
|
||||
|
|
@ -22378,7 +22411,7 @@ generate_pkgconfig(
|
|||
"gRPC"
|
||||
"high performance general RPC framework"
|
||||
"${gRPC_CORE_VERSION}"
|
||||
"gpr openssl absl_any_invocable absl_base absl_bind_front absl_cord absl_core_headers absl_flat_hash_map absl_flat_hash_set absl_function_ref absl_hash absl_inlined_vector absl_memory absl_optional absl_random_random absl_span absl_status absl_statusor absl_str_format absl_strings absl_synchronization absl_time absl_type_traits absl_utility absl_variant"
|
||||
"gpr openssl absl_any_invocable absl_base absl_bind_front absl_cleanup absl_cord absl_core_headers absl_flat_hash_map absl_flat_hash_set absl_function_ref absl_hash absl_inlined_vector absl_memory absl_optional absl_random_random absl_span absl_status absl_statusor absl_str_format absl_strings absl_synchronization absl_time absl_type_traits absl_utility absl_variant"
|
||||
"-lgrpc -laddress_sorting -lre2 -lupb -lcares -lz"
|
||||
""
|
||||
"grpc.pc")
|
||||
|
|
@ -22388,7 +22421,7 @@ generate_pkgconfig(
|
|||
"gRPC unsecure"
|
||||
"high performance general RPC framework without SSL"
|
||||
"${gRPC_CORE_VERSION}"
|
||||
"gpr absl_any_invocable absl_base absl_bind_front absl_cord absl_core_headers absl_flat_hash_map absl_flat_hash_set absl_function_ref absl_hash absl_inlined_vector absl_memory absl_optional absl_random_random absl_span absl_status absl_statusor absl_str_format absl_strings absl_synchronization absl_time absl_type_traits absl_utility absl_variant"
|
||||
"gpr absl_any_invocable absl_base absl_bind_front absl_cleanup absl_cord absl_core_headers absl_flat_hash_map absl_flat_hash_set absl_function_ref absl_hash absl_inlined_vector absl_memory absl_optional absl_random_random absl_span absl_status absl_statusor absl_str_format absl_strings absl_synchronization absl_time absl_type_traits absl_utility absl_variant"
|
||||
"-lgrpc_unsecure"
|
||||
""
|
||||
"grpc_unsecure.pc")
|
||||
|
|
@ -22408,7 +22441,7 @@ generate_pkgconfig(
|
|||
"gRPC++ unsecure"
|
||||
"C++ wrapper for gRPC without SSL"
|
||||
"${gRPC_CPP_VERSION}"
|
||||
"grpc_unsecure absl_any_invocable absl_base absl_bind_front absl_cord absl_core_headers absl_flat_hash_map absl_flat_hash_set absl_function_ref absl_hash absl_inlined_vector absl_memory absl_optional absl_random_random absl_span absl_status absl_statusor absl_str_format absl_strings absl_synchronization absl_time absl_type_traits absl_utility absl_variant"
|
||||
"grpc_unsecure absl_any_invocable absl_base absl_bind_front absl_cleanup absl_cord absl_core_headers absl_flat_hash_map absl_flat_hash_set absl_function_ref absl_hash absl_inlined_vector absl_memory absl_optional absl_random_random absl_span absl_status absl_statusor absl_str_format absl_strings absl_synchronization absl_time absl_type_traits absl_utility absl_variant"
|
||||
"-lgrpc++_unsecure"
|
||||
""
|
||||
"grpc++_unsecure.pc")
|
||||
|
|
|
|||
|
|
@ -1586,6 +1586,7 @@ LIBGRPC_SRC = \
|
|||
src/core/lib/surface/call.cc \
|
||||
src/core/lib/surface/call_details.cc \
|
||||
src/core/lib/surface/call_log_batch.cc \
|
||||
src/core/lib/surface/call_trace.cc \
|
||||
src/core/lib/surface/channel.cc \
|
||||
src/core/lib/surface/channel_init.cc \
|
||||
src/core/lib/surface/channel_ping.cc \
|
||||
|
|
@ -1601,6 +1602,7 @@ LIBGRPC_SRC = \
|
|||
src/core/lib/surface/validate_metadata.cc \
|
||||
src/core/lib/surface/version.cc \
|
||||
src/core/lib/transport/bdp_estimator.cc \
|
||||
src/core/lib/transport/call_fragments.cc \
|
||||
src/core/lib/transport/connectivity_state.cc \
|
||||
src/core/lib/transport/error_utils.cc \
|
||||
src/core/lib/transport/handshaker.cc \
|
||||
|
|
@ -2018,6 +2020,7 @@ LIBGRPC_UNSECURE_SRC = \
|
|||
src/core/lib/surface/call.cc \
|
||||
src/core/lib/surface/call_details.cc \
|
||||
src/core/lib/surface/call_log_batch.cc \
|
||||
src/core/lib/surface/call_trace.cc \
|
||||
src/core/lib/surface/channel.cc \
|
||||
src/core/lib/surface/channel_init.cc \
|
||||
src/core/lib/surface/channel_ping.cc \
|
||||
|
|
@ -2033,6 +2036,7 @@ LIBGRPC_UNSECURE_SRC = \
|
|||
src/core/lib/surface/validate_metadata.cc \
|
||||
src/core/lib/surface/version.cc \
|
||||
src/core/lib/transport/bdp_estimator.cc \
|
||||
src/core/lib/transport/call_fragments.cc \
|
||||
src/core/lib/transport/connectivity_state.cc \
|
||||
src/core/lib/transport/error_utils.cc \
|
||||
src/core/lib/transport/handshaker.cc \
|
||||
|
|
|
|||
|
|
@ -26,6 +26,9 @@ EXPERIMENTS = {
|
|||
],
|
||||
},
|
||||
"off": {
|
||||
"core_end2end_test": [
|
||||
"promise_based_client_call",
|
||||
],
|
||||
"endpoint_test": [
|
||||
"tcp_frame_size_tuning",
|
||||
"tcp_rcv_lowat",
|
||||
|
|
@ -44,6 +47,9 @@ EXPERIMENTS = {
|
|||
"hpack_test": [
|
||||
"periodic_resource_quota_reclamation",
|
||||
],
|
||||
"lame_client_test": [
|
||||
"promise_based_client_call",
|
||||
],
|
||||
"promise_test": [
|
||||
"periodic_resource_quota_reclamation",
|
||||
],
|
||||
|
|
|
|||
|
|
@ -866,6 +866,7 @@ libs:
|
|||
- src/core/lib/promise/latch.h
|
||||
- src/core/lib/promise/loop.h
|
||||
- src/core/lib/promise/map.h
|
||||
- src/core/lib/promise/pipe.h
|
||||
- src/core/lib/promise/poll.h
|
||||
- src/core/lib/promise/promise.h
|
||||
- src/core/lib/promise/race.h
|
||||
|
|
@ -955,6 +956,7 @@ libs:
|
|||
- src/core/lib/surface/builtins.h
|
||||
- src/core/lib/surface/call.h
|
||||
- src/core/lib/surface/call_test_only.h
|
||||
- src/core/lib/surface/call_trace.h
|
||||
- src/core/lib/surface/channel.h
|
||||
- src/core/lib/surface/channel_init.h
|
||||
- src/core/lib/surface/channel_stack_type.h
|
||||
|
|
@ -967,6 +969,7 @@ libs:
|
|||
- src/core/lib/surface/server.h
|
||||
- src/core/lib/surface/validate_metadata.h
|
||||
- src/core/lib/transport/bdp_estimator.h
|
||||
- src/core/lib/transport/call_fragments.h
|
||||
- src/core/lib/transport/connectivity_state.h
|
||||
- src/core/lib/transport/error_utils.h
|
||||
- src/core/lib/transport/handshaker.h
|
||||
|
|
@ -1643,6 +1646,7 @@ libs:
|
|||
- src/core/lib/surface/call.cc
|
||||
- src/core/lib/surface/call_details.cc
|
||||
- src/core/lib/surface/call_log_batch.cc
|
||||
- src/core/lib/surface/call_trace.cc
|
||||
- src/core/lib/surface/channel.cc
|
||||
- src/core/lib/surface/channel_init.cc
|
||||
- src/core/lib/surface/channel_ping.cc
|
||||
|
|
@ -1658,6 +1662,7 @@ libs:
|
|||
- src/core/lib/surface/validate_metadata.cc
|
||||
- src/core/lib/surface/version.cc
|
||||
- src/core/lib/transport/bdp_estimator.cc
|
||||
- src/core/lib/transport/call_fragments.cc
|
||||
- src/core/lib/transport/connectivity_state.cc
|
||||
- src/core/lib/transport/error_utils.cc
|
||||
- src/core/lib/transport/handshaker.cc
|
||||
|
|
@ -1703,6 +1708,7 @@ libs:
|
|||
- src/core/tsi/transport_security.cc
|
||||
- src/core/tsi/transport_security_grpc.cc
|
||||
deps:
|
||||
- absl/cleanup:cleanup
|
||||
- absl/container:flat_hash_map
|
||||
- absl/container:flat_hash_set
|
||||
- absl/container:inlined_vector
|
||||
|
|
@ -2064,6 +2070,7 @@ libs:
|
|||
- src/core/lib/promise/latch.h
|
||||
- src/core/lib/promise/loop.h
|
||||
- src/core/lib/promise/map.h
|
||||
- src/core/lib/promise/pipe.h
|
||||
- src/core/lib/promise/poll.h
|
||||
- src/core/lib/promise/promise.h
|
||||
- src/core/lib/promise/race.h
|
||||
|
|
@ -2122,6 +2129,7 @@ libs:
|
|||
- src/core/lib/surface/builtins.h
|
||||
- src/core/lib/surface/call.h
|
||||
- src/core/lib/surface/call_test_only.h
|
||||
- src/core/lib/surface/call_trace.h
|
||||
- src/core/lib/surface/channel.h
|
||||
- src/core/lib/surface/channel_init.h
|
||||
- src/core/lib/surface/channel_stack_type.h
|
||||
|
|
@ -2134,6 +2142,7 @@ libs:
|
|||
- src/core/lib/surface/server.h
|
||||
- src/core/lib/surface/validate_metadata.h
|
||||
- src/core/lib/transport/bdp_estimator.h
|
||||
- src/core/lib/transport/call_fragments.h
|
||||
- src/core/lib/transport/connectivity_state.h
|
||||
- src/core/lib/transport/error_utils.h
|
||||
- src/core/lib/transport/handshaker.h
|
||||
|
|
@ -2444,6 +2453,7 @@ libs:
|
|||
- src/core/lib/surface/call.cc
|
||||
- src/core/lib/surface/call_details.cc
|
||||
- src/core/lib/surface/call_log_batch.cc
|
||||
- src/core/lib/surface/call_trace.cc
|
||||
- src/core/lib/surface/channel.cc
|
||||
- src/core/lib/surface/channel_init.cc
|
||||
- src/core/lib/surface/channel_ping.cc
|
||||
|
|
@ -2459,6 +2469,7 @@ libs:
|
|||
- src/core/lib/surface/validate_metadata.cc
|
||||
- src/core/lib/surface/version.cc
|
||||
- src/core/lib/transport/bdp_estimator.cc
|
||||
- src/core/lib/transport/call_fragments.cc
|
||||
- src/core/lib/transport/connectivity_state.cc
|
||||
- src/core/lib/transport/error_utils.cc
|
||||
- src/core/lib/transport/handshaker.cc
|
||||
|
|
@ -2480,6 +2491,7 @@ libs:
|
|||
- src/core/tsi/transport_security.cc
|
||||
- src/core/tsi/transport_security_grpc.cc
|
||||
deps:
|
||||
- absl/cleanup:cleanup
|
||||
- absl/container:flat_hash_map
|
||||
- absl/container:flat_hash_set
|
||||
- absl/container:inlined_vector
|
||||
|
|
@ -2839,7 +2851,6 @@ libs:
|
|||
- src/cpp/util/string_ref.cc
|
||||
- src/cpp/util/time_cc.cc
|
||||
deps:
|
||||
- absl/cleanup:cleanup
|
||||
- grpc
|
||||
baselib: true
|
||||
- name: grpc++_alts
|
||||
|
|
@ -4383,7 +4394,6 @@ targets:
|
|||
- test/core/transport/binder/binder_transport_test.cc
|
||||
- test/core/transport/binder/mock_objects.cc
|
||||
deps:
|
||||
- absl/cleanup:cleanup
|
||||
- grpc_test_util
|
||||
uses_polling: false
|
||||
- name: bitset_test
|
||||
|
|
@ -4463,6 +4473,16 @@ targets:
|
|||
- test/core/channel/call_finalization_test.cc
|
||||
deps:
|
||||
- grpc_test_util
|
||||
- name: call_fragments_test
|
||||
gtest: true
|
||||
build: test
|
||||
language: c++
|
||||
headers:
|
||||
- test/core/promise/test_context.h
|
||||
src:
|
||||
- test/core/transport/call_fragments_test.cc
|
||||
deps:
|
||||
- grpc_test_util
|
||||
- name: call_push_pull_test
|
||||
gtest: true
|
||||
build: test
|
||||
|
|
@ -5549,7 +5569,6 @@ targets:
|
|||
- test/core/transport/binder/endpoint_binder_pool_test.cc
|
||||
- test/core/transport/binder/mock_objects.cc
|
||||
deps:
|
||||
- absl/cleanup:cleanup
|
||||
- grpc_test_util
|
||||
uses_polling: false
|
||||
- name: endpoint_config_test
|
||||
|
|
@ -5965,7 +5984,6 @@ targets:
|
|||
- test/core/transport/binder/end2end/fake_binder.cc
|
||||
- test/core/transport/binder/end2end/fake_binder_test.cc
|
||||
deps:
|
||||
- absl/cleanup:cleanup
|
||||
- grpc_test_util
|
||||
uses_polling: false
|
||||
- name: fake_resolver_test
|
||||
|
|
@ -9721,7 +9739,6 @@ targets:
|
|||
- src/core/lib/iomgr/socket_mutator.cc
|
||||
- test/core/event_engine/posix/tcp_posix_socket_utils_test.cc
|
||||
deps:
|
||||
- absl/cleanup:cleanup
|
||||
- grpc_test_util
|
||||
platforms:
|
||||
- linux
|
||||
|
|
@ -9857,7 +9874,6 @@ targets:
|
|||
- src/core/lib/gprpp/load_file.cc
|
||||
- test/core/gprpp/load_file_test.cc
|
||||
deps:
|
||||
- absl/cleanup:cleanup
|
||||
- grpc_test_util
|
||||
uses_polling: false
|
||||
- name: test_core_gprpp_time_test
|
||||
|
|
@ -10408,7 +10424,6 @@ targets:
|
|||
- src/cpp/util/time_cc.cc
|
||||
- test/core/transport/binder/transport_stream_receiver_test.cc
|
||||
deps:
|
||||
- absl/cleanup:cleanup
|
||||
- grpc_test_util
|
||||
uses_polling: false
|
||||
- name: try_join_test
|
||||
|
|
@ -10687,7 +10702,6 @@ targets:
|
|||
- test/core/transport/binder/mock_objects.cc
|
||||
- test/core/transport/binder/wire_reader_test.cc
|
||||
deps:
|
||||
- absl/cleanup:cleanup
|
||||
- grpc_test_util
|
||||
uses_polling: false
|
||||
- name: wire_writer_test
|
||||
|
|
@ -10796,7 +10810,6 @@ targets:
|
|||
- test/core/transport/binder/mock_objects.cc
|
||||
- test/core/transport/binder/wire_writer_test.cc
|
||||
deps:
|
||||
- absl/cleanup:cleanup
|
||||
- grpc_test_util
|
||||
uses_polling: false
|
||||
- name: work_queue_test
|
||||
|
|
|
|||
|
|
@ -710,6 +710,7 @@ if test "$PHP_GRPC" != "no"; then
|
|||
src/core/lib/surface/call.cc \
|
||||
src/core/lib/surface/call_details.cc \
|
||||
src/core/lib/surface/call_log_batch.cc \
|
||||
src/core/lib/surface/call_trace.cc \
|
||||
src/core/lib/surface/channel.cc \
|
||||
src/core/lib/surface/channel_init.cc \
|
||||
src/core/lib/surface/channel_ping.cc \
|
||||
|
|
@ -725,6 +726,7 @@ if test "$PHP_GRPC" != "no"; then
|
|||
src/core/lib/surface/validate_metadata.cc \
|
||||
src/core/lib/surface/version.cc \
|
||||
src/core/lib/transport/bdp_estimator.cc \
|
||||
src/core/lib/transport/call_fragments.cc \
|
||||
src/core/lib/transport/connectivity_state.cc \
|
||||
src/core/lib/transport/error_utils.cc \
|
||||
src/core/lib/transport/handshaker.cc \
|
||||
|
|
|
|||
|
|
@ -676,6 +676,7 @@ if (PHP_GRPC != "no") {
|
|||
"src\\core\\lib\\surface\\call.cc " +
|
||||
"src\\core\\lib\\surface\\call_details.cc " +
|
||||
"src\\core\\lib\\surface\\call_log_batch.cc " +
|
||||
"src\\core\\lib\\surface\\call_trace.cc " +
|
||||
"src\\core\\lib\\surface\\channel.cc " +
|
||||
"src\\core\\lib\\surface\\channel_init.cc " +
|
||||
"src\\core\\lib\\surface\\channel_ping.cc " +
|
||||
|
|
@ -691,6 +692,7 @@ if (PHP_GRPC != "no") {
|
|||
"src\\core\\lib\\surface\\validate_metadata.cc " +
|
||||
"src\\core\\lib\\surface\\version.cc " +
|
||||
"src\\core\\lib\\transport\\bdp_estimator.cc " +
|
||||
"src\\core\\lib\\transport\\call_fragments.cc " +
|
||||
"src\\core\\lib\\transport\\connectivity_state.cc " +
|
||||
"src\\core\\lib\\transport\\error_utils.cc " +
|
||||
"src\\core\\lib\\transport\\handshaker.cc " +
|
||||
|
|
|
|||
|
|
@ -840,6 +840,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/pipe.h',
|
||||
'src/core/lib/promise/poll.h',
|
||||
'src/core/lib/promise/promise.h',
|
||||
'src/core/lib/promise/race.h',
|
||||
|
|
@ -929,6 +930,7 @@ Pod::Spec.new do |s|
|
|||
'src/core/lib/surface/builtins.h',
|
||||
'src/core/lib/surface/call.h',
|
||||
'src/core/lib/surface/call_test_only.h',
|
||||
'src/core/lib/surface/call_trace.h',
|
||||
'src/core/lib/surface/channel.h',
|
||||
'src/core/lib/surface/channel_init.h',
|
||||
'src/core/lib/surface/channel_stack_type.h',
|
||||
|
|
@ -941,6 +943,7 @@ Pod::Spec.new do |s|
|
|||
'src/core/lib/surface/server.h',
|
||||
'src/core/lib/surface/validate_metadata.h',
|
||||
'src/core/lib/transport/bdp_estimator.h',
|
||||
'src/core/lib/transport/call_fragments.h',
|
||||
'src/core/lib/transport/connectivity_state.h',
|
||||
'src/core/lib/transport/error_utils.h',
|
||||
'src/core/lib/transport/handshaker.h',
|
||||
|
|
@ -1703,6 +1706,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/pipe.h',
|
||||
'src/core/lib/promise/poll.h',
|
||||
'src/core/lib/promise/promise.h',
|
||||
'src/core/lib/promise/race.h',
|
||||
|
|
@ -1792,6 +1796,7 @@ Pod::Spec.new do |s|
|
|||
'src/core/lib/surface/builtins.h',
|
||||
'src/core/lib/surface/call.h',
|
||||
'src/core/lib/surface/call_test_only.h',
|
||||
'src/core/lib/surface/call_trace.h',
|
||||
'src/core/lib/surface/channel.h',
|
||||
'src/core/lib/surface/channel_init.h',
|
||||
'src/core/lib/surface/channel_stack_type.h',
|
||||
|
|
@ -1804,6 +1809,7 @@ Pod::Spec.new do |s|
|
|||
'src/core/lib/surface/server.h',
|
||||
'src/core/lib/surface/validate_metadata.h',
|
||||
'src/core/lib/transport/bdp_estimator.h',
|
||||
'src/core/lib/transport/call_fragments.h',
|
||||
'src/core/lib/transport/connectivity_state.h',
|
||||
'src/core/lib/transport/error_utils.h',
|
||||
'src/core/lib/transport/handshaker.h',
|
||||
|
|
|
|||
|
|
@ -175,6 +175,7 @@ Pod::Spec.new do |s|
|
|||
ss.dependency 'BoringSSL-GRPC', '0.0.24'
|
||||
ss.dependency 'abseil/base/base', abseil_version
|
||||
ss.dependency 'abseil/base/core_headers', abseil_version
|
||||
ss.dependency 'abseil/cleanup/cleanup', abseil_version
|
||||
ss.dependency 'abseil/container/flat_hash_map', abseil_version
|
||||
ss.dependency 'abseil/container/flat_hash_set', abseil_version
|
||||
ss.dependency 'abseil/container/inlined_vector', abseil_version
|
||||
|
|
@ -1359,6 +1360,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/pipe.h',
|
||||
'src/core/lib/promise/poll.h',
|
||||
'src/core/lib/promise/promise.h',
|
||||
'src/core/lib/promise/race.h',
|
||||
|
|
@ -1535,6 +1537,8 @@ Pod::Spec.new do |s|
|
|||
'src/core/lib/surface/call_details.cc',
|
||||
'src/core/lib/surface/call_log_batch.cc',
|
||||
'src/core/lib/surface/call_test_only.h',
|
||||
'src/core/lib/surface/call_trace.cc',
|
||||
'src/core/lib/surface/call_trace.h',
|
||||
'src/core/lib/surface/channel.cc',
|
||||
'src/core/lib/surface/channel.h',
|
||||
'src/core/lib/surface/channel_init.cc',
|
||||
|
|
@ -1562,6 +1566,8 @@ Pod::Spec.new do |s|
|
|||
'src/core/lib/surface/version.cc',
|
||||
'src/core/lib/transport/bdp_estimator.cc',
|
||||
'src/core/lib/transport/bdp_estimator.h',
|
||||
'src/core/lib/transport/call_fragments.cc',
|
||||
'src/core/lib/transport/call_fragments.h',
|
||||
'src/core/lib/transport/connectivity_state.cc',
|
||||
'src/core/lib/transport/connectivity_state.h',
|
||||
'src/core/lib/transport/error_utils.cc',
|
||||
|
|
@ -2330,6 +2336,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/pipe.h',
|
||||
'src/core/lib/promise/poll.h',
|
||||
'src/core/lib/promise/promise.h',
|
||||
'src/core/lib/promise/race.h',
|
||||
|
|
@ -2419,6 +2426,7 @@ Pod::Spec.new do |s|
|
|||
'src/core/lib/surface/builtins.h',
|
||||
'src/core/lib/surface/call.h',
|
||||
'src/core/lib/surface/call_test_only.h',
|
||||
'src/core/lib/surface/call_trace.h',
|
||||
'src/core/lib/surface/channel.h',
|
||||
'src/core/lib/surface/channel_init.h',
|
||||
'src/core/lib/surface/channel_stack_type.h',
|
||||
|
|
@ -2431,6 +2439,7 @@ Pod::Spec.new do |s|
|
|||
'src/core/lib/surface/server.h',
|
||||
'src/core/lib/surface/validate_metadata.h',
|
||||
'src/core/lib/transport/bdp_estimator.h',
|
||||
'src/core/lib/transport/call_fragments.h',
|
||||
'src/core/lib/transport/connectivity_state.h',
|
||||
'src/core/lib/transport/error_utils.h',
|
||||
'src/core/lib/transport/handshaker.h',
|
||||
|
|
|
|||
|
|
@ -1271,6 +1271,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/pipe.h )
|
||||
s.files += %w( src/core/lib/promise/poll.h )
|
||||
s.files += %w( src/core/lib/promise/promise.h )
|
||||
s.files += %w( src/core/lib/promise/race.h )
|
||||
|
|
@ -1447,6 +1448,8 @@ Gem::Specification.new do |s|
|
|||
s.files += %w( src/core/lib/surface/call_details.cc )
|
||||
s.files += %w( src/core/lib/surface/call_log_batch.cc )
|
||||
s.files += %w( src/core/lib/surface/call_test_only.h )
|
||||
s.files += %w( src/core/lib/surface/call_trace.cc )
|
||||
s.files += %w( src/core/lib/surface/call_trace.h )
|
||||
s.files += %w( src/core/lib/surface/channel.cc )
|
||||
s.files += %w( src/core/lib/surface/channel.h )
|
||||
s.files += %w( src/core/lib/surface/channel_init.cc )
|
||||
|
|
@ -1474,6 +1477,8 @@ Gem::Specification.new do |s|
|
|||
s.files += %w( src/core/lib/surface/version.cc )
|
||||
s.files += %w( src/core/lib/transport/bdp_estimator.cc )
|
||||
s.files += %w( src/core/lib/transport/bdp_estimator.h )
|
||||
s.files += %w( src/core/lib/transport/call_fragments.cc )
|
||||
s.files += %w( src/core/lib/transport/call_fragments.h )
|
||||
s.files += %w( src/core/lib/transport/connectivity_state.cc )
|
||||
s.files += %w( src/core/lib/transport/connectivity_state.h )
|
||||
s.files += %w( src/core/lib/transport/error_utils.cc )
|
||||
|
|
@ -1620,6 +1625,8 @@ Gem::Specification.new do |s|
|
|||
s.files += %w( third_party/abseil-cpp/absl/base/policy_checks.h )
|
||||
s.files += %w( third_party/abseil-cpp/absl/base/port.h )
|
||||
s.files += %w( third_party/abseil-cpp/absl/base/thread_annotations.h )
|
||||
s.files += %w( third_party/abseil-cpp/absl/cleanup/cleanup.h )
|
||||
s.files += %w( third_party/abseil-cpp/absl/cleanup/internal/cleanup.h )
|
||||
s.files += %w( third_party/abseil-cpp/absl/container/fixed_array.h )
|
||||
s.files += %w( third_party/abseil-cpp/absl/container/flat_hash_map.h )
|
||||
s.files += %w( third_party/abseil-cpp/absl/container/flat_hash_set.h )
|
||||
|
|
|
|||
|
|
@ -355,6 +355,7 @@
|
|||
'target_name': 'grpc',
|
||||
'type': 'static_library',
|
||||
'dependencies': [
|
||||
'absl/cleanup:cleanup',
|
||||
'absl/container:flat_hash_map',
|
||||
'absl/container:flat_hash_set',
|
||||
'absl/container:inlined_vector',
|
||||
|
|
@ -1000,6 +1001,7 @@
|
|||
'src/core/lib/surface/call.cc',
|
||||
'src/core/lib/surface/call_details.cc',
|
||||
'src/core/lib/surface/call_log_batch.cc',
|
||||
'src/core/lib/surface/call_trace.cc',
|
||||
'src/core/lib/surface/channel.cc',
|
||||
'src/core/lib/surface/channel_init.cc',
|
||||
'src/core/lib/surface/channel_ping.cc',
|
||||
|
|
@ -1015,6 +1017,7 @@
|
|||
'src/core/lib/surface/validate_metadata.cc',
|
||||
'src/core/lib/surface/version.cc',
|
||||
'src/core/lib/transport/bdp_estimator.cc',
|
||||
'src/core/lib/transport/call_fragments.cc',
|
||||
'src/core/lib/transport/connectivity_state.cc',
|
||||
'src/core/lib/transport/error_utils.cc',
|
||||
'src/core/lib/transport/handshaker.cc',
|
||||
|
|
@ -1108,6 +1111,7 @@
|
|||
'target_name': 'grpc_unsecure',
|
||||
'type': 'static_library',
|
||||
'dependencies': [
|
||||
'absl/cleanup:cleanup',
|
||||
'absl/container:flat_hash_map',
|
||||
'absl/container:flat_hash_set',
|
||||
'absl/container:inlined_vector',
|
||||
|
|
@ -1410,6 +1414,7 @@
|
|||
'src/core/lib/surface/call.cc',
|
||||
'src/core/lib/surface/call_details.cc',
|
||||
'src/core/lib/surface/call_log_batch.cc',
|
||||
'src/core/lib/surface/call_trace.cc',
|
||||
'src/core/lib/surface/channel.cc',
|
||||
'src/core/lib/surface/channel_init.cc',
|
||||
'src/core/lib/surface/channel_ping.cc',
|
||||
|
|
@ -1425,6 +1430,7 @@
|
|||
'src/core/lib/surface/validate_metadata.cc',
|
||||
'src/core/lib/surface/version.cc',
|
||||
'src/core/lib/transport/bdp_estimator.cc',
|
||||
'src/core/lib/transport/call_fragments.cc',
|
||||
'src/core/lib/transport/connectivity_state.cc',
|
||||
'src/core/lib/transport/error_utils.cc',
|
||||
'src/core/lib/transport/handshaker.cc',
|
||||
|
|
@ -1480,7 +1486,6 @@
|
|||
'target_name': 'grpc++',
|
||||
'type': 'static_library',
|
||||
'dependencies': [
|
||||
'absl/cleanup:cleanup',
|
||||
'grpc',
|
||||
],
|
||||
'sources': [
|
||||
|
|
|
|||
|
|
@ -1253,6 +1253,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/pipe.h" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/lib/promise/poll.h" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/lib/promise/promise.h" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/lib/promise/race.h" role="src" />
|
||||
|
|
@ -1429,6 +1430,8 @@
|
|||
<file baseinstalldir="/" name="src/core/lib/surface/call_details.cc" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/lib/surface/call_log_batch.cc" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/lib/surface/call_test_only.h" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/lib/surface/call_trace.cc" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/lib/surface/call_trace.h" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/lib/surface/channel.cc" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/lib/surface/channel.h" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/lib/surface/channel_init.cc" role="src" />
|
||||
|
|
@ -1456,6 +1459,8 @@
|
|||
<file baseinstalldir="/" name="src/core/lib/surface/version.cc" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/lib/transport/bdp_estimator.cc" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/lib/transport/bdp_estimator.h" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/lib/transport/call_fragments.cc" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/lib/transport/call_fragments.h" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/lib/transport/connectivity_state.cc" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/lib/transport/connectivity_state.h" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/lib/transport/error_utils.cc" role="src" />
|
||||
|
|
@ -1624,6 +1629,8 @@
|
|||
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/policy_checks.h" role="src" />
|
||||
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/port.h" role="src" />
|
||||
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/thread_annotations.h" role="src" />
|
||||
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/cleanup/cleanup.h" role="src" />
|
||||
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/cleanup/internal/cleanup.h" role="src" />
|
||||
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/container/fixed_array.h" role="src" />
|
||||
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/container/flat_hash_map.h" role="src" />
|
||||
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/container/flat_hash_set.h" role="src" />
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include "src/core/lib/gprpp/time.h"
|
||||
#include "src/core/lib/promise/activity.h"
|
||||
#include "src/core/lib/promise/arena_promise.h"
|
||||
#include "src/core/lib/transport/call_fragments.h"
|
||||
#include "src/core/lib/transport/connectivity_state.h"
|
||||
#include "src/core/lib/transport/transport.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include "src/core/lib/channel/promise_based_filter.h"
|
||||
#include "src/core/lib/gprpp/sync.h"
|
||||
#include "src/core/lib/promise/arena_promise.h"
|
||||
#include "src/core/lib/transport/call_fragments.h"
|
||||
#include "src/core/lib/transport/transport.h"
|
||||
|
||||
// Channel arg key for enabling parsing fault injection via method config.
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@
|
|||
#include "src/core/lib/promise/seq.h"
|
||||
#include "src/core/lib/resource_quota/arena.h"
|
||||
#include "src/core/lib/slice/percent_encoding.h"
|
||||
#include "src/core/lib/transport/call_fragments.h"
|
||||
#include "src/core/lib/transport/status_conversion.h"
|
||||
#include "src/core/lib/transport/transport_fwd.h"
|
||||
#include "src/core/lib/transport/transport_impl.h"
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "src/core/lib/channel/promise_based_filter.h"
|
||||
#include "src/core/lib/promise/arena_promise.h"
|
||||
#include "src/core/lib/slice/slice.h"
|
||||
#include "src/core/lib/transport/call_fragments.h"
|
||||
#include "src/core/lib/transport/metadata_batch.h"
|
||||
#include "src/core/lib/transport/transport.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include "src/core/lib/config/core_configuration.h"
|
||||
#include "src/core/lib/surface/channel_init.h"
|
||||
#include "src/core/lib/surface/channel_stack_type.h"
|
||||
#include "src/core/lib/transport/call_fragments.h"
|
||||
#include "src/core/lib/transport/metadata_batch.h"
|
||||
|
||||
namespace grpc_core {
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "src/core/lib/channel/promise_based_filter.h"
|
||||
#include "src/core/lib/promise/arena_promise.h"
|
||||
#include "src/core/lib/slice/slice.h"
|
||||
#include "src/core/lib/transport/call_fragments.h"
|
||||
#include "src/core/lib/transport/transport.h"
|
||||
|
||||
namespace grpc_core {
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
#include "src/core/lib/resource_quota/arena.h"
|
||||
#include "src/core/lib/slice/percent_encoding.h"
|
||||
#include "src/core/lib/slice/slice.h"
|
||||
#include "src/core/lib/transport/call_fragments.h"
|
||||
#include "src/core/lib/transport/metadata_batch.h"
|
||||
|
||||
namespace grpc_core {
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "src/core/lib/channel/channel_fwd.h"
|
||||
#include "src/core/lib/channel/promise_based_filter.h"
|
||||
#include "src/core/lib/promise/arena_promise.h"
|
||||
#include "src/core/lib/transport/call_fragments.h"
|
||||
#include "src/core/lib/transport/transport.h"
|
||||
|
||||
namespace grpc_core {
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@
|
|||
#include "src/core/lib/slice/slice.h"
|
||||
#include "src/core/lib/surface/channel_init.h"
|
||||
#include "src/core/lib/surface/channel_stack_type.h"
|
||||
#include "src/core/lib/transport/call_fragments.h"
|
||||
#include "src/core/lib/transport/metadata_batch.h"
|
||||
#include "src/core/lib/uri/uri_parser.h"
|
||||
#include "src/cpp/server/load_reporter/constants.h"
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "src/core/lib/channel/channel_args.h"
|
||||
#include "src/core/lib/channel/promise_based_filter.h"
|
||||
#include "src/core/lib/promise/arena_promise.h"
|
||||
#include "src/core/lib/transport/call_fragments.h"
|
||||
#include "src/core/lib/transport/transport.h"
|
||||
|
||||
namespace grpc_core {
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
#include "src/core/lib/promise/promise.h"
|
||||
#include "src/core/lib/resource_quota/arena.h"
|
||||
#include "src/core/lib/service_config/service_config_call_data.h"
|
||||
#include "src/core/lib/transport/call_fragments.h"
|
||||
#include "src/core/lib/transport/transport.h"
|
||||
|
||||
namespace grpc_core {
|
||||
|
|
|
|||
|
|
@ -1175,6 +1175,7 @@ static bool contains_non_ok_status(grpc_metadata_batch* batch) {
|
|||
|
||||
static void log_metadata(const grpc_metadata_batch* md_batch, uint32_t id,
|
||||
bool is_client, bool is_initial) {
|
||||
gpr_log(GPR_INFO, "--metadata--");
|
||||
const std::string prefix = absl::StrCat(
|
||||
"HTTP:", id, is_initial ? ":HDR" : ":TRL", is_client ? ":CLI:" : ":SVR:");
|
||||
md_batch->Log([&prefix](absl::string_view key, absl::string_view value) {
|
||||
|
|
|
|||
|
|
@ -1258,6 +1258,9 @@ void HPackParser::BeginFrame(grpc_metadata_batch* metadata_buffer,
|
|||
uint32_t metadata_size_limit, Boundary boundary,
|
||||
Priority priority, LogInfo log_info) {
|
||||
metadata_buffer_ = metadata_buffer;
|
||||
if (metadata_buffer != nullptr) {
|
||||
metadata_buffer->Set(GrpcStatusFromWire(), true);
|
||||
}
|
||||
boundary_ = boundary;
|
||||
priority_ = priority;
|
||||
dynamic_table_updates_allowed_ = 2;
|
||||
|
|
|
|||
|
|
@ -299,12 +299,12 @@ grpc_core::NextPromiseFactory ServerNext(grpc_channel_element* elem) {
|
|||
} // namespace
|
||||
|
||||
grpc_core::ArenaPromise<grpc_core::ServerMetadataHandle>
|
||||
grpc_channel_stack::MakeCallPromise(grpc_core::CallArgs call_args) {
|
||||
if (is_client) {
|
||||
return ClientNext(grpc_channel_stack_element(this, 0))(
|
||||
std::move(call_args));
|
||||
} else {
|
||||
return ServerNext(grpc_channel_stack_element(this, this->count - 1))(
|
||||
std::move(call_args));
|
||||
}
|
||||
grpc_channel_stack::MakeClientCallPromise(grpc_core::CallArgs call_args) {
|
||||
return ClientNext(grpc_channel_stack_element(this, 0))(std::move(call_args));
|
||||
}
|
||||
|
||||
grpc_core::ArenaPromise<grpc_core::ServerMetadataHandle>
|
||||
grpc_channel_stack::MakeServerCallPromise(grpc_core::CallArgs call_args) {
|
||||
return ServerNext(grpc_channel_stack_element(this, this->count - 1))(
|
||||
std::move(call_args));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@
|
|||
#include "src/core/lib/iomgr/polling_entity.h"
|
||||
#include "src/core/lib/promise/arena_promise.h"
|
||||
#include "src/core/lib/resource_quota/arena.h"
|
||||
#include "src/core/lib/transport/call_fragments.h"
|
||||
#include "src/core/lib/transport/transport.h"
|
||||
|
||||
struct grpc_channel_element_args {
|
||||
|
|
@ -202,7 +203,6 @@ struct grpc_call_element {
|
|||
guarantees they live within a single malloc() allocation */
|
||||
struct grpc_channel_stack {
|
||||
grpc_stream_refcount refcount;
|
||||
bool is_client;
|
||||
size_t count;
|
||||
/* Memory required for a call stack (computed at channel stack
|
||||
initialization) */
|
||||
|
|
@ -225,8 +225,10 @@ struct grpc_channel_stack {
|
|||
return grpc_core::RefCountedPtr<grpc_channel_stack>(this);
|
||||
}
|
||||
|
||||
grpc_core::ArenaPromise<grpc_core::ServerMetadataHandle> MakeCallPromise(
|
||||
grpc_core::CallArgs call_args);
|
||||
grpc_core::ArenaPromise<grpc_core::ServerMetadataHandle>
|
||||
MakeClientCallPromise(grpc_core::CallArgs call_args);
|
||||
grpc_core::ArenaPromise<grpc_core::ServerMetadataHandle>
|
||||
MakeServerCallPromise(grpc_core::CallArgs call_args);
|
||||
};
|
||||
|
||||
/* A call stack tracks a set of related filters for one call, and guarantees
|
||||
|
|
|
|||
|
|
@ -71,6 +71,11 @@ class ChannelStackBuilder {
|
|||
// Mutable vector of proposed stack entries.
|
||||
std::vector<const grpc_channel_filter*>* mutable_stack() { return &stack_; }
|
||||
|
||||
// Immutable vector of proposed stack entries.
|
||||
const std::vector<const grpc_channel_filter*>& stack() const {
|
||||
return stack_;
|
||||
}
|
||||
|
||||
// The type of channel stack being built.
|
||||
grpc_channel_stack_type channel_stack_type() const { return type_; }
|
||||
|
||||
|
|
@ -80,6 +85,11 @@ class ChannelStackBuilder {
|
|||
// Helper to add a filter to the end of the stack.
|
||||
void AppendFilter(const grpc_channel_filter* filter);
|
||||
|
||||
// Determine whether a promise-based call stack is able to be built.
|
||||
// Iterates each filter and ensures that there's a promise factory there.
|
||||
// This will go away once the promise conversion is completed.
|
||||
virtual bool IsPromising() const = 0;
|
||||
|
||||
// Build the channel stack.
|
||||
// After success, *result holds the new channel stack,
|
||||
// prefix_bytes are allocated before the channel stack,
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include <string.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/status/status.h"
|
||||
|
|
@ -30,21 +31,39 @@
|
|||
#include <grpc/support/alloc.h>
|
||||
|
||||
#include "src/core/lib/channel/channel_args.h"
|
||||
#include "src/core/lib/channel/channel_fwd.h"
|
||||
#include "src/core/lib/channel/channel_stack.h"
|
||||
#include "src/core/lib/debug/trace.h"
|
||||
#include "src/core/lib/gpr/useful.h"
|
||||
#include "src/core/lib/iomgr/error.h"
|
||||
#include "src/core/lib/surface/call_trace.h"
|
||||
#include "src/core/lib/transport/error_utils.h"
|
||||
#include "src/core/lib/transport/transport.h"
|
||||
|
||||
namespace grpc_core {
|
||||
|
||||
bool ChannelStackBuilderImpl::IsPromising() const {
|
||||
for (const auto* filter : stack()) {
|
||||
if (filter->make_call_promise == nullptr) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
absl::StatusOr<RefCountedPtr<grpc_channel_stack>>
|
||||
ChannelStackBuilderImpl::Build() {
|
||||
auto* stack = mutable_stack();
|
||||
std::vector<const grpc_channel_filter*> stack;
|
||||
const bool is_promising = IsPromising();
|
||||
|
||||
for (const auto* filter : this->stack()) {
|
||||
if (is_promising && grpc_call_trace.enabled()) {
|
||||
stack.push_back(PromiseTracingFilterFor(filter));
|
||||
}
|
||||
stack.push_back(filter);
|
||||
}
|
||||
|
||||
// calculate the size of the channel stack
|
||||
size_t channel_stack_size =
|
||||
grpc_channel_stack_size(stack->data(), stack->size());
|
||||
grpc_channel_stack_size(stack.data(), stack.size());
|
||||
|
||||
// allocate memory
|
||||
auto* channel_stack =
|
||||
|
|
@ -72,7 +91,7 @@ ChannelStackBuilderImpl::Build() {
|
|||
grpc_channel_stack_destroy(stk);
|
||||
gpr_free(stk);
|
||||
},
|
||||
channel_stack, stack->data(), stack->size(), final_args, name(),
|
||||
channel_stack, stack.data(), stack.size(), final_args, name(),
|
||||
channel_stack);
|
||||
|
||||
if (!error.ok()) {
|
||||
|
|
@ -83,7 +102,7 @@ ChannelStackBuilderImpl::Build() {
|
|||
}
|
||||
|
||||
// run post-initialization functions
|
||||
for (size_t i = 0; i < stack->size(); i++) {
|
||||
for (size_t i = 0; i < stack.size(); i++) {
|
||||
auto* elem = grpc_channel_stack_element(channel_stack, i);
|
||||
elem->filter->post_init_channel_elem(channel_stack, elem);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,8 @@ class ChannelStackBuilderImpl final : public ChannelStackBuilder {
|
|||
public:
|
||||
using ChannelStackBuilder::ChannelStackBuilder;
|
||||
|
||||
bool IsPromising() const override;
|
||||
|
||||
// Build the channel stack.
|
||||
// After success, *result holds the new channel stack,
|
||||
// prefix_bytes are allocated before the channel stack,
|
||||
|
|
|
|||
|
|
@ -20,21 +20,57 @@
|
|||
|
||||
#include "src/core/lib/channel/connected_channel.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/base/thread_annotations.h"
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "absl/strings/str_join.h"
|
||||
#include "absl/types/optional.h"
|
||||
#include "absl/types/variant.h"
|
||||
|
||||
#include <grpc/impl/codegen/grpc_types.h>
|
||||
#include <grpc/support/alloc.h>
|
||||
#include <grpc/support/log.h>
|
||||
|
||||
#include "src/core/lib/channel/channel_args.h"
|
||||
#include "src/core/lib/channel/channel_fwd.h"
|
||||
#include "src/core/lib/channel/channel_stack.h"
|
||||
#include "src/core/lib/channel/context.h"
|
||||
#include "src/core/lib/debug/trace.h"
|
||||
#include "src/core/lib/gpr/alloc.h"
|
||||
#include "src/core/lib/gprpp/debug_location.h"
|
||||
#include "src/core/lib/gprpp/match.h"
|
||||
#include "src/core/lib/gprpp/orphanable.h"
|
||||
#include "src/core/lib/gprpp/sync.h"
|
||||
#include "src/core/lib/iomgr/call_combiner.h"
|
||||
#include "src/core/lib/iomgr/closure.h"
|
||||
#include "src/core/lib/iomgr/error.h"
|
||||
#include "src/core/lib/iomgr/exec_ctx.h"
|
||||
#include "src/core/lib/iomgr/polling_entity.h"
|
||||
#include "src/core/lib/promise/activity.h"
|
||||
#include "src/core/lib/promise/arena_promise.h"
|
||||
#include "src/core/lib/promise/context.h"
|
||||
#include "src/core/lib/promise/latch.h"
|
||||
#include "src/core/lib/promise/pipe.h"
|
||||
#include "src/core/lib/promise/poll.h"
|
||||
#include "src/core/lib/resource_quota/arena.h"
|
||||
#include "src/core/lib/slice/slice_buffer.h"
|
||||
#include "src/core/lib/surface/call.h"
|
||||
#include "src/core/lib/surface/call_trace.h"
|
||||
#include "src/core/lib/surface/channel_stack_type.h"
|
||||
#include "src/core/lib/transport/call_fragments.h"
|
||||
#include "src/core/lib/transport/metadata_batch.h"
|
||||
#include "src/core/lib/transport/transport.h"
|
||||
#include "src/core/lib/transport/transport_fwd.h"
|
||||
#include "src/core/lib/transport/transport_impl.h"
|
||||
|
||||
#define MAX_BUFFER_LENGTH 8192
|
||||
|
||||
|
|
@ -205,39 +241,661 @@ static void connected_channel_get_channel_info(
|
|||
grpc_channel_element* /*elem*/, const grpc_channel_info* /*channel_info*/) {
|
||||
}
|
||||
|
||||
const grpc_channel_filter grpc_connected_filter = {
|
||||
connected_channel_start_transport_stream_op_batch,
|
||||
nullptr,
|
||||
connected_channel_start_transport_op,
|
||||
sizeof(call_data),
|
||||
connected_channel_init_call_elem,
|
||||
set_pollset_or_pollset_set,
|
||||
connected_channel_destroy_call_elem,
|
||||
sizeof(channel_data),
|
||||
connected_channel_init_channel_elem,
|
||||
[](grpc_channel_stack* channel_stack, grpc_channel_element* elem) {
|
||||
/* HACK(ctiller): increase call stack size for the channel to make space
|
||||
for channel data. We need a cleaner (but performant) way to do this,
|
||||
and I'm not sure what that is yet.
|
||||
This is only "safe" because call stacks place no additional data after
|
||||
the last call element, and the last call element MUST be the connected
|
||||
channel. */
|
||||
channel_stack->call_stack_size += grpc_transport_stream_size(
|
||||
static_cast<channel_data*>(elem->channel_data)->transport);
|
||||
},
|
||||
connected_channel_destroy_channel_elem,
|
||||
connected_channel_get_channel_info,
|
||||
"connected",
|
||||
namespace grpc_core {
|
||||
namespace {
|
||||
|
||||
class ClientStream : public Orphanable {
|
||||
public:
|
||||
ClientStream(grpc_transport* transport, CallArgs call_args)
|
||||
: transport_(transport),
|
||||
stream_(nullptr, StreamDeleter(this)),
|
||||
server_initial_metadata_latch_(call_args.server_initial_metadata),
|
||||
client_to_server_messages_(call_args.outgoing_messages),
|
||||
server_to_client_messages_(call_args.incoming_messages),
|
||||
client_initial_metadata_(std::move(call_args.client_initial_metadata)) {
|
||||
call_context_->IncrementRefCount("client_stream");
|
||||
GRPC_STREAM_REF_INIT(
|
||||
&stream_refcount_, 1,
|
||||
[](void* p, grpc_error_handle) {
|
||||
static_cast<ClientStream*>(p)->BeginDestroy();
|
||||
},
|
||||
this, "client_stream");
|
||||
if (grpc_call_trace.enabled()) {
|
||||
gpr_log(GPR_INFO, "%sInitImpl: intitial_metadata=%s",
|
||||
Activity::current()->DebugTag().c_str(),
|
||||
client_initial_metadata_->DebugString().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void Orphan() override {
|
||||
bool finished;
|
||||
{
|
||||
MutexLock lock(&mu_);
|
||||
if (grpc_call_trace.enabled()) {
|
||||
gpr_log(GPR_INFO, "%sDropStream: %s",
|
||||
Activity::current()->DebugTag().c_str(),
|
||||
ActiveOpsString().c_str());
|
||||
}
|
||||
finished = finished_;
|
||||
}
|
||||
// If we hadn't already observed the stream to be finished, we need to
|
||||
// cancel it at the transport.
|
||||
if (!finished) {
|
||||
IncrementRefCount("shutdown client stream");
|
||||
auto* cancel_op =
|
||||
GetContext<Arena>()->New<grpc_transport_stream_op_batch>();
|
||||
cancel_op->cancel_stream = true;
|
||||
cancel_op->payload = &batch_payload_;
|
||||
auto* stream = stream_.get();
|
||||
cancel_op->on_complete = NewClosure(
|
||||
[this](grpc_error_handle) { Unref("shutdown client stream"); });
|
||||
batch_payload_.cancel_stream.cancel_error = GRPC_ERROR_CANCELLED;
|
||||
grpc_transport_perform_stream_op(transport_, stream, cancel_op);
|
||||
}
|
||||
Unref("orphan client stream");
|
||||
}
|
||||
|
||||
void IncrementRefCount(const char* reason) {
|
||||
#ifndef NDEBUG
|
||||
grpc_stream_ref(&stream_refcount_, reason);
|
||||
#else
|
||||
(void)reason;
|
||||
grpc_stream_ref(&stream_refcount_);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Unref(const char* reason) {
|
||||
#ifndef NDEBUG
|
||||
grpc_stream_unref(&stream_refcount_, reason);
|
||||
#else
|
||||
(void)reason;
|
||||
grpc_stream_unref(&stream_refcount_);
|
||||
#endif
|
||||
}
|
||||
|
||||
void BeginDestroy() {
|
||||
if (stream_ != nullptr) {
|
||||
stream_.reset();
|
||||
} else {
|
||||
StreamDestroyed();
|
||||
}
|
||||
}
|
||||
|
||||
Poll<ServerMetadataHandle> PollOnce() {
|
||||
MutexLock lock(&mu_);
|
||||
GPR_ASSERT(!finished_);
|
||||
|
||||
if (grpc_call_trace.enabled()) {
|
||||
gpr_log(GPR_INFO, "%sPollConnectedChannel: %s",
|
||||
Activity::current()->DebugTag().c_str(),
|
||||
ActiveOpsString().c_str());
|
||||
}
|
||||
|
||||
auto push_recv_message = [this]() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) {
|
||||
recv_message_state_ = PendingReceiveMessage{};
|
||||
auto& pending_recv_message =
|
||||
absl::get<PendingReceiveMessage>(recv_message_state_);
|
||||
memset(&recv_message_, 0, sizeof(recv_message_));
|
||||
recv_message_.payload = &batch_payload_;
|
||||
recv_message_.on_complete = nullptr;
|
||||
recv_message_.recv_message = true;
|
||||
batch_payload_.recv_message.recv_message = &pending_recv_message.payload;
|
||||
batch_payload_.recv_message.flags = &pending_recv_message.flags;
|
||||
batch_payload_.recv_message.call_failed_before_recv_message = nullptr;
|
||||
batch_payload_.recv_message.recv_message_ready =
|
||||
&recv_message_batch_done_;
|
||||
IncrementRefCount("recv_message");
|
||||
recv_message_waker_ = Activity::current()->MakeOwningWaker();
|
||||
push_recv_message_ = true;
|
||||
SchedulePush();
|
||||
};
|
||||
|
||||
if (!std::exchange(requested_metadata_, true)) {
|
||||
if (grpc_call_trace.enabled()) {
|
||||
gpr_log(GPR_INFO, "%sPollConnectedChannel: requesting metadata",
|
||||
Activity::current()->DebugTag().c_str());
|
||||
}
|
||||
stream_.reset(static_cast<grpc_stream*>(
|
||||
GetContext<Arena>()->Alloc(transport_->vtable->sizeof_stream)));
|
||||
grpc_transport_init_stream(transport_, stream_.get(), &stream_refcount_,
|
||||
nullptr, GetContext<Arena>());
|
||||
grpc_transport_set_pops(transport_, stream_.get(),
|
||||
GetContext<CallContext>()->polling_entity());
|
||||
memset(&metadata_, 0, sizeof(metadata_));
|
||||
metadata_.send_initial_metadata = true;
|
||||
metadata_.recv_initial_metadata = true;
|
||||
metadata_.recv_trailing_metadata = true;
|
||||
metadata_.payload = &batch_payload_;
|
||||
metadata_.on_complete = &metadata_batch_done_;
|
||||
batch_payload_.send_initial_metadata.send_initial_metadata =
|
||||
client_initial_metadata_.get();
|
||||
batch_payload_.send_initial_metadata.peer_string =
|
||||
GetContext<CallContext>()->peer_string_atm_ptr();
|
||||
server_initial_metadata_ =
|
||||
GetContext<FragmentAllocator>()->MakeServerMetadata();
|
||||
batch_payload_.recv_initial_metadata.recv_initial_metadata =
|
||||
server_initial_metadata_.get();
|
||||
batch_payload_.recv_initial_metadata.recv_initial_metadata_ready =
|
||||
&recv_initial_metadata_ready_;
|
||||
batch_payload_.recv_initial_metadata.trailing_metadata_available =
|
||||
nullptr;
|
||||
batch_payload_.recv_initial_metadata.peer_string = nullptr;
|
||||
server_trailing_metadata_ =
|
||||
GetContext<FragmentAllocator>()->MakeClientMetadata();
|
||||
batch_payload_.recv_trailing_metadata.recv_trailing_metadata =
|
||||
server_trailing_metadata_.get();
|
||||
batch_payload_.recv_trailing_metadata.collect_stats =
|
||||
&GetContext<CallContext>()->call_stats()->transport_stream_stats;
|
||||
batch_payload_.recv_trailing_metadata.recv_trailing_metadata_ready =
|
||||
&recv_trailing_metadata_ready_;
|
||||
push_metadata_ = true;
|
||||
IncrementRefCount("metadata_batch_done");
|
||||
IncrementRefCount("initial_metadata_ready");
|
||||
IncrementRefCount("trailing_metadata_ready");
|
||||
initial_metadata_waker_ = Activity::current()->MakeOwningWaker();
|
||||
trailing_metadata_waker_ = Activity::current()->MakeOwningWaker();
|
||||
SchedulePush();
|
||||
}
|
||||
if (absl::holds_alternative<Closed>(send_message_state_)) {
|
||||
message_to_send_.reset();
|
||||
}
|
||||
if (absl::holds_alternative<Idle>(send_message_state_)) {
|
||||
message_to_send_.reset();
|
||||
send_message_state_ = client_to_server_messages_->Next();
|
||||
}
|
||||
if (auto* next = absl::get_if<PipeReceiver<MessageHandle>::NextType>(
|
||||
&send_message_state_)) {
|
||||
auto r = (*next)();
|
||||
if (auto* p = absl::get_if<NextResult<MessageHandle>>(&r)) {
|
||||
memset(&send_message_, 0, sizeof(send_message_));
|
||||
send_message_.payload = &batch_payload_;
|
||||
send_message_.on_complete = &send_message_batch_done_;
|
||||
// No value => half close from above.
|
||||
if (p->has_value()) {
|
||||
message_to_send_ = std::move(**p);
|
||||
send_message_state_ = SendMessageToTransport{};
|
||||
send_message_.send_message = true;
|
||||
batch_payload_.send_message.send_message =
|
||||
message_to_send_->payload();
|
||||
batch_payload_.send_message.flags = message_to_send_->flags();
|
||||
} else {
|
||||
GPR_ASSERT(!absl::holds_alternative<Closed>(send_message_state_));
|
||||
client_trailing_metadata_ =
|
||||
GetContext<FragmentAllocator>()->MakeClientMetadata();
|
||||
send_message_state_ = Closed{};
|
||||
send_message_.send_trailing_metadata = true;
|
||||
batch_payload_.send_trailing_metadata.send_trailing_metadata =
|
||||
client_trailing_metadata_.get();
|
||||
batch_payload_.send_trailing_metadata.sent = nullptr;
|
||||
}
|
||||
IncrementRefCount("send_message");
|
||||
send_message_waker_ = Activity::current()->MakeOwningWaker();
|
||||
push_send_message_ = true;
|
||||
SchedulePush();
|
||||
}
|
||||
}
|
||||
if (auto* pending =
|
||||
absl::get_if<PendingReceiveMessage>(&recv_message_state_)) {
|
||||
if (pending->received) {
|
||||
if (pending->payload.has_value()) {
|
||||
if (grpc_call_trace.enabled()) {
|
||||
gpr_log(GPR_INFO,
|
||||
"%sRecvMessageBatchDone: received payload of %" PRIdPTR
|
||||
" bytes",
|
||||
recv_message_waker_.ActivityDebugTag().c_str(),
|
||||
pending->payload->Length());
|
||||
}
|
||||
recv_message_state_ = server_to_client_messages_->Push(
|
||||
GetContext<FragmentAllocator>()->MakeMessage(
|
||||
std::move(*pending->payload), pending->flags));
|
||||
} else {
|
||||
if (grpc_call_trace.enabled()) {
|
||||
gpr_log(GPR_INFO, "%sRecvMessageBatchDone: received no payload",
|
||||
recv_message_waker_.ActivityDebugTag().c_str());
|
||||
}
|
||||
recv_message_state_ = Closed{};
|
||||
std::exchange(server_to_client_messages_, nullptr)->Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (server_initial_metadata_state_ ==
|
||||
ServerInitialMetadataState::kReceivedButNotSet) {
|
||||
server_initial_metadata_state_ = ServerInitialMetadataState::kSet;
|
||||
server_initial_metadata_latch_->Set(server_initial_metadata_.get());
|
||||
}
|
||||
if (absl::holds_alternative<Idle>(recv_message_state_)) {
|
||||
if (grpc_call_trace.enabled()) {
|
||||
gpr_log(GPR_INFO, "%sPollConnectedChannel: requesting message",
|
||||
Activity::current()->DebugTag().c_str());
|
||||
}
|
||||
push_recv_message();
|
||||
}
|
||||
if (server_initial_metadata_state_ == ServerInitialMetadataState::kSet &&
|
||||
!absl::holds_alternative<PipeSender<MessageHandle>::PushType>(
|
||||
recv_message_state_) &&
|
||||
std::exchange(queued_trailing_metadata_, false)) {
|
||||
if (grpc_call_trace.enabled()) {
|
||||
gpr_log(GPR_INFO,
|
||||
"%sPollConnectedChannel: finished request, returning: {%s}; "
|
||||
"active_ops: %s",
|
||||
Activity::current()->DebugTag().c_str(),
|
||||
server_trailing_metadata_->DebugString().c_str(),
|
||||
ActiveOpsString().c_str());
|
||||
}
|
||||
finished_ = true;
|
||||
return ServerMetadataHandle(std::move(server_trailing_metadata_));
|
||||
}
|
||||
if (auto* push = absl::get_if<PipeSender<MessageHandle>::PushType>(
|
||||
&recv_message_state_)) {
|
||||
auto r = (*push)();
|
||||
if (bool* result = absl::get_if<bool>(&r)) {
|
||||
if (*result) {
|
||||
if (!finished_) {
|
||||
if (grpc_call_trace.enabled()) {
|
||||
gpr_log(GPR_INFO,
|
||||
"%sPollConnectedChannel: pushed message; requesting next",
|
||||
Activity::current()->DebugTag().c_str());
|
||||
}
|
||||
push_recv_message();
|
||||
} else {
|
||||
if (grpc_call_trace.enabled()) {
|
||||
gpr_log(GPR_INFO,
|
||||
"%sPollConnectedChannel: pushed message and finished; "
|
||||
"marking closed",
|
||||
Activity::current()->DebugTag().c_str());
|
||||
}
|
||||
recv_message_state_ = Closed{};
|
||||
}
|
||||
} else {
|
||||
if (grpc_call_trace.enabled()) {
|
||||
gpr_log(GPR_INFO,
|
||||
"%sPollConnectedChannel: failed to push message; marking "
|
||||
"closed",
|
||||
Activity::current()->DebugTag().c_str());
|
||||
}
|
||||
recv_message_state_ = Closed{};
|
||||
}
|
||||
}
|
||||
}
|
||||
return Pending{};
|
||||
}
|
||||
|
||||
void RecvInitialMetadataReady(grpc_error_handle error) {
|
||||
GPR_ASSERT(error == GRPC_ERROR_NONE);
|
||||
{
|
||||
MutexLock lock(&mu_);
|
||||
server_initial_metadata_state_ =
|
||||
ServerInitialMetadataState::kReceivedButNotSet;
|
||||
initial_metadata_waker_.Wakeup();
|
||||
}
|
||||
Unref("initial_metadata_ready");
|
||||
}
|
||||
|
||||
void RecvTrailingMetadataReady(grpc_error_handle error) {
|
||||
GPR_ASSERT(error == GRPC_ERROR_NONE);
|
||||
{
|
||||
MutexLock lock(&mu_);
|
||||
queued_trailing_metadata_ = true;
|
||||
trailing_metadata_waker_.Wakeup();
|
||||
}
|
||||
Unref("trailing_metadata_ready");
|
||||
}
|
||||
|
||||
void MetadataBatchDone(grpc_error_handle error) {
|
||||
GPR_ASSERT(error == GRPC_ERROR_NONE);
|
||||
Unref("metadata_batch_done");
|
||||
}
|
||||
|
||||
void SendMessageBatchDone(grpc_error_handle error) {
|
||||
{
|
||||
MutexLock lock(&mu_);
|
||||
if (error != GRPC_ERROR_NONE) {
|
||||
// Note that we're in error here, the call will be closed by the
|
||||
// transport in a moment, and we'll return from the promise with an
|
||||
// error - so we don't need to do any extra work to close out pipes or
|
||||
// the like.
|
||||
send_message_state_ = Closed{};
|
||||
}
|
||||
if (!absl::holds_alternative<Closed>(send_message_state_)) {
|
||||
send_message_state_ = Idle{};
|
||||
}
|
||||
send_message_waker_.Wakeup();
|
||||
}
|
||||
Unref("send_message");
|
||||
}
|
||||
|
||||
void RecvMessageBatchDone(grpc_error_handle error) {
|
||||
{
|
||||
MutexLock lock(&mu_);
|
||||
if (error != GRPC_ERROR_NONE) {
|
||||
if (grpc_call_trace.enabled()) {
|
||||
gpr_log(GPR_INFO, "%sRecvMessageBatchDone: error=%s",
|
||||
recv_message_waker_.ActivityDebugTag().c_str(),
|
||||
grpc_error_std_string(error).c_str());
|
||||
}
|
||||
} else if (absl::holds_alternative<Closed>(recv_message_state_)) {
|
||||
if (grpc_call_trace.enabled()) {
|
||||
gpr_log(GPR_INFO, "%sRecvMessageBatchDone: already closed, ignoring",
|
||||
recv_message_waker_.ActivityDebugTag().c_str());
|
||||
}
|
||||
} else {
|
||||
auto pending =
|
||||
absl::get_if<PendingReceiveMessage>(&recv_message_state_);
|
||||
GPR_ASSERT(pending != nullptr);
|
||||
GPR_ASSERT(pending->received == false);
|
||||
pending->received = true;
|
||||
}
|
||||
recv_message_waker_.Wakeup();
|
||||
}
|
||||
Unref("recv_message");
|
||||
}
|
||||
|
||||
// Called from outside the activity to push work down to the transport.
|
||||
void Push() {
|
||||
auto do_push = [this](grpc_transport_stream_op_batch* batch) {
|
||||
if (stream_ != nullptr) {
|
||||
grpc_transport_perform_stream_op(transport_, stream_.get(), batch);
|
||||
} else {
|
||||
grpc_transport_stream_op_batch_finish_with_failure_from_transport(
|
||||
batch, GRPC_ERROR_CANCELLED);
|
||||
}
|
||||
};
|
||||
bool push_metadata;
|
||||
bool push_send_message;
|
||||
bool push_recv_message;
|
||||
{
|
||||
MutexLock lock(&mu_);
|
||||
push_metadata = std::exchange(push_metadata_, false);
|
||||
push_send_message = std::exchange(push_send_message_, false);
|
||||
push_recv_message = std::exchange(push_recv_message_, false);
|
||||
scheduled_push_ = false;
|
||||
}
|
||||
if (push_metadata) do_push(&metadata_);
|
||||
if (push_send_message) do_push(&send_message_);
|
||||
if (push_recv_message) do_push(&recv_message_);
|
||||
Unref("push");
|
||||
}
|
||||
|
||||
void StreamDestroyed() {
|
||||
call_context_->RunInContext([this] {
|
||||
auto* cc = call_context_;
|
||||
this->~ClientStream();
|
||||
cc->Unref("child_stream");
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
struct Idle {};
|
||||
struct Closed {};
|
||||
struct SendMessageToTransport {};
|
||||
|
||||
enum class ServerInitialMetadataState : uint8_t {
|
||||
// Initial metadata has not been received from the server.
|
||||
kNotReceived,
|
||||
// Initial metadata has been received from the server via the transport, but
|
||||
// has not yet been set on the latch to publish it up the call stack.
|
||||
kReceivedButNotSet,
|
||||
// Initial metadata has been received from the server via the transport and
|
||||
// has been set on the latch to publish it up the call stack.
|
||||
kSet,
|
||||
};
|
||||
|
||||
class StreamDeleter {
|
||||
public:
|
||||
explicit StreamDeleter(ClientStream* impl) : impl_(impl) {}
|
||||
void operator()(grpc_stream* stream) const {
|
||||
if (stream == nullptr) return;
|
||||
grpc_transport_destroy_stream(impl_->transport_, stream,
|
||||
&impl_->stream_destroyed_);
|
||||
}
|
||||
|
||||
private:
|
||||
ClientStream* impl_;
|
||||
};
|
||||
using StreamPtr = std::unique_ptr<grpc_stream, StreamDeleter>;
|
||||
|
||||
void SchedulePush() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) {
|
||||
if (std::exchange(scheduled_push_, true)) return;
|
||||
IncrementRefCount("push");
|
||||
ExecCtx::Run(DEBUG_LOCATION, &push_, GRPC_ERROR_NONE);
|
||||
}
|
||||
|
||||
std::string ActiveOpsString() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) {
|
||||
std::vector<std::string> ops;
|
||||
if (finished_) ops.push_back("FINISHED");
|
||||
// Pushes
|
||||
std::vector<std::string> pushes;
|
||||
if (push_metadata_) pushes.push_back("metadata");
|
||||
if (push_send_message_) pushes.push_back("send_message");
|
||||
if (push_recv_message_) pushes.push_back("recv_message");
|
||||
if (!pushes.empty()) {
|
||||
ops.push_back(
|
||||
absl::StrCat(scheduled_push_ ? "push:" : "unscheduled-push:",
|
||||
absl::StrJoin(pushes, ",")));
|
||||
} else if (scheduled_push_) {
|
||||
ops.push_back("push:nothing");
|
||||
}
|
||||
// Results from transport
|
||||
std::vector<std::string> queued;
|
||||
if (server_initial_metadata_state_ ==
|
||||
ServerInitialMetadataState::kReceivedButNotSet) {
|
||||
queued.push_back("initial_metadata");
|
||||
}
|
||||
if (queued_trailing_metadata_) queued.push_back("trailing_metadata");
|
||||
if (!queued.empty()) {
|
||||
ops.push_back(absl::StrCat("queued:", absl::StrJoin(queued, ",")));
|
||||
}
|
||||
// Send message
|
||||
std::string send_message_state = SendMessageString();
|
||||
if (send_message_state != "WAITING") {
|
||||
ops.push_back(absl::StrCat("send_message:", send_message_state));
|
||||
}
|
||||
// Receive message
|
||||
std::string recv_message_state = RecvMessageString();
|
||||
if (recv_message_state != "IDLE") {
|
||||
ops.push_back(absl::StrCat("recv_message:", recv_message_state));
|
||||
}
|
||||
return absl::StrJoin(ops, " ");
|
||||
}
|
||||
|
||||
std::string SendMessageString() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) {
|
||||
return Match(
|
||||
send_message_state_, [](Idle) -> std::string { return "IDLE"; },
|
||||
[](Closed) -> std::string { return "CLOSED"; },
|
||||
[](const PipeReceiver<MessageHandle>::NextType&) -> std::string {
|
||||
return "WAITING";
|
||||
},
|
||||
[](SendMessageToTransport) -> std::string { return "SENDING"; });
|
||||
}
|
||||
|
||||
std::string RecvMessageString() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) {
|
||||
return Match(
|
||||
recv_message_state_, [](Idle) -> std::string { return "IDLE"; },
|
||||
[](Closed) -> std::string { return "CLOSED"; },
|
||||
[](const PendingReceiveMessage&) -> std::string { return "WAITING"; },
|
||||
[](const absl::optional<MessageHandle>& message) -> std::string {
|
||||
return absl::StrCat(
|
||||
"READY:", message.has_value()
|
||||
? absl::StrCat((*message)->payload()->Length(), "b")
|
||||
: "EOS");
|
||||
},
|
||||
[](const PipeSender<MessageHandle>::PushType&) -> std::string {
|
||||
return "PUSHING";
|
||||
});
|
||||
}
|
||||
|
||||
Mutex mu_;
|
||||
bool requested_metadata_ = false;
|
||||
bool push_metadata_ ABSL_GUARDED_BY(mu_) = false;
|
||||
bool push_send_message_ ABSL_GUARDED_BY(mu_) = false;
|
||||
bool push_recv_message_ ABSL_GUARDED_BY(mu_) = false;
|
||||
bool scheduled_push_ ABSL_GUARDED_BY(mu_) = false;
|
||||
ServerInitialMetadataState server_initial_metadata_state_
|
||||
ABSL_GUARDED_BY(mu_) = ServerInitialMetadataState::kNotReceived;
|
||||
bool queued_trailing_metadata_ ABSL_GUARDED_BY(mu_) = false;
|
||||
bool finished_ ABSL_GUARDED_BY(mu_) = false;
|
||||
CallContext* const call_context_{GetContext<CallContext>()};
|
||||
Waker initial_metadata_waker_ ABSL_GUARDED_BY(mu_);
|
||||
Waker trailing_metadata_waker_ ABSL_GUARDED_BY(mu_);
|
||||
Waker send_message_waker_ ABSL_GUARDED_BY(mu_);
|
||||
Waker recv_message_waker_ ABSL_GUARDED_BY(mu_);
|
||||
grpc_transport* const transport_;
|
||||
grpc_stream_refcount stream_refcount_;
|
||||
StreamPtr stream_;
|
||||
Latch<ServerMetadata*>* server_initial_metadata_latch_;
|
||||
PipeReceiver<MessageHandle>* client_to_server_messages_;
|
||||
PipeSender<MessageHandle>* server_to_client_messages_;
|
||||
MessageHandle message_to_send_ ABSL_GUARDED_BY(mu_);
|
||||
absl::variant<Idle, Closed, PipeReceiver<MessageHandle>::NextType,
|
||||
SendMessageToTransport>
|
||||
send_message_state_ ABSL_GUARDED_BY(mu_);
|
||||
struct PendingReceiveMessage {
|
||||
absl::optional<SliceBuffer> payload;
|
||||
uint32_t flags;
|
||||
bool received = false;
|
||||
};
|
||||
absl::variant<Idle, PendingReceiveMessage, Closed,
|
||||
PipeSender<MessageHandle>::PushType>
|
||||
recv_message_state_ ABSL_GUARDED_BY(mu_);
|
||||
grpc_closure recv_initial_metadata_ready_ =
|
||||
MakeMemberClosure<ClientStream, &ClientStream::RecvInitialMetadataReady>(
|
||||
this, DEBUG_LOCATION);
|
||||
grpc_closure recv_trailing_metadata_ready_ =
|
||||
MakeMemberClosure<ClientStream, &ClientStream::RecvTrailingMetadataReady>(
|
||||
this, DEBUG_LOCATION);
|
||||
grpc_closure push_ = MakeMemberClosure<ClientStream, &ClientStream::Push>(
|
||||
this, DEBUG_LOCATION);
|
||||
ClientMetadataHandle client_initial_metadata_;
|
||||
ClientMetadataHandle client_trailing_metadata_;
|
||||
ServerMetadataHandle server_initial_metadata_;
|
||||
ServerMetadataHandle server_trailing_metadata_;
|
||||
grpc_transport_stream_op_batch metadata_;
|
||||
grpc_closure metadata_batch_done_ =
|
||||
MakeMemberClosure<ClientStream, &ClientStream::MetadataBatchDone>(
|
||||
this, DEBUG_LOCATION);
|
||||
grpc_transport_stream_op_batch send_message_;
|
||||
grpc_closure send_message_batch_done_ =
|
||||
MakeMemberClosure<ClientStream, &ClientStream::SendMessageBatchDone>(
|
||||
this, DEBUG_LOCATION);
|
||||
grpc_closure recv_message_batch_done_ =
|
||||
MakeMemberClosure<ClientStream, &ClientStream::RecvMessageBatchDone>(
|
||||
this, DEBUG_LOCATION);
|
||||
grpc_transport_stream_op_batch recv_message_;
|
||||
grpc_transport_stream_op_batch_payload batch_payload_{
|
||||
GetContext<grpc_call_context_element>()};
|
||||
grpc_closure stream_destroyed_ =
|
||||
MakeMemberClosure<ClientStream, &ClientStream::StreamDestroyed>(
|
||||
this, DEBUG_LOCATION);
|
||||
};
|
||||
|
||||
class ClientConnectedCallPromise {
|
||||
public:
|
||||
ClientConnectedCallPromise(grpc_transport* transport, CallArgs call_args)
|
||||
: impl_(GetContext<Arena>()->New<ClientStream>(transport,
|
||||
std::move(call_args))) {}
|
||||
|
||||
ClientConnectedCallPromise(const ClientConnectedCallPromise&) = delete;
|
||||
ClientConnectedCallPromise& operator=(const ClientConnectedCallPromise&) =
|
||||
delete;
|
||||
ClientConnectedCallPromise(ClientConnectedCallPromise&& other) noexcept
|
||||
: impl_(std::exchange(other.impl_, nullptr)) {}
|
||||
ClientConnectedCallPromise& operator=(
|
||||
ClientConnectedCallPromise&& other) noexcept {
|
||||
impl_ = std::move(other.impl_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
static ArenaPromise<ServerMetadataHandle> Make(grpc_transport* transport,
|
||||
CallArgs call_args) {
|
||||
return ClientConnectedCallPromise(transport, std::move(call_args));
|
||||
}
|
||||
|
||||
Poll<ServerMetadataHandle> operator()() { return impl_->PollOnce(); }
|
||||
|
||||
private:
|
||||
OrphanablePtr<ClientStream> impl_;
|
||||
};
|
||||
|
||||
template <ArenaPromise<ServerMetadataHandle> (*make_call_promise)(
|
||||
grpc_transport*, CallArgs)>
|
||||
grpc_channel_filter MakeConnectedFilter() {
|
||||
// Create a vtable that contains both the legacy call methods (for filter
|
||||
// stack based calls) and the new promise based method for creating promise
|
||||
// based calls (the latter iff make_call_promise != nullptr).
|
||||
// In this way the filter can be inserted into either kind of channel stack,
|
||||
// and only if all the filters in the stack are promise based will the call
|
||||
// be promise based.
|
||||
return {
|
||||
connected_channel_start_transport_stream_op_batch,
|
||||
make_call_promise == nullptr
|
||||
? nullptr
|
||||
: +[](grpc_channel_element* elem, CallArgs call_args,
|
||||
NextPromiseFactory) {
|
||||
grpc_transport* transport =
|
||||
static_cast<channel_data*>(elem->channel_data)->transport;
|
||||
return make_call_promise(transport, std::move(call_args));
|
||||
},
|
||||
connected_channel_start_transport_op,
|
||||
sizeof(call_data),
|
||||
connected_channel_init_call_elem,
|
||||
set_pollset_or_pollset_set,
|
||||
connected_channel_destroy_call_elem,
|
||||
sizeof(channel_data),
|
||||
connected_channel_init_channel_elem,
|
||||
+[](grpc_channel_stack* channel_stack, grpc_channel_element* elem) {
|
||||
/* HACK(ctiller): increase call stack size for the channel to make space
|
||||
for channel data. We need a cleaner (but performant) way to do this,
|
||||
and I'm not sure what that is yet.
|
||||
This is only "safe" because call stacks place no additional data
|
||||
after the last call element, and the last call element MUST be the
|
||||
connected channel. */
|
||||
channel_stack->call_stack_size += grpc_transport_stream_size(
|
||||
static_cast<channel_data*>(elem->channel_data)->transport);
|
||||
},
|
||||
connected_channel_destroy_channel_elem,
|
||||
connected_channel_get_channel_info,
|
||||
"connected",
|
||||
};
|
||||
}
|
||||
|
||||
ArenaPromise<ServerMetadataHandle> MakeTransportCallPromise(
|
||||
grpc_transport* transport, CallArgs call_args) {
|
||||
return transport->vtable->make_call_promise(transport, std::move(call_args));
|
||||
}
|
||||
|
||||
const grpc_channel_filter kPromiseBasedTransportFilter =
|
||||
MakeConnectedFilter<MakeTransportCallPromise>();
|
||||
|
||||
const grpc_channel_filter kClientEmulatedFilter =
|
||||
MakeConnectedFilter<ClientConnectedCallPromise::Make>();
|
||||
|
||||
const grpc_channel_filter kNoPromiseFilter = MakeConnectedFilter<nullptr>();
|
||||
|
||||
} // namespace
|
||||
} // namespace grpc_core
|
||||
|
||||
bool grpc_add_connected_filter(grpc_core::ChannelStackBuilder* builder) {
|
||||
grpc_transport* t = builder->transport();
|
||||
GPR_ASSERT(t != nullptr);
|
||||
builder->AppendFilter(&grpc_connected_filter);
|
||||
// Choose the right vtable for the connected filter.
|
||||
// We can't know promise based call or not here (that decision needs the
|
||||
// collaboration of all of the filters on the channel, and we don't want
|
||||
// ordering constraints on when we add filters).
|
||||
// We can know if this results in a promise based call how we'll create our
|
||||
// promise (if indeed we can), and so that is the choice made here.
|
||||
if (t->vtable->make_call_promise != nullptr) {
|
||||
// Option 1, and our ideal: the transport supports promise based calls, and
|
||||
// so we simply use the transport directly.
|
||||
builder->AppendFilter(&grpc_core::kPromiseBasedTransportFilter);
|
||||
} else if (grpc_channel_stack_type_is_client(builder->channel_stack_type())) {
|
||||
// Option 2: the transport does not support promise based calls, but we're
|
||||
// on the client and so we have an implementation that we can use to convert
|
||||
// to batches.
|
||||
builder->AppendFilter(&grpc_core::kClientEmulatedFilter);
|
||||
} else {
|
||||
// Option 3: the transport does not support promise based calls, and we're
|
||||
// on the server so we can't construct promise based calls just yet.
|
||||
builder->AppendFilter(&grpc_core::kNoPromiseFilter);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
grpc_stream* grpc_connected_channel_get_stream(grpc_call_element* elem) {
|
||||
call_data* calld = static_cast<call_data*>(elem->call_data);
|
||||
return TRANSPORT_STREAM_FROM_CALL_DATA(calld);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,13 +24,9 @@
|
|||
#include "src/core/lib/channel/channel_fwd.h"
|
||||
#include "src/core/lib/channel/channel_stack.h"
|
||||
#include "src/core/lib/channel/channel_stack_builder.h"
|
||||
#include "src/core/lib/transport/transport.h"
|
||||
|
||||
extern const grpc_channel_filter grpc_connected_filter;
|
||||
|
||||
bool grpc_add_connected_filter(grpc_core::ChannelStackBuilder* builder);
|
||||
|
||||
/* Debug helper to dig the transport stream out of a call element */
|
||||
grpc_stream* grpc_connected_channel_get_stream(grpc_call_element* elem);
|
||||
|
||||
#endif /* GRPC_CORE_LIB_CHANNEL_CONNECTED_CHANNEL_H */
|
||||
|
|
|
|||
|
|
@ -665,7 +665,7 @@ void ClientCallData::StartPromise(Flusher* flusher) {
|
|||
promise_ = filter->MakeCallPromise(
|
||||
CallArgs{WrapMetadata(send_initial_metadata_batch_->payload
|
||||
->send_initial_metadata.send_initial_metadata),
|
||||
server_initial_metadata_latch()},
|
||||
server_initial_metadata_latch(), nullptr, nullptr},
|
||||
[this](CallArgs call_args) {
|
||||
return MakeNextPromise(std::move(call_args));
|
||||
});
|
||||
|
|
@ -1154,12 +1154,12 @@ void ServerCallData::RecvInitialMetadataReady(grpc_error_handle error) {
|
|||
ScopedContext context(this);
|
||||
// Construct the promise.
|
||||
ChannelFilter* filter = static_cast<ChannelFilter*>(elem()->channel_data);
|
||||
promise_ =
|
||||
filter->MakeCallPromise(CallArgs{WrapMetadata(recv_initial_metadata_),
|
||||
server_initial_metadata_latch()},
|
||||
[this](CallArgs call_args) {
|
||||
return MakeNextPromise(std::move(call_args));
|
||||
});
|
||||
promise_ = filter->MakeCallPromise(
|
||||
CallArgs{WrapMetadata(recv_initial_metadata_),
|
||||
server_initial_metadata_latch(), nullptr, nullptr},
|
||||
[this](CallArgs call_args) {
|
||||
return MakeNextPromise(std::move(call_args));
|
||||
});
|
||||
// Poll once.
|
||||
WakeInsideCombiner(&flusher);
|
||||
if (auto* closure =
|
||||
|
|
|
|||
|
|
@ -19,6 +19,9 @@
|
|||
// promise-style. Most of this will be removed once the promises conversion is
|
||||
// completed.
|
||||
|
||||
// TODO(ctiller): When removing this file, also reduce the number of *'s on the
|
||||
// server initial metadata latch.
|
||||
|
||||
#include <grpc/support/port_platform.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
|
@ -27,6 +30,7 @@
|
|||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <new>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/container/inlined_vector.h"
|
||||
|
|
@ -56,6 +60,7 @@
|
|||
#include "src/core/lib/promise/latch.h"
|
||||
#include "src/core/lib/promise/poll.h"
|
||||
#include "src/core/lib/resource_quota/arena.h"
|
||||
#include "src/core/lib/transport/call_fragments.h"
|
||||
#include "src/core/lib/transport/error_utils.h"
|
||||
#include "src/core/lib/transport/metadata_batch.h"
|
||||
#include "src/core/lib/transport/transport.h"
|
||||
|
|
@ -146,6 +151,8 @@ class BaseCallData : public Activity, private Wakeable {
|
|||
Waker MakeNonOwningWaker() final;
|
||||
Waker MakeOwningWaker() final;
|
||||
|
||||
std::string ActivityDebugTag() const override { return DebugTag(); }
|
||||
|
||||
void Finalize(const grpc_call_final_info* final_info) {
|
||||
finalization_.Run(final_info);
|
||||
}
|
||||
|
|
@ -234,13 +241,13 @@ class BaseCallData : public Activity, private Wakeable {
|
|||
grpc_transport_stream_op_batch* batch_;
|
||||
};
|
||||
|
||||
static MetadataHandle<grpc_metadata_batch> WrapMetadata(
|
||||
static FragmentHandle<grpc_metadata_batch> WrapMetadata(
|
||||
grpc_metadata_batch* p) {
|
||||
return MetadataHandle<grpc_metadata_batch>(p);
|
||||
return FragmentHandle<grpc_metadata_batch>(p, false);
|
||||
}
|
||||
|
||||
static grpc_metadata_batch* UnwrapMetadata(
|
||||
MetadataHandle<grpc_metadata_batch> p) {
|
||||
FragmentHandle<grpc_metadata_batch> p) {
|
||||
return p.Unwrap();
|
||||
}
|
||||
|
||||
|
|
@ -311,8 +318,8 @@ class ClientCallData : public BaseCallData {
|
|||
kQueued,
|
||||
// We've forwarded the op to the next filter.
|
||||
kForwarded,
|
||||
// The op has completed from below, but we haven't yet forwarded it up (the
|
||||
// promise gets to interject and mutate it).
|
||||
// The op has completed from below, but we haven't yet forwarded it up
|
||||
// (the promise gets to interject and mutate it).
|
||||
kComplete,
|
||||
// We've called the recv_metadata_ready callback from the original
|
||||
// recv_trailing_metadata op that was presented to us.
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@
|
|||
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/status/statusor.h"
|
||||
#include "absl/utility/utility.h"
|
||||
|
||||
#include <grpc/event_engine/endpoint_config.h>
|
||||
#include <grpc/event_engine/event_engine.h>
|
||||
|
|
@ -74,7 +73,7 @@ struct PosixTcpOptions {
|
|||
PosixTcpOptions() = default;
|
||||
// Move ctor
|
||||
PosixTcpOptions(PosixTcpOptions&& other) noexcept {
|
||||
socket_mutator = absl::exchange(other.socket_mutator, nullptr);
|
||||
socket_mutator = std::exchange(other.socket_mutator, nullptr);
|
||||
resource_quota = std::move(other.resource_quota);
|
||||
CopyIntegerOptions(other);
|
||||
}
|
||||
|
|
@ -83,7 +82,7 @@ struct PosixTcpOptions {
|
|||
if (socket_mutator != nullptr) {
|
||||
grpc_socket_mutator_unref(socket_mutator);
|
||||
}
|
||||
socket_mutator = absl::exchange(other.socket_mutator, nullptr);
|
||||
socket_mutator = std::exchange(other.socket_mutator, nullptr);
|
||||
resource_quota = std::move(other.resource_quota);
|
||||
CopyIntegerOptions(other);
|
||||
return *this;
|
||||
|
|
|
|||
|
|
@ -48,6 +48,9 @@ const char* const description_event_engine_client =
|
|||
"Use EventEngine clients instead of iomgr's grpc_tcp_client";
|
||||
const char* const description_monitoring_experiment =
|
||||
"Placeholder experiment to prove/disprove our monitoring is working";
|
||||
const char* const description_promise_based_client_call =
|
||||
"If set, use the new gRPC promise based call code when it's appropriate "
|
||||
"(ie when all filters in a stack are promise based)";
|
||||
#ifdef NDEBUG
|
||||
const bool kDefaultForDebugOnly = false;
|
||||
#else
|
||||
|
|
@ -73,6 +76,7 @@ const ExperimentMetadata g_experiment_metadata[] = {
|
|||
kDefaultForDebugOnly},
|
||||
{"event_engine_client", description_event_engine_client, false},
|
||||
{"monitoring_experiment", description_monitoring_experiment, true},
|
||||
{"promise_based_client_call", description_promise_based_client_call, false},
|
||||
};
|
||||
|
||||
} // namespace grpc_core
|
||||
|
|
|
|||
|
|
@ -42,6 +42,9 @@ inline bool IsUnconstrainedMaxQuotaBufferSizeEnabled() {
|
|||
inline bool IsNewHpackHuffmanDecoderEnabled() { return IsExperimentEnabled(8); }
|
||||
inline bool IsEventEngineClientEnabled() { return IsExperimentEnabled(9); }
|
||||
inline bool IsMonitoringExperimentEnabled() { return IsExperimentEnabled(10); }
|
||||
inline bool IsPromiseBasedClientCallEnabled() {
|
||||
return IsExperimentEnabled(11);
|
||||
}
|
||||
|
||||
struct ExperimentMetadata {
|
||||
const char* name;
|
||||
|
|
@ -49,7 +52,7 @@ struct ExperimentMetadata {
|
|||
bool default_value;
|
||||
};
|
||||
|
||||
constexpr const size_t kNumExperiments = 11;
|
||||
constexpr const size_t kNumExperiments = 12;
|
||||
extern const ExperimentMetadata g_experiment_metadata[kNumExperiments];
|
||||
|
||||
} // namespace grpc_core
|
||||
|
|
|
|||
|
|
@ -119,3 +119,11 @@
|
|||
expiry: 2022/10/01
|
||||
owner: ctiller@google.com
|
||||
test_tags: []
|
||||
- name: promise_based_client_call
|
||||
description:
|
||||
If set, use the new gRPC promise based call code when it's appropriate
|
||||
(ie when all filters in a stack are promise based)
|
||||
default: false
|
||||
expiry: 2023/01/01
|
||||
owner: ctiller@google.com
|
||||
test_tags: ["core_end2end_test", "lame_client_test"]
|
||||
|
|
|
|||
|
|
@ -118,6 +118,54 @@ inline grpc_closure* grpc_closure_init(grpc_closure* closure,
|
|||
grpc_closure_init(closure, cb, cb_arg)
|
||||
#endif
|
||||
|
||||
namespace grpc_core {
|
||||
template <typename T, void (T::*cb)(grpc_error_handle)>
|
||||
grpc_closure MakeMemberClosure(T* p, DebugLocation location = DebugLocation()) {
|
||||
grpc_closure out;
|
||||
GRPC_CLOSURE_INIT(
|
||||
&out, [](void* p, grpc_error_handle e) { (static_cast<T*>(p)->*cb)(e); },
|
||||
p, nullptr);
|
||||
#ifndef NDEBUG
|
||||
out.file_created = location.file();
|
||||
out.line_created = location.line();
|
||||
#else
|
||||
(void)location;
|
||||
#endif
|
||||
return out;
|
||||
}
|
||||
|
||||
template <typename T, void (T::*cb)()>
|
||||
grpc_closure MakeMemberClosure(T* p, DebugLocation location = DebugLocation()) {
|
||||
grpc_closure out;
|
||||
GRPC_CLOSURE_INIT(
|
||||
&out, [](void* p, grpc_error_handle) { (static_cast<T*>(p)->*cb)(); }, p,
|
||||
nullptr);
|
||||
#ifndef NDEBUG
|
||||
out.file_created = location.file();
|
||||
out.line_created = location.line();
|
||||
#else
|
||||
(void)location;
|
||||
#endif
|
||||
return out;
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
grpc_closure* NewClosure(F f) {
|
||||
struct Closure : public grpc_closure {
|
||||
explicit Closure(F f) : f(std::move(f)) {}
|
||||
F f;
|
||||
static void Run(void* arg, grpc_error_handle error) {
|
||||
auto self = static_cast<Closure*>(arg);
|
||||
self->f(error);
|
||||
delete self;
|
||||
}
|
||||
};
|
||||
Closure* c = new Closure(std::move(f));
|
||||
GRPC_CLOSURE_INIT(c, Closure::Run, c, nullptr);
|
||||
return c;
|
||||
}
|
||||
} // namespace grpc_core
|
||||
|
||||
namespace closure_impl {
|
||||
|
||||
struct wrapped_closure {
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ struct PosixTcpOptions {
|
|||
PosixTcpOptions() = default;
|
||||
// Move ctor
|
||||
PosixTcpOptions(PosixTcpOptions&& other) noexcept {
|
||||
socket_mutator = absl::exchange(other.socket_mutator, nullptr);
|
||||
socket_mutator = std::exchange(other.socket_mutator, nullptr);
|
||||
resource_quota = std::move(other.resource_quota);
|
||||
CopyIntegerOptions(other);
|
||||
}
|
||||
|
|
@ -73,7 +73,7 @@ struct PosixTcpOptions {
|
|||
if (socket_mutator != nullptr) {
|
||||
grpc_socket_mutator_unref(socket_mutator);
|
||||
}
|
||||
socket_mutator = absl::exchange(other.socket_mutator, nullptr);
|
||||
socket_mutator = std::exchange(other.socket_mutator, nullptr);
|
||||
resource_quota = std::move(other.resource_quota);
|
||||
CopyIntegerOptions(other);
|
||||
return *this;
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@
|
|||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "absl/strings/str_format.h"
|
||||
|
||||
#include "src/core/lib/gprpp/atomic_utils.h"
|
||||
|
||||
namespace grpc_core {
|
||||
|
|
@ -32,6 +34,8 @@ namespace promise_detail {
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// HELPER TYPES
|
||||
|
||||
std::string Unwakeable::ActivityDebugTag() const { return "<unknown>"; }
|
||||
|
||||
// Weak handle to an Activity.
|
||||
// Handle can persist while Activity goes away.
|
||||
class FreestandingActivity::Handle final : public Wakeable {
|
||||
|
|
@ -74,6 +78,11 @@ class FreestandingActivity::Handle final : public Wakeable {
|
|||
|
||||
void Drop() override { Unref(); }
|
||||
|
||||
std::string ActivityDebugTag() const override {
|
||||
MutexLock lock(&mu_);
|
||||
return activity_ == nullptr ? "<unknown>" : activity_->DebugTag();
|
||||
}
|
||||
|
||||
private:
|
||||
// Unref the Handle (not the activity).
|
||||
void Unref() {
|
||||
|
|
@ -85,7 +94,7 @@ class FreestandingActivity::Handle final : public Wakeable {
|
|||
// Two initial refs: one for the waiter that caused instantiation, one for the
|
||||
// activity.
|
||||
std::atomic<size_t> refs_{2};
|
||||
Mutex mu_ ABSL_ACQUIRED_AFTER(activity_->mu_);
|
||||
mutable Mutex mu_ ABSL_ACQUIRED_AFTER(activity_->mu_);
|
||||
FreestandingActivity* activity_ ABSL_GUARDED_BY(mu_);
|
||||
};
|
||||
|
||||
|
|
@ -117,4 +126,9 @@ Waker FreestandingActivity::MakeNonOwningWaker() {
|
|||
}
|
||||
|
||||
} // namespace promise_detail
|
||||
|
||||
std::string Activity::DebugTag() const {
|
||||
return absl::StrFormat("ACTIVITY[%p]", this);
|
||||
}
|
||||
|
||||
} // namespace grpc_core
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/base/thread_annotations.h"
|
||||
|
|
@ -43,6 +44,8 @@
|
|||
|
||||
namespace grpc_core {
|
||||
|
||||
class Activity;
|
||||
|
||||
// A Wakeable object is used by queues to wake activities.
|
||||
class Wakeable {
|
||||
public:
|
||||
|
|
@ -52,19 +55,23 @@ class Wakeable {
|
|||
// Drop this wakeable without waking up the underlying activity.
|
||||
virtual void Drop() = 0;
|
||||
|
||||
// Return the underlying activity debug tag, or "<unknown>" if not available.
|
||||
virtual std::string ActivityDebugTag() const = 0;
|
||||
|
||||
protected:
|
||||
inline ~Wakeable() {}
|
||||
};
|
||||
|
||||
namespace activity_detail {
|
||||
namespace promise_detail {
|
||||
struct Unwakeable final : public Wakeable {
|
||||
void Wakeup() override {}
|
||||
void Drop() override {}
|
||||
std::string ActivityDebugTag() const override;
|
||||
};
|
||||
static Unwakeable* unwakeable() {
|
||||
return NoDestructSingleton<Unwakeable>::Get();
|
||||
}
|
||||
} // namespace activity_detail
|
||||
} // namespace promise_detail
|
||||
|
||||
class AtomicWaker;
|
||||
|
||||
|
|
@ -73,7 +80,7 @@ class AtomicWaker;
|
|||
class Waker {
|
||||
public:
|
||||
explicit Waker(Wakeable* wakeable) : wakeable_(wakeable) {}
|
||||
Waker() : Waker(activity_detail::unwakeable()) {}
|
||||
Waker() : Waker(promise_detail::unwakeable()) {}
|
||||
~Waker() { wakeable_->Drop(); }
|
||||
Waker(const Waker&) = delete;
|
||||
Waker& operator=(const Waker&) = delete;
|
||||
|
|
@ -95,11 +102,15 @@ class Waker {
|
|||
return wakeable_ == other.wakeable_;
|
||||
}
|
||||
|
||||
std::string ActivityDebugTag() {
|
||||
return wakeable_ == nullptr ? "<unknown>" : wakeable_->ActivityDebugTag();
|
||||
}
|
||||
|
||||
private:
|
||||
friend class AtomicWaker;
|
||||
|
||||
Wakeable* Take() {
|
||||
return std::exchange(wakeable_, activity_detail::unwakeable());
|
||||
return std::exchange(wakeable_, promise_detail::unwakeable());
|
||||
}
|
||||
|
||||
Wakeable* wakeable_;
|
||||
|
|
@ -109,7 +120,7 @@ class Waker {
|
|||
class AtomicWaker {
|
||||
public:
|
||||
explicit AtomicWaker(Wakeable* wakeable) : wakeable_(wakeable) {}
|
||||
AtomicWaker() : AtomicWaker(activity_detail::unwakeable()) {}
|
||||
AtomicWaker() : AtomicWaker(promise_detail::unwakeable()) {}
|
||||
explicit AtomicWaker(Waker waker) : AtomicWaker(waker.Take()) {}
|
||||
~AtomicWaker() { wakeable_.load(std::memory_order_acquire)->Drop(); }
|
||||
AtomicWaker(const AtomicWaker&) = delete;
|
||||
|
|
@ -123,7 +134,7 @@ class AtomicWaker {
|
|||
// Return true if there is a not-unwakeable wakeable present.
|
||||
bool Armed() const noexcept {
|
||||
return wakeable_.load(std::memory_order_relaxed) !=
|
||||
activity_detail::unwakeable();
|
||||
promise_detail::unwakeable();
|
||||
}
|
||||
|
||||
// Set to some new waker
|
||||
|
|
@ -133,7 +144,7 @@ class AtomicWaker {
|
|||
|
||||
private:
|
||||
Wakeable* Take() {
|
||||
return wakeable_.exchange(activity_detail::unwakeable(),
|
||||
return wakeable_.exchange(promise_detail::unwakeable(),
|
||||
std::memory_order_acq_rel);
|
||||
}
|
||||
|
||||
|
|
@ -179,6 +190,9 @@ class Activity : public Orphanable {
|
|||
// delivered until long after the activity should be destroyed.
|
||||
virtual Waker MakeNonOwningWaker() = 0;
|
||||
|
||||
// Some descriptive text to add to log messages to identify this activity.
|
||||
virtual std::string DebugTag() const;
|
||||
|
||||
protected:
|
||||
// Check if this activity is the current activity executing on the current
|
||||
// thread.
|
||||
|
|
@ -333,6 +347,8 @@ class FreestandingActivity : public Activity, private Wakeable {
|
|||
|
||||
Mutex* mu() ABSL_LOCK_RETURNED(mu_) { return &mu_; }
|
||||
|
||||
std::string ActivityDebugTag() const override { return DebugTag(); }
|
||||
|
||||
private:
|
||||
class Handle;
|
||||
|
||||
|
|
|
|||
|
|
@ -86,13 +86,9 @@ class CallPushPull {
|
|||
if (!done_.is_set(kDoneMain)) {
|
||||
auto p = main_();
|
||||
if (auto* status = absl::get_if<kPollReadyIdx>(&p)) {
|
||||
if (IsStatusOk(*status)) {
|
||||
done_.set(kDoneMain);
|
||||
Destruct(&main_);
|
||||
Construct(&result_, std::move(*status));
|
||||
} else {
|
||||
return std::move(*status);
|
||||
}
|
||||
done_.set(kDoneMain);
|
||||
Destruct(&main_);
|
||||
Construct(&result_, std::move(*status));
|
||||
}
|
||||
}
|
||||
if (!done_.is_set(kDonePull)) {
|
||||
|
|
@ -134,6 +130,10 @@ class CallPushPull {
|
|||
// When polling, the push is polled first, then the main call (descending the
|
||||
// stack), then the pull (as we ascend once more).
|
||||
//
|
||||
// If the push or the pull fail early, then the entire call fails.
|
||||
// If the main part of the call fails, we wait until both push and pull are also
|
||||
// done.
|
||||
//
|
||||
// This strategy minimizes repolls.
|
||||
template <typename FMain, typename FPush, typename FPull>
|
||||
promise_detail::CallPushPull<FMain, FPush, FPull> CallPushPull(FMain f_main,
|
||||
|
|
|
|||
|
|
@ -240,6 +240,8 @@ class Center {
|
|||
template <typename T>
|
||||
class PipeSender {
|
||||
public:
|
||||
using PushType = pipe_detail::Push<T>;
|
||||
|
||||
PipeSender(const PipeSender&) = delete;
|
||||
PipeSender& operator=(const PipeSender&) = delete;
|
||||
|
||||
|
|
@ -257,11 +259,15 @@ class PipeSender {
|
|||
if (center_ != nullptr) center_->UnrefSend();
|
||||
}
|
||||
|
||||
void Close() {
|
||||
if (auto* center = std::exchange(center_, nullptr)) center->UnrefSend();
|
||||
}
|
||||
|
||||
// Send a single message along the pipe.
|
||||
// Returns a promise that will resolve to a bool - true if the message was
|
||||
// sent, false if it could never be sent. Blocks the promise until the
|
||||
// receiver is either closed or able to receive another message.
|
||||
pipe_detail::Push<T> Push(T value);
|
||||
PushType Push(T value);
|
||||
|
||||
private:
|
||||
friend struct Pipe<T>;
|
||||
|
|
@ -273,6 +279,8 @@ class PipeSender {
|
|||
template <typename T>
|
||||
class PipeReceiver {
|
||||
public:
|
||||
using NextType = pipe_detail::Next<T>;
|
||||
|
||||
PipeReceiver(const PipeReceiver&) = delete;
|
||||
PipeReceiver& operator=(const PipeReceiver&) = delete;
|
||||
|
||||
|
|
@ -294,7 +302,7 @@ class PipeReceiver {
|
|||
// message was received, or no value if the other end of the pipe was closed.
|
||||
// Blocks the promise until the receiver is either closed or a message is
|
||||
// available.
|
||||
pipe_detail::Next<T> Next();
|
||||
NextType Next();
|
||||
|
||||
private:
|
||||
friend struct Pipe<T>;
|
||||
|
|
@ -434,7 +442,8 @@ void NextResult<T>::reset() {
|
|||
// polling code) would likely be more appropriate.
|
||||
template <typename T>
|
||||
struct Pipe {
|
||||
Pipe() : Pipe(GetContext<Arena>()->New<pipe_detail::Center<T>>()) {}
|
||||
Pipe() : Pipe(GetContext<Arena>()) {}
|
||||
explicit Pipe(Arena* arena) : Pipe(arena->New<pipe_detail::Center<T>>()) {}
|
||||
Pipe(const Pipe&) = delete;
|
||||
Pipe& operator=(const Pipe&) = delete;
|
||||
Pipe(Pipe&&) noexcept = default;
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "absl/types/variant.h"
|
||||
|
||||
namespace grpc_core {
|
||||
|
|
@ -61,6 +63,17 @@ struct PollTraits<Poll<T>> {
|
|||
static constexpr bool is_poll() { return true; }
|
||||
};
|
||||
|
||||
// Convert a poll to a string
|
||||
template <typename T, typename F>
|
||||
std::string PollToString(
|
||||
const Poll<T>& poll,
|
||||
F t_to_string = [](const T& t) { return t.ToString(); }) {
|
||||
if (absl::holds_alternative<Pending>(poll)) {
|
||||
return "<<pending>>";
|
||||
}
|
||||
return t_to_string(absl::get<T>(poll));
|
||||
}
|
||||
|
||||
} // namespace grpc_core
|
||||
|
||||
#endif // GRPC_CORE_LIB_PROMISE_POLL_H
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include "src/core/lib/promise/promise.h"
|
||||
#include "src/core/lib/security/authorization/authorization_engine.h"
|
||||
#include "src/core/lib/security/authorization/evaluate_args.h"
|
||||
#include "src/core/lib/transport/call_fragments.h"
|
||||
#include "src/core/lib/transport/transport.h"
|
||||
|
||||
namespace grpc_core {
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "src/core/lib/security/authorization/authorization_policy_provider.h"
|
||||
#include "src/core/lib/security/authorization/evaluate_args.h"
|
||||
#include "src/core/lib/security/context/security_context.h"
|
||||
#include "src/core/lib/transport/call_fragments.h"
|
||||
#include "src/core/lib/transport/transport.h"
|
||||
|
||||
namespace grpc_core {
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
#include <grpc/grpc_security.h>
|
||||
|
||||
#include "src/core/lib/security/credentials/credentials.h"
|
||||
#include "src/core/lib/transport/transport.h"
|
||||
#include "src/core/lib/transport/call_fragments.h"
|
||||
|
||||
namespace grpc_core {
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
#include "src/core/lib/gprpp/ref_counted_ptr.h"
|
||||
#include "src/core/lib/promise/try_seq.h"
|
||||
#include "src/core/lib/surface/api_trace.h"
|
||||
#include "src/core/lib/transport/transport.h"
|
||||
#include "src/core/lib/transport/call_fragments.h"
|
||||
|
||||
//
|
||||
// grpc_composite_channel_credentials
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@
|
|||
#include "src/core/lib/promise/arena_promise.h"
|
||||
#include "src/core/lib/security/credentials/credentials.h"
|
||||
#include "src/core/lib/security/security_connector/security_connector.h"
|
||||
#include "src/core/lib/transport/transport.h"
|
||||
#include "src/core/lib/transport/call_fragments.h"
|
||||
|
||||
/* -- Composite channel credentials. -- */
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include "src/core/lib/promise/promise.h"
|
||||
#include "src/core/lib/security/security_connector/fake/fake_security_connector.h"
|
||||
#include "src/core/lib/security/security_connector/security_connector.h"
|
||||
#include "src/core/lib/transport/call_fragments.h"
|
||||
#include "src/core/lib/transport/metadata_batch.h"
|
||||
|
||||
/* -- Fake transport security credentials. -- */
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@
|
|||
#include "src/core/lib/promise/arena_promise.h"
|
||||
#include "src/core/lib/security/credentials/credentials.h"
|
||||
#include "src/core/lib/slice/slice.h"
|
||||
#include "src/core/lib/transport/transport.h"
|
||||
#include "src/core/lib/transport/call_fragments.h"
|
||||
|
||||
#define GRPC_ARG_FAKE_SECURITY_EXPECTED_TARGETS \
|
||||
"grpc.fake_security.expected_targets"
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include "src/core/lib/iomgr/exec_ctx.h"
|
||||
#include "src/core/lib/promise/promise.h"
|
||||
#include "src/core/lib/surface/api_trace.h"
|
||||
#include "src/core/lib/transport/call_fragments.h"
|
||||
#include "src/core/lib/transport/metadata_batch.h"
|
||||
|
||||
grpc_core::ArenaPromise<absl::StatusOr<grpc_core::ClientMetadataHandle>>
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
#include "src/core/lib/promise/arena_promise.h"
|
||||
#include "src/core/lib/security/credentials/credentials.h"
|
||||
#include "src/core/lib/slice/slice.h"
|
||||
#include "src/core/lib/transport/transport.h"
|
||||
#include "src/core/lib/transport/call_fragments.h"
|
||||
|
||||
class grpc_google_iam_credentials : public grpc_call_credentials {
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@
|
|||
#include "src/core/lib/promise/promise.h"
|
||||
#include "src/core/lib/security/credentials/call_creds_util.h"
|
||||
#include "src/core/lib/surface/api_trace.h"
|
||||
#include "src/core/lib/transport/call_fragments.h"
|
||||
#include "src/core/lib/transport/metadata_batch.h"
|
||||
#include "src/core/lib/uri/uri_parser.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@
|
|||
#include "src/core/lib/security/credentials/credentials.h"
|
||||
#include "src/core/lib/security/credentials/jwt/json_token.h"
|
||||
#include "src/core/lib/slice/slice.h"
|
||||
#include "src/core/lib/transport/transport.h"
|
||||
#include "src/core/lib/transport/call_fragments.h"
|
||||
|
||||
class grpc_service_account_jwt_access_credentials
|
||||
: public grpc_call_credentials {
|
||||
|
|
|
|||
|
|
@ -57,9 +57,9 @@
|
|||
#include "src/core/lib/promise/promise.h"
|
||||
#include "src/core/lib/security/util/json_util.h"
|
||||
#include "src/core/lib/surface/api_trace.h"
|
||||
#include "src/core/lib/transport/call_fragments.h"
|
||||
#include "src/core/lib/transport/error_utils.h"
|
||||
#include "src/core/lib/transport/metadata_batch.h"
|
||||
#include "src/core/lib/transport/transport.h"
|
||||
#include "src/core/lib/uri/uri_parser.h"
|
||||
|
||||
using grpc_core::Json;
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@
|
|||
#include "src/core/lib/promise/arena_promise.h"
|
||||
#include "src/core/lib/security/credentials/credentials.h"
|
||||
#include "src/core/lib/slice/slice.h"
|
||||
#include "src/core/lib/transport/transport.h"
|
||||
#include "src/core/lib/transport/call_fragments.h"
|
||||
#include "src/core/lib/uri/uri_parser.h"
|
||||
|
||||
// Constants.
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
#include "src/core/lib/slice/slice_internal.h"
|
||||
#include "src/core/lib/surface/api_trace.h"
|
||||
#include "src/core/lib/surface/validate_metadata.h"
|
||||
#include "src/core/lib/transport/call_fragments.h"
|
||||
#include "src/core/lib/transport/metadata_batch.h"
|
||||
|
||||
grpc_core::TraceFlag grpc_plugin_credentials_trace(false, "plugin_credentials");
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@
|
|||
#include "src/core/lib/security/credentials/call_creds_util.h"
|
||||
#include "src/core/lib/security/credentials/credentials.h"
|
||||
#include "src/core/lib/slice/slice.h"
|
||||
#include "src/core/lib/transport/transport.h"
|
||||
#include "src/core/lib/transport/call_fragments.h"
|
||||
|
||||
extern grpc_core::TraceFlag grpc_plugin_credentials_trace;
|
||||
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@
|
|||
#include "src/core/lib/security/security_connector/security_connector.h"
|
||||
#include "src/core/lib/security/transport/auth_filters.h"
|
||||
#include "src/core/lib/slice/slice.h"
|
||||
#include "src/core/lib/transport/call_fragments.h"
|
||||
#include "src/core/lib/transport/metadata_batch.h"
|
||||
#include "src/core/lib/transport/transport.h"
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -24,14 +24,17 @@
|
|||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "absl/functional/any_invocable.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/types/optional.h"
|
||||
|
||||
#include <grpc/impl/codegen/compression_types.h>
|
||||
#include <grpc/impl/codegen/grpc_types.h>
|
||||
#include <grpc/support/atm.h>
|
||||
#include <grpc/support/log.h>
|
||||
|
||||
#include "src/core/lib/channel/channel_fwd.h"
|
||||
#include "src/core/lib/channel/channel_stack.h"
|
||||
#include "src/core/lib/channel/context.h"
|
||||
#include "src/core/lib/debug/trace.h"
|
||||
#include "src/core/lib/gprpp/ref_counted_ptr.h"
|
||||
|
|
@ -39,6 +42,8 @@
|
|||
#include "src/core/lib/iomgr/closure.h"
|
||||
#include "src/core/lib/iomgr/error.h"
|
||||
#include "src/core/lib/iomgr/iomgr_fwd.h"
|
||||
#include "src/core/lib/iomgr/polling_entity.h"
|
||||
#include "src/core/lib/promise/context.h"
|
||||
#include "src/core/lib/resource_quota/arena.h"
|
||||
#include "src/core/lib/slice/slice.h"
|
||||
#include "src/core/lib/surface/api_trace.h"
|
||||
|
|
@ -67,6 +72,45 @@ typedef struct grpc_call_create_args {
|
|||
grpc_core::Timestamp send_deadline;
|
||||
} grpc_call_create_args;
|
||||
|
||||
namespace grpc_core {
|
||||
class PromiseBasedCall;
|
||||
|
||||
// TODO(ctiller): move more call things into this type
|
||||
class CallContext {
|
||||
public:
|
||||
explicit CallContext(PromiseBasedCall* call) : call_(call) {}
|
||||
|
||||
// Run some action in the call activity context. This is needed to adapt some
|
||||
// legacy systems to promises, and will likely disappear once that conversion
|
||||
// is complete.
|
||||
void RunInContext(absl::AnyInvocable<void()> fn);
|
||||
|
||||
// TODO(ctiller): remove this once transport APIs are promise based
|
||||
void IncrementRefCount(const char* reason = "call_context");
|
||||
|
||||
// TODO(ctiller): remove this once transport APIs are promise based
|
||||
void Unref(const char* reason = "call_context");
|
||||
|
||||
grpc_call_stats* call_stats() { return &call_stats_; }
|
||||
gpr_atm* peer_string_atm_ptr();
|
||||
grpc_polling_entity* polling_entity() { return &pollent_; }
|
||||
|
||||
private:
|
||||
friend class PromiseBasedCall;
|
||||
// Call final info.
|
||||
grpc_call_stats call_stats_;
|
||||
// Pollset stuff, can't wait to remove.
|
||||
// TODO(ctiller): bring forth EventEngine.
|
||||
grpc_polling_entity pollent_;
|
||||
// TODO(ctiller): remove this once transport APIs are promise based and we
|
||||
// don't need refcounting here.
|
||||
PromiseBasedCall* const call_;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ContextType<CallContext> {};
|
||||
} // namespace grpc_core
|
||||
|
||||
/* Create a new call based on \a args.
|
||||
Regardless of success or failure, always returns a valid new call into *call
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -0,0 +1,114 @@
|
|||
// 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 <grpc/support/port_platform.h>
|
||||
|
||||
#include "src/core/lib/surface/call_trace.h"
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/base/thread_annotations.h"
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "absl/meta/type_traits.h"
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/types/variant.h"
|
||||
|
||||
#include <grpc/support/log.h>
|
||||
|
||||
#include "src/core/lib/channel/channel_stack.h"
|
||||
#include "src/core/lib/gprpp/no_destruct.h"
|
||||
#include "src/core/lib/gprpp/sync.h"
|
||||
#include "src/core/lib/iomgr/closure.h"
|
||||
#include "src/core/lib/promise/activity.h"
|
||||
#include "src/core/lib/promise/arena_promise.h"
|
||||
#include "src/core/lib/transport/call_fragments.h"
|
||||
#include "src/core/lib/transport/metadata_batch.h"
|
||||
#include "src/core/lib/transport/transport.h"
|
||||
|
||||
namespace grpc_core {
|
||||
|
||||
const grpc_channel_filter* PromiseTracingFilterFor(
|
||||
const grpc_channel_filter* filter) {
|
||||
struct DerivedFilter : public grpc_channel_filter {
|
||||
explicit DerivedFilter(const grpc_channel_filter* filter)
|
||||
: grpc_channel_filter{
|
||||
/* start_transport_stream_op_batch: */ grpc_call_next_op,
|
||||
/* make_call_promise: */
|
||||
[](grpc_channel_element* elem, CallArgs call_args,
|
||||
NextPromiseFactory next_promise_factory)
|
||||
-> ArenaPromise<ServerMetadataHandle> {
|
||||
auto* source_filter =
|
||||
static_cast<const DerivedFilter*>(elem->filter)->filter;
|
||||
gpr_log(
|
||||
GPR_DEBUG,
|
||||
"%sCreateCallPromise[%s]: client_initial_metadata=%s",
|
||||
Activity::current()->DebugTag().c_str(),
|
||||
source_filter->name,
|
||||
call_args.client_initial_metadata->DebugString().c_str());
|
||||
return [source_filter, child = next_promise_factory(
|
||||
std::move(call_args))]() mutable {
|
||||
gpr_log(GPR_DEBUG, "%sPollCallPromise[%s]: begin",
|
||||
Activity::current()->DebugTag().c_str(),
|
||||
source_filter->name);
|
||||
auto r = child();
|
||||
if (auto* p = absl::get_if<ServerMetadataHandle>(&r)) {
|
||||
gpr_log(GPR_DEBUG, "%sPollCallPromise[%s]: done: %s",
|
||||
Activity::current()->DebugTag().c_str(),
|
||||
source_filter->name, (*p)->DebugString().c_str());
|
||||
} else {
|
||||
gpr_log(GPR_DEBUG, "%sPollCallPromise[%s]: <<pending>",
|
||||
Activity::current()->DebugTag().c_str(),
|
||||
source_filter->name);
|
||||
}
|
||||
return r;
|
||||
};
|
||||
},
|
||||
grpc_channel_next_op, /* sizeof_call_data: */ 0,
|
||||
/* init_call_elem: */
|
||||
[](grpc_call_element*, const grpc_call_element_args*) {
|
||||
return absl::OkStatus();
|
||||
},
|
||||
grpc_call_stack_ignore_set_pollset_or_pollset_set,
|
||||
/* destroy_call_elem: */
|
||||
[](grpc_call_element*, const grpc_call_final_info*,
|
||||
grpc_closure*) {},
|
||||
/* sizeof_channel_data: */ 0, /* init_channel_elem: */
|
||||
[](grpc_channel_element*, grpc_channel_element_args*) {
|
||||
return absl::OkStatus();
|
||||
},
|
||||
/* post_init_channel_elem: */
|
||||
[](grpc_channel_stack*, grpc_channel_element*) {},
|
||||
/* destroy_channel_elem: */ [](grpc_channel_element*) {},
|
||||
grpc_channel_next_get_info, filter->name},
|
||||
filter(filter) {}
|
||||
const grpc_channel_filter* const filter;
|
||||
};
|
||||
struct Globals {
|
||||
Mutex mu;
|
||||
absl::flat_hash_map<const grpc_channel_filter*,
|
||||
std::unique_ptr<DerivedFilter>>
|
||||
map ABSL_GUARDED_BY(mu);
|
||||
};
|
||||
auto* globals = NoDestructSingleton<Globals>::Get();
|
||||
MutexLock lock(&globals->mu);
|
||||
auto it = globals->map.find(filter);
|
||||
if (it != globals->map.end()) return it->second.get();
|
||||
return globals->map.emplace(filter, std::make_unique<DerivedFilter>(filter))
|
||||
.first->second.get();
|
||||
}
|
||||
|
||||
} // namespace grpc_core
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
// 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.
|
||||
|
||||
#ifndef GRPC_CORE_LIB_SURFACE_CALL_TRACE_H
|
||||
#define GRPC_CORE_LIB_SURFACE_CALL_TRACE_H
|
||||
|
||||
#include <grpc/support/port_platform.h>
|
||||
|
||||
#include "src/core/lib/channel/channel_fwd.h"
|
||||
#include "src/core/lib/debug/trace.h"
|
||||
|
||||
extern grpc_core::TraceFlag grpc_call_trace;
|
||||
|
||||
namespace grpc_core {
|
||||
const grpc_channel_filter* PromiseTracingFilterFor(
|
||||
const grpc_channel_filter* filter);
|
||||
}
|
||||
|
||||
#endif // GRPC_CORE_LIB_SURFACE_CALL_TRACE_H
|
||||
|
|
@ -62,11 +62,12 @@
|
|||
|
||||
namespace grpc_core {
|
||||
|
||||
Channel::Channel(bool is_client, std::string target,
|
||||
Channel::Channel(bool is_client, bool is_promising, std::string target,
|
||||
const ChannelArgs& channel_args,
|
||||
grpc_compression_options compression_options,
|
||||
RefCountedPtr<grpc_channel_stack> channel_stack)
|
||||
: is_client_(is_client),
|
||||
is_promising_(is_promising),
|
||||
compression_options_(compression_options),
|
||||
call_size_estimate_(channel_stack->call_stack_size +
|
||||
grpc_call_get_initial_size_estimate()),
|
||||
|
|
@ -150,8 +151,8 @@ absl::StatusOr<RefCountedPtr<Channel>> Channel::CreateWithBuilder(
|
|||
|
||||
return RefCountedPtr<Channel>(new Channel(
|
||||
grpc_channel_stack_type_is_client(builder->channel_stack_type()),
|
||||
std::string(builder->target()), channel_args, compression_options,
|
||||
std::move(*r)));
|
||||
builder->IsPromising(), std::string(builder->target()), channel_args,
|
||||
compression_options, std::move(*r)));
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include <atomic>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
|
|
@ -34,6 +35,7 @@
|
|||
#include "absl/strings/string_view.h"
|
||||
#include "absl/types/optional.h"
|
||||
|
||||
#include <grpc/event_engine/event_engine.h>
|
||||
#include <grpc/event_engine/memory_allocator.h>
|
||||
#include <grpc/impl/codegen/compression_types.h>
|
||||
#include <grpc/impl/codegen/grpc_types.h>
|
||||
|
|
@ -44,6 +46,7 @@
|
|||
#include "src/core/lib/channel/channel_stack.h" // IWYU pragma: keep
|
||||
#include "src/core/lib/channel/channel_stack_builder.h"
|
||||
#include "src/core/lib/channel/channelz.h"
|
||||
#include "src/core/lib/event_engine/default_event_engine.h"
|
||||
#include "src/core/lib/gprpp/cpp_impl_of.h"
|
||||
#include "src/core/lib/gprpp/debug_location.h"
|
||||
#include "src/core/lib/gprpp/ref_counted.h"
|
||||
|
|
@ -141,6 +144,7 @@ class Channel : public RefCounted<Channel>,
|
|||
absl::string_view target() const { return target_; }
|
||||
MemoryAllocator* allocator() { return &allocator_; }
|
||||
bool is_client() const { return is_client_; }
|
||||
bool is_promising() const { return is_promising_; }
|
||||
RegisteredCall* RegisterCall(const char* method, const char* host);
|
||||
|
||||
int TestOnlyRegisteredCalls() {
|
||||
|
|
@ -153,12 +157,18 @@ class Channel : public RefCounted<Channel>,
|
|||
return registration_table_.method_registration_attempts;
|
||||
}
|
||||
|
||||
grpc_event_engine::experimental::EventEngine* event_engine() const {
|
||||
return event_engine_.get();
|
||||
}
|
||||
|
||||
private:
|
||||
Channel(bool is_client, std::string target, const ChannelArgs& channel_args,
|
||||
Channel(bool is_client, bool is_promising, std::string target,
|
||||
const ChannelArgs& channel_args,
|
||||
grpc_compression_options compression_options,
|
||||
RefCountedPtr<grpc_channel_stack> channel_stack);
|
||||
|
||||
const bool is_client_;
|
||||
const bool is_promising_;
|
||||
const grpc_compression_options compression_options_;
|
||||
std::atomic<size_t> call_size_estimate_;
|
||||
CallRegistrationTable registration_table_;
|
||||
|
|
@ -166,6 +176,8 @@ class Channel : public RefCounted<Channel>,
|
|||
MemoryAllocator allocator_;
|
||||
std::string target_;
|
||||
const RefCountedPtr<grpc_channel_stack> channel_stack_;
|
||||
const std::shared_ptr<grpc_event_engine::experimental::EventEngine>
|
||||
event_engine_ = grpc_event_engine::experimental::GetDefaultEventEngine();
|
||||
};
|
||||
|
||||
} // namespace grpc_core
|
||||
|
|
|
|||
|
|
@ -41,10 +41,12 @@
|
|||
#include "src/core/lib/gprpp/ref_counted_ptr.h"
|
||||
#include "src/core/lib/gprpp/sync.h"
|
||||
#include "src/core/lib/iomgr/exec_ctx.h"
|
||||
#include "src/core/lib/promise/pipe.h"
|
||||
#include "src/core/lib/promise/promise.h"
|
||||
#include "src/core/lib/surface/api_trace.h"
|
||||
#include "src/core/lib/surface/channel.h"
|
||||
#include "src/core/lib/surface/channel_stack_type.h"
|
||||
#include "src/core/lib/transport/call_fragments.h"
|
||||
#include "src/core/lib/transport/connectivity_state.h"
|
||||
#include "src/core/lib/transport/transport.h"
|
||||
|
||||
|
|
@ -72,7 +74,10 @@ LameClientFilter::State::State()
|
|||
: state_tracker("lame_client", GRPC_CHANNEL_SHUTDOWN) {}
|
||||
|
||||
ArenaPromise<ServerMetadataHandle> LameClientFilter::MakeCallPromise(
|
||||
CallArgs, NextPromiseFactory) {
|
||||
CallArgs args, NextPromiseFactory) {
|
||||
// TODO(ctiller): remove if check once promise_based_filter is removed (Close
|
||||
// is still needed)
|
||||
if (args.incoming_messages != nullptr) args.incoming_messages->Close();
|
||||
return Immediate(ServerMetadataHandle(error_));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include "src/core/lib/gprpp/sync.h"
|
||||
#include "src/core/lib/iomgr/error.h"
|
||||
#include "src/core/lib/promise/arena_promise.h"
|
||||
#include "src/core/lib/transport/call_fragments.h"
|
||||
#include "src/core/lib/transport/connectivity_state.h"
|
||||
#include "src/core/lib/transport/transport.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,45 @@
|
|||
// 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 <grpc/support/port_platform.h>
|
||||
|
||||
#include "src/core/lib/transport/call_fragments.h"
|
||||
|
||||
namespace grpc_core {
|
||||
|
||||
FragmentAllocator::Node* FragmentAllocator::AllocateNode() {
|
||||
if (free_list_ != nullptr) {
|
||||
Node* node = free_list_;
|
||||
free_list_ = free_list_->next_free;
|
||||
return node;
|
||||
}
|
||||
return static_cast<Node*>(GetContext<Arena>()->Alloc(sizeof(Node)));
|
||||
}
|
||||
|
||||
void FragmentAllocator::FreeNode(Node* node) {
|
||||
node->next_free = free_list_;
|
||||
free_list_ = node;
|
||||
}
|
||||
|
||||
void FragmentAllocator::Delete(grpc_metadata_batch* p) {
|
||||
p->~grpc_metadata_batch();
|
||||
FreeNode(reinterpret_cast<Node*>(p));
|
||||
}
|
||||
|
||||
void FragmentAllocator::Delete(Message* m) {
|
||||
m->~Message();
|
||||
FreeNode(reinterpret_cast<Node*>(m));
|
||||
}
|
||||
|
||||
} // namespace grpc_core
|
||||
|
|
@ -0,0 +1,232 @@
|
|||
// 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.
|
||||
|
||||
#ifndef GRPC_CORE_LIB_TRANSPORT_CALL_FRAGMENTS_H
|
||||
#define GRPC_CORE_LIB_TRANSPORT_CALL_FRAGMENTS_H
|
||||
|
||||
#include <grpc/support/port_platform.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <new>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/types/optional.h"
|
||||
|
||||
#include <grpc/status.h>
|
||||
|
||||
#include "src/core/lib/promise/context.h"
|
||||
#include "src/core/lib/resource_quota/arena.h"
|
||||
#include "src/core/lib/slice/slice.h"
|
||||
#include "src/core/lib/slice/slice_buffer.h"
|
||||
#include "src/core/lib/transport/metadata_batch.h"
|
||||
|
||||
namespace grpc_core {
|
||||
|
||||
// TODO(ctiller): eliminate once MetadataHandle is constructable directly.
|
||||
namespace promise_filter_detail {
|
||||
class BaseCallData;
|
||||
} // namespace promise_filter_detail
|
||||
|
||||
class FragmentAllocator;
|
||||
|
||||
// Small owned "handle" type to ensure one accessor at a time to metadata.
|
||||
// The focus here is to get promises to use the syntax we'd like - we'll
|
||||
// probably substitute some other smart pointer later.
|
||||
template <typename T>
|
||||
class FragmentHandle {
|
||||
public:
|
||||
FragmentHandle() = default;
|
||||
|
||||
FragmentHandle(const FragmentHandle&) = delete;
|
||||
FragmentHandle& operator=(const FragmentHandle&) = delete;
|
||||
|
||||
FragmentHandle(FragmentHandle&& other) noexcept
|
||||
: handle_(other.handle_),
|
||||
allocated_by_allocator_(other.allocated_by_allocator_) {
|
||||
other.handle_ = nullptr;
|
||||
other.allocated_by_allocator_ = false;
|
||||
}
|
||||
FragmentHandle& operator=(FragmentHandle&& other) noexcept {
|
||||
DestroyHandle();
|
||||
handle_ = other.handle_;
|
||||
allocated_by_allocator_ = other.allocated_by_allocator_;
|
||||
other.handle_ = nullptr;
|
||||
other.allocated_by_allocator_ = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
explicit FragmentHandle(const absl::Status& status);
|
||||
|
||||
~FragmentHandle() { DestroyHandle(); }
|
||||
|
||||
T* operator->() const { return handle_; }
|
||||
bool has_value() const { return handle_ != nullptr; }
|
||||
T* get() const { return handle_; }
|
||||
void reset() { *this = FragmentHandle(); }
|
||||
|
||||
static FragmentHandle TestOnlyWrap(T* p) { return FragmentHandle(p, false); }
|
||||
|
||||
private:
|
||||
// We restrict access to construction from a pointer to limit the number of
|
||||
// cases that need dealing with as this code evolves.
|
||||
friend class promise_filter_detail::BaseCallData;
|
||||
friend class FragmentAllocator;
|
||||
|
||||
explicit FragmentHandle(T* handle, bool allocated_by_allocator)
|
||||
: handle_(handle), allocated_by_allocator_(allocated_by_allocator) {}
|
||||
|
||||
void DestroyHandle();
|
||||
|
||||
T* Unwrap() {
|
||||
T* result = handle_;
|
||||
handle_ = nullptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
T* handle_ = nullptr;
|
||||
// TODO(ctiller): remove this once promise_based_filter goes away.
|
||||
// This bit determines whether the pointer is allocated by a metadata
|
||||
// allocator or some other system. If it's held by a metadata allocator, we'll
|
||||
// release it back when we're done with it.
|
||||
bool allocated_by_allocator_ = false;
|
||||
};
|
||||
|
||||
// Server metadata type
|
||||
// TODO(ctiller): This should be a bespoke instance of MetadataMap<>
|
||||
using ServerMetadata = grpc_metadata_batch;
|
||||
using ServerMetadataHandle = FragmentHandle<ServerMetadata>;
|
||||
|
||||
// Client initial metadata type
|
||||
// TODO(ctiller): This should be a bespoke instance of MetadataMap<>
|
||||
using ClientMetadata = grpc_metadata_batch;
|
||||
using ClientMetadataHandle = FragmentHandle<ClientMetadata>;
|
||||
|
||||
class Message {
|
||||
public:
|
||||
Message() = default;
|
||||
~Message() = default;
|
||||
Message(SliceBuffer payload, uint32_t flags)
|
||||
: payload_(std::move(payload)), flags_(flags) {}
|
||||
Message(const Message&) = delete;
|
||||
Message& operator=(const Message&) = delete;
|
||||
|
||||
uint32_t flags() const { return flags_; }
|
||||
SliceBuffer* payload() { return &payload_; }
|
||||
const SliceBuffer* payload() const { return &payload_; }
|
||||
|
||||
private:
|
||||
SliceBuffer payload_;
|
||||
uint32_t flags_ = 0;
|
||||
};
|
||||
|
||||
using MessageHandle = FragmentHandle<Message>;
|
||||
|
||||
// Ok/not-ok check for trailing metadata, so that it can be used as result types
|
||||
// for TrySeq.
|
||||
inline bool IsStatusOk(const ServerMetadataHandle& m) {
|
||||
return m->get(GrpcStatusMetadata()).value_or(GRPC_STATUS_UNKNOWN) ==
|
||||
GRPC_STATUS_OK;
|
||||
}
|
||||
|
||||
// Within a call arena we need metadata at least four times - (client,server) x
|
||||
// (initial,trailing), and possibly more for early returning promises.
|
||||
// Since we often don't need these *simultaneously*, we can save memory by
|
||||
// allocating/releasing them.
|
||||
// We'd still like the memory to be part of the arena though, so this type
|
||||
// creates a small free list of metadata objects and a central (call context)
|
||||
// based place to create/destroy them.
|
||||
class FragmentAllocator {
|
||||
public:
|
||||
FragmentAllocator() = default;
|
||||
~FragmentAllocator() = default;
|
||||
FragmentAllocator(const FragmentAllocator&) = delete;
|
||||
FragmentAllocator& operator=(const FragmentAllocator&) = delete;
|
||||
|
||||
ClientMetadataHandle MakeClientMetadata() {
|
||||
auto* node = AllocateNode();
|
||||
// TODO(ctiller): once we finish the promise transition, have metadata map
|
||||
// know about arena contexts and allocate directly from there.
|
||||
// (we could do so before, but there's enough places where we don't have a
|
||||
// promise context up that it's too much whackamole)
|
||||
new (&node->batch) ClientMetadata(GetContext<Arena>());
|
||||
return ClientMetadataHandle(&node->batch, true);
|
||||
}
|
||||
|
||||
ServerMetadataHandle MakeServerMetadata() { return MakeClientMetadata(); }
|
||||
|
||||
template <typename... Args>
|
||||
MessageHandle MakeMessage(Args&&... args) {
|
||||
auto* node = AllocateNode();
|
||||
new (&node->message) Message(std::forward<Args>(args)...);
|
||||
return MessageHandle(&node->message, true);
|
||||
}
|
||||
|
||||
private:
|
||||
union Node {
|
||||
Node* next_free;
|
||||
grpc_metadata_batch batch;
|
||||
Message message;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
friend class FragmentHandle;
|
||||
|
||||
void Delete(grpc_metadata_batch* p);
|
||||
void Delete(Message* m);
|
||||
|
||||
Node* AllocateNode();
|
||||
void FreeNode(Node* node);
|
||||
|
||||
Node* free_list_ = nullptr;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ContextType<FragmentAllocator> {};
|
||||
|
||||
template <typename T>
|
||||
FragmentHandle<T>::FragmentHandle(const absl::Status& status) {
|
||||
// TODO(ctiller): currently we guarantee that MetadataAllocator is only
|
||||
// present for promise based calls, and if we're using promise_based_filter
|
||||
// it's not present. If we're in a promise based call, the correct thing is to
|
||||
// use the metadata allocator to track the memory we need. If we're not, we
|
||||
// need to do the hacky thing promise_based_filter does.
|
||||
// This all goes away when promise_based_filter goes away, and this code will
|
||||
// just assume there's an allocator present and move forward.
|
||||
if (auto* allocator = GetContext<FragmentAllocator>()) {
|
||||
handle_ = nullptr;
|
||||
allocated_by_allocator_ = false;
|
||||
*this = allocator->MakeServerMetadata();
|
||||
} else {
|
||||
handle_ = GetContext<Arena>()->New<T>(GetContext<Arena>());
|
||||
allocated_by_allocator_ = false;
|
||||
}
|
||||
handle_->Set(GrpcStatusMetadata(),
|
||||
static_cast<grpc_status_code>(status.code()));
|
||||
if (status.ok()) return;
|
||||
handle_->Set(GrpcMessageMetadata(),
|
||||
Slice::FromCopiedString(status.message()));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void FragmentHandle<T>::DestroyHandle() {
|
||||
if (allocated_by_allocator_) {
|
||||
GetContext<FragmentAllocator>()->Delete(handle_);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace grpc_core
|
||||
|
||||
#endif // GRPC_CORE_LIB_TRANSPORT_CALL_FRAGMENTS_H
|
||||
|
|
@ -387,6 +387,14 @@ struct GrpcStatusContext {
|
|||
static const std::string& DisplayValue(const std::string& x);
|
||||
};
|
||||
|
||||
// Annotation added by a transport to note that the status came from the wire.
|
||||
struct GrpcStatusFromWire {
|
||||
static absl::string_view DebugKey() { return "GrpcStatusFromWire"; }
|
||||
static constexpr bool kRepeatable = false;
|
||||
using ValueType = bool;
|
||||
static absl::string_view DisplayValue(bool x) { return x ? "true" : "false"; }
|
||||
};
|
||||
|
||||
// Annotation added by client surface code to denote wait-for-ready state
|
||||
struct WaitForReady {
|
||||
struct ValueType {
|
||||
|
|
@ -645,6 +653,13 @@ struct AdaptDisplayValueToLog<const std::string&> {
|
|||
static std::string ToString(const std::string& value) { return value; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct AdaptDisplayValueToLog<absl::string_view> {
|
||||
static std::string ToString(absl::string_view value) {
|
||||
return std::string(value);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct AdaptDisplayValueToLog<Slice> {
|
||||
static std::string ToString(Slice value) {
|
||||
|
|
@ -1301,7 +1316,8 @@ using grpc_metadata_batch_base = grpc_core::MetadataMap<
|
|||
grpc_core::LbCostBinMetadata, grpc_core::LbTokenMetadata,
|
||||
// Non-encodable things
|
||||
grpc_core::GrpcStreamNetworkState, grpc_core::PeerString,
|
||||
grpc_core::GrpcStatusContext, grpc_core::WaitForReady>;
|
||||
grpc_core::GrpcStatusContext, grpc_core::GrpcStatusFromWire,
|
||||
grpc_core::WaitForReady>;
|
||||
|
||||
struct grpc_metadata_batch : public grpc_metadata_batch_base {
|
||||
using grpc_metadata_batch_base::grpc_metadata_batch_base;
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
|
||||
#include <new>
|
||||
|
||||
#include "absl/status/status.h"
|
||||
|
||||
#include "src/core/lib/gpr/alloc.h"
|
||||
#include "src/core/lib/iomgr/exec_ctx.h"
|
||||
#include "src/core/lib/iomgr/executor.h"
|
||||
|
|
@ -183,6 +185,36 @@ void grpc_transport_stream_op_batch_queue_finish_with_failure(
|
|||
}
|
||||
}
|
||||
|
||||
void grpc_transport_stream_op_batch_finish_with_failure_from_transport(
|
||||
grpc_transport_stream_op_batch* batch, grpc_error_handle error) {
|
||||
if (batch->cancel_stream) {
|
||||
GRPC_ERROR_UNREF(batch->payload->cancel_stream.cancel_error);
|
||||
}
|
||||
// Construct a list of closures to execute.
|
||||
if (batch->recv_initial_metadata) {
|
||||
grpc_core::ExecCtx::Run(
|
||||
DEBUG_LOCATION,
|
||||
batch->payload->recv_initial_metadata.recv_initial_metadata_ready,
|
||||
GRPC_ERROR_REF(error));
|
||||
}
|
||||
if (batch->recv_message) {
|
||||
grpc_core::ExecCtx::Run(DEBUG_LOCATION,
|
||||
batch->payload->recv_message.recv_message_ready,
|
||||
GRPC_ERROR_REF(error));
|
||||
}
|
||||
if (batch->recv_trailing_metadata) {
|
||||
grpc_core::ExecCtx::Run(
|
||||
DEBUG_LOCATION,
|
||||
batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready,
|
||||
GRPC_ERROR_REF(error));
|
||||
}
|
||||
if (batch->on_complete != nullptr) {
|
||||
grpc_core::ExecCtx::Run(DEBUG_LOCATION, batch->on_complete,
|
||||
GRPC_ERROR_REF(error));
|
||||
}
|
||||
GRPC_ERROR_UNREF(error);
|
||||
}
|
||||
|
||||
struct made_transport_op {
|
||||
grpc_closure outer_on_complete;
|
||||
grpc_closure* inner_on_complete = nullptr;
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@
|
|||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/types/optional.h"
|
||||
|
||||
|
|
@ -50,11 +49,11 @@
|
|||
#include "src/core/lib/iomgr/iomgr_fwd.h"
|
||||
#include "src/core/lib/iomgr/polling_entity.h"
|
||||
#include "src/core/lib/promise/arena_promise.h"
|
||||
#include "src/core/lib/promise/context.h"
|
||||
#include "src/core/lib/promise/latch.h"
|
||||
#include "src/core/lib/promise/pipe.h"
|
||||
#include "src/core/lib/resource_quota/arena.h"
|
||||
#include "src/core/lib/slice/slice.h"
|
||||
#include "src/core/lib/slice/slice_buffer.h"
|
||||
#include "src/core/lib/transport/call_fragments.h"
|
||||
#include "src/core/lib/transport/connectivity_state.h"
|
||||
#include "src/core/lib/transport/metadata_batch.h"
|
||||
#include "src/core/lib/transport/transport_fwd.h"
|
||||
|
|
@ -81,83 +80,21 @@ struct grpc_transport_stream_op_batch_payload;
|
|||
(GRPC_WRITE_INTERNAL_COMPRESS | GRPC_WRITE_INTERNAL_TEST_ONLY_WAS_COMPRESSED)
|
||||
|
||||
namespace grpc_core {
|
||||
// TODO(ctiller): eliminate once MetadataHandle is constructable directly.
|
||||
namespace promise_filter_detail {
|
||||
class BaseCallData;
|
||||
}
|
||||
|
||||
// Small unowned "handle" type to ensure one accessor at a time to metadata.
|
||||
// The focus here is to get promises to use the syntax we'd like - we'll
|
||||
// probably substitute some other smart pointer later.
|
||||
template <typename T>
|
||||
class MetadataHandle {
|
||||
public:
|
||||
MetadataHandle() = default;
|
||||
|
||||
MetadataHandle(const MetadataHandle&) = delete;
|
||||
MetadataHandle& operator=(const MetadataHandle&) = delete;
|
||||
|
||||
MetadataHandle(MetadataHandle&& other) noexcept : handle_(other.handle_) {
|
||||
other.handle_ = nullptr;
|
||||
}
|
||||
MetadataHandle& operator=(MetadataHandle&& other) noexcept {
|
||||
handle_ = other.handle_;
|
||||
other.handle_ = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
explicit MetadataHandle(const absl::Status& status) {
|
||||
handle_ = GetContext<Arena>()->New<T>(GetContext<Arena>());
|
||||
handle_->Set(GrpcStatusMetadata(),
|
||||
static_cast<grpc_status_code>(status.code()));
|
||||
if (status.ok()) return;
|
||||
handle_->Set(GrpcMessageMetadata(),
|
||||
Slice::FromCopiedString(status.message()));
|
||||
}
|
||||
|
||||
T* operator->() const { return handle_; }
|
||||
bool has_value() const { return handle_ != nullptr; }
|
||||
T* get() const { return handle_; }
|
||||
|
||||
static MetadataHandle TestOnlyWrap(T* p) { return MetadataHandle(p); }
|
||||
|
||||
private:
|
||||
friend class promise_filter_detail::BaseCallData;
|
||||
|
||||
explicit MetadataHandle(T* handle) : handle_(handle) {}
|
||||
T* Unwrap() {
|
||||
T* result = handle_;
|
||||
handle_ = nullptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
T* handle_ = nullptr;
|
||||
};
|
||||
|
||||
// Server metadata type
|
||||
// TODO(ctiller): This should be a bespoke instance of MetadataMap<>
|
||||
using ServerMetadata = grpc_metadata_batch;
|
||||
using ServerMetadataHandle = MetadataHandle<ServerMetadata>;
|
||||
|
||||
// Ok/not-ok check for trailing metadata, so that it can be used as result types
|
||||
// for TrySeq.
|
||||
inline bool IsStatusOk(const ServerMetadataHandle& m) {
|
||||
return m->get(GrpcStatusMetadata()).value_or(GRPC_STATUS_UNKNOWN) ==
|
||||
GRPC_STATUS_OK;
|
||||
}
|
||||
|
||||
// Client initial metadata type
|
||||
// TODO(ctiller): This should be a bespoke instance of MetadataMap<>
|
||||
using ClientMetadata = grpc_metadata_batch;
|
||||
using ClientMetadataHandle = MetadataHandle<ClientMetadata>;
|
||||
|
||||
// Server initial metadata type
|
||||
// TODO(ctiller): This should be a bespoke instance of MetadataMap<>
|
||||
using ServerMetadataHandle = MetadataHandle<grpc_metadata_batch>;
|
||||
|
||||
struct CallArgs {
|
||||
// Initial metadata from the client to the server.
|
||||
// During promise setup this can be manipulated by filters (and then
|
||||
// passed on to the next filter).
|
||||
ClientMetadataHandle client_initial_metadata;
|
||||
// Initial metadata from the server to the client.
|
||||
// Set once when it's available.
|
||||
// During promise setup filters can substitute their own latch for this
|
||||
// and consequently intercept the sent value and mutate/observe it.
|
||||
Latch<ServerMetadata*>* server_initial_metadata;
|
||||
// Messages travelling from the application to the transport.
|
||||
PipeReceiver<MessageHandle>* outgoing_messages;
|
||||
// Messages travelling from the transport to the application.
|
||||
PipeSender<MessageHandle>* incoming_messages;
|
||||
};
|
||||
|
||||
using NextPromiseFactory =
|
||||
|
|
@ -538,6 +475,10 @@ void grpc_transport_stream_op_batch_finish_with_failure(
|
|||
void grpc_transport_stream_op_batch_queue_finish_with_failure(
|
||||
grpc_transport_stream_op_batch* batch, grpc_error_handle error,
|
||||
grpc_core::CallCombinerClosureList* closures);
|
||||
// Fail a batch from within the transport (i.e. without the activity lock/call
|
||||
// combiner taken).
|
||||
void grpc_transport_stream_op_batch_finish_with_failure_from_transport(
|
||||
grpc_transport_stream_op_batch* batch, grpc_error_handle error);
|
||||
|
||||
std::string grpc_transport_stream_op_batch_string(
|
||||
grpc_transport_stream_op_batch* op);
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "src/core/lib/iomgr/iomgr_fwd.h"
|
||||
#include "src/core/lib/promise/arena_promise.h"
|
||||
#include "src/core/lib/resource_quota/arena.h"
|
||||
#include "src/core/lib/transport/call_fragments.h"
|
||||
#include "src/core/lib/transport/transport.h"
|
||||
#include "src/core/lib/transport/transport_fwd.h"
|
||||
|
||||
|
|
@ -56,7 +57,7 @@ typedef struct grpc_transport_vtable {
|
|||
There is an on-going migration to move all filters to providing this, and
|
||||
then to drop perform_stream_op. */
|
||||
grpc_core::ArenaPromise<grpc_core::ServerMetadataHandle> (*make_call_promise)(
|
||||
grpc_transport* self, grpc_core::ClientMetadataHandle initial_metadata);
|
||||
grpc_transport* self, grpc_core::CallArgs call_args);
|
||||
|
||||
/* implementation of grpc_transport_set_pollset */
|
||||
void (*set_pollset)(grpc_transport* self, grpc_stream* stream,
|
||||
|
|
|
|||
|
|
@ -685,6 +685,7 @@ CORE_SOURCE_FILES = [
|
|||
'src/core/lib/surface/call.cc',
|
||||
'src/core/lib/surface/call_details.cc',
|
||||
'src/core/lib/surface/call_log_batch.cc',
|
||||
'src/core/lib/surface/call_trace.cc',
|
||||
'src/core/lib/surface/channel.cc',
|
||||
'src/core/lib/surface/channel_init.cc',
|
||||
'src/core/lib/surface/channel_ping.cc',
|
||||
|
|
@ -700,6 +701,7 @@ CORE_SOURCE_FILES = [
|
|||
'src/core/lib/surface/validate_metadata.cc',
|
||||
'src/core/lib/surface/version.cc',
|
||||
'src/core/lib/transport/bdp_estimator.cc',
|
||||
'src/core/lib/transport/call_fragments.cc',
|
||||
'src/core/lib/transport/connectivity_state.cc',
|
||||
'src/core/lib/transport/error_utils.cc',
|
||||
'src/core/lib/transport/handshaker.cc',
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ typedef struct grpc_end2end_test_config grpc_end2end_test_config;
|
|||
#define FEATURE_MASK_DOES_NOT_SUPPORT_NETWORK_STATUS_CHANGE 256
|
||||
#define FEATURE_MASK_SUPPORTS_WORKAROUNDS 512
|
||||
#define FEATURE_MASK_DOES_NOT_SUPPORT_CLIENT_HANDSHAKE_COMPLETE_FIRST 1024
|
||||
#define FEATURE_MASK_DOES_NOT_SUPPORT_DEADLINES 2048
|
||||
|
||||
#define FAIL_AUTH_CHECK_SERVER_ARG_NAME "fail_auth_check"
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@
|
|||
#include <grpc/support/log.h>
|
||||
|
||||
#include "src/core/lib/channel/channel_args.h"
|
||||
#include "src/core/lib/gprpp/env.h"
|
||||
#include "src/core/lib/gprpp/host_port.h"
|
||||
#include "test/core/end2end/end2end_tests.h"
|
||||
#include "test/core/end2end/fixtures/http_proxy_fixture.h"
|
||||
|
|
@ -75,9 +74,12 @@ void chttp2_init_client_fullstack(grpc_end2end_test_fixture* f,
|
|||
absl::StrFormat("http://%s@%s", proxy_auth_str,
|
||||
grpc_end2end_http_proxy_get_proxy_name(ffd->proxy));
|
||||
}
|
||||
grpc_core::SetEnv("http_proxy", proxy_uri.c_str());
|
||||
grpc_channel_credentials* creds = grpc_insecure_credentials_create();
|
||||
f->client = grpc_channel_create(ffd->server_addr.c_str(), creds, client_args);
|
||||
f->client = grpc_channel_create(ffd->server_addr.c_str(), creds,
|
||||
grpc_core::ChannelArgs::FromC(client_args)
|
||||
.Set(GRPC_ARG_HTTP_PROXY, proxy_uri)
|
||||
.ToC()
|
||||
.get());
|
||||
grpc_channel_credentials_release(creds);
|
||||
GPR_ASSERT(f->client);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,176 @@
|
|||
/*
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/status/statusor.h"
|
||||
|
||||
#include <grpc/grpc.h>
|
||||
#include <grpc/status.h>
|
||||
#include <grpc/support/alloc.h>
|
||||
#include <grpc/support/log.h>
|
||||
|
||||
#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
|
||||
#include "src/core/lib/channel/channel_args.h"
|
||||
#include "src/core/lib/channel/channel_args_preconditioning.h"
|
||||
#include "src/core/lib/channel/channelz.h"
|
||||
#include "src/core/lib/config/core_configuration.h"
|
||||
#include "src/core/lib/gprpp/ref_counted_ptr.h"
|
||||
#include "src/core/lib/iomgr/endpoint.h"
|
||||
#include "src/core/lib/iomgr/endpoint_pair.h"
|
||||
#include "src/core/lib/iomgr/error.h"
|
||||
#include "src/core/lib/iomgr/exec_ctx.h"
|
||||
#include "src/core/lib/surface/channel.h"
|
||||
#include "src/core/lib/surface/channel_stack_type.h"
|
||||
#include "src/core/lib/surface/completion_queue.h"
|
||||
#include "src/core/lib/surface/server.h"
|
||||
#include "src/core/lib/transport/transport.h"
|
||||
#include "src/core/lib/transport/transport_fwd.h"
|
||||
#include "test/core/end2end/end2end_tests.h"
|
||||
#include "test/core/util/test_config.h"
|
||||
|
||||
/* chttp2 transport that is immediately available (used for testing
|
||||
connected_channel without a client_channel) */
|
||||
|
||||
struct custom_fixture_data {
|
||||
grpc_endpoint_pair ep;
|
||||
};
|
||||
|
||||
static void server_setup_transport(void* ts, grpc_transport* transport) {
|
||||
grpc_end2end_test_fixture* f = static_cast<grpc_end2end_test_fixture*>(ts);
|
||||
grpc_core::ExecCtx exec_ctx;
|
||||
custom_fixture_data* fixture_data =
|
||||
static_cast<custom_fixture_data*>(f->fixture_data);
|
||||
grpc_endpoint_add_to_pollset(fixture_data->ep.server, grpc_cq_pollset(f->cq));
|
||||
grpc_core::Server* core_server = grpc_core::Server::FromC(f->server);
|
||||
grpc_error_handle error = core_server->SetupTransport(
|
||||
transport, nullptr, core_server->channel_args(), nullptr);
|
||||
if (error == GRPC_ERROR_NONE) {
|
||||
grpc_chttp2_transport_start_reading(transport, nullptr, nullptr, nullptr);
|
||||
} else {
|
||||
GRPC_ERROR_UNREF(error);
|
||||
grpc_transport_destroy(transport);
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
grpc_end2end_test_fixture* f;
|
||||
const grpc_channel_args* client_args;
|
||||
} sp_client_setup;
|
||||
|
||||
static void client_setup_transport(void* ts, grpc_transport* transport) {
|
||||
sp_client_setup* cs = static_cast<sp_client_setup*>(ts);
|
||||
|
||||
auto args = grpc_core::ChannelArgs::FromC(cs->client_args)
|
||||
.Set(GRPC_ARG_MINIMAL_STACK, true)
|
||||
.Set(GRPC_ARG_DEFAULT_AUTHORITY, "test-authority");
|
||||
auto channel = grpc_core::Channel::Create(
|
||||
"socketpair-target", args, GRPC_CLIENT_DIRECT_CHANNEL, transport);
|
||||
if (channel.ok()) {
|
||||
cs->f->client = channel->release()->c_ptr();
|
||||
grpc_chttp2_transport_start_reading(transport, nullptr, nullptr, nullptr);
|
||||
} else {
|
||||
cs->f->client = grpc_lame_client_channel_create(
|
||||
nullptr, static_cast<grpc_status_code>(channel.status().code()),
|
||||
"lame channel");
|
||||
grpc_transport_destroy(transport);
|
||||
}
|
||||
}
|
||||
|
||||
static grpc_end2end_test_fixture chttp2_create_fixture_socketpair(
|
||||
const grpc_channel_args* /*client_args*/,
|
||||
const grpc_channel_args* /*server_args*/) {
|
||||
custom_fixture_data* fixture_data = static_cast<custom_fixture_data*>(
|
||||
gpr_malloc(sizeof(custom_fixture_data)));
|
||||
grpc_end2end_test_fixture f;
|
||||
memset(&f, 0, sizeof(f));
|
||||
f.fixture_data = fixture_data;
|
||||
f.cq = grpc_completion_queue_create_for_next(nullptr);
|
||||
fixture_data->ep = grpc_iomgr_create_endpoint_pair("fixture", nullptr);
|
||||
return f;
|
||||
}
|
||||
|
||||
static void chttp2_init_client_socketpair(
|
||||
grpc_end2end_test_fixture* f, const grpc_channel_args* client_args) {
|
||||
grpc_core::ExecCtx exec_ctx;
|
||||
auto* fixture_data = static_cast<custom_fixture_data*>(f->fixture_data);
|
||||
grpc_transport* transport;
|
||||
sp_client_setup cs;
|
||||
auto final_client_args = grpc_core::CoreConfiguration::Get()
|
||||
.channel_args_preconditioning()
|
||||
.PreconditionChannelArgs(client_args)
|
||||
.Set(GRPC_ARG_MINIMAL_STACK, true);
|
||||
auto c_client_args = final_client_args.ToC();
|
||||
cs.client_args = c_client_args.get();
|
||||
cs.f = f;
|
||||
transport = grpc_create_chttp2_transport(final_client_args,
|
||||
fixture_data->ep.client, true);
|
||||
client_setup_transport(&cs, transport);
|
||||
GPR_ASSERT(f->client);
|
||||
}
|
||||
|
||||
static void chttp2_init_server_socketpair(
|
||||
grpc_end2end_test_fixture* f, const grpc_channel_args* server_args) {
|
||||
grpc_core::ExecCtx exec_ctx;
|
||||
auto* fixture_data = static_cast<custom_fixture_data*>(f->fixture_data);
|
||||
grpc_transport* transport;
|
||||
GPR_ASSERT(!f->server);
|
||||
f->server = grpc_server_create(server_args, nullptr);
|
||||
grpc_server_register_completion_queue(f->server, f->cq, nullptr);
|
||||
grpc_server_start(f->server);
|
||||
auto final_server_args = grpc_core::CoreConfiguration::Get()
|
||||
.channel_args_preconditioning()
|
||||
.PreconditionChannelArgs(server_args)
|
||||
.Set(GRPC_ARG_MINIMAL_STACK, true);
|
||||
transport = grpc_create_chttp2_transport(final_server_args,
|
||||
fixture_data->ep.server, false);
|
||||
server_setup_transport(f, transport);
|
||||
}
|
||||
|
||||
static void chttp2_tear_down_socketpair(grpc_end2end_test_fixture* f) {
|
||||
grpc_core::ExecCtx exec_ctx;
|
||||
gpr_free(f->fixture_data);
|
||||
}
|
||||
|
||||
/* All test configurations */
|
||||
static grpc_end2end_test_config configs[] = {
|
||||
{"chttp2/socketpair+minstack",
|
||||
FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER |
|
||||
FEATURE_MASK_DOES_NOT_SUPPORT_DEADLINES,
|
||||
nullptr, chttp2_create_fixture_socketpair, chttp2_init_client_socketpair,
|
||||
chttp2_init_server_socketpair, chttp2_tear_down_socketpair},
|
||||
};
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
size_t i;
|
||||
|
||||
grpc::testing::TestEnvironment env(&argc, argv);
|
||||
grpc_end2end_tests_pre_init();
|
||||
grpc_init();
|
||||
|
||||
for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) {
|
||||
grpc_end2end_tests(argc, argv, configs[i]);
|
||||
}
|
||||
|
||||
grpc_shutdown();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -33,6 +33,7 @@ def _fixture_options(
|
|||
is_inproc = False,
|
||||
is_1byte = False,
|
||||
is_http2 = True,
|
||||
is_minstack = False,
|
||||
supports_proxy_auth = False,
|
||||
supports_write_buffering = True,
|
||||
client_channel = True,
|
||||
|
|
@ -51,6 +52,7 @@ def _fixture_options(
|
|||
is_inproc = is_inproc,
|
||||
is_1byte = is_1byte,
|
||||
is_http2 = is_http2,
|
||||
is_minstack = is_minstack,
|
||||
supports_proxy_auth = supports_proxy_auth,
|
||||
supports_write_buffering = supports_write_buffering,
|
||||
client_channel = client_channel,
|
||||
|
|
@ -95,6 +97,12 @@ END2END_FIXTURES = {
|
|||
dns_resolver = False,
|
||||
client_channel = False,
|
||||
),
|
||||
"h2_sockpair_with_minstack": _fixture_options(
|
||||
fullstack = False,
|
||||
dns_resolver = False,
|
||||
client_channel = False,
|
||||
is_minstack = True,
|
||||
),
|
||||
"h2_sockpair+trace": _fixture_options(
|
||||
fullstack = False,
|
||||
dns_resolver = False,
|
||||
|
|
@ -165,6 +173,7 @@ def _test_options(
|
|||
traceable = False,
|
||||
exclude_inproc = False,
|
||||
exclude_1byte = False,
|
||||
exclude_minstack = False,
|
||||
needs_http2 = False,
|
||||
needs_proxy_auth = False,
|
||||
needs_write_buffering = False,
|
||||
|
|
@ -182,6 +191,7 @@ def _test_options(
|
|||
traceable = traceable,
|
||||
exclude_inproc = exclude_inproc,
|
||||
exclude_1byte = exclude_1byte,
|
||||
exclude_minstack = exclude_minstack,
|
||||
needs_http2 = needs_http2,
|
||||
needs_proxy_auth = needs_proxy_auth,
|
||||
needs_write_buffering = needs_write_buffering,
|
||||
|
|
@ -217,7 +227,7 @@ END2END_TESTS = {
|
|||
"cancel_in_a_vacuum": _test_options(),
|
||||
"cancel_with_status": _test_options(),
|
||||
"client_streaming": _test_options(),
|
||||
"compressed_payload": _test_options(proxyable = False, exclude_inproc = True),
|
||||
"compressed_payload": _test_options(proxyable = False, exclude_inproc = True, exclude_minstack = True),
|
||||
"connectivity": _test_options(
|
||||
needs_fullstack = True,
|
||||
needs_names = True,
|
||||
|
|
@ -249,11 +259,12 @@ END2END_TESTS = {
|
|||
"max_concurrent_streams": _test_options(
|
||||
proxyable = False,
|
||||
exclude_inproc = True,
|
||||
exclude_minstack = True,
|
||||
),
|
||||
"max_connection_age": _test_options(exclude_inproc = True),
|
||||
"max_connection_idle": _test_options(needs_fullstack = True, proxyable = False),
|
||||
"max_message_length": _test_options(),
|
||||
"negative_deadline": _test_options(),
|
||||
"max_message_length": _test_options(exclude_minstack = True),
|
||||
"negative_deadline": _test_options(exclude_minstack = True),
|
||||
"no_error_on_hotpath": _test_options(proxyable = False),
|
||||
"no_logging": _test_options(traceable = False),
|
||||
"no_op": _test_options(),
|
||||
|
|
@ -389,6 +400,9 @@ def _compatible(fopt, topt):
|
|||
if topt.exclude_1byte:
|
||||
if fopt.is_1byte:
|
||||
return False
|
||||
if topt.exclude_minstack:
|
||||
if fopt.is_minstack:
|
||||
return False
|
||||
if topt.needs_http2:
|
||||
if not fopt.is_http2:
|
||||
return False
|
||||
|
|
|
|||
|
|
@ -257,6 +257,10 @@ void cancel_after_accept(grpc_end2end_test_config config) {
|
|||
unsigned i;
|
||||
|
||||
for (i = 0; i < GPR_ARRAY_SIZE(cancellation_modes); i++) {
|
||||
if (config.feature_mask & FEATURE_MASK_DOES_NOT_SUPPORT_DEADLINES &&
|
||||
cancellation_modes[i].expect_status == GRPC_STATUS_DEADLINE_EXCEEDED) {
|
||||
continue;
|
||||
}
|
||||
test_cancel_after_accept(config, cancellation_modes[i],
|
||||
false /* use_service_config */);
|
||||
if (config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL &&
|
||||
|
|
|
|||
|
|
@ -231,6 +231,10 @@ void cancel_after_client_done(grpc_end2end_test_config config) {
|
|||
unsigned i;
|
||||
|
||||
for (i = 0; i < GPR_ARRAY_SIZE(cancellation_modes); i++) {
|
||||
if (config.feature_mask & FEATURE_MASK_DOES_NOT_SUPPORT_DEADLINES &&
|
||||
cancellation_modes[i].expect_status == GRPC_STATUS_DEADLINE_EXCEEDED) {
|
||||
continue;
|
||||
}
|
||||
test_cancel_after_accept_and_writes_closed(config, cancellation_modes[i]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -187,6 +187,11 @@ void cancel_after_invoke(grpc_end2end_test_config config) {
|
|||
|
||||
for (j = 3; j < 6; j++) {
|
||||
for (i = 0; i < GPR_ARRAY_SIZE(cancellation_modes); i++) {
|
||||
if (config.feature_mask & FEATURE_MASK_DOES_NOT_SUPPORT_DEADLINES &&
|
||||
cancellation_modes[i].expect_status ==
|
||||
GRPC_STATUS_DEADLINE_EXCEEDED) {
|
||||
continue;
|
||||
}
|
||||
test_cancel_after_invoke(config, cancellation_modes[i], j);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -292,6 +292,10 @@ void cancel_after_round_trip(grpc_end2end_test_config config) {
|
|||
unsigned i;
|
||||
|
||||
for (i = 0; i < GPR_ARRAY_SIZE(cancellation_modes); i++) {
|
||||
if (config.feature_mask & FEATURE_MASK_DOES_NOT_SUPPORT_DEADLINES &&
|
||||
cancellation_modes[i].expect_status == GRPC_STATUS_DEADLINE_EXCEEDED) {
|
||||
continue;
|
||||
}
|
||||
test_cancel_after_round_trip(config, cancellation_modes[i],
|
||||
false /* use_service_config */);
|
||||
if (config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL &&
|
||||
|
|
|
|||
|
|
@ -160,7 +160,11 @@ static void test_cancel_before_invoke(grpc_end2end_test_config config,
|
|||
error = grpc_call_start_batch(c, ops, test_ops, tag(1), nullptr);
|
||||
GPR_ASSERT(GRPC_CALL_OK == error);
|
||||
|
||||
cqv.Expect(tag(1), true);
|
||||
// Filter based stack tracks this as a failed op, promise based stack tracks
|
||||
// it as a successful one with a failed request. The latter probably makes
|
||||
// more sense, but since we can't tell from outside which case we have we
|
||||
// accept either.
|
||||
cqv.Expect(tag(1), grpc_core::CqVerifier::AnyStatus());
|
||||
cqv.Verify();
|
||||
|
||||
GPR_ASSERT(status == GRPC_STATUS_CANCELLED);
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <grpc/grpc.h>
|
||||
#include <grpc/impl/codegen/propagation_bits.h>
|
||||
#include <grpc/slice.h>
|
||||
|
|
@ -28,6 +30,7 @@
|
|||
#include <grpc/support/log.h>
|
||||
#include <grpc/support/string_util.h>
|
||||
|
||||
#include "src/core/lib/surface/event_string.h"
|
||||
#include "test/core/end2end/cq_verifier.h"
|
||||
#include "test/core/end2end/end2end_tests.h"
|
||||
#include "test/core/util/test_config.h"
|
||||
|
|
@ -68,6 +71,7 @@ static void shutdown_server(grpc_end2end_test_fixture* f) {
|
|||
grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
|
||||
grpc_event ev = grpc_completion_queue_next(
|
||||
f->cq, grpc_timeout_seconds_to_deadline(5), nullptr);
|
||||
gpr_log(GPR_DEBUG, "shutdown event: %s", grpc_event_string(&ev).c_str());
|
||||
GPR_ASSERT(ev.type == GRPC_OP_COMPLETE);
|
||||
GPR_ASSERT(ev.tag == tag(1000));
|
||||
grpc_server_destroy(f->server);
|
||||
|
|
|
|||
|
|
@ -19,6 +19,10 @@
|
|||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "absl/strings/str_cat.h"
|
||||
|
||||
#include <grpc/byte_buffer.h>
|
||||
#include <grpc/grpc.h>
|
||||
#include <grpc/impl/codegen/propagation_bits.h>
|
||||
|
|
@ -94,8 +98,18 @@ static void test_invoke_request_with_flags(
|
|||
grpc_slice_from_copied_string("hello world");
|
||||
grpc_byte_buffer* request_payload =
|
||||
grpc_raw_byte_buffer_create(&request_payload_slice, 1);
|
||||
grpc_end2end_test_fixture f =
|
||||
begin_test(config, "test_invoke_request_with_flags", nullptr, nullptr);
|
||||
grpc_end2end_test_fixture f = begin_test(
|
||||
config,
|
||||
absl::StrCat("test_invoke_request_with_flags[",
|
||||
absl::Hex(flags_for_op[GRPC_OP_SEND_INITIAL_METADATA]), ",",
|
||||
absl::Hex(flags_for_op[GRPC_OP_SEND_MESSAGE]), ",",
|
||||
absl::Hex(flags_for_op[GRPC_OP_SEND_CLOSE_FROM_CLIENT]), ",",
|
||||
absl::Hex(flags_for_op[GRPC_OP_RECV_INITIAL_METADATA]), ",",
|
||||
absl::Hex(flags_for_op[GRPC_OP_RECV_STATUS_ON_CLIENT]),
|
||||
"]=>",
|
||||
grpc_call_error_to_string(call_start_batch_expected_result))
|
||||
.c_str(),
|
||||
nullptr, nullptr);
|
||||
grpc_core::CqVerifier cqv(f.cq);
|
||||
grpc_op ops[6];
|
||||
grpc_op* op;
|
||||
|
|
@ -154,6 +168,9 @@ static void test_invoke_request_with_flags(
|
|||
GPR_ASSERT(expectation == error);
|
||||
|
||||
if (expectation == GRPC_CALL_OK) {
|
||||
if (config.feature_mask & FEATURE_MASK_DOES_NOT_SUPPORT_DEADLINES) {
|
||||
GPR_ASSERT(GRPC_CALL_OK == grpc_call_cancel(c, nullptr));
|
||||
}
|
||||
cqv.Expect(tag(1), true);
|
||||
cqv.Verify();
|
||||
grpc_slice_unref(details);
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
|
|||
grpc_channel_args* client_args,
|
||||
grpc_channel_args* server_args) {
|
||||
grpc_end2end_test_fixture f;
|
||||
gpr_log(GPR_INFO, "%s", std::string(100, '*').c_str());
|
||||
gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
|
||||
f = config.create_fixture(client_args, server_args);
|
||||
config.init_server(&f, server_args);
|
||||
|
|
|
|||
|
|
@ -225,6 +225,8 @@ static void test(grpc_end2end_test_config config, bool request_status_early,
|
|||
|
||||
cqv.Expect(tag(2), true);
|
||||
cqv.Verify();
|
||||
|
||||
GPR_ASSERT(response_payload2_recv != nullptr);
|
||||
}
|
||||
|
||||
// Cancel the call so that the client sets up an error status.
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@
|
|||
#include "src/core/lib/security/security_connector/security_connector.h"
|
||||
#include "src/core/lib/security/transport/auth_filters.h"
|
||||
#include "src/core/lib/slice/slice.h"
|
||||
#include "src/core/lib/transport/call_fragments.h"
|
||||
#include "src/core/lib/transport/metadata_batch.h"
|
||||
#include "src/core/lib/transport/transport.h"
|
||||
#include "test/core/promise/test_context.h"
|
||||
|
|
@ -153,10 +154,8 @@ TEST_F(ClientAuthFilterTest, CallCredsFails) {
|
|||
TestContext<Arena> context(arena_.get());
|
||||
TestContext<grpc_call_context_element> promise_call_context(call_context_);
|
||||
auto promise = filter->MakeCallPromise(
|
||||
CallArgs{
|
||||
ClientMetadataHandle::TestOnlyWrap(&initial_metadata_batch_),
|
||||
nullptr,
|
||||
},
|
||||
CallArgs{ClientMetadataHandle::TestOnlyWrap(&initial_metadata_batch_),
|
||||
nullptr, nullptr, nullptr},
|
||||
[&](CallArgs /*call_args*/) {
|
||||
return ArenaPromise<ServerMetadataHandle>(
|
||||
[&]() -> Poll<ServerMetadataHandle> {
|
||||
|
|
@ -185,10 +184,8 @@ TEST_F(ClientAuthFilterTest, RewritesInvalidStatusFromCallCreds) {
|
|||
TestContext<Arena> context(arena_.get());
|
||||
TestContext<grpc_call_context_element> promise_call_context(call_context_);
|
||||
auto promise = filter->MakeCallPromise(
|
||||
CallArgs{
|
||||
ClientMetadataHandle::TestOnlyWrap(&initial_metadata_batch_),
|
||||
nullptr,
|
||||
},
|
||||
CallArgs{ClientMetadataHandle::TestOnlyWrap(&initial_metadata_batch_),
|
||||
nullptr, nullptr, nullptr},
|
||||
[&](CallArgs /*call_args*/) {
|
||||
return ArenaPromise<ServerMetadataHandle>(
|
||||
[&]() -> Poll<ServerMetadataHandle> {
|
||||
|
|
|
|||
|
|
@ -71,10 +71,8 @@ TEST(ClientAuthorityFilterTest, PromiseCompletesImmediatelyAndSetsAuthority) {
|
|||
// TODO(ctiller): use Activity here, once it's ready.
|
||||
TestContext<Arena> context(arena.get());
|
||||
auto promise = filter.MakeCallPromise(
|
||||
CallArgs{
|
||||
ClientMetadataHandle::TestOnlyWrap(&initial_metadata_batch),
|
||||
nullptr,
|
||||
},
|
||||
CallArgs{ClientMetadataHandle::TestOnlyWrap(&initial_metadata_batch),
|
||||
nullptr, nullptr, nullptr},
|
||||
[&](CallArgs call_args) {
|
||||
EXPECT_EQ(call_args.client_initial_metadata
|
||||
->get_pointer(HttpAuthorityMetadata())
|
||||
|
|
@ -105,10 +103,8 @@ TEST(ClientAuthorityFilterTest,
|
|||
// TODO(ctiller): use Activity here, once it's ready.
|
||||
TestContext<Arena> context(arena.get());
|
||||
auto promise = filter.MakeCallPromise(
|
||||
CallArgs{
|
||||
ClientMetadataHandle::TestOnlyWrap(&initial_metadata_batch),
|
||||
nullptr,
|
||||
},
|
||||
CallArgs{ClientMetadataHandle::TestOnlyWrap(&initial_metadata_batch),
|
||||
nullptr, nullptr, nullptr},
|
||||
[&](CallArgs call_args) {
|
||||
EXPECT_EQ(call_args.client_initial_metadata
|
||||
->get_pointer(HttpAuthorityMetadata())
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@
|
|||
#include "src/core/lib/slice/slice.h"
|
||||
#include "src/core/lib/slice/slice_internal.h"
|
||||
#include "src/core/lib/surface/channel_stack_type.h"
|
||||
#include "src/core/lib/transport/call_fragments.h"
|
||||
#include "src/core/lib/transport/handshaker.h"
|
||||
#include "src/core/lib/transport/metadata_batch.h"
|
||||
#include "src/core/lib/transport/transport.h"
|
||||
|
|
@ -116,8 +117,9 @@ const grpc_transport_vtable kFakeTransportVTable = {
|
|||
[](grpc_transport*, grpc_stream*, grpc_stream_refcount*, const void*,
|
||||
Arena*) -> int { abort(); },
|
||||
// make_call_promise
|
||||
[](grpc_transport*,
|
||||
ClientMetadataHandle) -> ArenaPromise<ServerMetadataHandle> { abort(); },
|
||||
[](grpc_transport*, CallArgs) -> ArenaPromise<ServerMetadataHandle> {
|
||||
abort();
|
||||
},
|
||||
// set_pollset
|
||||
[](grpc_transport*, grpc_stream*, grpc_pollset*) { abort(); },
|
||||
// set_pollset_set
|
||||
|
|
@ -317,11 +319,12 @@ const grpc_channel_filter* FindFilter(absl::string_view name) {
|
|||
|
||||
class MainLoop {
|
||||
public:
|
||||
MainLoop(RefCountedPtr<grpc_channel_stack> channel_stack,
|
||||
MainLoop(bool is_client, RefCountedPtr<grpc_channel_stack> channel_stack,
|
||||
const ChannelArgs& channel_args)
|
||||
: memory_allocator_(channel_args.GetObject<ResourceQuota>()
|
||||
->memory_quota()
|
||||
->CreateMemoryAllocator("test")),
|
||||
is_client_(is_client),
|
||||
channel_stack_(std::move(channel_stack)) {}
|
||||
|
||||
~MainLoop() {
|
||||
|
|
@ -349,9 +352,9 @@ class MainLoop {
|
|||
calls_.erase(action.call());
|
||||
break;
|
||||
case filter_fuzzer::Action::kCreateCall:
|
||||
calls_.emplace(
|
||||
action.call(),
|
||||
std::make_unique<Call>(this, action.call(), action.create_call()));
|
||||
calls_.emplace(action.call(), std::make_unique<Call>(
|
||||
this, action.call(),
|
||||
action.create_call(), is_client_));
|
||||
break;
|
||||
case filter_fuzzer::Action::kReceiveInitialMetadata:
|
||||
if (auto* call = GetCall(action.call())) {
|
||||
|
|
@ -407,6 +410,10 @@ class MainLoop {
|
|||
}
|
||||
void Drop() override { delete this; }
|
||||
|
||||
std::string ActivityDebugTag() const override {
|
||||
return "WakeCall(" + std::to_string(id_) + ")";
|
||||
}
|
||||
|
||||
private:
|
||||
MainLoop* const main_loop_;
|
||||
uint32_t id_;
|
||||
|
|
@ -460,14 +467,20 @@ class MainLoop {
|
|||
};
|
||||
|
||||
Call(MainLoop* main_loop, uint32_t id,
|
||||
const filter_fuzzer::Metadata& client_initial_metadata)
|
||||
const filter_fuzzer::Metadata& client_initial_metadata, bool is_client)
|
||||
: main_loop_(main_loop), id_(id) {
|
||||
ScopedContext context(this);
|
||||
auto* server_initial_metadata = arena_->New<Latch<ServerMetadata*>>();
|
||||
promise_ = main_loop_->channel_stack_->MakeCallPromise(
|
||||
CallArgs{std::move(*LoadMetadata(client_initial_metadata,
|
||||
&client_initial_metadata_)),
|
||||
server_initial_metadata});
|
||||
CallArgs call_args{std::move(*LoadMetadata(client_initial_metadata,
|
||||
&client_initial_metadata_)),
|
||||
server_initial_metadata, nullptr, nullptr};
|
||||
if (is_client) {
|
||||
promise_ = main_loop_->channel_stack_->MakeClientCallPromise(
|
||||
std::move(call_args));
|
||||
} else {
|
||||
promise_ = main_loop_->channel_stack_->MakeServerCallPromise(
|
||||
std::move(call_args));
|
||||
}
|
||||
Step();
|
||||
}
|
||||
|
||||
|
|
@ -574,7 +587,7 @@ class MainLoop {
|
|||
};
|
||||
|
||||
template <typename R>
|
||||
absl::optional<MetadataHandle<R>> LoadMetadata(
|
||||
absl::optional<FragmentHandle<R>> LoadMetadata(
|
||||
const filter_fuzzer::Metadata& metadata, std::unique_ptr<R>* out) {
|
||||
if (*out != nullptr) return absl::nullopt;
|
||||
*out = std::make_unique<R>(arena_.get());
|
||||
|
|
@ -582,7 +595,7 @@ class MainLoop {
|
|||
(*out)->Append(md.key(), Slice::FromCopiedString(md.value()),
|
||||
[](absl::string_view, const Slice&) {});
|
||||
}
|
||||
return MetadataHandle<R>::TestOnlyWrap(out->get());
|
||||
return FragmentHandle<R>::TestOnlyWrap(out->get());
|
||||
}
|
||||
|
||||
void Step() {
|
||||
|
|
@ -626,6 +639,7 @@ class MainLoop {
|
|||
}
|
||||
|
||||
MemoryAllocator memory_allocator_;
|
||||
const bool is_client_;
|
||||
RefCountedPtr<grpc_channel_stack> channel_stack_;
|
||||
std::map<uint32_t, std::unique_ptr<Call>> calls_;
|
||||
std::vector<uint32_t> wakeups_;
|
||||
|
|
@ -681,7 +695,7 @@ DEFINE_PROTO_FUZZER(const filter_fuzzer::Msg& msg) {
|
|||
}();
|
||||
|
||||
if (stack.ok()) {
|
||||
grpc_core::MainLoop main_loop(std::move(*stack), channel_args);
|
||||
grpc_core::MainLoop main_loop(is_client, std::move(*stack), channel_args);
|
||||
for (const auto& action : msg.actions()) {
|
||||
grpc_timer_manager_tick();
|
||||
main_loop.Run(action, &globals);
|
||||
|
|
|
|||
|
|
@ -344,6 +344,7 @@ class TestWakeable final : public Wakeable {
|
|||
drops_->fetch_add(1, std::memory_order_relaxed);
|
||||
delete this;
|
||||
}
|
||||
std::string ActivityDebugTag() const override { return "TestWakeable"; }
|
||||
|
||||
private:
|
||||
std::atomic<int>* const wakeups_;
|
||||
|
|
|
|||
|
|
@ -33,12 +33,20 @@ namespace grpc_core {
|
|||
static auto* g_memory_allocator = new MemoryAllocator(
|
||||
ResourceQuota::Default()->memory_quota()->CreateMemoryAllocator("test"));
|
||||
|
||||
TEST(ArenaPromiseTest, DefaultInitializationYieldsNoValue) {
|
||||
auto arena = MakeScopedArena(1024, g_memory_allocator);
|
||||
TestContext<Arena> context(arena.get());
|
||||
ArenaPromise<int> p;
|
||||
EXPECT_FALSE(p.has_value());
|
||||
}
|
||||
|
||||
TEST(ArenaPromiseTest, AllocatedWorks) {
|
||||
ExecCtx exec_ctx;
|
||||
auto arena = MakeScopedArena(1024, g_memory_allocator);
|
||||
TestContext<Arena> context(arena.get());
|
||||
int x = 42;
|
||||
ArenaPromise<int> p([x] { return Poll<int>(x); });
|
||||
EXPECT_TRUE(p.has_value());
|
||||
EXPECT_EQ(p(), Poll<int>(42));
|
||||
p = ArenaPromise<int>([] { return Poll<int>(43); });
|
||||
EXPECT_EQ(p(), Poll<int>(43));
|
||||
|
|
|
|||
|
|
@ -54,8 +54,8 @@ TEST(CallPushPullTest, OneReady) {
|
|||
TEST(CallPushPullTest, OneFailed) {
|
||||
auto a = CallPushPull(
|
||||
[]() -> Poll<absl::Status> { return absl::UnknownError("bah"); },
|
||||
[]() -> Poll<absl::Status> { return Pending{}; },
|
||||
[]() -> Poll<absl::Status> { return Pending{}; });
|
||||
[]() -> Poll<absl::Status> { return absl::OkStatus(); },
|
||||
[]() -> Poll<absl::Status> { return absl::OkStatus(); });
|
||||
EXPECT_EQ(a(), Poll<absl::Status>(absl::UnknownError("bah")));
|
||||
auto b = CallPushPull(
|
||||
[]() -> Poll<absl::Status> { return Pending{}; },
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@ grpc_cc_test(
|
|||
srcs = ["lame_client_test.cc"],
|
||||
external_deps = ["gtest"],
|
||||
language = "C++",
|
||||
tags = ["lame_client_test"],
|
||||
deps = [
|
||||
"//:gpr",
|
||||
"//:grpc",
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include "src/core/lib/channel/channel_fwd.h"
|
||||
#include "src/core/lib/channel/channel_stack.h"
|
||||
#include "src/core/lib/experiments/experiments.h"
|
||||
#include "src/core/lib/gprpp/orphanable.h"
|
||||
#include "src/core/lib/iomgr/closure.h"
|
||||
#include "src/core/lib/iomgr/error.h"
|
||||
|
|
@ -123,8 +124,11 @@ TEST(LameClientTest, MainTest) {
|
|||
tag(1), nullptr);
|
||||
ASSERT_EQ(GRPC_CALL_OK, error);
|
||||
|
||||
/* the call should immediately fail */
|
||||
cqv.Expect(tag(1), false);
|
||||
// Filter stack code considers this a failed to receive initial metadata
|
||||
// result, where as promise based code interprets this as a trailers only
|
||||
// failed request. Both are rational interpretations, so we accept the one
|
||||
// that is implemented for each stack.
|
||||
cqv.Expect(tag(1), grpc_core::IsPromiseBasedClientCallEnabled());
|
||||
cqv.Verify();
|
||||
|
||||
memset(ops, 0, sizeof(ops));
|
||||
|
|
|
|||
|
|
@ -65,6 +65,21 @@ grpc_cc_test(
|
|||
],
|
||||
)
|
||||
|
||||
grpc_cc_test(
|
||||
name = "call_fragments_test",
|
||||
srcs = ["call_fragments_test.cc"],
|
||||
external_deps = [
|
||||
"gtest",
|
||||
],
|
||||
language = "C++",
|
||||
deps = [
|
||||
"//:gpr",
|
||||
"//:grpc",
|
||||
"//test/core/promise:test_context",
|
||||
"//test/core/util:grpc_test_util",
|
||||
],
|
||||
)
|
||||
|
||||
grpc_cc_test(
|
||||
name = "metadata_map_test",
|
||||
srcs = ["metadata_map_test.cc"],
|
||||
|
|
|
|||
|
|
@ -0,0 +1,96 @@
|
|||
//
|
||||
// Copyright 2021 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/lib/transport/call_fragments.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <grpc/event_engine/memory_allocator.h>
|
||||
|
||||
#include "src/core/lib/gprpp/ref_counted_ptr.h"
|
||||
#include "src/core/lib/resource_quota/memory_quota.h"
|
||||
#include "src/core/lib/resource_quota/resource_quota.h"
|
||||
#include "test/core/promise/test_context.h"
|
||||
#include "test/core/util/test_config.h"
|
||||
|
||||
using testing::Each;
|
||||
|
||||
namespace grpc_core {
|
||||
namespace testing {
|
||||
|
||||
class CallFragmentsTest : public ::testing::Test {
|
||||
protected:
|
||||
CallFragmentsTest() {}
|
||||
~CallFragmentsTest() override {}
|
||||
|
||||
private:
|
||||
MemoryAllocator memory_allocator_ =
|
||||
ResourceQuota::Default()->memory_quota()->CreateMemoryAllocator("test");
|
||||
ScopedArenaPtr arena_ = MakeScopedArena(4096, &memory_allocator_);
|
||||
FragmentAllocator fragment_allocator_;
|
||||
|
||||
TestContext<Arena> arena_context_{arena_.get()};
|
||||
TestContext<FragmentAllocator> fragment_allocator_context_{
|
||||
&fragment_allocator_};
|
||||
};
|
||||
|
||||
// Ensure test fixture can init/destroy successfully.
|
||||
TEST_F(CallFragmentsTest, Nothing) {}
|
||||
|
||||
// Ensure we can create/destroy some client metadata.
|
||||
TEST_F(CallFragmentsTest, ClientMetadata) {
|
||||
GetContext<FragmentAllocator>()->MakeClientMetadata();
|
||||
}
|
||||
|
||||
// Ensure we can create/destroy some server metadata.
|
||||
TEST_F(CallFragmentsTest, ServerMetadata) {
|
||||
GetContext<FragmentAllocator>()->MakeServerMetadata();
|
||||
}
|
||||
|
||||
// Ensure repeated allocation/deallocations reuse memory.
|
||||
TEST_F(CallFragmentsTest, RepeatedAllocationsReuseMemory) {
|
||||
void* p = GetContext<FragmentAllocator>()->MakeClientMetadata().get();
|
||||
void* q = GetContext<FragmentAllocator>()->MakeClientMetadata().get();
|
||||
EXPECT_EQ(p, q);
|
||||
}
|
||||
|
||||
// Ensure repeated allocation reinitializes.
|
||||
TEST_F(CallFragmentsTest, RepeatedAllocationsReinitialize) {
|
||||
std::vector<void*> addresses;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
ClientMetadataHandle metadata =
|
||||
GetContext<FragmentAllocator>()->MakeClientMetadata();
|
||||
EXPECT_EQ(metadata->get_pointer(HttpPathMetadata()), nullptr);
|
||||
metadata->Set(HttpPathMetadata(), Slice::FromCopiedString("/"));
|
||||
EXPECT_EQ(metadata->get_pointer(HttpPathMetadata())->as_string_view(), "/");
|
||||
addresses.push_back(metadata.get());
|
||||
}
|
||||
EXPECT_THAT(addresses, Each(addresses[0]));
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
} // namespace grpc_core
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
grpc::testing::TestEnvironment env(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
};
|
||||
|
|
@ -2256,6 +2256,7 @@ src/core/lib/promise/intra_activity_waiter.h \
|
|||
src/core/lib/promise/latch.h \
|
||||
src/core/lib/promise/loop.h \
|
||||
src/core/lib/promise/map.h \
|
||||
src/core/lib/promise/pipe.h \
|
||||
src/core/lib/promise/poll.h \
|
||||
src/core/lib/promise/promise.h \
|
||||
src/core/lib/promise/race.h \
|
||||
|
|
@ -2432,6 +2433,8 @@ src/core/lib/surface/call.h \
|
|||
src/core/lib/surface/call_details.cc \
|
||||
src/core/lib/surface/call_log_batch.cc \
|
||||
src/core/lib/surface/call_test_only.h \
|
||||
src/core/lib/surface/call_trace.cc \
|
||||
src/core/lib/surface/call_trace.h \
|
||||
src/core/lib/surface/channel.cc \
|
||||
src/core/lib/surface/channel.h \
|
||||
src/core/lib/surface/channel_init.cc \
|
||||
|
|
@ -2459,6 +2462,8 @@ src/core/lib/surface/validate_metadata.h \
|
|||
src/core/lib/surface/version.cc \
|
||||
src/core/lib/transport/bdp_estimator.cc \
|
||||
src/core/lib/transport/bdp_estimator.h \
|
||||
src/core/lib/transport/call_fragments.cc \
|
||||
src/core/lib/transport/call_fragments.h \
|
||||
src/core/lib/transport/connectivity_state.cc \
|
||||
src/core/lib/transport/connectivity_state.h \
|
||||
src/core/lib/transport/error_utils.cc \
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue