static void server_on_recv(void *ptr, int success) { grpc_call_element *elem = ptr; call_data *calld = elem->call_data; channel_data *chand = elem->channel_data; if (success && !calld->got_initial_metadata) { size_t i; size_t nops = calld->recv_ops->nops; grpc_stream_op *ops = calld->recv_ops->ops; for (i = 0; i < nops; i++) { grpc_stream_op *op = &ops[i]; if (op->type != GRPC_OP_METADATA) continue; grpc_metadata_batch_filter(&op->data.metadata, server_filter, elem); if (0 != gpr_time_cmp(op->data.metadata.deadline, gpr_inf_future)) { calld->deadline = op->data.metadata.deadline; } calld->got_initial_metadata = 1; start_new_rpc(elem); break; } } switch (*calld->recv_state) { case GRPC_STREAM_OPEN: break; case GRPC_STREAM_SEND_CLOSED: break; case GRPC_STREAM_RECV_CLOSED: gpr_mu_lock(&chand->server->mu); if (calld->state == NOT_STARTED) { calld->state = ZOMBIED; grpc_iomgr_add_callback(kill_zombie, elem); } gpr_mu_unlock(&chand->server->mu); break; case GRPC_STREAM_CLOSED: gpr_mu_lock(&chand->server->mu); if (calld->state == NOT_STARTED) { calld->state = ZOMBIED; grpc_iomgr_add_callback(kill_zombie, elem); } else if (calld->state == PENDING) { call_list_remove(calld, PENDING_START); calld->state = ZOMBIED; grpc_iomgr_add_callback(kill_zombie, elem); } gpr_mu_unlock(&chand->server->mu); break; } calld->on_done_recv(calld->recv_user_data, success); }
void grpc_channel_internal_unref(grpc_channel *channel) { if (gpr_unref(&channel->refs)) { channel->destroy_closure.cb = destroy_channel; channel->destroy_closure.cb_arg = channel; grpc_iomgr_add_callback(&channel->destroy_closure); } }
static void on_secure_transport_setup_done(void *arg, grpc_security_status status, grpc_endpoint *wrapped_endpoint, grpc_endpoint *secure_endpoint) { connector *c = arg; grpc_iomgr_closure *notify; gpr_mu_lock(&c->mu); if (c->connecting_endpoint == NULL) { memset(c->result, 0, sizeof(*c->result)); gpr_mu_unlock(&c->mu); } else if (status != GRPC_SECURITY_OK) { GPR_ASSERT(c->connecting_endpoint == wrapped_endpoint); gpr_log(GPR_ERROR, "Secure transport setup failed with error %d.", status); memset(c->result, 0, sizeof(*c->result)); c->connecting_endpoint = NULL; gpr_mu_unlock(&c->mu); } else { GPR_ASSERT(c->connecting_endpoint == wrapped_endpoint); c->connecting_endpoint = NULL; gpr_mu_unlock(&c->mu); c->result->transport = grpc_create_chttp2_transport( c->args.channel_args, secure_endpoint, c->args.metadata_context, 1); grpc_chttp2_transport_start_reading(c->result->transport, NULL, 0); c->result->filters = gpr_malloc(sizeof(grpc_channel_filter *) * 2); c->result->filters[0] = &grpc_http_client_filter; c->result->filters[1] = &grpc_client_auth_filter; c->result->num_filters = 2; } notify = c->notify; c->notify = NULL; grpc_iomgr_add_callback(notify); }
static void maybe_destroy_channel(grpc_child_channel *channel) { lb_channel_data *chand = LINK_BACK_ELEM_FROM_CHANNEL(channel)->channel_data; if (chand->destroyed && chand->disconnected && chand->active_calls == 0 && !chand->sending_farewell && !chand->calling_back) { chand->finally_destroy_channel_closure.cb = finally_destroy_channel; chand->finally_destroy_channel_closure.cb_arg = channel; grpc_iomgr_add_callback(&chand->finally_destroy_channel_closure); } else if (chand->destroyed && !chand->disconnected && chand->active_calls == 0 && !chand->sending_farewell && !chand->sent_farewell) { chand->sending_farewell = 1; chand->send_farewells_closure.cb = send_farewells; chand->send_farewells_closure.cb_arg = channel; grpc_iomgr_add_callback(&chand->send_farewells_closure); } }
static void destroy_channel(channel_data *chand) { if (is_channel_orphaned(chand)) return; GPR_ASSERT(chand->server != NULL); orphan_channel(chand); server_ref(chand->server); grpc_iomgr_add_callback(finish_destroy_channel, chand); }
void grpc_call_internal_unref(grpc_call *c, const char *reason, int allow_immediate_deletion) { gpr_log(GPR_DEBUG, "CALL: unref %p %d -> %d [%s]", c, c->internal_refcount.count, c->internal_refcount.count - 1, reason); #else void grpc_call_internal_unref(grpc_call *c, int allow_immediate_deletion) { #endif if (gpr_unref(&c->internal_refcount)) { if (allow_immediate_deletion) { destroy_call(c, 1); } else { grpc_iomgr_add_callback(destroy_call, c); } } } static void set_status_code(grpc_call *call, status_source source, gpr_uint32 status) { call->status[source].is_set = 1; call->status[source].code = status; if (status != GRPC_STATUS_OK && !grpc_bbq_empty(&call->incoming_queue)) { grpc_bbq_flush(&call->incoming_queue); } }
void grpc_call_internal_unref(grpc_call *c, int allow_immediate_deletion) { if (gpr_unref(&c->internal_refcount)) { if (allow_immediate_deletion) { destroy_call(c, 1); } else { grpc_iomgr_add_callback(destroy_call, c); } } }
static void unref_by(grpc_fd *fd, int n) { gpr_atm old = gpr_atm_full_fetch_add(&fd->refst, -n); if (old == n) { grpc_iomgr_add_callback(&fd->on_done_closure); freelist_fd(fd); grpc_iomgr_unregister_object(&fd->iomgr_object); } else { GPR_ASSERT(old > n); } }
static void destroy_channel(channel_data *chand) { if (is_channel_orphaned(chand)) return; GPR_ASSERT(chand->server != NULL); orphan_channel(chand); server_ref(chand->server); maybe_finish_shutdown(chand->server); chand->finish_destroy_channel_closure.cb = finish_destroy_channel; chand->finish_destroy_channel_closure.cb_arg = chand; grpc_iomgr_add_callback(&chand->finish_destroy_channel_closure); }
static void dns_shutdown(grpc_resolver *resolver) { dns_resolver *r = (dns_resolver *)resolver; gpr_mu_lock(&r->mu); if (r->next_completion != NULL) { *r->target_config = NULL; grpc_iomgr_add_callback(r->next_completion); r->next_completion = NULL; } gpr_mu_unlock(&r->mu); }
static void unix_shutdown(grpc_resolver *resolver) { unix_resolver *r = (unix_resolver *)resolver; gpr_mu_lock(&r->mu); if (r->next_completion != NULL) { *r->target_config = NULL; /* TODO(ctiller): add delayed callback */ grpc_iomgr_add_callback(r->next_completion); r->next_completion = NULL; } gpr_mu_unlock(&r->mu); }
static void shutdown_channel(channel_data *chand, int send_goaway, int send_disconnect) { shutdown_channel_args *sca; GRPC_CHANNEL_INTERNAL_REF(chand->channel, "shutdown"); sca = gpr_malloc(sizeof(shutdown_channel_args)); sca->chand = chand; sca->send_goaway = send_goaway; sca->send_disconnect = send_disconnect; sca->finish_shutdown_channel_closure.cb = finish_shutdown_channel; sca->finish_shutdown_channel_closure.cb_arg = sca; grpc_iomgr_add_callback(&sca->finish_shutdown_channel_closure); }
static void dns_maybe_finish_next_locked(dns_resolver *r) { if (r->next_completion != NULL && r->resolved_version != r->published_version) { *r->target_config = r->resolved_config; if (r->resolved_config) { grpc_client_config_ref(r->resolved_config); } grpc_iomgr_add_callback(r->next_completion); r->next_completion = NULL; r->published_version = r->resolved_version; } }
static void connected(void *arg, grpc_endpoint *tcp) { connector *c = arg; grpc_iomgr_closure *notify; if (tcp != NULL) { grpc_setup_secure_transport(&c->security_connector->base, tcp, on_secure_transport_setup_done, c); } else { memset(c->result, 0, sizeof(*c->result)); notify = c->notify; c->notify = NULL; grpc_iomgr_add_callback(notify); } }
static void fake_oauth2_get_request_metadata(grpc_credentials *creds, const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) { grpc_fake_oauth2_credentials *c = (grpc_fake_oauth2_credentials *)creds; if (c->is_async) { grpc_iomgr_add_callback( on_simulated_token_fetch_done, grpc_credentials_metadata_request_create(creds, cb, user_data)); } else { cb(user_data, &c->access_token_md, 1, GRPC_CREDENTIALS_OK); } }
static void basic_pollset_add_fd(grpc_pollset *pollset, grpc_fd *fd, int and_unlock_pollset) { grpc_unary_promote_args *up_args; GPR_ASSERT(fd); if (fd == pollset->data.ptr) goto exit; if (!grpc_pollset_has_workers(pollset)) { /* Fast path -- no in flight cbs */ /* TODO(klempner): Comment this out and fix any test failures or establish * they are due to timing issues */ grpc_fd *fds[2]; fds[0] = pollset->data.ptr; fds[1] = fd; if (fds[0] == NULL) { pollset->data.ptr = fd; GRPC_FD_REF(fd, "basicpoll"); } else if (!grpc_fd_is_orphaned(fds[0])) { grpc_platform_become_multipoller(pollset, fds, GPR_ARRAY_SIZE(fds)); GRPC_FD_UNREF(fds[0], "basicpoll"); } else { /* old fd is orphaned and we haven't cleaned it up until now, so remain a * unary poller */ GRPC_FD_UNREF(fds[0], "basicpoll"); pollset->data.ptr = fd; GRPC_FD_REF(fd, "basicpoll"); } goto exit; } /* Now we need to promote. This needs to happen when we're not polling. Since * this may be called from poll, the wait needs to happen asynchronously. */ GRPC_FD_REF(fd, "basicpoll_add"); pollset->in_flight_cbs++; up_args = gpr_malloc(sizeof(*up_args)); up_args->pollset = pollset; up_args->fd = fd; up_args->original_vtable = pollset->vtable; up_args->promotion_closure.cb = basic_do_promote; up_args->promotion_closure.cb_arg = up_args; grpc_iomgr_add_callback(&up_args->promotion_closure); grpc_pollset_kick(pollset, GRPC_POLLSET_KICK_BROADCAST); exit: if (and_unlock_pollset) { gpr_mu_unlock(&pollset->mu); } }
/* Called when an alarm expires. */ static void alarm_cb(void *arg /* alarm_arg */, int success) { alarm_arg *a = arg; gpr_mu_lock(&a->mu); if (success) { a->counter++; a->done_success_ctr++; } else { a->done_cancel_ctr++; } a->done = 1; a->success = success; gpr_cv_signal(&a->cv); gpr_mu_unlock(&a->mu); grpc_iomgr_add_callback(followup_cb, &a->fcb_arg); }
void grpc_connectivity_state_destroy(grpc_connectivity_state_tracker *tracker) { grpc_connectivity_state_watcher *w; while ((w = tracker->watchers)) { tracker->watchers = w->next; if (GRPC_CHANNEL_FATAL_FAILURE != *w->current) { *w->current = GRPC_CHANNEL_FATAL_FAILURE; grpc_iomgr_add_callback(w->notify); } else { grpc_iomgr_add_delayed_callback(w->notify, 0); } gpr_free(w); } gpr_free(tracker->name); }
static void multipoll_with_epoll_pollset_add_fd(grpc_pollset *pollset, grpc_fd *fd, int and_unlock_pollset) { if (and_unlock_pollset) { gpr_mu_unlock(&pollset->mu); finally_add_fd(pollset, fd); } else { delayed_add *da = gpr_malloc(sizeof(*da)); da->pollset = pollset; da->fd = fd; GRPC_FD_REF(fd, "delayed_add"); grpc_iomgr_closure_init(&da->closure, perform_delayed_add, da); pollset->in_flight_cbs++; grpc_iomgr_add_callback(&da->closure); } }
static void fake_oauth2_get_request_metadata(grpc_credentials *creds, const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) { grpc_fake_oauth2_credentials *c = (grpc_fake_oauth2_credentials *)creds; if (c->is_async) { grpc_credentials_metadata_request *cb_arg = grpc_credentials_metadata_request_create(creds, cb, user_data); grpc_iomgr_closure_init(cb_arg->on_simulated_token_fetch_done_closure, on_simulated_token_fetch_done, cb_arg); grpc_iomgr_add_callback(cb_arg->on_simulated_token_fetch_done_closure); } else { cb(user_data, c->access_token_md->entries, 1, GRPC_CREDENTIALS_OK); } }
void grpc_server_destroy(grpc_server *server) { channel_data *c; listener *l; size_t i; call_data *calld; gpr_mu_lock(&server->mu); if (!server->shutdown) { gpr_mu_unlock(&server->mu); grpc_server_shutdown(server); gpr_mu_lock(&server->mu); } while (server->listeners_destroyed != num_listeners(server)) { for (i = 0; i < server->cq_count; i++) { gpr_mu_unlock(&server->mu); grpc_cq_hack_spin_pollset(server->cqs[i]); gpr_mu_lock(&server->mu); } gpr_cv_wait(&server->cv, &server->mu, gpr_time_add(gpr_now(), gpr_time_from_millis(100))); } while (server->listeners) { l = server->listeners; server->listeners = l->next; gpr_free(l); } while ((calld = call_list_remove_head(&server->lists[PENDING_START], PENDING_START)) != NULL) { gpr_log(GPR_DEBUG, "server destroys call %p", calld->call); calld->state = ZOMBIED; grpc_iomgr_add_callback( kill_zombie, grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0)); } for (c = server->root_channel_data.next; c != &server->root_channel_data; c = c->next) { shutdown_channel(c); } gpr_mu_unlock(&server->mu); server_unref(server); }
void grpc_fd_orphan(grpc_fd *fd, grpc_iomgr_closure *on_done, const char *reason) { fd->on_done_closure = on_done; shutdown(fd->fd, SHUT_RDWR); REF_BY(fd, 1, reason); /* remove active status, but keep referenced */ gpr_mu_lock(&fd->watcher_mu); if (!has_watchers(fd)) { close(fd->fd); if (fd->on_done_closure) { grpc_iomgr_add_callback(fd->on_done_closure); } } else { wake_all_watchers_locked(fd); } gpr_mu_unlock(&fd->watcher_mu); UNREF_BY(fd, 2, reason); /* drop the reference */ }
static void read_closed(grpc_call_element *elem) { call_data *calld = elem->call_data; channel_data *chand = elem->channel_data; gpr_mu_lock(&chand->server->mu); switch (calld->state) { case ACTIVATED: case PENDING: grpc_call_read_closed(elem); break; case NOT_STARTED: calld->state = ZOMBIED; grpc_iomgr_add_callback(kill_zombie, elem); break; case ZOMBIED: break; } gpr_mu_unlock(&chand->server->mu); }
int grpc_connectivity_state_notify_on_state_change( grpc_connectivity_state_tracker *tracker, grpc_connectivity_state *current, grpc_iomgr_closure *notify) { if (grpc_connectivity_state_trace) { gpr_log(GPR_DEBUG, "CONWATCH: %s: from %s [cur=%s]", tracker->name, grpc_connectivity_state_name(*current), grpc_connectivity_state_name(tracker->current_state)); } if (tracker->current_state != *current) { *current = tracker->current_state; grpc_iomgr_add_callback(notify); } else { grpc_connectivity_state_watcher *w = gpr_malloc(sizeof(*w)); w->current = current; w->notify = notify; w->next = tracker->watchers; tracker->watchers = w; } return tracker->current_state == GRPC_CHANNEL_IDLE; }
static void stream_closed(grpc_call_element *elem) { call_data *calld = elem->call_data; channel_data *chand = elem->channel_data; gpr_mu_lock(&chand->server->mu); switch (calld->state) { case ACTIVATED: break; case PENDING: call_list_remove(calld, PENDING_START); /* fallthrough intended */ case NOT_STARTED: calld->state = ZOMBIED; grpc_iomgr_add_callback(kill_zombie, elem); break; case ZOMBIED: break; } gpr_mu_unlock(&chand->server->mu); grpc_call_stream_closed(elem); }
void grpc_fd_end_poll(grpc_fd_watcher *watcher, int got_read, int got_write) { int was_polling = 0; int kick = 0; grpc_fd *fd = watcher->fd; if (fd == NULL) { return; } gpr_mu_lock(&fd->watcher_mu); if (watcher == fd->read_watcher) { /* remove read watcher, kick if we still need a read */ was_polling = 1; kick = kick || !got_read; fd->read_watcher = NULL; } if (watcher == fd->write_watcher) { /* remove write watcher, kick if we still need a write */ was_polling = 1; kick = kick || !got_write; fd->write_watcher = NULL; } if (!was_polling) { /* remove from inactive list */ watcher->next->prev = watcher->prev; watcher->prev->next = watcher->next; } if (kick) { maybe_wake_one_watcher_locked(fd); } if (grpc_fd_is_orphaned(fd) && !has_watchers(fd) && !fd->closed) { fd->closed = 1; close(fd->fd); if (fd->on_done_closure != NULL) { grpc_iomgr_add_callback(fd->on_done_closure); } } gpr_mu_unlock(&fd->watcher_mu); GRPC_FD_UNREF(fd, "poll"); }
static void unref_by(grpc_fd *fd, int n, const char *reason, const char *file, int line) { gpr_atm old; gpr_log(GPR_DEBUG, "FD %d %p unref %d %d -> %d [%s; %s:%d]", fd->fd, fd, n, gpr_atm_no_barrier_load(&fd->refst), gpr_atm_no_barrier_load(&fd->refst) - n, reason, file, line); #else static void unref_by(grpc_fd *fd, int n) { gpr_atm old; #endif old = gpr_atm_full_fetch_add(&fd->refst, -n); if (old == n) { if (fd->on_done_closure) { grpc_iomgr_add_callback(fd->on_done_closure); } grpc_iomgr_unregister_object(&fd->iomgr_object); freelist_fd(fd); } else { GPR_ASSERT(old > n); } }
static void unix_maybe_finish_next_locked(unix_resolver *r) { grpc_client_config *cfg; grpc_lb_policy *lb_policy; grpc_subchannel *subchannel; grpc_subchannel_args args; if (r->next_completion != NULL && !r->published) { cfg = grpc_client_config_create(); memset(&args, 0, sizeof(args)); args.addr = (struct sockaddr *)&r->addr; args.addr_len = r->addr_len; subchannel = grpc_subchannel_factory_create_subchannel(r->subchannel_factory, &args); lb_policy = r->lb_policy_factory(&subchannel, 1); grpc_client_config_set_lb_policy(cfg, lb_policy); GRPC_LB_POLICY_UNREF(lb_policy, "unix"); r->published = 1; *r->target_config = cfg; grpc_iomgr_add_callback(r->next_completion); r->next_completion = NULL; } }
void grpc_channel_internal_unref(grpc_channel *channel, const char *reason) { gpr_log(GPR_DEBUG, "CHANNEL: unref %p %d -> %d [%s]", channel, channel->refs.count, channel->refs.count - 1, reason); #else void grpc_channel_internal_unref(grpc_channel *channel) { #endif if (gpr_unref(&channel->refs)) { channel->destroy_closure.cb = destroy_channel; channel->destroy_closure.cb_arg = channel; grpc_iomgr_add_callback(&channel->destroy_closure); } } void grpc_channel_destroy(grpc_channel *channel) { grpc_transport_op op; grpc_channel_element *elem; memset(&op, 0, sizeof(op)); op.disconnect = 1; elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CHANNEL(channel), 0); elem->filter->start_transport_op(elem, &op); GRPC_CHANNEL_INTERNAL_UNREF(channel, "channel"); }
static void shutdown_channel(channel_data *chand) { grpc_channel_internal_ref(chand->channel); grpc_iomgr_add_callback(finish_shutdown_channel, chand); }