|
|
|
@ -41,6 +41,7 @@ |
|
|
|
|
#include "src/core/lib/iomgr/timer.h" |
|
|
|
|
#include "src/core/lib/profiling/timers.h" |
|
|
|
|
#include "src/core/lib/slice/slice_internal.h" |
|
|
|
|
#include "src/core/lib/support/debug_location.h" |
|
|
|
|
#include "src/core/lib/support/manual_constructor.h" |
|
|
|
|
#include "src/core/lib/surface/channel.h" |
|
|
|
|
#include "src/core/lib/surface/channel_init.h" |
|
|
|
@ -96,7 +97,7 @@ struct grpc_subchannel { |
|
|
|
|
grpc_connect_out_args connecting_result; |
|
|
|
|
|
|
|
|
|
/** callback for connection finishing */ |
|
|
|
|
grpc_closure connected; |
|
|
|
|
grpc_closure on_connected; |
|
|
|
|
|
|
|
|
|
/** callback for our alarm */ |
|
|
|
|
grpc_closure on_alarm; |
|
|
|
@ -139,11 +140,10 @@ struct grpc_subchannel_call { |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
#define SUBCHANNEL_CALL_TO_CALL_STACK(call) ((grpc_call_stack*)((call) + 1)) |
|
|
|
|
#define CHANNEL_STACK_FROM_CONNECTION(con) ((grpc_channel_stack*)(con)) |
|
|
|
|
#define CALLSTACK_TO_SUBCHANNEL_CALL(callstack) \ |
|
|
|
|
(((grpc_subchannel_call*)(callstack)) - 1) |
|
|
|
|
|
|
|
|
|
static void subchannel_connected(void* subchannel, grpc_error* error); |
|
|
|
|
static void on_subchannel_connected(void* subchannel, grpc_error* error); |
|
|
|
|
|
|
|
|
|
#ifndef NDEBUG |
|
|
|
|
#define REF_REASON reason |
|
|
|
@ -161,20 +161,20 @@ static void subchannel_connected(void* subchannel, grpc_error* error); |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
static void connection_destroy(void* arg, grpc_error* error) { |
|
|
|
|
grpc_connected_subchannel* c = (grpc_connected_subchannel*)arg; |
|
|
|
|
grpc_channel_stack_destroy(CHANNEL_STACK_FROM_CONNECTION(c)); |
|
|
|
|
gpr_free(c); |
|
|
|
|
grpc_channel_stack* stk = (grpc_channel_stack*)arg; |
|
|
|
|
grpc_channel_stack_destroy(stk); |
|
|
|
|
gpr_free(stk); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
grpc_connected_subchannel* grpc_connected_subchannel_ref( |
|
|
|
|
grpc_connected_subchannel* c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { |
|
|
|
|
GRPC_CHANNEL_STACK_REF(CHANNEL_STACK_FROM_CONNECTION(c), REF_REASON); |
|
|
|
|
c->Ref(DEBUG_LOCATION, REF_REASON); |
|
|
|
|
return c; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void grpc_connected_subchannel_unref( |
|
|
|
|
grpc_connected_subchannel* c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { |
|
|
|
|
GRPC_CHANNEL_STACK_UNREF(CHANNEL_STACK_FROM_CONNECTION(c), REF_REASON); |
|
|
|
|
c->Unref(DEBUG_LOCATION, REF_REASON); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@ -241,16 +241,15 @@ grpc_subchannel* grpc_subchannel_ref_from_weak_ref( |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void disconnect(grpc_subchannel* c) { |
|
|
|
|
grpc_connected_subchannel* con; |
|
|
|
|
grpc_subchannel_index_unregister(c->key, c); |
|
|
|
|
gpr_mu_lock(&c->mu); |
|
|
|
|
GPR_ASSERT(!c->disconnected); |
|
|
|
|
c->disconnected = true; |
|
|
|
|
grpc_connector_shutdown(c->connector, GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
|
|
|
|
"Subchannel disconnected")); |
|
|
|
|
con = GET_CONNECTED_SUBCHANNEL(c, no_barrier); |
|
|
|
|
grpc_connected_subchannel* con = GET_CONNECTED_SUBCHANNEL(c, no_barrier); |
|
|
|
|
if (con != nullptr) { |
|
|
|
|
GRPC_CONNECTED_SUBCHANNEL_UNREF(con, "connection"); |
|
|
|
|
GRPC_CONNECTED_SUBCHANNEL_UNREF(con, "disconnect"); |
|
|
|
|
gpr_atm_no_barrier_store(&c->connected_subchannel, (gpr_atm)0xdeadbeef); |
|
|
|
|
} |
|
|
|
|
gpr_mu_unlock(&c->mu); |
|
|
|
@ -372,7 +371,7 @@ grpc_subchannel* grpc_subchannel_create(grpc_connector* connector, |
|
|
|
|
if (new_args != nullptr) grpc_channel_args_destroy(new_args); |
|
|
|
|
c->root_external_state_watcher.next = c->root_external_state_watcher.prev = |
|
|
|
|
&c->root_external_state_watcher; |
|
|
|
|
GRPC_CLOSURE_INIT(&c->connected, subchannel_connected, c, |
|
|
|
|
GRPC_CLOSURE_INIT(&c->on_connected, on_subchannel_connected, c, |
|
|
|
|
grpc_schedule_on_exec_ctx); |
|
|
|
|
grpc_connectivity_state_init(&c->state_tracker, GRPC_CHANNEL_IDLE, |
|
|
|
|
"subchannel"); |
|
|
|
@ -395,7 +394,7 @@ static void continue_connect_locked(grpc_subchannel* c) { |
|
|
|
|
grpc_connectivity_state_set(&c->state_tracker, GRPC_CHANNEL_CONNECTING, |
|
|
|
|
GRPC_ERROR_NONE, "state_change"); |
|
|
|
|
grpc_connector_connect(c->connector, &args, &c->connecting_result, |
|
|
|
|
&c->connected); |
|
|
|
|
&c->on_connected); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
grpc_connectivity_state grpc_subchannel_check_connectivity(grpc_subchannel* c, |
|
|
|
@ -479,9 +478,10 @@ static void maybe_start_connecting_locked(grpc_subchannel* c) { |
|
|
|
|
const grpc_millis time_til_next = |
|
|
|
|
c->next_attempt_deadline - grpc_core::ExecCtx::Get()->Now(); |
|
|
|
|
if (time_til_next <= 0) { |
|
|
|
|
gpr_log(GPR_INFO, "Retry immediately"); |
|
|
|
|
gpr_log(GPR_INFO, "Subchannel %p: Retry immediately", c); |
|
|
|
|
} else { |
|
|
|
|
gpr_log(GPR_INFO, "Retry in %" PRIdPTR " milliseconds", time_til_next); |
|
|
|
|
gpr_log(GPR_INFO, "Subchannel %p: Retry in %" PRIdPTR " milliseconds", c, |
|
|
|
|
time_til_next); |
|
|
|
|
} |
|
|
|
|
GRPC_CLOSURE_INIT(&c->on_alarm, on_alarm, c, grpc_schedule_on_exec_ctx); |
|
|
|
|
grpc_timer_init(&c->alarm, c->next_attempt_deadline, &c->on_alarm); |
|
|
|
@ -525,75 +525,56 @@ void grpc_subchannel_notify_on_state_change( |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void grpc_connected_subchannel_process_transport_op( |
|
|
|
|
grpc_connected_subchannel* con, grpc_transport_op* op) { |
|
|
|
|
grpc_channel_stack* channel_stack = CHANNEL_STACK_FROM_CONNECTION(con); |
|
|
|
|
grpc_channel_element* top_elem = grpc_channel_stack_element(channel_stack, 0); |
|
|
|
|
top_elem->filter->start_transport_op(top_elem, op); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void subchannel_on_child_state_changed(void* p, grpc_error* error) { |
|
|
|
|
state_watcher* sw = (state_watcher*)p; |
|
|
|
|
grpc_subchannel* c = sw->subchannel; |
|
|
|
|
static void on_connected_subchannel_connectivity_changed(void* p, |
|
|
|
|
grpc_error* error) { |
|
|
|
|
state_watcher* connected_subchannel_watcher = (state_watcher*)p; |
|
|
|
|
grpc_subchannel* c = connected_subchannel_watcher->subchannel; |
|
|
|
|
gpr_mu* mu = &c->mu; |
|
|
|
|
|
|
|
|
|
gpr_mu_lock(mu); |
|
|
|
|
|
|
|
|
|
auto* con = GET_CONNECTED_SUBCHANNEL(c, no_barrier); |
|
|
|
|
/* if we failed just leave this closure */ |
|
|
|
|
if (sw->connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) { |
|
|
|
|
/* any errors on a subchannel ==> we're done, create a new one */ |
|
|
|
|
sw->connectivity_state = GRPC_CHANNEL_SHUTDOWN; |
|
|
|
|
if (connected_subchannel_watcher->connectivity_state == |
|
|
|
|
GRPC_CHANNEL_TRANSIENT_FAILURE) { |
|
|
|
|
if (!c->disconnected && con != nullptr) { |
|
|
|
|
GRPC_CONNECTED_SUBCHANNEL_UNREF(con, "transient_failure"); |
|
|
|
|
gpr_atm_no_barrier_store(&c->connected_subchannel, (gpr_atm) nullptr); |
|
|
|
|
grpc_connectivity_state_set(&c->state_tracker, |
|
|
|
|
GRPC_CHANNEL_TRANSIENT_FAILURE, |
|
|
|
|
GRPC_ERROR_REF(error), "reflect_child"); |
|
|
|
|
c->backoff_begun = false; |
|
|
|
|
c->backoff->Reset(); |
|
|
|
|
if (grpc_trace_stream_refcount.enabled()) { |
|
|
|
|
gpr_log(GPR_INFO, |
|
|
|
|
"Connected subchannel %p of subchannel %p has gone into " |
|
|
|
|
"TRANSIENT_FAILURE. Attempting to reconnect.", |
|
|
|
|
con, c); |
|
|
|
|
} |
|
|
|
|
maybe_start_connecting_locked(c); |
|
|
|
|
goto done; |
|
|
|
|
} else { |
|
|
|
|
connected_subchannel_watcher->connectivity_state = GRPC_CHANNEL_SHUTDOWN; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
grpc_connectivity_state_set(&c->state_tracker, sw->connectivity_state, |
|
|
|
|
grpc_connectivity_state_set(&c->state_tracker, |
|
|
|
|
connected_subchannel_watcher->connectivity_state, |
|
|
|
|
GRPC_ERROR_REF(error), "reflect_child"); |
|
|
|
|
if (sw->connectivity_state != GRPC_CHANNEL_SHUTDOWN) { |
|
|
|
|
grpc_connected_subchannel_notify_on_state_change( |
|
|
|
|
GET_CONNECTED_SUBCHANNEL(c, no_barrier), nullptr, |
|
|
|
|
&sw->connectivity_state, &sw->closure); |
|
|
|
|
if (connected_subchannel_watcher->connectivity_state < |
|
|
|
|
GRPC_CHANNEL_TRANSIENT_FAILURE) { |
|
|
|
|
GRPC_SUBCHANNEL_WEAK_REF(c, "state_watcher"); |
|
|
|
|
sw = nullptr; |
|
|
|
|
con->NotifyOnStateChange(nullptr, |
|
|
|
|
&connected_subchannel_watcher->connectivity_state, |
|
|
|
|
&connected_subchannel_watcher->closure); |
|
|
|
|
connected_subchannel_watcher = nullptr; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
done: |
|
|
|
|
gpr_mu_unlock(mu); |
|
|
|
|
GRPC_SUBCHANNEL_WEAK_UNREF(c, "state_watcher"); |
|
|
|
|
gpr_free(sw); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void connected_subchannel_state_op(grpc_connected_subchannel* con, |
|
|
|
|
grpc_pollset_set* interested_parties, |
|
|
|
|
grpc_connectivity_state* state, |
|
|
|
|
grpc_closure* closure) { |
|
|
|
|
grpc_transport_op* op = grpc_make_transport_op(nullptr); |
|
|
|
|
grpc_channel_element* elem; |
|
|
|
|
op->connectivity_state = state; |
|
|
|
|
op->on_connectivity_state_change = closure; |
|
|
|
|
op->bind_pollset_set = interested_parties; |
|
|
|
|
elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CONNECTION(con), 0); |
|
|
|
|
elem->filter->start_transport_op(elem, op); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void grpc_connected_subchannel_notify_on_state_change( |
|
|
|
|
grpc_connected_subchannel* con, grpc_pollset_set* interested_parties, |
|
|
|
|
grpc_connectivity_state* state, grpc_closure* closure) { |
|
|
|
|
connected_subchannel_state_op(con, interested_parties, state, closure); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void grpc_connected_subchannel_ping(grpc_connected_subchannel* con, |
|
|
|
|
grpc_closure* on_initiate, |
|
|
|
|
grpc_closure* on_ack) { |
|
|
|
|
grpc_transport_op* op = grpc_make_transport_op(nullptr); |
|
|
|
|
grpc_channel_element* elem; |
|
|
|
|
op->send_ping.on_initiate = on_initiate; |
|
|
|
|
op->send_ping.on_ack = on_ack; |
|
|
|
|
elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CONNECTION(con), 0); |
|
|
|
|
elem->filter->start_transport_op(elem, op); |
|
|
|
|
gpr_free(connected_subchannel_watcher); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static bool publish_transport_locked(grpc_subchannel* c) { |
|
|
|
|
grpc_connected_subchannel* con; |
|
|
|
|
grpc_channel_stack* stk; |
|
|
|
|
state_watcher* sw_subchannel; |
|
|
|
|
|
|
|
|
|
/* construct channel stack */ |
|
|
|
|
grpc_channel_stack_builder* builder = grpc_channel_stack_builder_create(); |
|
|
|
|
grpc_channel_stack_builder_set_channel_arguments( |
|
|
|
@ -605,8 +586,9 @@ static bool publish_transport_locked(grpc_subchannel* c) { |
|
|
|
|
grpc_channel_stack_builder_destroy(builder); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
grpc_channel_stack* stk; |
|
|
|
|
grpc_error* error = grpc_channel_stack_builder_finish( |
|
|
|
|
builder, 0, 1, connection_destroy, nullptr, (void**)&con); |
|
|
|
|
builder, 0, 1, connection_destroy, nullptr, (void**)&stk); |
|
|
|
|
if (error != GRPC_ERROR_NONE) { |
|
|
|
|
grpc_transport_destroy(c->connecting_result.transport); |
|
|
|
|
gpr_log(GPR_ERROR, "error initializing subchannel stack: %s", |
|
|
|
@ -614,20 +596,21 @@ static bool publish_transport_locked(grpc_subchannel* c) { |
|
|
|
|
GRPC_ERROR_UNREF(error); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
stk = CHANNEL_STACK_FROM_CONNECTION(con); |
|
|
|
|
memset(&c->connecting_result, 0, sizeof(c->connecting_result)); |
|
|
|
|
|
|
|
|
|
/* initialize state watcher */ |
|
|
|
|
sw_subchannel = (state_watcher*)gpr_malloc(sizeof(*sw_subchannel)); |
|
|
|
|
sw_subchannel->subchannel = c; |
|
|
|
|
sw_subchannel->connectivity_state = GRPC_CHANNEL_READY; |
|
|
|
|
GRPC_CLOSURE_INIT(&sw_subchannel->closure, subchannel_on_child_state_changed, |
|
|
|
|
sw_subchannel, grpc_schedule_on_exec_ctx); |
|
|
|
|
state_watcher* connected_subchannel_watcher = |
|
|
|
|
(state_watcher*)gpr_zalloc(sizeof(*connected_subchannel_watcher)); |
|
|
|
|
connected_subchannel_watcher->subchannel = c; |
|
|
|
|
connected_subchannel_watcher->connectivity_state = GRPC_CHANNEL_READY; |
|
|
|
|
GRPC_CLOSURE_INIT(&connected_subchannel_watcher->closure, |
|
|
|
|
on_connected_subchannel_connectivity_changed, |
|
|
|
|
connected_subchannel_watcher, grpc_schedule_on_exec_ctx); |
|
|
|
|
|
|
|
|
|
if (c->disconnected) { |
|
|
|
|
gpr_free(sw_subchannel); |
|
|
|
|
gpr_free(connected_subchannel_watcher); |
|
|
|
|
grpc_channel_stack_destroy(stk); |
|
|
|
|
gpr_free(con); |
|
|
|
|
gpr_free(stk); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -636,6 +619,8 @@ static bool publish_transport_locked(grpc_subchannel* c) { |
|
|
|
|
I'd have expected the rel_cas below to be enough, but |
|
|
|
|
seemingly it's not. |
|
|
|
|
Re-evaluate if we really need this. */ |
|
|
|
|
grpc_connected_subchannel* con = |
|
|
|
|
grpc_core::New<grpc_connected_subchannel>(stk); |
|
|
|
|
gpr_atm_full_barrier(); |
|
|
|
|
GPR_ASSERT(gpr_atm_rel_cas(&c->connected_subchannel, 0, (gpr_atm)con)); |
|
|
|
|
|
|
|
|
@ -643,9 +628,9 @@ static bool publish_transport_locked(grpc_subchannel* c) { |
|
|
|
|
ref for connecting is donated to the state watcher */ |
|
|
|
|
GRPC_SUBCHANNEL_WEAK_REF(c, "state_watcher"); |
|
|
|
|
GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); |
|
|
|
|
grpc_connected_subchannel_notify_on_state_change( |
|
|
|
|
con, c->pollset_set, &sw_subchannel->connectivity_state, |
|
|
|
|
&sw_subchannel->closure); |
|
|
|
|
con->NotifyOnStateChange(c->pollset_set, |
|
|
|
|
&connected_subchannel_watcher->connectivity_state, |
|
|
|
|
&connected_subchannel_watcher->closure); |
|
|
|
|
|
|
|
|
|
/* signal completion */ |
|
|
|
|
grpc_connectivity_state_set(&c->state_tracker, GRPC_CHANNEL_READY, |
|
|
|
@ -653,11 +638,11 @@ static bool publish_transport_locked(grpc_subchannel* c) { |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void subchannel_connected(void* arg, grpc_error* error) { |
|
|
|
|
static void on_subchannel_connected(void* arg, grpc_error* error) { |
|
|
|
|
grpc_subchannel* c = (grpc_subchannel*)arg; |
|
|
|
|
grpc_channel_args* delete_channel_args = c->connecting_result.channel_args; |
|
|
|
|
|
|
|
|
|
GRPC_SUBCHANNEL_WEAK_REF(c, "connected"); |
|
|
|
|
GRPC_SUBCHANNEL_WEAK_REF(c, "on_subchannel_connected"); |
|
|
|
|
gpr_mu_lock(&c->mu); |
|
|
|
|
c->connecting = false; |
|
|
|
|
if (c->connecting_result.transport != nullptr && |
|
|
|
@ -736,36 +721,6 @@ const grpc_subchannel_key* grpc_subchannel_get_key( |
|
|
|
|
return subchannel->key; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
grpc_error* grpc_connected_subchannel_create_call( |
|
|
|
|
grpc_connected_subchannel* con, |
|
|
|
|
const grpc_connected_subchannel_call_args* args, |
|
|
|
|
grpc_subchannel_call** call) { |
|
|
|
|
grpc_channel_stack* chanstk = CHANNEL_STACK_FROM_CONNECTION(con); |
|
|
|
|
*call = (grpc_subchannel_call*)gpr_arena_alloc( |
|
|
|
|
args->arena, sizeof(grpc_subchannel_call) + chanstk->call_stack_size); |
|
|
|
|
grpc_call_stack* callstk = SUBCHANNEL_CALL_TO_CALL_STACK(*call); |
|
|
|
|
(*call)->connection = GRPC_CONNECTED_SUBCHANNEL_REF(con, "subchannel_call"); |
|
|
|
|
const grpc_call_element_args call_args = { |
|
|
|
|
callstk, /* call_stack */ |
|
|
|
|
nullptr, /* server_transport_data */ |
|
|
|
|
args->context, /* context */ |
|
|
|
|
args->path, /* path */ |
|
|
|
|
args->start_time, /* start_time */ |
|
|
|
|
args->deadline, /* deadline */ |
|
|
|
|
args->arena, /* arena */ |
|
|
|
|
args->call_combiner /* call_combiner */ |
|
|
|
|
}; |
|
|
|
|
grpc_error* error = grpc_call_stack_init(chanstk, 1, subchannel_call_destroy, |
|
|
|
|
*call, &call_args); |
|
|
|
|
if (error != GRPC_ERROR_NONE) { |
|
|
|
|
const char* error_string = grpc_error_string(error); |
|
|
|
|
gpr_log(GPR_ERROR, "error: %s", error_string); |
|
|
|
|
return error; |
|
|
|
|
} |
|
|
|
|
grpc_call_stack_set_pollset_or_pollset_set(callstk, args->pollent); |
|
|
|
|
return GRPC_ERROR_NONE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
grpc_call_stack* grpc_subchannel_call_get_call_stack( |
|
|
|
|
grpc_subchannel_call* subchannel_call) { |
|
|
|
|
return SUBCHANNEL_CALL_TO_CALL_STACK(subchannel_call); |
|
|
|
@ -801,3 +756,70 @@ grpc_arg grpc_create_subchannel_address_arg(const grpc_resolved_address* addr) { |
|
|
|
|
(char*)GRPC_ARG_SUBCHANNEL_ADDRESS, |
|
|
|
|
addr->len > 0 ? grpc_sockaddr_to_uri(addr) : gpr_strdup("")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
grpc_connected_subchannel::grpc_connected_subchannel( |
|
|
|
|
grpc_channel_stack* channel_stack) |
|
|
|
|
: grpc_core::RefCountedWithTracing(&grpc_trace_stream_refcount), |
|
|
|
|
channel_stack_(channel_stack) {} |
|
|
|
|
|
|
|
|
|
grpc_connected_subchannel* grpc_connected_subchannel::Ref( |
|
|
|
|
const grpc_core::DebugLocation& location, const char* reason) { |
|
|
|
|
GRPC_CHANNEL_STACK_REF(channel_stack_, REF_REASON); |
|
|
|
|
grpc_core::RefCountedWithTracing::Ref(location, reason); |
|
|
|
|
return this; |
|
|
|
|
} |
|
|
|
|
void grpc_connected_subchannel::Unref(const grpc_core::DebugLocation& location, |
|
|
|
|
const char* reason) { |
|
|
|
|
GRPC_CHANNEL_STACK_UNREF(channel_stack_, REF_REASON); |
|
|
|
|
grpc_core::RefCountedWithTracing::Unref(location, reason); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void grpc_connected_subchannel::NotifyOnStateChange( |
|
|
|
|
grpc_pollset_set* interested_parties, grpc_connectivity_state* state, |
|
|
|
|
grpc_closure* closure) { |
|
|
|
|
grpc_transport_op* op = grpc_make_transport_op(nullptr); |
|
|
|
|
grpc_channel_element* elem; |
|
|
|
|
op->connectivity_state = state; |
|
|
|
|
op->on_connectivity_state_change = closure; |
|
|
|
|
op->bind_pollset_set = interested_parties; |
|
|
|
|
elem = grpc_channel_stack_element(channel_stack_, 0); |
|
|
|
|
elem->filter->start_transport_op(elem, op); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void grpc_connected_subchannel::Ping(grpc_closure* on_initiate, |
|
|
|
|
grpc_closure* on_ack) { |
|
|
|
|
grpc_transport_op* op = grpc_make_transport_op(nullptr); |
|
|
|
|
grpc_channel_element* elem; |
|
|
|
|
op->send_ping.on_initiate = on_initiate; |
|
|
|
|
op->send_ping.on_ack = on_ack; |
|
|
|
|
elem = grpc_channel_stack_element(channel_stack_, 0); |
|
|
|
|
elem->filter->start_transport_op(elem, op); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
grpc_error* grpc_connected_subchannel::CreateCall(const CallArgs* args, |
|
|
|
|
grpc_subchannel_call** call) { |
|
|
|
|
*call = (grpc_subchannel_call*)gpr_arena_alloc( |
|
|
|
|
args->arena, |
|
|
|
|
sizeof(grpc_subchannel_call) + channel_stack_->call_stack_size); |
|
|
|
|
grpc_call_stack* callstk = SUBCHANNEL_CALL_TO_CALL_STACK(*call); |
|
|
|
|
(*call)->connection = Ref(DEBUG_LOCATION, "subchannel_call"); |
|
|
|
|
const grpc_call_element_args call_args = { |
|
|
|
|
callstk, /* call_stack */ |
|
|
|
|
nullptr, /* server_transport_data */ |
|
|
|
|
args->context, /* context */ |
|
|
|
|
args->path, /* path */ |
|
|
|
|
args->start_time, /* start_time */ |
|
|
|
|
args->deadline, /* deadline */ |
|
|
|
|
args->arena, /* arena */ |
|
|
|
|
args->call_combiner /* call_combiner */ |
|
|
|
|
}; |
|
|
|
|
grpc_error* error = grpc_call_stack_init( |
|
|
|
|
channel_stack_, 1, subchannel_call_destroy, *call, &call_args); |
|
|
|
|
if (error != GRPC_ERROR_NONE) { |
|
|
|
|
const char* error_string = grpc_error_string(error); |
|
|
|
|
gpr_log(GPR_ERROR, "error: %s", error_string); |
|
|
|
|
return error; |
|
|
|
|
} |
|
|
|
|
grpc_call_stack_set_pollset_or_pollset_set(callstk, args->pollent); |
|
|
|
|
return GRPC_ERROR_NONE; |
|
|
|
|
} |
|
|
|
|