/******************************************************************************* * Main inproc transport functions */ static void inproc_transports_create(grpc_exec_ctx *exec_ctx, grpc_transport **server_transport, const grpc_channel_args *server_args, grpc_transport **client_transport, const grpc_channel_args *client_args) { INPROC_LOG(GPR_DEBUG, "inproc_transports_create"); inproc_transport *st = gpr_zalloc(sizeof(*st)); inproc_transport *ct = gpr_zalloc(sizeof(*ct)); // Share one lock between both sides since both sides get affected st->mu = ct->mu = gpr_malloc(sizeof(*st->mu)); gpr_mu_init(&st->mu->mu); gpr_ref_init(&st->mu->refs, 2); st->base.vtable = &inproc_vtable; ct->base.vtable = &inproc_vtable; // Start each side of transport with 2 refs since they each have a ref // to the other gpr_ref_init(&st->refs, 2); gpr_ref_init(&ct->refs, 2); st->is_client = false; ct->is_client = true; grpc_connectivity_state_init(&st->connectivity, GRPC_CHANNEL_READY, "inproc_server"); grpc_connectivity_state_init(&ct->connectivity, GRPC_CHANNEL_READY, "inproc_client"); st->other_side = ct; ct->other_side = st; st->stream_list = NULL; ct->stream_list = NULL; *server_transport = (grpc_transport *)st; *client_transport = (grpc_transport *)ct; }
static grpc_lb_policy *create_round_robin(grpc_lb_policy_factory *factory, grpc_lb_policy_args *args) { size_t i; round_robin_lb_policy *p = gpr_malloc(sizeof(*p)); GPR_ASSERT(args->num_subchannels > 0); memset(p, 0, sizeof(*p)); grpc_lb_policy_init(&p->base, &round_robin_lb_policy_vtable); p->num_subchannels = args->num_subchannels; p->subchannels = gpr_malloc(sizeof(*p->subchannels) * p->num_subchannels); memset(p->subchannels, 0, sizeof(*p->subchannels) * p->num_subchannels); grpc_connectivity_state_init(&p->state_tracker, GRPC_CHANNEL_IDLE, "round_robin"); gpr_mu_init(&p->mu); for (i = 0; i < args->num_subchannels; i++) { subchannel_data *sd = gpr_malloc(sizeof(*sd)); memset(sd, 0, sizeof(*sd)); p->subchannels[i] = sd; sd->policy = p; sd->index = i; sd->subchannel = args->subchannels[i]; grpc_closure_init(&sd->connectivity_changed_closure, rr_connectivity_changed, sd); } /* The (dummy node) root of the ready list */ p->ready_list.subchannel = NULL; p->ready_list.prev = NULL; p->ready_list.next = NULL; p->ready_list_last_pick = &p->ready_list; return &p->base; }
static void test_check(void) { grpc_connectivity_state_tracker tracker; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; gpr_log(GPR_DEBUG, "test_check"); grpc_connectivity_state_init(&tracker, GRPC_CHANNEL_IDLE, "xxx"); GPR_ASSERT(grpc_connectivity_state_check(&tracker) == GRPC_CHANNEL_IDLE); grpc_connectivity_state_destroy(&exec_ctx, &tracker); grpc_exec_ctx_finish(&exec_ctx); }
static grpc_lb_policy *create_round_robin(grpc_exec_ctx *exec_ctx, grpc_lb_policy_factory *factory, grpc_lb_policy_args *args) { GPR_ASSERT(args->addresses != NULL); GPR_ASSERT(args->client_channel_factory != NULL); round_robin_lb_policy *p = gpr_malloc(sizeof(*p)); memset(p, 0, sizeof(*p)); p->subchannels = gpr_malloc(sizeof(*p->subchannels) * args->addresses->naddrs); memset(p->subchannels, 0, sizeof(*p->subchannels) * args->addresses->naddrs); grpc_subchannel_args sc_args; size_t subchannel_idx = 0; for (size_t i = 0; i < args->addresses->naddrs; i++) { memset(&sc_args, 0, sizeof(grpc_subchannel_args)); sc_args.addr = (struct sockaddr *)(args->addresses->addrs[i].addr); sc_args.addr_len = (size_t)args->addresses->addrs[i].len; grpc_subchannel *subchannel = grpc_client_channel_factory_create_subchannel( exec_ctx, args->client_channel_factory, &sc_args); if (subchannel != NULL) { subchannel_data *sd = gpr_malloc(sizeof(*sd)); memset(sd, 0, sizeof(*sd)); p->subchannels[subchannel_idx] = sd; sd->policy = p; sd->index = subchannel_idx; sd->subchannel = subchannel; ++subchannel_idx; grpc_closure_init(&sd->connectivity_changed_closure, rr_connectivity_changed, sd); } } if (subchannel_idx == 0) { gpr_free(p->subchannels); gpr_free(p); return NULL; } p->num_subchannels = subchannel_idx; /* The (dummy node) root of the ready list */ p->ready_list.subchannel = NULL; p->ready_list.prev = NULL; p->ready_list.next = NULL; p->ready_list_last_pick = &p->ready_list; grpc_lb_policy_init(&p->base, &round_robin_lb_policy_vtable); grpc_connectivity_state_init(&p->state_tracker, GRPC_CHANNEL_IDLE, "round_robin"); gpr_mu_init(&p->mu); return &p->base; }
/* Constructor for channel_data */ static void cuc_init_channel_elem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_channel_element_args *args) { channel_data *chand = elem->channel_data; memset(chand, 0, sizeof(*chand)); grpc_closure_init(&chand->connectivity_cb, monitor_subchannel, chand); GPR_ASSERT(args->is_last); GPR_ASSERT(elem->filter == &grpc_client_uchannel_filter); chand->owning_stack = args->channel_stack; grpc_connectivity_state_init(&chand->state_tracker, GRPC_CHANNEL_IDLE, "client_uchannel"); gpr_mu_init(&chand->mu_state); }
static grpc_lb_policy *create_pick_first(grpc_lb_policy_factory *factory, grpc_lb_policy_args *args) { pick_first_lb_policy *p = gpr_malloc(sizeof(*p)); GPR_ASSERT(args->num_subchannels > 0); memset(p, 0, sizeof(*p)); grpc_lb_policy_init(&p->base, &pick_first_lb_policy_vtable); p->subchannels = gpr_malloc(sizeof(grpc_subchannel *) * args->num_subchannels); p->num_subchannels = args->num_subchannels; grpc_connectivity_state_init(&p->state_tracker, GRPC_CHANNEL_IDLE, "pick_first"); memcpy(p->subchannels, args->subchannels, sizeof(grpc_subchannel *) * args->num_subchannels); grpc_iomgr_closure_init(&p->connectivity_changed, pf_connectivity_changed, p); gpr_mu_init(&p->mu); return &p->base; }
/* Constructor for channel_data */ static void init_channel_elem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_channel_element_args *args) { channel_data *chand = elem->channel_data; memset(chand, 0, sizeof(*chand)); GPR_ASSERT(args->is_last); GPR_ASSERT(elem->filter == &grpc_client_channel_filter); gpr_mu_init(&chand->mu_config); grpc_closure_init(&chand->on_config_changed, cc_on_config_changed, chand); chand->owning_stack = args->channel_stack; grpc_connectivity_state_init(&chand->state_tracker, GRPC_CHANNEL_IDLE, "client_channel"); chand->interested_parties = grpc_pollset_set_create(); }
static void test_subscribe_with_failure_then_destroy(void) { grpc_connectivity_state_tracker tracker; grpc_closure *closure = grpc_closure_create(must_fail, THE_ARG); grpc_connectivity_state state = GRPC_CHANNEL_FATAL_FAILURE; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; gpr_log(GPR_DEBUG, "test_subscribe_with_failure_then_destroy"); g_counter = 0; grpc_connectivity_state_init(&tracker, GRPC_CHANNEL_FATAL_FAILURE, "xxx"); GPR_ASSERT(0 == grpc_connectivity_state_notify_on_state_change( &exec_ctx, &tracker, &state, closure)); grpc_exec_ctx_flush(&exec_ctx); GPR_ASSERT(state == GRPC_CHANNEL_FATAL_FAILURE); GPR_ASSERT(g_counter == 0); grpc_connectivity_state_destroy(&exec_ctx, &tracker); grpc_exec_ctx_finish(&exec_ctx); GPR_ASSERT(state == GRPC_CHANNEL_FATAL_FAILURE); GPR_ASSERT(g_counter == 1); }
static grpc_lb_policy *create_round_robin(grpc_lb_policy_factory *factory, grpc_lb_policy_args *args) { size_t i; round_robin_lb_policy *p = gpr_malloc(sizeof(*p)); GPR_ASSERT(args->num_subchannels > 0); memset(p, 0, sizeof(*p)); grpc_lb_policy_init(&p->base, &round_robin_lb_policy_vtable); p->subchannels = gpr_malloc(sizeof(grpc_subchannel *) * args->num_subchannels); p->num_subchannels = args->num_subchannels; grpc_connectivity_state_init(&p->state_tracker, GRPC_CHANNEL_IDLE, "round_robin"); memcpy(p->subchannels, args->subchannels, sizeof(grpc_subchannel *) * args->num_subchannels); gpr_mu_init(&p->mu); p->connectivity_changed_cbs = gpr_malloc(sizeof(grpc_closure) * args->num_subchannels); p->subchannel_connectivity = gpr_malloc(sizeof(grpc_connectivity_state) * args->num_subchannels); p->cb_args = gpr_malloc(sizeof(connectivity_changed_cb_arg) * args->num_subchannels); for (i = 0; i < args->num_subchannels; i++) { p->cb_args[i].subchannel_idx = i; p->cb_args[i].p = p; grpc_closure_init(&p->connectivity_changed_cbs[i], rr_connectivity_changed, &p->cb_args[i]); } /* The (dummy node) root of the ready list */ p->ready_list.subchannel = NULL; p->ready_list.prev = NULL; p->ready_list.next = NULL; p->ready_list_last_pick = &p->ready_list; p->subchannel_index_to_readylist_node = gpr_malloc(sizeof(grpc_subchannel *) * args->num_subchannels); memset(p->subchannel_index_to_readylist_node, 0, sizeof(grpc_subchannel *) * args->num_subchannels); return &p->base; }
static void init_transport(grpc_chttp2_transport *t, const grpc_channel_args *channel_args, grpc_endpoint *ep, grpc_mdctx *mdctx, int is_client) { size_t i; int j; GPR_ASSERT(strlen(GRPC_CHTTP2_CLIENT_CONNECT_STRING) == GRPC_CHTTP2_CLIENT_CONNECT_STRLEN); memset(t, 0, sizeof(*t)); t->base.vtable = &vtable; t->ep = ep; /* one ref is for destroy, the other for when ep becomes NULL */ gpr_ref_init(&t->refs, 2); gpr_mu_init(&t->mu); grpc_mdctx_ref(mdctx); t->peer_string = grpc_endpoint_get_peer(ep); t->metadata_context = mdctx; t->endpoint_reading = 1; t->global.next_stream_id = is_client ? 1 : 2; t->global.is_client = is_client; t->global.outgoing_window = DEFAULT_WINDOW; t->global.incoming_window = DEFAULT_WINDOW; t->global.connection_window_target = DEFAULT_CONNECTION_WINDOW_TARGET; t->global.ping_counter = 1; t->global.pings.next = t->global.pings.prev = &t->global.pings; t->parsing.is_client = is_client; t->parsing.str_grpc_timeout = grpc_mdstr_from_string(t->metadata_context, "grpc-timeout", 0); t->parsing.deframe_state = is_client ? GRPC_DTS_FH_0 : GRPC_DTS_CLIENT_PREFIX_0; t->writing.is_client = is_client; grpc_connectivity_state_init(&t->channel_callback.state_tracker, GRPC_CHANNEL_READY, "transport"); gpr_slice_buffer_init(&t->global.qbuf); gpr_slice_buffer_init(&t->writing.outbuf); grpc_chttp2_hpack_compressor_init(&t->writing.hpack_compressor, mdctx); grpc_iomgr_closure_init(&t->writing_action, writing_action, t); grpc_iomgr_closure_init(&t->reading_action, reading_action, t); gpr_slice_buffer_init(&t->parsing.qbuf); grpc_chttp2_goaway_parser_init(&t->parsing.goaway_parser); grpc_chttp2_hpack_parser_init(&t->parsing.hpack_parser, t->metadata_context); if (is_client) { gpr_slice_buffer_add( &t->global.qbuf, gpr_slice_from_copied_string(GRPC_CHTTP2_CLIENT_CONNECT_STRING)); } /* 8 is a random stab in the dark as to a good initial size: it's small enough that it shouldn't waste memory for infrequently used connections, yet large enough that the exponential growth should happen nicely when it's needed. TODO(ctiller): tune this */ grpc_chttp2_stream_map_init(&t->parsing_stream_map, 8); grpc_chttp2_stream_map_init(&t->new_stream_map, 8); /* copy in initial settings to all setting sets */ for (i = 0; i < GRPC_CHTTP2_NUM_SETTINGS; i++) { t->parsing.settings[i] = grpc_chttp2_settings_parameters[i].default_value; for (j = 0; j < GRPC_NUM_SETTING_SETS; j++) { t->global.settings[j][i] = grpc_chttp2_settings_parameters[i].default_value; } } t->global.dirtied_local_settings = 1; /* Hack: it's common for implementations to assume 65536 bytes initial send window -- this should by rights be 0 */ t->global.force_send_settings = 1 << GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE; t->global.sent_local_settings = 0; /* configure http2 the way we like it */ if (is_client) { push_setting(t, GRPC_CHTTP2_SETTINGS_ENABLE_PUSH, 0); push_setting(t, GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 0); } push_setting(t, GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, DEFAULT_WINDOW); if (channel_args) { for (i = 0; i < channel_args->num_args; i++) { if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_MAX_CONCURRENT_STREAMS)) { if (is_client) { gpr_log(GPR_ERROR, "%s: is ignored on the client", GRPC_ARG_MAX_CONCURRENT_STREAMS); } else if (channel_args->args[i].type != GRPC_ARG_INTEGER) { gpr_log(GPR_ERROR, "%s: must be an integer", GRPC_ARG_MAX_CONCURRENT_STREAMS); } else { push_setting(t, GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, channel_args->args[i].value.integer); } } else if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER)) { if (channel_args->args[i].type != GRPC_ARG_INTEGER) { gpr_log(GPR_ERROR, "%s: must be an integer", GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER); } else if ((t->global.next_stream_id & 1) != (channel_args->args[i].value.integer & 1)) { gpr_log(GPR_ERROR, "%s: low bit must be %d on %s", GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER, t->global.next_stream_id & 1, is_client ? "client" : "server"); } else { t->global.next_stream_id = channel_args->args[i].value.integer; } } } } }
static grpc_lb_policy *round_robin_create(grpc_exec_ctx *exec_ctx, grpc_lb_policy_factory *factory, grpc_lb_policy_args *args) { GPR_ASSERT(args->client_channel_factory != NULL); /* Get server name. */ const grpc_arg *arg = grpc_channel_args_find(args->args, GRPC_ARG_SERVER_NAME); const char *server_name = arg != NULL && arg->type == GRPC_ARG_STRING ? arg->value.string : NULL; /* Find the number of backend addresses. We ignore balancer * addresses, since we don't know how to handle them. */ arg = grpc_channel_args_find(args->args, GRPC_ARG_LB_ADDRESSES); GPR_ASSERT(arg != NULL && arg->type == GRPC_ARG_POINTER); grpc_lb_addresses *addresses = arg->value.pointer.p; size_t num_addrs = 0; for (size_t i = 0; i < addresses->num_addresses; i++) { if (!addresses->addresses[i].is_balancer) ++num_addrs; } if (num_addrs == 0) return NULL; round_robin_lb_policy *p = gpr_malloc(sizeof(*p)); memset(p, 0, sizeof(*p)); p->num_addresses = num_addrs; p->subchannels = gpr_malloc(sizeof(*p->subchannels) * num_addrs); memset(p->subchannels, 0, sizeof(*p->subchannels) * num_addrs); grpc_subchannel_args sc_args; size_t subchannel_idx = 0; for (size_t i = 0; i < addresses->num_addresses; i++) { /* Skip balancer addresses, since we only know how to handle backends. */ if (addresses->addresses[i].is_balancer) continue; memset(&sc_args, 0, sizeof(grpc_subchannel_args)); /* server_name will be copied as part of the subchannel creation. This makes * the copying of server_name (a borrowed pointer) OK. */ sc_args.server_name = server_name; sc_args.addr = &addresses->addresses[i].address; sc_args.args = args->args; grpc_subchannel *subchannel = grpc_client_channel_factory_create_subchannel( exec_ctx, args->client_channel_factory, &sc_args); if (subchannel != NULL) { subchannel_data *sd = gpr_malloc(sizeof(*sd)); memset(sd, 0, sizeof(*sd)); p->subchannels[subchannel_idx] = sd; sd->policy = p; sd->index = subchannel_idx; sd->subchannel = subchannel; sd->user_data_vtable = addresses->user_data_vtable; if (sd->user_data_vtable != NULL) { sd->user_data = sd->user_data_vtable->copy(addresses->addresses[i].user_data); } ++subchannel_idx; grpc_closure_init(&sd->connectivity_changed_closure, rr_connectivity_changed, sd); } } if (subchannel_idx == 0) { /* couldn't create any subchannel. Bail out */ gpr_free(p->subchannels); gpr_free(p); return NULL; } p->num_subchannels = subchannel_idx; /* The (dummy node) root of the ready list */ p->ready_list.subchannel = NULL; p->ready_list.prev = NULL; p->ready_list.next = NULL; p->ready_list_last_pick = &p->ready_list; grpc_lb_policy_init(&p->base, &round_robin_lb_policy_vtable); grpc_connectivity_state_init(&p->state_tracker, GRPC_CHANNEL_IDLE, "round_robin"); if (grpc_lb_round_robin_trace) { gpr_log(GPR_DEBUG, "Created RR policy at %p with %lu subchannels", (void *)p, (unsigned long)p->num_subchannels); } gpr_mu_init(&p->mu); return &p->base; }
static grpc_lb_policy *round_robin_create(grpc_exec_ctx *exec_ctx, grpc_lb_policy_factory *factory, grpc_lb_policy_args *args) { GPR_ASSERT(args->addresses != NULL); GPR_ASSERT(args->client_channel_factory != NULL); /* Find the number of backend addresses. We ignore balancer * addresses, since we don't know how to handle them. */ size_t num_addrs = 0; for (size_t i = 0; i < args->addresses->num_addresses; i++) { if (!args->addresses->addresses[i].is_balancer) ++num_addrs; } if (num_addrs == 0) return NULL; round_robin_lb_policy *p = gpr_malloc(sizeof(*p)); memset(p, 0, sizeof(*p)); p->num_addresses = num_addrs; p->subchannels = gpr_malloc(sizeof(*p->subchannels) * num_addrs); memset(p->subchannels, 0, sizeof(*p->subchannels) * num_addrs); grpc_subchannel_args sc_args; size_t subchannel_idx = 0; for (size_t i = 0; i < args->addresses->num_addresses; i++) { /* Skip balancer addresses, since we only know how to handle backends. */ if (args->addresses->addresses[i].is_balancer) continue; memset(&sc_args, 0, sizeof(grpc_subchannel_args)); /* server_name will be copied as part of the subchannel creation. This makes * the copying of args->server_name (a borrowed pointer) OK. */ sc_args.server_name = args->server_name; sc_args.addr = (struct sockaddr *)(&args->addresses->addresses[i].address.addr); sc_args.addr_len = args->addresses->addresses[i].address.len; sc_args.args = args->additional_args; grpc_subchannel *subchannel = grpc_client_channel_factory_create_subchannel( exec_ctx, args->client_channel_factory, &sc_args); if (subchannel != NULL) { subchannel_data *sd = gpr_malloc(sizeof(*sd)); memset(sd, 0, sizeof(*sd)); p->subchannels[subchannel_idx] = sd; sd->policy = p; sd->index = subchannel_idx; sd->subchannel = subchannel; sd->user_data = args->addresses->addresses[i].user_data; ++subchannel_idx; grpc_closure_init(&sd->connectivity_changed_closure, rr_connectivity_changed, sd); } } if (subchannel_idx == 0) { /* couldn't create any subchannel. Bail out */ gpr_free(p->subchannels); gpr_free(p); return NULL; } p->num_subchannels = subchannel_idx; /* The (dummy node) root of the ready list */ p->ready_list.subchannel = NULL; p->ready_list.prev = NULL; p->ready_list.next = NULL; p->ready_list_last_pick = &p->ready_list; grpc_lb_policy_init(&p->base, &round_robin_lb_policy_vtable); grpc_connectivity_state_init(&p->state_tracker, GRPC_CHANNEL_IDLE, "round_robin"); gpr_mu_init(&p->mu); return &p->base; }