static grpc_call_error queue_call_request(grpc_exec_ctx *exec_ctx, grpc_server *server, size_t cq_idx, requested_call *rc) { call_data *calld = NULL; request_matcher *rm = NULL; int request_id; if (gpr_atm_acq_load(&server->shutdown_flag)) { fail_call(exec_ctx, server, cq_idx, rc, GRPC_ERROR_CREATE("Server Shutdown")); return GRPC_CALL_OK; } request_id = gpr_stack_lockfree_pop(server->request_freelist_per_cq[cq_idx]); if (request_id == -1) { /* out of request ids: just fail this one */ fail_call(exec_ctx, server, cq_idx, rc, grpc_error_set_int(GRPC_ERROR_CREATE("Out of request ids"), GRPC_ERROR_INT_LIMIT, server->max_requested_calls_per_cq)); return GRPC_CALL_OK; } switch (rc->type) { case BATCH_CALL: rm = &server->unregistered_request_matcher; break; case REGISTERED_CALL: rm = &rc->data.registered.registered_method->request_matcher; break; } server->requested_calls_per_cq[cq_idx][request_id] = *rc; gpr_free(rc); if (gpr_stack_lockfree_push(rm->requests_per_cq[cq_idx], request_id)) { /* this was the first queued request: we need to lock and start matching calls */ gpr_mu_lock(&server->mu_call); while ((calld = rm->pending_head) != NULL) { request_id = gpr_stack_lockfree_pop(rm->requests_per_cq[cq_idx]); if (request_id == -1) break; rm->pending_head = calld->pending_next; gpr_mu_unlock(&server->mu_call); gpr_mu_lock(&calld->mu_state); if (calld->state == ZOMBIED) { gpr_mu_unlock(&calld->mu_state); grpc_closure_init( &calld->kill_zombie_closure, kill_zombie, grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0)); grpc_exec_ctx_sched(exec_ctx, &calld->kill_zombie_closure, GRPC_ERROR_NONE, NULL); } else { GPR_ASSERT(calld->state == PENDING); calld->state = ACTIVATED; gpr_mu_unlock(&calld->mu_state); publish_call(exec_ctx, server, calld, cq_idx, &server->requested_calls_per_cq[cq_idx][request_id]); } gpr_mu_lock(&server->mu_call); } gpr_mu_unlock(&server->mu_call); } return GRPC_CALL_OK; }
static grpc_call_error queue_call_request(grpc_server *server, requested_call *rc) { call_data *calld = NULL; requested_call_array *requested_calls = NULL; gpr_mu_lock(&server->mu); if (server->shutdown) { gpr_mu_unlock(&server->mu); fail_call(server, rc); return GRPC_CALL_OK; } switch (rc->type) { case LEGACY_CALL: case BATCH_CALL: calld = call_list_remove_head(&server->lists[PENDING_START], PENDING_START); requested_calls = &server->requested_calls; break; case REGISTERED_CALL: calld = call_list_remove_head( &rc->data.registered.registered_method->pending, PENDING_START); requested_calls = &rc->data.registered.registered_method->requested; break; } if (calld) { GPR_ASSERT(calld->state == PENDING); calld->state = ACTIVATED; gpr_mu_unlock(&server->mu); begin_call(server, calld, rc); return GRPC_CALL_OK; } else { *requested_call_array_add(requested_calls) = *rc; gpr_mu_unlock(&server->mu); return GRPC_CALL_OK; } }
static void request_matcher_kill_requests(grpc_exec_ctx *exec_ctx, grpc_server *server, request_matcher *rm) { int request_id; while ((request_id = gpr_stack_lockfree_pop(rm->requests)) != -1) { fail_call(exec_ctx, server, &server->requested_calls[request_id]); } }
static void request_matcher_kill_requests(grpc_exec_ctx *exec_ctx, grpc_server *server, request_matcher *rm) { int request_id; for (size_t i = 0; i < server->cq_count; i++) { while ((request_id = gpr_stack_lockfree_pop(rm->requests_per_cq[i])) != -1) { fail_call(exec_ctx, server, i, &server->requested_calls[request_id]); } } }
static void request_matcher_kill_requests(grpc_exec_ctx *exec_ctx, grpc_server *server, request_matcher *rm, grpc_error *error) { int request_id; for (size_t i = 0; i < server->cq_count; i++) { while ((request_id = gpr_stack_lockfree_pop(rm->requests_per_cq[i])) != -1) { fail_call(exec_ctx, server, i, &server->requested_calls_per_cq[i][request_id], GRPC_ERROR_REF(error)); } } GRPC_ERROR_UNREF(error); }
static void shutdown_internal(grpc_server *server, gpr_uint8 have_shutdown_tag, void *shutdown_tag) { listener *l; requested_call_array requested_calls; channel_data **channels; channel_data *c; size_t nchannels; size_t i, j; grpc_channel_op op; grpc_channel_element *elem; registered_method *rm; /* lock, and gather up some stuff to do */ gpr_mu_lock(&server->mu); if (have_shutdown_tag) { for (i = 0; i < server->cq_count; i++) { grpc_cq_begin_op(server->cqs[i], NULL, GRPC_SERVER_SHUTDOWN); } server->shutdown_tags = gpr_realloc(server->shutdown_tags, sizeof(void *) * (server->num_shutdown_tags + 1)); server->shutdown_tags[server->num_shutdown_tags++] = shutdown_tag; } if (server->shutdown) { gpr_mu_unlock(&server->mu); return; } nchannels = 0; for (c = server->root_channel_data.next; c != &server->root_channel_data; c = c->next) { nchannels++; } channels = gpr_malloc(sizeof(channel_data *) * nchannels); i = 0; for (c = server->root_channel_data.next; c != &server->root_channel_data; c = c->next) { grpc_channel_internal_ref(c->channel); channels[i] = c; i++; } /* collect all unregistered then registered calls */ requested_calls = server->requested_calls; memset(&server->requested_calls, 0, sizeof(server->requested_calls)); for (rm = server->registered_methods; rm; rm = rm->next) { if (requested_calls.count + rm->requested.count > requested_calls.capacity) { requested_calls.capacity = GPR_MAX(requested_calls.count + rm->requested.count, 2 * requested_calls.capacity); requested_calls.calls = gpr_realloc(requested_calls.calls, sizeof(*requested_calls.calls) * requested_calls.capacity); } memcpy(requested_calls.calls + requested_calls.count, rm->requested.calls, sizeof(*requested_calls.calls) * rm->requested.count); requested_calls.count += rm->requested.count; gpr_free(rm->requested.calls); memset(&rm->requested, 0, sizeof(rm->requested)); } server->shutdown = 1; if (server->lists[ALL_CALLS] == NULL) { for (i = 0; i < server->num_shutdown_tags; i++) { for (j = 0; j < server->cq_count; j++) { grpc_cq_end_server_shutdown(server->cqs[j], server->shutdown_tags[i]); } } } gpr_mu_unlock(&server->mu); for (i = 0; i < nchannels; i++) { c = channels[i]; elem = grpc_channel_stack_element( grpc_channel_get_channel_stack(c->channel), 0); op.type = GRPC_CHANNEL_GOAWAY; op.dir = GRPC_CALL_DOWN; op.data.goaway.status = GRPC_STATUS_OK; op.data.goaway.message = gpr_slice_from_copied_string("Server shutdown"); elem->filter->channel_op(elem, NULL, &op); grpc_channel_internal_unref(c->channel); } gpr_free(channels); /* terminate all the requested calls */ for (i = 0; i < requested_calls.count; i++) { fail_call(server, &requested_calls.calls[i]); } gpr_free(requested_calls.calls); /* Shutdown listeners */ for (l = server->listeners; l; l = l->next) { l->destroy(server, l->arg); } }
void grpc_server_shutdown_and_notify(grpc_server *server, grpc_completion_queue *cq, void *tag) { listener *l; requested_call_array requested_calls; channel_data *c; size_t i; registered_method *rm; shutdown_tag *sdt; /* lock, and gather up some stuff to do */ gpr_mu_lock(&server->mu_global); grpc_cq_begin_op(cq, NULL); server->shutdown_tags = gpr_realloc(server->shutdown_tags, sizeof(shutdown_tag) * (server->num_shutdown_tags + 1)); sdt = &server->shutdown_tags[server->num_shutdown_tags++]; sdt->tag = tag; sdt->cq = cq; if (server->shutdown) { gpr_mu_unlock(&server->mu_global); return; } for (c = server->root_channel_data.next; c != &server->root_channel_data; c = c->next) { shutdown_channel(c, 1, c->num_calls == 0); } /* collect all unregistered then registered calls */ gpr_mu_lock(&server->mu_call); requested_calls = server->requested_calls; memset(&server->requested_calls, 0, sizeof(server->requested_calls)); for (rm = server->registered_methods; rm; rm = rm->next) { if (requested_calls.count + rm->requested.count > requested_calls.capacity) { requested_calls.capacity = GPR_MAX(requested_calls.count + rm->requested.count, 2 * requested_calls.capacity); requested_calls.calls = gpr_realloc(requested_calls.calls, sizeof(*requested_calls.calls) * requested_calls.capacity); } memcpy(requested_calls.calls + requested_calls.count, rm->requested.calls, sizeof(*requested_calls.calls) * rm->requested.count); requested_calls.count += rm->requested.count; gpr_free(rm->requested.calls); memset(&rm->requested, 0, sizeof(rm->requested)); } gpr_mu_unlock(&server->mu_call); server->shutdown = 1; maybe_finish_shutdown(server); gpr_mu_unlock(&server->mu_global); /* terminate all the requested calls */ for (i = 0; i < requested_calls.count; i++) { fail_call(server, &requested_calls.calls[i]); } gpr_free(requested_calls.calls); /* Shutdown listeners */ for (l = server->listeners; l; l = l->next) { l->destroy(server, l->arg); } }