@ -242,6 +242,8 @@ class Call : public CppImplOf<Call, grpc_call> {
void HandleCompressionAlgorithmNotAccepted (
grpc_compression_algorithm compression_algorithm ) GPR_ATTRIBUTE_NOINLINE ;
gpr_cycle_counter start_time ( ) const { return start_time_ ; }
private :
RefCountedPtr < Channel > channel_ ;
Arena * const arena_ ;
@ -263,6 +265,7 @@ class Call : public CppImplOf<Call, grpc_call> {
// of the recv_initial_metadata op. The mutex should be mostly uncontended.
mutable Mutex peer_mu_ ;
Slice peer_string_ ;
gpr_cycle_counter start_time_ = gpr_get_cycle_counter ( ) ;
} ;
Call : : ParentCall * Call : : GetOrCreateParentCall ( ) {
@ -706,7 +709,6 @@ class FilterStackCall final : public Call {
CallCombiner call_combiner_ ;
grpc_completion_queue * cq_ ;
grpc_polling_entity pollent_ ;
gpr_cycle_counter start_time_ = gpr_get_cycle_counter ( ) ;
/// has grpc_call_unref been called
bool destroy_called_ = false ;
@ -868,7 +870,7 @@ grpc_error_handle FilterStackCall::Create(grpc_call_create_args* args,
grpc_call_element_args call_args = {
call - > call_stack ( ) , args - > server_transport_data ,
call - > context_ , path ,
call - > start_time_ , call - > send_deadline ( ) ,
call - > start_time ( ) , call - > send_deadline ( ) ,
call - > arena ( ) , & call - > call_combiner_ } ;
add_init_error ( & error , grpc_call_stack_init ( channel_stack , 1 , DestroyCall ,
call , & call_args ) ) ;
@ -950,7 +952,7 @@ void FilterStackCall::DestroyCall(void* call, grpc_error_handle /*error*/) {
& ( c - > final_info_ . error_string ) ) ;
c - > status_error_ . set ( absl : : OkStatus ( ) ) ;
c - > final_info_ . stats . latency =
gpr_cycle_counter_sub ( gpr_get_cycle_counter ( ) , c - > start_time_ ) ;
gpr_cycle_counter_sub ( gpr_get_cycle_counter ( ) , c - > start_time ( ) ) ;
grpc_call_stack_destroy ( c - > call_stack ( ) , & c - > final_info_ ,
GRPC_CLOSURE_INIT ( & c - > release_call_ , ReleaseCall , c ,
grpc_schedule_on_exec_ctx ) ) ;
@ -1995,11 +1997,18 @@ class PromiseBasedCall : public Call,
void UpdateDeadline ( Timestamp deadline ) ABSL_LOCKS_EXCLUDED ( deadline_mu_ ) ;
void ResetDeadline ( ) ABSL_LOCKS_EXCLUDED ( deadline_mu_ ) ;
Timestamp deadline ( ) {
MutexLock lock ( & deadline_mu_ ) ;
return deadline_ ;
}
// Implementation of EventEngine::Closure, called when deadline expires
void Run ( ) override ;
virtual ServerCallContext * server_call_context ( ) { return nullptr ; }
bool failed_before_recv_message ( ) const final {
return failed_before_recv_message_ . load ( std : : memory_order_relaxed ) ;
}
using Call : : arena ;
@ -2145,6 +2154,8 @@ class PromiseBasedCall : public Call,
final_info . stats = final_stats_ ;
final_info . final_status = status ;
final_info . error_string = status_details ;
final_info . stats . latency =
gpr_cycle_counter_sub ( gpr_get_cycle_counter ( ) , start_time ( ) ) ;
finalization_ . Run ( & final_info ) ;
}
@ -2320,6 +2331,7 @@ class PromiseBasedCall : public Call,
// GRPC_OP_SEND_MESSAGE (one count each), and 0 once those payloads have been
// pushed onto the outgoing pipe.
std : : atomic < uint8_t > sends_queued_ { 0 } ;
std : : atomic < bool > failed_before_recv_message_ { false } ;
// Waiter for when sends_queued_ becomes 0.
IntraActivityWaiter waiting_for_queued_sends_ ;
grpc_byte_buffer * * recv_message_ = nullptr ;
@ -2346,16 +2358,7 @@ PromiseBasedCall::PromiseBasedCall(Arena* arena, uint32_t initial_external_refs,
Party ( arena , initial_external_refs ) ,
cq_ ( args . cq ) {
if ( args . cq ! = nullptr ) {
GPR_ASSERT ( args . pollset_set_alternative = = nullptr & &
" Only one of 'cq' and 'pollset_set_alternative' should be "
" non-nullptr. " ) ;
GRPC_CQ_INTERNAL_REF ( args . cq , " bind " ) ;
call_context_ . pollent_ =
grpc_polling_entity_create_from_pollset ( grpc_cq_pollset ( args . cq ) ) ;
}
if ( args . pollset_set_alternative ! = nullptr ) {
call_context_ . pollent_ = grpc_polling_entity_create_from_pollset_set (
args . pollset_set_alternative ) ;
}
}
@ -2468,8 +2471,6 @@ void PromiseBasedCall::FinishOpOnCompletion(Completion* completion,
void PromiseBasedCall : : SetCompletionQueue ( grpc_completion_queue * cq ) {
cq_ = cq ;
GRPC_CQ_INTERNAL_REF ( cq , " bind " ) ;
call_context_ . pollent_ =
grpc_polling_entity_create_from_pollset ( grpc_cq_pollset ( cq ) ) ;
}
void PromiseBasedCall : : UpdateDeadline ( Timestamp deadline ) {
@ -2577,6 +2578,7 @@ void PromiseBasedCall::StartRecvMessage(
" finishes: received end-of-stream with error " ,
DebugTag ( ) . c_str ( ) ) ;
}
failed_before_recv_message_ . store ( true ) ;
FailCompletion ( completion ) ;
* recv_message_ = nullptr ;
} else {
@ -2609,6 +2611,8 @@ void CallContext::UpdateDeadline(Timestamp deadline) {
call_ - > UpdateDeadline ( deadline ) ;
}
Timestamp CallContext : : deadline ( ) const { return call_ - > deadline ( ) ; }
ServerCallContext * CallContext : : server_call_context ( ) {
return call_ - > server_call_context ( ) ;
}
@ -2639,6 +2643,17 @@ class ClientPromiseBasedCall final : public PromiseBasedCall {
ClientPromiseBasedCall ( Arena * arena , grpc_call_create_args * args )
: PromiseBasedCall ( arena , 1 , * args ) {
global_stats ( ) . IncrementClientCallsCreated ( ) ;
if ( args - > cq ! = nullptr ) {
GPR_ASSERT ( args - > pollset_set_alternative = = nullptr & &
" Only one of 'cq' and 'pollset_set_alternative' should be "
" non-nullptr. " ) ;
polling_entity_ . Set (
grpc_polling_entity_create_from_pollset ( grpc_cq_pollset ( args - > cq ) ) ) ;
}
if ( args - > pollset_set_alternative ! = nullptr ) {
polling_entity_ . Set ( grpc_polling_entity_create_from_pollset_set (
args - > pollset_set_alternative ) ) ;
}
ScopedContext context ( this ) ;
send_initial_metadata_ =
GetContext < Arena > ( ) - > MakePooled < ClientMetadata > ( GetContext < Arena > ( ) ) ;
@ -2691,7 +2706,6 @@ class ClientPromiseBasedCall final : public PromiseBasedCall {
}
absl : : string_view GetServerAuthority ( ) const override { abort ( ) ; }
bool is_trailers_only ( ) const override { return is_trailers_only_ ; }
bool failed_before_recv_message ( ) const override { return false ; }
grpc_call_error StartBatch ( const grpc_op * ops , size_t nops , void * notify_tag ,
bool is_notify_tag_closure ) override ;
@ -2730,6 +2744,7 @@ class ClientPromiseBasedCall final : public PromiseBasedCall {
Pipe < ServerMetadataHandle > server_initial_metadata_ { arena ( ) } ;
Latch < ServerMetadataHandle > server_trailing_metadata_ ;
Latch < ServerMetadataHandle > cancel_error_ ;
Latch < grpc_polling_entity > polling_entity_ ;
Pipe < MessageHandle > client_to_server_messages_ { arena ( ) } ;
Pipe < MessageHandle > server_to_client_messages_ { arena ( ) } ;
bool is_trailers_only_ ;
@ -2763,11 +2778,11 @@ void ClientPromiseBasedCall::StartPromise(
token = std : : move ( token ) ] ( ) mutable {
return Race (
cancel_error_ . Wait ( ) ,
Map ( channel ( ) - > channel_stack ( ) - > MakeClientCallPromise (
CallArgs { std : : move ( client_initial_metadata ) ,
std : : move ( token ) , & server_initial_metadata_ . sender ,
& client_to_server_messages_ . receiver ,
& server_to_client_messages_ . sender } ) ,
Map ( channel ( ) - > channel_stack ( ) - > MakeClientCallPromise ( CallArgs {
std : : move ( client_initial_metadata ) , std : : move ( token ) ,
& polling_entity_ , & server_initial_metadata_ . sender ,
& client_to_server_messages_ . receiver ,
& server_to_client_messages_ . sender } ) ,
[ this ] ( ServerMetadataHandle trailing_metadata ) {
// If we're cancelled the transport doesn't get to return
// stats.
@ -3023,9 +3038,13 @@ class ServerPromiseBasedCall final : public PromiseBasedCall {
void CancelWithError ( grpc_error_handle ) override ;
grpc_call_error StartBatch ( const grpc_op * ops , size_t nops , void * notify_tag ,
bool is_notify_tag_closure ) override ;
bool failed_before_recv_message ( ) const override { return false ; }
bool is_trailers_only ( ) const override { abort ( ) ; }
absl : : string_view GetServerAuthority ( ) const override { return " " ; }
absl : : string_view GetServerAuthority ( ) const override {
const Slice * authority_metadata =
client_initial_metadata_ - > get_pointer ( HttpAuthorityMetadata ( ) ) ;
if ( authority_metadata = = nullptr ) return " " ;
return authority_metadata - > as_string_view ( ) ;
}
// Polling order for the server promise stack:
//
@ -3189,7 +3208,7 @@ ServerPromiseBasedCall::ServerPromiseBasedCall(Arena* arena,
Spawn ( " server_promise " ,
channel ( ) - > channel_stack ( ) - > MakeServerCallPromise (
CallArgs { nullptr , ClientInitialMetadataOutstandingToken : : Empty ( ) ,
nullptr , nullptr , nullptr } ) ,
nullptr , nullptr , nullptr , nullptr } ) ,
[ this ] ( ServerMetadataHandle result ) { Finish ( std : : move ( result ) ) ; } ) ;
}
@ -3207,15 +3226,27 @@ void ServerPromiseBasedCall::Finish(ServerMetadataHandle result) {
if ( server_initial_metadata_ ! = nullptr ) {
server_initial_metadata_ - > Close ( ) ;
}
const auto status =
result - > get ( GrpcStatusMetadata ( ) ) . value_or ( GRPC_STATUS_UNKNOWN ) ;
channelz : : ServerNode * channelz_node = server_ - > channelz_node ( ) ;
if ( channelz_node ! = nullptr ) {
if ( result - > get ( GrpcStatusMetadata ( ) ) . value_or ( GRPC_STATUS_UNKNOWN ) = =
GRPC_STATUS_OK ) {
if ( status = = GRPC_STATUS_OK ) {
channelz_node - > RecordCallSucceeded ( ) ;
} else {
channelz_node - > RecordCallFailed ( ) ;
}
}
absl : : string_view message_string ;
if ( Slice * message = result - > get_pointer ( GrpcMessageMetadata ( ) ) ) {
message_string = message - > as_string_view ( ) ;
}
AcceptTransportStatsFromContext ( ) ;
if ( message_string . empty ( ) ) {
RunFinalization ( status , nullptr ) ;
} else {
std : : string error_string ( message_string ) ;
RunFinalization ( status , error_string . c_str ( ) ) ;
}
set_completed ( ) ;
ResetDeadline ( ) ;
PropagateCancellationToChildren ( ) ;
@ -3307,7 +3338,12 @@ void ServerPromiseBasedCall::CommitBatch(const grpc_op* ops, size_t nops,
metadata - > Set ( GrpcStatusMetadata ( ) ,
op . data . send_status_from_server . status ) ;
if ( auto * details = op . data . send_status_from_server . status_details ) {
metadata - > Set ( GrpcMessageMetadata ( ) , Slice ( CSliceRef ( * details ) ) ) ;
// TODO(ctiller): this should not be a copy, but we have callers that
// allocate and pass in a slice created with
// grpc_slice_from_static_string and then delete the string after
// passing it in, which shouldn't be a supported API.
metadata - > Set ( GrpcMessageMetadata ( ) ,
Slice ( grpc_slice_copy ( * details ) ) ) ;
}
spawner . Spawn (
" call_send_status_from_server " ,
@ -3403,11 +3439,14 @@ ServerCallContext::MakeTopOfServerCallPromise(
grpc_metadata_array * publish_initial_metadata ,
absl : : FunctionRef < void ( grpc_call * call ) > publish ) {
call_ - > SetCompletionQueue ( cq ) ;
call_args . polling_entity - > Set (
grpc_polling_entity_create_from_pollset ( grpc_cq_pollset ( cq ) ) ) ;
call_ - > server_to_client_messages_ = call_args . server_to_client_messages ;
call_ - > client_to_server_messages_ = call_args . client_to_server_messages ;
call_ - > server_initial_metadata_ = call_args . server_initial_metadata ;
call_ - > client_initial_metadata_ =
std : : move ( call_args . client_initial_metadata ) ;
call_ - > set_send_deadline ( call_ - > deadline ( ) ) ;
call_ - > ProcessIncomingInitialMetadata ( * call_ - > client_initial_metadata_ ) ;
PublishMetadataArray ( call_ - > client_initial_metadata_ . get ( ) ,
publish_initial_metadata ) ;