|
|
|
@ -53,7 +53,7 @@ typedef enum { PENDING_START, ALL_CALLS, CALL_LIST_COUNT } call_list; |
|
|
|
|
|
|
|
|
|
typedef struct listener { |
|
|
|
|
void *arg; |
|
|
|
|
void (*start)(grpc_server *server, void *arg, grpc_pollset *pollset); |
|
|
|
|
void (*start)(grpc_server *server, void *arg, grpc_pollset **pollsets, size_t pollset_count); |
|
|
|
|
void (*destroy)(grpc_server *server, void *arg); |
|
|
|
|
struct listener *next; |
|
|
|
|
} listener; |
|
|
|
@ -101,6 +101,7 @@ struct registered_method { |
|
|
|
|
char *host; |
|
|
|
|
call_data *pending; |
|
|
|
|
requested_call_array requested; |
|
|
|
|
grpc_completion_queue *cq; |
|
|
|
|
registered_method *next; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
@ -127,7 +128,11 @@ struct grpc_server { |
|
|
|
|
size_t channel_filter_count; |
|
|
|
|
const grpc_channel_filter **channel_filters; |
|
|
|
|
grpc_channel_args *channel_args; |
|
|
|
|
grpc_completion_queue *cq; |
|
|
|
|
grpc_completion_queue *unregistered_cq; |
|
|
|
|
|
|
|
|
|
grpc_completion_queue **cqs; |
|
|
|
|
grpc_pollset **pollsets; |
|
|
|
|
size_t cq_count; |
|
|
|
|
|
|
|
|
|
gpr_mu mu; |
|
|
|
|
|
|
|
|
@ -169,6 +174,7 @@ struct call_data { |
|
|
|
|
grpc_mdstr *host; |
|
|
|
|
|
|
|
|
|
legacy_data *legacy; |
|
|
|
|
grpc_completion_queue *cq_new; |
|
|
|
|
|
|
|
|
|
call_data **root[CALL_LIST_COUNT]; |
|
|
|
|
call_link links[CALL_LIST_COUNT]; |
|
|
|
@ -496,7 +502,7 @@ static void init_call_elem(grpc_call_element *elem, |
|
|
|
|
static void destroy_call_elem(grpc_call_element *elem) { |
|
|
|
|
channel_data *chand = elem->channel_data; |
|
|
|
|
call_data *calld = elem->call_data; |
|
|
|
|
int i; |
|
|
|
|
size_t i; |
|
|
|
|
|
|
|
|
|
gpr_mu_lock(&chand->server->mu); |
|
|
|
|
for (i = 0; i < CALL_LIST_COUNT; i++) { |
|
|
|
@ -504,7 +510,9 @@ static void destroy_call_elem(grpc_call_element *elem) { |
|
|
|
|
} |
|
|
|
|
if (chand->server->shutdown && chand->server->have_shutdown_tag && |
|
|
|
|
chand->server->lists[ALL_CALLS] == NULL) { |
|
|
|
|
grpc_cq_end_server_shutdown(chand->server->cq, chand->server->shutdown_tag); |
|
|
|
|
for (i = 0; i < chand->server->cq_count; i++) { |
|
|
|
|
grpc_cq_end_server_shutdown(chand->server->cqs[i], chand->server->shutdown_tag); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
gpr_mu_unlock(&chand->server->mu); |
|
|
|
|
|
|
|
|
@ -557,6 +565,16 @@ static const grpc_channel_filter server_surface_filter = { |
|
|
|
|
sizeof(channel_data), init_channel_elem, destroy_channel_elem, "server", |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static void addcq(grpc_server *server, grpc_completion_queue *cq) { |
|
|
|
|
size_t i, n; |
|
|
|
|
for (i = 0; i < server->cq_count; i++) { |
|
|
|
|
if (server->cqs[i] == cq) return; |
|
|
|
|
} |
|
|
|
|
n = server->cq_count++; |
|
|
|
|
server->cqs = gpr_realloc(server->cqs, server->cq_count * sizeof(grpc_completion_queue*)); |
|
|
|
|
server->cqs[n] = cq; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
grpc_server *grpc_server_create_from_filters(grpc_completion_queue *cq, |
|
|
|
|
grpc_channel_filter **filters, |
|
|
|
|
size_t filter_count, |
|
|
|
@ -566,10 +584,11 @@ grpc_server *grpc_server_create_from_filters(grpc_completion_queue *cq, |
|
|
|
|
|
|
|
|
|
grpc_server *server = gpr_malloc(sizeof(grpc_server)); |
|
|
|
|
memset(server, 0, sizeof(grpc_server)); |
|
|
|
|
if (cq) addcq(server, cq); |
|
|
|
|
|
|
|
|
|
gpr_mu_init(&server->mu); |
|
|
|
|
|
|
|
|
|
server->cq = cq; |
|
|
|
|
server->unregistered_cq = cq; |
|
|
|
|
/* decremented by grpc_server_destroy */ |
|
|
|
|
gpr_ref_init(&server->internal_refcount, 1); |
|
|
|
|
server->root_channel_data.next = server->root_channel_data.prev = |
|
|
|
@ -605,7 +624,7 @@ static int streq(const char *a, const char *b) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void *grpc_server_register_method(grpc_server *server, const char *method, |
|
|
|
|
const char *host) { |
|
|
|
|
const char *host, grpc_completion_queue *cq_new_rpc) { |
|
|
|
|
registered_method *m; |
|
|
|
|
if (!method) { |
|
|
|
|
gpr_log(GPR_ERROR, "%s method string cannot be NULL", __FUNCTION__); |
|
|
|
@ -618,20 +637,28 @@ void *grpc_server_register_method(grpc_server *server, const char *method, |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
addcq(server, cq_new_rpc); |
|
|
|
|
m = gpr_malloc(sizeof(registered_method)); |
|
|
|
|
memset(m, 0, sizeof(*m)); |
|
|
|
|
m->method = gpr_strdup(method); |
|
|
|
|
m->host = gpr_strdup(host); |
|
|
|
|
m->next = server->registered_methods; |
|
|
|
|
m->cq = cq_new_rpc; |
|
|
|
|
server->registered_methods = m; |
|
|
|
|
return m; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void grpc_server_start(grpc_server *server) { |
|
|
|
|
listener *l; |
|
|
|
|
size_t i; |
|
|
|
|
|
|
|
|
|
server->pollsets = gpr_malloc(sizeof(grpc_pollset*) * server->cq_count); |
|
|
|
|
for (i = 0; i < server->cq_count; i++) { |
|
|
|
|
server->pollsets[i] = grpc_cq_pollset(server->cqs[i]); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (l = server->listeners; l; l = l->next) { |
|
|
|
|
l->start(server, l->arg, grpc_cq_pollset(server->cq)); |
|
|
|
|
l->start(server, l->arg, server->pollsets, server->cq_count); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -664,7 +691,9 @@ grpc_transport_setup_result grpc_server_setup_transport( |
|
|
|
|
} |
|
|
|
|
filters[i] = &grpc_connected_channel_filter; |
|
|
|
|
|
|
|
|
|
grpc_transport_add_to_pollset(transport, grpc_cq_pollset(s->cq)); |
|
|
|
|
for (i = 0; i < s->cq_count; i++) { |
|
|
|
|
grpc_transport_add_to_pollset(transport, grpc_cq_pollset(s->cqs[i])); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
channel = grpc_channel_create_from_filters(filters, num_filters, |
|
|
|
|
s->channel_args, mdctx, 0); |
|
|
|
@ -765,9 +794,11 @@ static void shutdown_internal(grpc_server *server, gpr_uint8 have_shutdown_tag, |
|
|
|
|
server->have_shutdown_tag = have_shutdown_tag; |
|
|
|
|
server->shutdown_tag = shutdown_tag; |
|
|
|
|
if (have_shutdown_tag) { |
|
|
|
|
grpc_cq_begin_op(server->cq, NULL, GRPC_SERVER_SHUTDOWN); |
|
|
|
|
if (server->lists[ALL_CALLS] == NULL) { |
|
|
|
|
grpc_cq_end_server_shutdown(server->cq, shutdown_tag); |
|
|
|
|
for (i = 0; i < server->cq_count; i++) { |
|
|
|
|
grpc_cq_begin_op(server->cqs[i], NULL, GRPC_SERVER_SHUTDOWN); |
|
|
|
|
if (server->lists[ALL_CALLS] == NULL) { |
|
|
|
|
grpc_cq_end_server_shutdown(server->cqs[i], shutdown_tag); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
gpr_mu_unlock(&server->mu); |
|
|
|
@ -826,7 +857,7 @@ void grpc_server_destroy(grpc_server *server) { |
|
|
|
|
|
|
|
|
|
void grpc_server_add_listener(grpc_server *server, void *arg, |
|
|
|
|
void (*start)(grpc_server *server, void *arg, |
|
|
|
|
grpc_pollset *pollset), |
|
|
|
|
grpc_pollset **pollsets, size_t pollset_count), |
|
|
|
|
void (*destroy)(grpc_server *server, void *arg)) { |
|
|
|
|
listener *l = gpr_malloc(sizeof(listener)); |
|
|
|
|
l->arg = arg; |
|
|
|
@ -878,7 +909,7 @@ grpc_call_error grpc_server_request_call(grpc_server *server, grpc_call **call, |
|
|
|
|
grpc_completion_queue *cq_bind, |
|
|
|
|
void *tag) { |
|
|
|
|
requested_call rc; |
|
|
|
|
grpc_cq_begin_op(server->cq, NULL, GRPC_OP_COMPLETE); |
|
|
|
|
grpc_cq_begin_op(server->unregistered_cq, NULL, GRPC_OP_COMPLETE); |
|
|
|
|
rc.type = BATCH_CALL; |
|
|
|
|
rc.tag = tag; |
|
|
|
|
rc.data.batch.cq_bind = cq_bind; |
|
|
|
@ -889,12 +920,13 @@ grpc_call_error grpc_server_request_call(grpc_server *server, grpc_call **call, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
grpc_call_error grpc_server_request_registered_call( |
|
|
|
|
grpc_server *server, void *registered_method, grpc_call **call, |
|
|
|
|
grpc_server *server, void *rm, grpc_call **call, |
|
|
|
|
gpr_timespec *deadline, grpc_metadata_array *initial_metadata, |
|
|
|
|
grpc_byte_buffer **optional_payload, grpc_completion_queue *cq_bind, |
|
|
|
|
void *tag) { |
|
|
|
|
requested_call rc; |
|
|
|
|
grpc_cq_begin_op(server->cq, NULL, GRPC_OP_COMPLETE); |
|
|
|
|
registered_method *registered_method = rm; |
|
|
|
|
grpc_cq_begin_op(registered_method->cq, NULL, GRPC_OP_COMPLETE); |
|
|
|
|
rc.type = REGISTERED_CALL; |
|
|
|
|
rc.tag = tag; |
|
|
|
|
rc.data.registered.cq_bind = cq_bind; |
|
|
|
@ -909,7 +941,7 @@ grpc_call_error grpc_server_request_registered_call( |
|
|
|
|
grpc_call_error grpc_server_request_call_old(grpc_server *server, |
|
|
|
|
void *tag_new) { |
|
|
|
|
requested_call rc; |
|
|
|
|
grpc_cq_begin_op(server->cq, NULL, GRPC_SERVER_RPC_NEW); |
|
|
|
|
grpc_cq_begin_op(server->unregistered_cq, NULL, GRPC_SERVER_RPC_NEW); |
|
|
|
|
rc.type = LEGACY_CALL; |
|
|
|
|
rc.tag = tag_new; |
|
|
|
|
return queue_call_request(server, &rc); |
|
|
|
@ -965,6 +997,7 @@ static void begin_call(grpc_server *server, call_data *calld, |
|
|
|
|
r->op = GRPC_IOREQ_RECV_INITIAL_METADATA; |
|
|
|
|
r->data.recv_metadata = rc->data.batch.initial_metadata; |
|
|
|
|
r++; |
|
|
|
|
calld->cq_new = server->unregistered_cq; |
|
|
|
|
publish = publish_registered_or_batch; |
|
|
|
|
break; |
|
|
|
|
case REGISTERED_CALL: |
|
|
|
@ -979,6 +1012,7 @@ static void begin_call(grpc_server *server, call_data *calld, |
|
|
|
|
r->data.recv_message = rc->data.registered.optional_payload; |
|
|
|
|
r++; |
|
|
|
|
} |
|
|
|
|
calld->cq_new = rc->data.registered.registered_method->cq; |
|
|
|
|
publish = publish_registered_or_batch; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
@ -991,19 +1025,19 @@ static void begin_call(grpc_server *server, call_data *calld, |
|
|
|
|
static void fail_call(grpc_server *server, requested_call *rc) { |
|
|
|
|
switch (rc->type) { |
|
|
|
|
case LEGACY_CALL: |
|
|
|
|
grpc_cq_end_new_rpc(server->cq, rc->tag, NULL, do_nothing, NULL, NULL, |
|
|
|
|
grpc_cq_end_new_rpc(server->unregistered_cq, rc->tag, NULL, do_nothing, NULL, NULL, |
|
|
|
|
NULL, gpr_inf_past, 0, NULL); |
|
|
|
|
break; |
|
|
|
|
case BATCH_CALL: |
|
|
|
|
*rc->data.batch.call = NULL; |
|
|
|
|
rc->data.batch.initial_metadata->count = 0; |
|
|
|
|
grpc_cq_end_op_complete(server->cq, rc->tag, NULL, do_nothing, NULL, |
|
|
|
|
grpc_cq_end_op_complete(server->unregistered_cq, rc->tag, NULL, do_nothing, NULL, |
|
|
|
|
GRPC_OP_ERROR); |
|
|
|
|
break; |
|
|
|
|
case REGISTERED_CALL: |
|
|
|
|
*rc->data.registered.call = NULL; |
|
|
|
|
rc->data.registered.initial_metadata->count = 0; |
|
|
|
|
grpc_cq_end_op_complete(server->cq, rc->tag, NULL, do_nothing, NULL, |
|
|
|
|
grpc_cq_end_op_complete(rc->data.registered.registered_method->cq, rc->tag, NULL, do_nothing, NULL, |
|
|
|
|
GRPC_OP_ERROR); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
@ -1017,7 +1051,7 @@ static void publish_legacy(grpc_call *call, grpc_op_error status, void *tag) { |
|
|
|
|
grpc_server *server = chand->server; |
|
|
|
|
|
|
|
|
|
if (status == GRPC_OP_OK) { |
|
|
|
|
grpc_cq_end_new_rpc(server->cq, tag, call, do_nothing, NULL, |
|
|
|
|
grpc_cq_end_new_rpc(server->unregistered_cq, tag, call, do_nothing, NULL, |
|
|
|
|
grpc_mdstr_as_c_string(calld->path), |
|
|
|
|
grpc_mdstr_as_c_string(calld->host), calld->deadline, |
|
|
|
|
calld->legacy->initial_metadata.count, |
|
|
|
@ -1032,9 +1066,8 @@ static void publish_registered_or_batch(grpc_call *call, grpc_op_error status, |
|
|
|
|
void *tag) { |
|
|
|
|
grpc_call_element *elem = |
|
|
|
|
grpc_call_stack_element(grpc_call_get_call_stack(call), 0); |
|
|
|
|
channel_data *chand = elem->channel_data; |
|
|
|
|
grpc_server *server = chand->server; |
|
|
|
|
grpc_cq_end_op_complete(server->cq, tag, call, do_nothing, NULL, status); |
|
|
|
|
call_data *calld = elem->call_data; |
|
|
|
|
grpc_cq_end_op_complete(calld->cq_new, tag, call, do_nothing, NULL, status); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const grpc_channel_args *grpc_server_get_channel_args(grpc_server *server) { |
|
|
|
|