|
|
|
@ -110,38 +110,54 @@ void pf_destroy(grpc_lb_policy *pol) { |
|
|
|
|
|
|
|
|
|
void pf_shutdown(grpc_lb_policy *pol) { |
|
|
|
|
pick_first_lb_policy *p = (pick_first_lb_policy *)pol; |
|
|
|
|
grpc_connectivity_state_flusher f; |
|
|
|
|
pending_pick *pp; |
|
|
|
|
gpr_mu_lock(&p->mu); |
|
|
|
|
del_interested_parties_locked(p); |
|
|
|
|
p->shutdown = 1; |
|
|
|
|
while ((pp = p->pending_picks)) { |
|
|
|
|
p->pending_picks = pp->next; |
|
|
|
|
*pp->target = NULL; |
|
|
|
|
grpc_workqueue_push(p->workqueue, pp->on_complete, 0); |
|
|
|
|
gpr_free(pp); |
|
|
|
|
} |
|
|
|
|
pp = p->pending_picks; |
|
|
|
|
p->pending_picks = NULL; |
|
|
|
|
grpc_connectivity_state_set(&p->state_tracker, GRPC_CHANNEL_FATAL_FAILURE, |
|
|
|
|
"shutdown"); |
|
|
|
|
grpc_connectivity_state_begin_flush(&p->state_tracker, &f); |
|
|
|
|
gpr_mu_unlock(&p->mu); |
|
|
|
|
grpc_connectivity_state_end_flush(&f); |
|
|
|
|
while (pp != NULL) { |
|
|
|
|
pending_pick *next = pp->next; |
|
|
|
|
*pp->target = NULL; |
|
|
|
|
pp->on_complete->cb(pp->on_complete->cb_arg, 0); |
|
|
|
|
gpr_free(pp); |
|
|
|
|
pp = next; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void start_picking(pick_first_lb_policy *p) { |
|
|
|
|
/* returns a closure to call, or NULL */ |
|
|
|
|
static grpc_iomgr_closure *start_picking(pick_first_lb_policy *p) { |
|
|
|
|
p->started_picking = 1; |
|
|
|
|
p->checking_subchannel = 0; |
|
|
|
|
p->checking_connectivity = GRPC_CHANNEL_IDLE; |
|
|
|
|
GRPC_LB_POLICY_REF(&p->base, "pick_first_connectivity"); |
|
|
|
|
grpc_subchannel_notify_on_state_change(p->subchannels[p->checking_subchannel], |
|
|
|
|
&p->checking_connectivity, |
|
|
|
|
&p->connectivity_changed); |
|
|
|
|
if (grpc_subchannel_notify_on_state_change( |
|
|
|
|
p->subchannels[p->checking_subchannel], &p->checking_connectivity, |
|
|
|
|
&p->connectivity_changed) |
|
|
|
|
.state_already_changed) { |
|
|
|
|
return &p->connectivity_changed; |
|
|
|
|
} else { |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void pf_exit_idle(grpc_lb_policy *pol) { |
|
|
|
|
pick_first_lb_policy *p = (pick_first_lb_policy *)pol; |
|
|
|
|
grpc_iomgr_closure *call = NULL; |
|
|
|
|
gpr_mu_lock(&p->mu); |
|
|
|
|
if (!p->started_picking) { |
|
|
|
|
start_picking(p); |
|
|
|
|
call = start_picking(p); |
|
|
|
|
} |
|
|
|
|
gpr_mu_unlock(&p->mu); |
|
|
|
|
if (call) { |
|
|
|
|
call->cb(call->cb_arg, 1); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void pf_pick(grpc_lb_policy *pol, grpc_pollset *pollset, |
|
|
|
@ -155,8 +171,9 @@ void pf_pick(grpc_lb_policy *pol, grpc_pollset *pollset, |
|
|
|
|
*target = p->selected; |
|
|
|
|
on_complete->cb(on_complete->cb_arg, 1); |
|
|
|
|
} else { |
|
|
|
|
grpc_iomgr_closure *call = NULL; |
|
|
|
|
if (!p->started_picking) { |
|
|
|
|
start_picking(p); |
|
|
|
|
call = start_picking(p); |
|
|
|
|
} |
|
|
|
|
grpc_subchannel_add_interested_party(p->subchannels[p->checking_subchannel], |
|
|
|
|
pollset); |
|
|
|
@ -167,6 +184,9 @@ void pf_pick(grpc_lb_policy *pol, grpc_pollset *pollset, |
|
|
|
|
pp->on_complete = on_complete; |
|
|
|
|
p->pending_picks = pp; |
|
|
|
|
gpr_mu_unlock(&p->mu); |
|
|
|
|
if (call) { |
|
|
|
|
call->cb(call->cb_arg, 1); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -174,6 +194,8 @@ static void pf_connectivity_changed(void *arg, int iomgr_success) { |
|
|
|
|
pick_first_lb_policy *p = arg; |
|
|
|
|
pending_pick *pp; |
|
|
|
|
int unref = 0; |
|
|
|
|
grpc_iomgr_closure *cbs = NULL; |
|
|
|
|
grpc_connectivity_state_flusher f; |
|
|
|
|
|
|
|
|
|
gpr_mu_lock(&p->mu); |
|
|
|
|
|
|
|
|
@ -183,8 +205,12 @@ static void pf_connectivity_changed(void *arg, int iomgr_success) { |
|
|
|
|
grpc_connectivity_state_set(&p->state_tracker, p->checking_connectivity, |
|
|
|
|
"selected_changed"); |
|
|
|
|
if (p->checking_connectivity != GRPC_CHANNEL_FATAL_FAILURE) { |
|
|
|
|
grpc_subchannel_notify_on_state_change( |
|
|
|
|
p->selected, &p->checking_connectivity, &p->connectivity_changed); |
|
|
|
|
if (grpc_subchannel_notify_on_state_change( |
|
|
|
|
p->selected, &p->checking_connectivity, &p->connectivity_changed) |
|
|
|
|
.state_already_changed) { |
|
|
|
|
p->connectivity_changed.next = cbs; |
|
|
|
|
cbs = &p->connectivity_changed; |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
unref = 1; |
|
|
|
|
} |
|
|
|
@ -199,11 +225,17 @@ static void pf_connectivity_changed(void *arg, int iomgr_success) { |
|
|
|
|
p->pending_picks = pp->next; |
|
|
|
|
*pp->target = p->selected; |
|
|
|
|
grpc_subchannel_del_interested_party(p->selected, pp->pollset); |
|
|
|
|
grpc_workqueue_push(p->workqueue, pp->on_complete, 1); |
|
|
|
|
pp->on_complete->next = cbs; |
|
|
|
|
cbs = pp->on_complete; |
|
|
|
|
gpr_free(pp); |
|
|
|
|
} |
|
|
|
|
grpc_subchannel_notify_on_state_change( |
|
|
|
|
p->selected, &p->checking_connectivity, &p->connectivity_changed); |
|
|
|
|
if (grpc_subchannel_notify_on_state_change(p->selected, |
|
|
|
|
&p->checking_connectivity, |
|
|
|
|
&p->connectivity_changed) |
|
|
|
|
.state_already_changed) { |
|
|
|
|
p->connectivity_changed.next = cbs; |
|
|
|
|
cbs = &p->connectivity_changed; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case GRPC_CHANNEL_TRANSIENT_FAILURE: |
|
|
|
|
grpc_connectivity_state_set(&p->state_tracker, |
|
|
|
@ -216,9 +248,13 @@ static void pf_connectivity_changed(void *arg, int iomgr_success) { |
|
|
|
|
p->subchannels[p->checking_subchannel]); |
|
|
|
|
add_interested_parties_locked(p); |
|
|
|
|
if (p->checking_connectivity == GRPC_CHANNEL_TRANSIENT_FAILURE) { |
|
|
|
|
grpc_subchannel_notify_on_state_change( |
|
|
|
|
p->subchannels[p->checking_subchannel], &p->checking_connectivity, |
|
|
|
|
&p->connectivity_changed); |
|
|
|
|
if (grpc_subchannel_notify_on_state_change( |
|
|
|
|
p->subchannels[p->checking_subchannel], |
|
|
|
|
&p->checking_connectivity, &p->connectivity_changed) |
|
|
|
|
.state_already_changed) { |
|
|
|
|
p->connectivity_changed.next = cbs; |
|
|
|
|
cbs = &p->connectivity_changed; |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
goto loop; |
|
|
|
|
} |
|
|
|
@ -227,9 +263,13 @@ static void pf_connectivity_changed(void *arg, int iomgr_success) { |
|
|
|
|
case GRPC_CHANNEL_IDLE: |
|
|
|
|
grpc_connectivity_state_set(&p->state_tracker, p->checking_connectivity, |
|
|
|
|
"connecting_changed"); |
|
|
|
|
grpc_subchannel_notify_on_state_change( |
|
|
|
|
p->subchannels[p->checking_subchannel], &p->checking_connectivity, |
|
|
|
|
&p->connectivity_changed); |
|
|
|
|
if (grpc_subchannel_notify_on_state_change( |
|
|
|
|
p->subchannels[p->checking_subchannel], |
|
|
|
|
&p->checking_connectivity, &p->connectivity_changed) |
|
|
|
|
.state_already_changed) { |
|
|
|
|
p->connectivity_changed.next = cbs; |
|
|
|
|
cbs = &p->connectivity_changed; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case GRPC_CHANNEL_FATAL_FAILURE: |
|
|
|
|
del_interested_parties_locked(p); |
|
|
|
@ -244,7 +284,8 @@ static void pf_connectivity_changed(void *arg, int iomgr_success) { |
|
|
|
|
while ((pp = p->pending_picks)) { |
|
|
|
|
p->pending_picks = pp->next; |
|
|
|
|
*pp->target = NULL; |
|
|
|
|
grpc_workqueue_push(p->workqueue, pp->on_complete, 1); |
|
|
|
|
pp->on_complete->next = cbs; |
|
|
|
|
cbs = pp->on_complete; |
|
|
|
|
gpr_free(pp); |
|
|
|
|
} |
|
|
|
|
unref = 1; |
|
|
|
@ -261,7 +302,15 @@ static void pf_connectivity_changed(void *arg, int iomgr_success) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
grpc_connectivity_state_begin_flush(&p->state_tracker, &f); |
|
|
|
|
gpr_mu_unlock(&p->mu); |
|
|
|
|
grpc_connectivity_state_end_flush(&f); |
|
|
|
|
|
|
|
|
|
while (cbs != NULL) { |
|
|
|
|
grpc_iomgr_closure *next = cbs->next; |
|
|
|
|
cbs->cb(cbs->cb_arg, 1); |
|
|
|
|
cbs = next; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (unref) { |
|
|
|
|
GRPC_LB_POLICY_UNREF(&p->base, "pick_first_connectivity"); |
|
|
|
@ -299,14 +348,16 @@ static grpc_connectivity_state pf_check_connectivity(grpc_lb_policy *pol) { |
|
|
|
|
return st; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void pf_notify_on_state_change(grpc_lb_policy *pol, |
|
|
|
|
grpc_connectivity_state *current, |
|
|
|
|
grpc_iomgr_closure *notify) { |
|
|
|
|
static grpc_connectivity_state_notify_on_state_change_result |
|
|
|
|
pf_notify_on_state_change(grpc_lb_policy *pol, grpc_connectivity_state *current, |
|
|
|
|
grpc_iomgr_closure *notify) { |
|
|
|
|
pick_first_lb_policy *p = (pick_first_lb_policy *)pol; |
|
|
|
|
grpc_connectivity_state_notify_on_state_change_result r; |
|
|
|
|
gpr_mu_lock(&p->mu); |
|
|
|
|
grpc_connectivity_state_notify_on_state_change(&p->state_tracker, current, |
|
|
|
|
notify); |
|
|
|
|
r = grpc_connectivity_state_notify_on_state_change(&p->state_tracker, current, |
|
|
|
|
notify); |
|
|
|
|
gpr_mu_unlock(&p->mu); |
|
|
|
|
return r; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static const grpc_lb_policy_vtable pick_first_lb_policy_vtable = { |
|
|
|
@ -332,8 +383,8 @@ static grpc_lb_policy *create_pick_first(grpc_lb_policy_factory *factory, |
|
|
|
|
p->num_subchannels = args->num_subchannels; |
|
|
|
|
p->workqueue = args->workqueue; |
|
|
|
|
GRPC_WORKQUEUE_REF(p->workqueue, "pick_first"); |
|
|
|
|
grpc_connectivity_state_init(&p->state_tracker, args->workqueue, |
|
|
|
|
GRPC_CHANNEL_IDLE, "pick_first"); |
|
|
|
|
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); |
|
|
|
|