|
|
|
@ -72,15 +72,39 @@ enum requested_call_type { BATCH_CALL, REGISTERED_CALL }; |
|
|
|
|
struct registered_method; |
|
|
|
|
|
|
|
|
|
struct requested_call { |
|
|
|
|
grpc_core::ManualConstructor< |
|
|
|
|
grpc_core::MultiProducerSingleConsumerQueue::Node> |
|
|
|
|
mpscq_node; |
|
|
|
|
requested_call_type type; |
|
|
|
|
void* tag; |
|
|
|
|
grpc_completion_queue* cq_bound_to_call; |
|
|
|
|
grpc_call** call; |
|
|
|
|
requested_call(void* tag_arg, grpc_completion_queue* call_cq, |
|
|
|
|
grpc_call** call_arg, grpc_metadata_array* initial_md, |
|
|
|
|
grpc_call_details* details) |
|
|
|
|
: type(BATCH_CALL), |
|
|
|
|
tag(tag_arg), |
|
|
|
|
cq_bound_to_call(call_cq), |
|
|
|
|
call(call_arg), |
|
|
|
|
initial_metadata(initial_md) { |
|
|
|
|
details->reserved = nullptr; |
|
|
|
|
data.batch.details = details; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
requested_call(void* tag_arg, grpc_completion_queue* call_cq, |
|
|
|
|
grpc_call** call_arg, grpc_metadata_array* initial_md, |
|
|
|
|
registered_method* rm, gpr_timespec* deadline, |
|
|
|
|
grpc_byte_buffer** optional_payload) |
|
|
|
|
: type(REGISTERED_CALL), |
|
|
|
|
tag(tag_arg), |
|
|
|
|
cq_bound_to_call(call_cq), |
|
|
|
|
call(call_arg), |
|
|
|
|
initial_metadata(initial_md) { |
|
|
|
|
data.registered.method = rm; |
|
|
|
|
data.registered.deadline = deadline; |
|
|
|
|
data.registered.optional_payload = optional_payload; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
grpc_core::MultiProducerSingleConsumerQueue::Node mpscq_node; |
|
|
|
|
const requested_call_type type; |
|
|
|
|
void* const tag; |
|
|
|
|
grpc_completion_queue* const cq_bound_to_call; |
|
|
|
|
grpc_call** const call; |
|
|
|
|
grpc_cq_completion completion; |
|
|
|
|
grpc_metadata_array* initial_metadata; |
|
|
|
|
grpc_metadata_array* const initial_metadata; |
|
|
|
|
union { |
|
|
|
|
struct { |
|
|
|
|
grpc_call_details* details; |
|
|
|
@ -134,6 +158,10 @@ enum call_state { |
|
|
|
|
|
|
|
|
|
struct call_data; |
|
|
|
|
|
|
|
|
|
grpc_call_error ValidateServerRequest( |
|
|
|
|
grpc_completion_queue* cq_for_notification, void* tag, |
|
|
|
|
grpc_byte_buffer** optional_payload, registered_method* rm); |
|
|
|
|
|
|
|
|
|
// RPCs that come in from the transport must be matched against RPC requests
|
|
|
|
|
// from the application. An incoming request from the application can be matched
|
|
|
|
|
// to an RPC that has already arrived or can be queued up for later use.
|
|
|
|
@ -242,14 +270,26 @@ struct call_data { |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
struct registered_method { |
|
|
|
|
char* method; |
|
|
|
|
char* host; |
|
|
|
|
grpc_server_register_method_payload_handling payload_handling; |
|
|
|
|
uint32_t flags; |
|
|
|
|
registered_method( |
|
|
|
|
const char* method_arg, const char* host_arg, |
|
|
|
|
grpc_server_register_method_payload_handling payload_handling_arg, |
|
|
|
|
uint32_t flags_arg) |
|
|
|
|
: method(gpr_strdup(method_arg)), |
|
|
|
|
host(gpr_strdup(host_arg)), |
|
|
|
|
payload_handling(payload_handling_arg), |
|
|
|
|
flags(flags_arg) {} |
|
|
|
|
|
|
|
|
|
~registered_method() { |
|
|
|
|
gpr_free(method); |
|
|
|
|
gpr_free(host); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
char* const method; |
|
|
|
|
char* const host; |
|
|
|
|
const grpc_server_register_method_payload_handling payload_handling; |
|
|
|
|
const uint32_t flags; |
|
|
|
|
/* one request matcher per method */ |
|
|
|
|
// TODO(vjpai): Move this to a unique_ptr once this has a real
|
|
|
|
|
// constructor/destructor
|
|
|
|
|
RequestMatcherInterface* matcher = nullptr; |
|
|
|
|
std::unique_ptr<RequestMatcherInterface> matcher; |
|
|
|
|
registered_method* next; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
@ -285,6 +325,8 @@ struct grpc_server { |
|
|
|
|
bool starting; |
|
|
|
|
gpr_cv starting_cv; |
|
|
|
|
|
|
|
|
|
// TODO(vjpai): Convert from a linked-list head pointer to a std::vector once
|
|
|
|
|
// grpc_server has a real constructor/destructor
|
|
|
|
|
registered_method* registered_methods; |
|
|
|
|
/** one request matcher for unregistered methods */ |
|
|
|
|
// TODO(vjpai): Convert to a std::unique_ptr once grpc_server has a real
|
|
|
|
@ -444,7 +486,7 @@ class RealRequestMatcher : public RequestMatcherInterface { |
|
|
|
|
|
|
|
|
|
void RequestCallWithPossiblePublish(size_t request_queue_index, |
|
|
|
|
requested_call* call) override { |
|
|
|
|
if (requests_per_cq_[request_queue_index].Push(call->mpscq_node.get())) { |
|
|
|
|
if (requests_per_cq_[request_queue_index].Push(&call->mpscq_node)) { |
|
|
|
|
/* this was the first queued request: we need to lock and start
|
|
|
|
|
matching calls */ |
|
|
|
|
gpr_mu_lock(&server_->mu_call); |
|
|
|
@ -530,6 +572,103 @@ class RealRequestMatcher : public RequestMatcherInterface { |
|
|
|
|
std::vector<LockedMultiProducerSingleConsumerQueue> requests_per_cq_; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
// AllocatingRequestMatchers don't allow the application to request an RPC in
|
|
|
|
|
// advance or queue up any incoming RPC for later match. Instead, MatchOrQueue
|
|
|
|
|
// will call out to an allocation function passed in at the construction of the
|
|
|
|
|
// object. These request matchers are designed for the C++ callback API, so they
|
|
|
|
|
// only support 1 completion queue (passed in at the constructor).
|
|
|
|
|
class AllocatingRequestMatcherBase : public RequestMatcherInterface { |
|
|
|
|
public: |
|
|
|
|
AllocatingRequestMatcherBase(grpc_server* server, grpc_completion_queue* cq) |
|
|
|
|
: server_(server), cq_(cq) { |
|
|
|
|
size_t idx; |
|
|
|
|
for (idx = 0; idx < server->cq_count; idx++) { |
|
|
|
|
if (server->cqs[idx] == cq) { |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
GPR_ASSERT(idx < server->cq_count); |
|
|
|
|
cq_idx_ = idx; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void ZombifyPending() override {} |
|
|
|
|
|
|
|
|
|
void KillRequests(grpc_error* error) override { GRPC_ERROR_UNREF(error); } |
|
|
|
|
|
|
|
|
|
size_t request_queue_count() const override { return 0; } |
|
|
|
|
|
|
|
|
|
void RequestCallWithPossiblePublish(size_t /*request_queue_index*/, |
|
|
|
|
requested_call* /*call*/) final { |
|
|
|
|
GPR_ASSERT(false); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
grpc_server* server() const override { return server_; } |
|
|
|
|
|
|
|
|
|
// Supply the completion queue related to this request matcher
|
|
|
|
|
grpc_completion_queue* cq() const { return cq_; } |
|
|
|
|
|
|
|
|
|
// Supply the completion queue's index relative to the server.
|
|
|
|
|
size_t cq_idx() const { return cq_idx_; } |
|
|
|
|
|
|
|
|
|
private: |
|
|
|
|
grpc_server* const server_; |
|
|
|
|
grpc_completion_queue* const cq_; |
|
|
|
|
size_t cq_idx_; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
// An allocating request matcher for non-registered methods (used for generic
|
|
|
|
|
// API and unimplemented RPCs).
|
|
|
|
|
class AllocatingRequestMatcherBatch : public AllocatingRequestMatcherBase { |
|
|
|
|
public: |
|
|
|
|
AllocatingRequestMatcherBatch( |
|
|
|
|
grpc_server* server, grpc_completion_queue* cq, |
|
|
|
|
std::function<grpc_core::ServerBatchCallAllocation()> allocator) |
|
|
|
|
: AllocatingRequestMatcherBase(server, cq), |
|
|
|
|
allocator_(std::move(allocator)) {} |
|
|
|
|
void MatchOrQueue(size_t /*start_request_queue_index*/, |
|
|
|
|
call_data* calld) override { |
|
|
|
|
grpc_core::ServerBatchCallAllocation call_info = allocator_(); |
|
|
|
|
GPR_ASSERT(ValidateServerRequest(cq(), static_cast<void*>(call_info.tag), |
|
|
|
|
nullptr, nullptr) == GRPC_CALL_OK); |
|
|
|
|
requested_call* rc = new requested_call( |
|
|
|
|
static_cast<void*>(call_info.tag), cq(), call_info.call, |
|
|
|
|
call_info.initial_metadata, call_info.details); |
|
|
|
|
gpr_atm_no_barrier_store(&calld->state, ACTIVATED); |
|
|
|
|
publish_call(server(), calld, cq_idx(), rc); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private: |
|
|
|
|
std::function<grpc_core::ServerBatchCallAllocation()> allocator_; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
// An allocating request matcher for registered methods.
|
|
|
|
|
class AllocatingRequestMatcherRegistered : public AllocatingRequestMatcherBase { |
|
|
|
|
public: |
|
|
|
|
AllocatingRequestMatcherRegistered( |
|
|
|
|
grpc_server* server, grpc_completion_queue* cq, registered_method* rm, |
|
|
|
|
std::function<grpc_core::ServerRegisteredCallAllocation()> allocator) |
|
|
|
|
: AllocatingRequestMatcherBase(server, cq), |
|
|
|
|
registered_method_(rm), |
|
|
|
|
allocator_(std::move(allocator)) {} |
|
|
|
|
void MatchOrQueue(size_t /*start_request_queue_index*/, |
|
|
|
|
call_data* calld) override { |
|
|
|
|
grpc_core::ServerRegisteredCallAllocation call_info = allocator_(); |
|
|
|
|
GPR_ASSERT(ValidateServerRequest(cq(), static_cast<void*>(call_info.tag), |
|
|
|
|
call_info.optional_payload, |
|
|
|
|
registered_method_) == GRPC_CALL_OK); |
|
|
|
|
requested_call* rc = new requested_call( |
|
|
|
|
static_cast<void*>(call_info.tag), cq(), call_info.call, |
|
|
|
|
call_info.initial_metadata, registered_method_, call_info.deadline, |
|
|
|
|
call_info.optional_payload); |
|
|
|
|
gpr_atm_no_barrier_store(&calld->state, ACTIVATED); |
|
|
|
|
publish_call(server(), calld, cq_idx(), rc); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private: |
|
|
|
|
registered_method* const registered_method_; |
|
|
|
|
std::function<grpc_core::ServerRegisteredCallAllocation()> allocator_; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* server proper |
|
|
|
|
*/ |
|
|
|
@ -546,10 +685,7 @@ void server_delete(grpc_server* server) { |
|
|
|
|
gpr_cv_destroy(&server->starting_cv); |
|
|
|
|
while ((rm = server->registered_methods) != nullptr) { |
|
|
|
|
server->registered_methods = rm->next; |
|
|
|
|
delete rm->matcher; |
|
|
|
|
gpr_free(rm->method); |
|
|
|
|
gpr_free(rm->host); |
|
|
|
|
gpr_free(rm); |
|
|
|
|
delete rm; |
|
|
|
|
} |
|
|
|
|
delete server->unregistered_request_matcher; |
|
|
|
|
for (i = 0; i < server->cq_count; i++) { |
|
|
|
@ -603,7 +739,9 @@ void destroy_channel(channel_data* chand) { |
|
|
|
|
op); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void done_request_event(void* req, grpc_cq_completion* /*c*/) { gpr_free(req); } |
|
|
|
|
void done_request_event(void* req, grpc_cq_completion* /*c*/) { |
|
|
|
|
delete static_cast<requested_call*>(req); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void publish_call(grpc_server* server, call_data* calld, size_t cq_idx, |
|
|
|
|
requested_call* rc) { |
|
|
|
@ -718,7 +856,8 @@ void start_new_rpc(grpc_call_element* elem) { |
|
|
|
|
GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST)) { |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
finish_start_new_rpc(server, elem, rm->server_registered_method->matcher, |
|
|
|
|
finish_start_new_rpc(server, elem, |
|
|
|
|
rm->server_registered_method->matcher.get(), |
|
|
|
|
rm->server_registered_method->payload_handling); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
@ -735,7 +874,8 @@ void start_new_rpc(grpc_call_element* elem) { |
|
|
|
|
GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST)) { |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
finish_start_new_rpc(server, elem, rm->server_registered_method->matcher, |
|
|
|
|
finish_start_new_rpc(server, elem, |
|
|
|
|
rm->server_registered_method->matcher.get(), |
|
|
|
|
rm->server_registered_method->payload_handling); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
@ -1101,7 +1241,7 @@ grpc_call_error queue_call_request(grpc_server* server, size_t cq_idx, |
|
|
|
|
rm = server->unregistered_request_matcher; |
|
|
|
|
break; |
|
|
|
|
case REGISTERED_CALL: |
|
|
|
|
rm = rc->data.registered.method->matcher; |
|
|
|
|
rm = rc->data.registered.method->matcher.get(); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
rm->RequestCallWithPossiblePublish(cq_idx, rc); |
|
|
|
@ -1119,6 +1259,26 @@ void fail_call(grpc_server* server, size_t cq_idx, requested_call* rc, |
|
|
|
|
} |
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
namespace grpc_core { |
|
|
|
|
|
|
|
|
|
void SetServerRegisteredMethodAllocator( |
|
|
|
|
grpc_server* server, grpc_completion_queue* cq, void* method_tag, |
|
|
|
|
std::function<ServerRegisteredCallAllocation()> allocator) { |
|
|
|
|
registered_method* rm = static_cast<registered_method*>(method_tag); |
|
|
|
|
rm->matcher.reset(new AllocatingRequestMatcherRegistered( |
|
|
|
|
server, cq, rm, std::move(allocator))); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void SetServerBatchMethodAllocator( |
|
|
|
|
grpc_server* server, grpc_completion_queue* cq, |
|
|
|
|
std::function<ServerBatchCallAllocation()> allocator) { |
|
|
|
|
GPR_DEBUG_ASSERT(server->unregistered_request_matcher == nullptr); |
|
|
|
|
server->unregistered_request_matcher = |
|
|
|
|
new AllocatingRequestMatcherBatch(server, cq, std::move(allocator)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
}; // namespace grpc_core
|
|
|
|
|
|
|
|
|
|
const grpc_channel_filter grpc_server_top_filter = { |
|
|
|
|
server_start_transport_stream_op_batch, |
|
|
|
|
grpc_channel_next_op, |
|
|
|
@ -1224,12 +1384,8 @@ void* grpc_server_register_method( |
|
|
|
|
flags); |
|
|
|
|
return nullptr; |
|
|
|
|
} |
|
|
|
|
m = static_cast<registered_method*>(gpr_zalloc(sizeof(registered_method))); |
|
|
|
|
m->method = gpr_strdup(method); |
|
|
|
|
m->host = gpr_strdup(host); |
|
|
|
|
m = new registered_method(method, host, payload_handling, flags); |
|
|
|
|
m->next = server->registered_methods; |
|
|
|
|
m->payload_handling = payload_handling; |
|
|
|
|
m->flags = flags; |
|
|
|
|
server->registered_methods = m; |
|
|
|
|
return m; |
|
|
|
|
} |
|
|
|
@ -1250,9 +1406,13 @@ void grpc_server_start(grpc_server* server) { |
|
|
|
|
grpc_cq_pollset(server->cqs[i]); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
server->unregistered_request_matcher = new RealRequestMatcher(server); |
|
|
|
|
if (server->unregistered_request_matcher == nullptr) { |
|
|
|
|
server->unregistered_request_matcher = new RealRequestMatcher(server); |
|
|
|
|
} |
|
|
|
|
for (registered_method* rm = server->registered_methods; rm; rm = rm->next) { |
|
|
|
|
rm->matcher = new RealRequestMatcher(server); |
|
|
|
|
if (rm->matcher == nullptr) { |
|
|
|
|
rm->matcher.reset(new RealRequestMatcher(server)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
gpr_mu_lock(&server->mu_global); |
|
|
|
@ -1523,15 +1683,51 @@ void grpc_server_add_listener( |
|
|
|
|
server->listeners = l; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
namespace { |
|
|
|
|
grpc_call_error ValidateServerRequest( |
|
|
|
|
grpc_completion_queue* cq_for_notification, void* tag, |
|
|
|
|
grpc_byte_buffer** optional_payload, registered_method* rm) { |
|
|
|
|
if ((rm == nullptr && optional_payload != nullptr) || |
|
|
|
|
((rm != nullptr) && ((optional_payload == nullptr) != |
|
|
|
|
(rm->payload_handling == GRPC_SRM_PAYLOAD_NONE)))) { |
|
|
|
|
return GRPC_CALL_ERROR_PAYLOAD_TYPE_MISMATCH; |
|
|
|
|
} |
|
|
|
|
if (grpc_cq_begin_op(cq_for_notification, tag) == false) { |
|
|
|
|
return GRPC_CALL_ERROR_COMPLETION_QUEUE_SHUTDOWN; |
|
|
|
|
} |
|
|
|
|
return GRPC_CALL_OK; |
|
|
|
|
} |
|
|
|
|
grpc_call_error ValidateServerRequestAndCq( |
|
|
|
|
size_t* cq_idx, grpc_server* server, |
|
|
|
|
grpc_completion_queue* cq_for_notification, void* tag, |
|
|
|
|
grpc_byte_buffer** optional_payload, registered_method* rm) { |
|
|
|
|
size_t idx; |
|
|
|
|
for (idx = 0; idx < server->cq_count; idx++) { |
|
|
|
|
if (server->cqs[idx] == cq_for_notification) { |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (idx == server->cq_count) { |
|
|
|
|
return GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE; |
|
|
|
|
} |
|
|
|
|
grpc_call_error error = |
|
|
|
|
ValidateServerRequest(cq_for_notification, tag, optional_payload, rm); |
|
|
|
|
if (error != GRPC_CALL_OK) { |
|
|
|
|
return error; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
*cq_idx = idx; |
|
|
|
|
return GRPC_CALL_OK; |
|
|
|
|
} |
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
grpc_call_error grpc_server_request_call( |
|
|
|
|
grpc_server* server, grpc_call** call, grpc_call_details* details, |
|
|
|
|
grpc_metadata_array* initial_metadata, |
|
|
|
|
grpc_completion_queue* cq_bound_to_call, |
|
|
|
|
grpc_completion_queue* cq_for_notification, void* tag) { |
|
|
|
|
grpc_call_error error; |
|
|
|
|
grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; |
|
|
|
|
grpc_core::ExecCtx exec_ctx; |
|
|
|
|
requested_call* rc = static_cast<requested_call*>(gpr_malloc(sizeof(*rc))); |
|
|
|
|
GRPC_STATS_INC_SERVER_REQUESTED_CALLS(); |
|
|
|
|
GRPC_API_TRACE( |
|
|
|
|
"grpc_server_request_call(" |
|
|
|
@ -1540,33 +1736,17 @@ grpc_call_error grpc_server_request_call( |
|
|
|
|
7, |
|
|
|
|
(server, call, details, initial_metadata, cq_bound_to_call, |
|
|
|
|
cq_for_notification, tag)); |
|
|
|
|
|
|
|
|
|
size_t cq_idx; |
|
|
|
|
for (cq_idx = 0; cq_idx < server->cq_count; cq_idx++) { |
|
|
|
|
if (server->cqs[cq_idx] == cq_for_notification) { |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (cq_idx == server->cq_count) { |
|
|
|
|
gpr_free(rc); |
|
|
|
|
error = GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE; |
|
|
|
|
goto done; |
|
|
|
|
grpc_call_error error = ValidateServerRequestAndCq( |
|
|
|
|
&cq_idx, server, cq_for_notification, tag, nullptr, nullptr); |
|
|
|
|
if (error != GRPC_CALL_OK) { |
|
|
|
|
return error; |
|
|
|
|
} |
|
|
|
|
if (grpc_cq_begin_op(cq_for_notification, tag) == false) { |
|
|
|
|
gpr_free(rc); |
|
|
|
|
error = GRPC_CALL_ERROR_COMPLETION_QUEUE_SHUTDOWN; |
|
|
|
|
goto done; |
|
|
|
|
} |
|
|
|
|
details->reserved = nullptr; |
|
|
|
|
rc->type = BATCH_CALL; |
|
|
|
|
rc->tag = tag; |
|
|
|
|
rc->cq_bound_to_call = cq_bound_to_call; |
|
|
|
|
rc->call = call; |
|
|
|
|
rc->data.batch.details = details; |
|
|
|
|
rc->initial_metadata = initial_metadata; |
|
|
|
|
error = queue_call_request(server, cq_idx, rc); |
|
|
|
|
done: |
|
|
|
|
|
|
|
|
|
return error; |
|
|
|
|
|
|
|
|
|
requested_call* rc = new requested_call(tag, cq_bound_to_call, call, |
|
|
|
|
initial_metadata, details); |
|
|
|
|
return queue_call_request(server, cq_idx, rc); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
grpc_call_error grpc_server_request_registered_call( |
|
|
|
@ -1577,7 +1757,6 @@ grpc_call_error grpc_server_request_registered_call( |
|
|
|
|
grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; |
|
|
|
|
grpc_core::ExecCtx exec_ctx; |
|
|
|
|
GRPC_STATS_INC_SERVER_REQUESTED_CALLS(); |
|
|
|
|
requested_call* rc = static_cast<requested_call*>(gpr_malloc(sizeof(*rc))); |
|
|
|
|
registered_method* rm = static_cast<registered_method*>(rmp); |
|
|
|
|
GRPC_API_TRACE( |
|
|
|
|
"grpc_server_request_registered_call(" |
|
|
|
@ -1589,33 +1768,15 @@ grpc_call_error grpc_server_request_registered_call( |
|
|
|
|
cq_bound_to_call, cq_for_notification, tag)); |
|
|
|
|
|
|
|
|
|
size_t cq_idx; |
|
|
|
|
for (cq_idx = 0; cq_idx < server->cq_count; cq_idx++) { |
|
|
|
|
if (server->cqs[cq_idx] == cq_for_notification) { |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (cq_idx == server->cq_count) { |
|
|
|
|
gpr_free(rc); |
|
|
|
|
return GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE; |
|
|
|
|
} |
|
|
|
|
if ((optional_payload == nullptr) != |
|
|
|
|
(rm->payload_handling == GRPC_SRM_PAYLOAD_NONE)) { |
|
|
|
|
gpr_free(rc); |
|
|
|
|
return GRPC_CALL_ERROR_PAYLOAD_TYPE_MISMATCH; |
|
|
|
|
grpc_call_error error = ValidateServerRequestAndCq( |
|
|
|
|
&cq_idx, server, cq_for_notification, tag, optional_payload, rm); |
|
|
|
|
if (error != GRPC_CALL_OK) { |
|
|
|
|
return error; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (grpc_cq_begin_op(cq_for_notification, tag) == false) { |
|
|
|
|
gpr_free(rc); |
|
|
|
|
return GRPC_CALL_ERROR_COMPLETION_QUEUE_SHUTDOWN; |
|
|
|
|
} |
|
|
|
|
rc->type = REGISTERED_CALL; |
|
|
|
|
rc->tag = tag; |
|
|
|
|
rc->cq_bound_to_call = cq_bound_to_call; |
|
|
|
|
rc->call = call; |
|
|
|
|
rc->data.registered.method = rm; |
|
|
|
|
rc->data.registered.deadline = deadline; |
|
|
|
|
rc->initial_metadata = initial_metadata; |
|
|
|
|
rc->data.registered.optional_payload = optional_payload; |
|
|
|
|
requested_call* rc = |
|
|
|
|
new requested_call(tag, cq_bound_to_call, call, initial_metadata, rm, |
|
|
|
|
deadline, optional_payload); |
|
|
|
|
return queue_call_request(server, cq_idx, rc); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|