static void send_farewells(void *c, int success) { grpc_child_channel *channel = c; grpc_channel_element *lbelem = LINK_BACK_ELEM_FROM_CHANNEL(channel); lb_channel_data *chand = lbelem->channel_data; int send_goaway; grpc_channel_op op; gpr_mu_lock(&chand->mu); send_goaway = !chand->sent_goaway; chand->sent_goaway = 1; gpr_mu_unlock(&chand->mu); if (send_goaway) { 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("Client disconnect"); grpc_channel_next_op(lbelem, &op); } op.type = GRPC_CHANNEL_DISCONNECT; op.dir = GRPC_CALL_DOWN; grpc_channel_next_op(lbelem, &op); gpr_mu_lock(&chand->mu); chand->sending_farewell = 0; chand->sent_farewell = 1; maybe_destroy_channel(channel); gpr_mu_unlock(&chand->mu); }
static void channel_op(grpc_channel_element *elem, grpc_channel_element *from_elem, grpc_channel_op *op) { channel_data *chand = elem->channel_data; grpc_server *server = chand->server; switch (op->type) { case GRPC_ACCEPT_CALL: /* create a call */ grpc_call_create(chand->channel, NULL, op->data.accept_call.transport_server_data, NULL, 0, gpr_inf_future); break; case GRPC_TRANSPORT_CLOSED: /* if the transport is closed for a server channel, we destroy the channel */ gpr_mu_lock(&server->mu); server_ref(server); destroy_channel(chand); gpr_mu_unlock(&server->mu); server_unref(server); break; case GRPC_TRANSPORT_GOAWAY: gpr_slice_unref(op->data.goaway.message); break; default: GPR_ASSERT(op->dir == GRPC_CALL_DOWN); grpc_channel_next_op(elem, op); break; } }
static void channel_op(grpc_channel_element* elem, grpc_channel_element* from_elem, grpc_channel_op* op) { switch (op->type) { case GRPC_TRANSPORT_CLOSED: /* TODO(hongyu): Annotate trace information for all calls of the channel */ break; default: break; } grpc_channel_next_op(elem, op); }
/* Called on special channel events, such as disconnection or new incoming calls on the server */ static void channel_op(grpc_channel_element *elem, grpc_channel_element *from_elem, grpc_channel_op *op) { /* grab pointers to our data from the channel element */ channel_data *channeld = elem->channel_data; ignore_unused(channeld); switch (op->type) { default: /* pass control up or down the stack depending on op->dir */ grpc_channel_next_op(elem, op); break; } }
/* Currently we assume all channel operations should just be pushed up. */ static void lb_channel_op(grpc_channel_element *elem, grpc_channel_element *from_elem, grpc_channel_op *op) { lb_channel_data *chand = elem->channel_data; grpc_channel_element *back; int calling_back = 0; switch (op->dir) { case GRPC_CALL_UP: gpr_mu_lock(&chand->mu); back = chand->back; if (back) { chand->calling_back++; calling_back = 1; } gpr_mu_unlock(&chand->mu); if (back) { back->filter->channel_op(chand->back, elem, op); } else if (op->type == GRPC_TRANSPORT_GOAWAY) { gpr_slice_unref(op->data.goaway.message); } break; case GRPC_CALL_DOWN: grpc_channel_next_op(elem, op); break; } gpr_mu_lock(&chand->mu); switch (op->type) { case GRPC_TRANSPORT_CLOSED: chand->disconnected = 1; maybe_destroy_channel(grpc_channel_stack_from_top_element(elem)); break; case GRPC_CHANNEL_GOAWAY: chand->sent_goaway = 1; break; case GRPC_CHANNEL_DISCONNECT: case GRPC_TRANSPORT_GOAWAY: case GRPC_ACCEPT_CALL: break; } if (calling_back) { chand->calling_back--; gpr_cv_signal(&chand->cv); maybe_destroy_channel(grpc_channel_stack_from_top_element(elem)); } gpr_mu_unlock(&chand->mu); }
static void channel_op(grpc_channel_element *elem, grpc_channel_element *from_elem, grpc_channel_op *op) { switch (op->type) { case GRPC_ACCEPT_CALL: gpr_log(GPR_ERROR, "Client cannot accept new calls"); break; case GRPC_TRANSPORT_CLOSED: grpc_client_channel_closed(elem); break; case GRPC_TRANSPORT_GOAWAY: gpr_slice_unref(op->data.goaway.message); break; default: GPR_ASSERT(op->dir == GRPC_CALL_DOWN); grpc_channel_next_op(elem, op); } }
static void destroy_channel(grpc_exec_ctx *exec_ctx, channel_data *chand) { if (is_channel_orphaned(chand)) return; GPR_ASSERT(chand->server != NULL); orphan_channel(chand); server_ref(chand->server); maybe_finish_shutdown(exec_ctx, chand->server); chand->finish_destroy_channel_closure.cb = finish_destroy_channel; chand->finish_destroy_channel_closure.cb_arg = chand; grpc_transport_op op; memset(&op, 0, sizeof(op)); op.set_accept_stream = true; op.on_consumed = &chand->finish_destroy_channel_closure; grpc_channel_next_op(exec_ctx, grpc_channel_stack_element( grpc_channel_get_channel_stack(chand->channel), 0), &op); }
static void channel_connectivity_changed(grpc_exec_ctx *exec_ctx, void *cd, grpc_error *error) { channel_data *chand = cd; grpc_server *server = chand->server; if (chand->connectivity_state != GRPC_CHANNEL_SHUTDOWN) { grpc_transport_op op; memset(&op, 0, sizeof(op)); op.on_connectivity_state_change = &chand->channel_connectivity_changed, op.connectivity_state = &chand->connectivity_state; grpc_channel_next_op(exec_ctx, grpc_channel_stack_element( grpc_channel_get_channel_stack(chand->channel), 0), &op); } else { gpr_mu_lock(&server->mu_global); destroy_channel(exec_ctx, chand); gpr_mu_unlock(&server->mu_global); GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, chand->channel, "connectivity"); } }
void grpc_child_channel_handle_op(grpc_child_channel *channel, grpc_channel_op *op) { grpc_channel_next_op(LINK_BACK_ELEM_FROM_CHANNEL(channel), op); }
static void channel_op(grpc_channel_element *elem, grpc_channel_element *from_elem, grpc_channel_op *op) { channel_data *chand = elem->channel_data; grpc_child_channel *child_channel; grpc_channel_op rop; GPR_ASSERT(elem->filter == &grpc_client_channel_filter); switch (op->type) { case GRPC_CHANNEL_GOAWAY: /* sending goaway: clear out the active child on the way through */ gpr_mu_lock(&chand->mu); child_channel = chand->active_child; chand->active_child = NULL; gpr_mu_unlock(&chand->mu); if (child_channel) { grpc_child_channel_handle_op(child_channel, op); grpc_child_channel_destroy(child_channel, 1); } else { gpr_slice_unref(op->data.goaway.message); } break; case GRPC_CHANNEL_DISCONNECT: /* sending disconnect: clear out the active child on the way through */ gpr_mu_lock(&chand->mu); child_channel = chand->active_child; chand->active_child = NULL; gpr_mu_unlock(&chand->mu); if (child_channel) { grpc_child_channel_destroy(child_channel, 1); } /* fake a transport closed to satisfy the refcounting in client */ rop.type = GRPC_TRANSPORT_CLOSED; rop.dir = GRPC_CALL_UP; grpc_channel_next_op(elem, &rop); break; case GRPC_TRANSPORT_GOAWAY: /* receiving goaway: if it's from our active child, drop the active child; in all cases consume the event here */ gpr_mu_lock(&chand->mu); child_channel = grpc_channel_stack_from_top_element(from_elem); if (child_channel == chand->active_child) { chand->active_child = NULL; } else { child_channel = NULL; } gpr_mu_unlock(&chand->mu); if (child_channel) { grpc_child_channel_destroy(child_channel, 0); } gpr_slice_unref(op->data.goaway.message); break; case GRPC_TRANSPORT_CLOSED: /* receiving disconnect: if it's from our active child, drop the active child; in all cases consume the event here */ gpr_mu_lock(&chand->mu); child_channel = grpc_channel_stack_from_top_element(from_elem); if (child_channel == chand->active_child) { chand->active_child = NULL; } else { child_channel = NULL; } gpr_mu_unlock(&chand->mu); if (child_channel) { grpc_child_channel_destroy(child_channel, 0); } break; default: switch (op->dir) { case GRPC_CALL_UP: grpc_channel_next_op(elem, op); break; case GRPC_CALL_DOWN: gpr_log(GPR_ERROR, "unhandled channel op: %d", op->type); abort(); break; } break; } }