|
|
|
@ -73,7 +73,7 @@ class PickFirst : public LoadBalancingPolicy { |
|
|
|
|
: SubchannelData(subchannel_list, address, subchannel, combiner) {} |
|
|
|
|
|
|
|
|
|
void ProcessConnectivityChangeLocked( |
|
|
|
|
grpc_connectivity_state connectivity_state, grpc_error* error) override; |
|
|
|
|
grpc_connectivity_state connectivity_state) override; |
|
|
|
|
|
|
|
|
|
// Processes the connectivity change to READY for an unselected subchannel.
|
|
|
|
|
void ProcessUnselectedReadyLocked(); |
|
|
|
@ -191,10 +191,11 @@ void PickFirst::ExitIdleLocked() { |
|
|
|
|
idle_ = false; |
|
|
|
|
if (subchannel_list_ == nullptr || |
|
|
|
|
subchannel_list_->num_subchannels() == 0) { |
|
|
|
|
grpc_error* error = |
|
|
|
|
GRPC_ERROR_CREATE_FROM_STATIC_STRING("No addresses to connect to"); |
|
|
|
|
grpc_error* error = grpc_error_set_int( |
|
|
|
|
GRPC_ERROR_CREATE_FROM_STATIC_STRING("No addresses to connect to"), |
|
|
|
|
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE); |
|
|
|
|
channel_control_helper()->UpdateState( |
|
|
|
|
GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_ERROR_REF(error), |
|
|
|
|
GRPC_CHANNEL_TRANSIENT_FAILURE, |
|
|
|
|
UniquePtr<SubchannelPicker>(New<TransientFailurePicker>(error))); |
|
|
|
|
} else { |
|
|
|
|
subchannel_list_->subchannel(0) |
|
|
|
@ -268,9 +269,11 @@ void PickFirst::UpdateLocked(UpdateArgs args) { |
|
|
|
|
// haven't gotten a non-empty update by the time the application tries
|
|
|
|
|
// to start a new call.)
|
|
|
|
|
if (!idle_) { |
|
|
|
|
grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Empty update"); |
|
|
|
|
grpc_error* error = grpc_error_set_int( |
|
|
|
|
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Empty update"), |
|
|
|
|
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE); |
|
|
|
|
channel_control_helper()->UpdateState( |
|
|
|
|
GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_ERROR_REF(error), |
|
|
|
|
GRPC_CHANNEL_TRANSIENT_FAILURE, |
|
|
|
|
UniquePtr<SubchannelPicker>(New<TransientFailurePicker>(error))); |
|
|
|
|
} |
|
|
|
|
return; |
|
|
|
@ -284,9 +287,7 @@ void PickFirst::UpdateLocked(UpdateArgs args) { |
|
|
|
|
// check and instead do it in ExitIdleLocked().
|
|
|
|
|
for (size_t i = 0; i < subchannel_list->num_subchannels(); ++i) { |
|
|
|
|
PickFirstSubchannelData* sd = subchannel_list->subchannel(i); |
|
|
|
|
grpc_error* error = GRPC_ERROR_NONE; |
|
|
|
|
grpc_connectivity_state state = sd->CheckConnectivityStateLocked(&error); |
|
|
|
|
GRPC_ERROR_UNREF(error); |
|
|
|
|
grpc_connectivity_state state = sd->CheckConnectivityStateLocked(); |
|
|
|
|
if (state == GRPC_CHANNEL_READY) { |
|
|
|
|
subchannel_list_ = std::move(subchannel_list); |
|
|
|
|
sd->StartConnectivityWatchLocked(); |
|
|
|
@ -340,7 +341,7 @@ void PickFirst::UpdateLocked(UpdateArgs args) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked( |
|
|
|
|
grpc_connectivity_state connectivity_state, grpc_error* error) { |
|
|
|
|
grpc_connectivity_state connectivity_state) { |
|
|
|
|
PickFirst* p = static_cast<PickFirst*>(subchannel_list()->policy()); |
|
|
|
|
AutoChildRefsUpdater guard(p); |
|
|
|
|
// The notification must be for a subchannel in either the current or
|
|
|
|
@ -371,17 +372,16 @@ void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked( |
|
|
|
|
p->subchannel_list_ = std::move(p->latest_pending_subchannel_list_); |
|
|
|
|
// Set our state to that of the pending subchannel list.
|
|
|
|
|
if (p->subchannel_list_->in_transient_failure()) { |
|
|
|
|
grpc_error* new_error = |
|
|
|
|
GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( |
|
|
|
|
"selected subchannel failed; switching to pending update", |
|
|
|
|
&error, 1); |
|
|
|
|
grpc_error* error = grpc_error_set_int( |
|
|
|
|
GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
|
|
|
|
"selected subchannel failed; switching to pending update"), |
|
|
|
|
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE); |
|
|
|
|
p->channel_control_helper()->UpdateState( |
|
|
|
|
GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_ERROR_REF(new_error), |
|
|
|
|
UniquePtr<SubchannelPicker>( |
|
|
|
|
New<TransientFailurePicker>(new_error))); |
|
|
|
|
GRPC_CHANNEL_TRANSIENT_FAILURE, |
|
|
|
|
UniquePtr<SubchannelPicker>(New<TransientFailurePicker>(error))); |
|
|
|
|
} else { |
|
|
|
|
p->channel_control_helper()->UpdateState( |
|
|
|
|
GRPC_CHANNEL_CONNECTING, GRPC_ERROR_NONE, |
|
|
|
|
GRPC_CHANNEL_CONNECTING, |
|
|
|
|
UniquePtr<SubchannelPicker>(New<QueuePicker>(p->Ref()))); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
@ -395,7 +395,7 @@ void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked( |
|
|
|
|
p->selected_ = nullptr; |
|
|
|
|
StopConnectivityWatchLocked(); |
|
|
|
|
p->channel_control_helper()->UpdateState( |
|
|
|
|
GRPC_CHANNEL_IDLE, GRPC_ERROR_NONE, |
|
|
|
|
GRPC_CHANNEL_IDLE, |
|
|
|
|
UniquePtr<SubchannelPicker>(New<QueuePicker>(p->Ref()))); |
|
|
|
|
} else { |
|
|
|
|
// This is unlikely but can happen when a subchannel has been asked
|
|
|
|
@ -403,19 +403,17 @@ void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked( |
|
|
|
|
// some connectivity state notifications.
|
|
|
|
|
if (connectivity_state == GRPC_CHANNEL_READY) { |
|
|
|
|
p->channel_control_helper()->UpdateState( |
|
|
|
|
GRPC_CHANNEL_READY, GRPC_ERROR_NONE, |
|
|
|
|
UniquePtr<SubchannelPicker>( |
|
|
|
|
New<Picker>(connected_subchannel()->Ref()))); |
|
|
|
|
GRPC_CHANNEL_READY, UniquePtr<SubchannelPicker>(New<Picker>( |
|
|
|
|
connected_subchannel()->Ref()))); |
|
|
|
|
} else { // CONNECTING
|
|
|
|
|
p->channel_control_helper()->UpdateState( |
|
|
|
|
connectivity_state, GRPC_ERROR_REF(error), |
|
|
|
|
connectivity_state, |
|
|
|
|
UniquePtr<SubchannelPicker>(New<QueuePicker>(p->Ref()))); |
|
|
|
|
} |
|
|
|
|
// Renew notification.
|
|
|
|
|
RenewConnectivityWatchLocked(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
GRPC_ERROR_UNREF(error); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
// If we get here, there are two possible cases:
|
|
|
|
@ -452,13 +450,13 @@ void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked( |
|
|
|
|
subchannel_list()->set_in_transient_failure(true); |
|
|
|
|
// Only report new state in case 1.
|
|
|
|
|
if (subchannel_list() == p->subchannel_list_.get()) { |
|
|
|
|
grpc_error* new_error = |
|
|
|
|
GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( |
|
|
|
|
"failed to connect to all addresses", &error, 1); |
|
|
|
|
grpc_error* error = grpc_error_set_int( |
|
|
|
|
GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
|
|
|
|
"failed to connect to all addresses"), |
|
|
|
|
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE); |
|
|
|
|
p->channel_control_helper()->UpdateState( |
|
|
|
|
GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_ERROR_REF(new_error), |
|
|
|
|
UniquePtr<SubchannelPicker>( |
|
|
|
|
New<TransientFailurePicker>(new_error))); |
|
|
|
|
GRPC_CHANNEL_TRANSIENT_FAILURE, |
|
|
|
|
UniquePtr<SubchannelPicker>(New<TransientFailurePicker>(error))); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
sd->CheckConnectivityStateAndStartWatchingLocked(); |
|
|
|
@ -469,7 +467,7 @@ void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked( |
|
|
|
|
// Only update connectivity state in case 1.
|
|
|
|
|
if (subchannel_list() == p->subchannel_list_.get()) { |
|
|
|
|
p->channel_control_helper()->UpdateState( |
|
|
|
|
GRPC_CHANNEL_CONNECTING, GRPC_ERROR_NONE, |
|
|
|
|
GRPC_CHANNEL_CONNECTING, |
|
|
|
|
UniquePtr<SubchannelPicker>(New<QueuePicker>(p->Ref()))); |
|
|
|
|
} |
|
|
|
|
// Renew notification.
|
|
|
|
@ -479,7 +477,6 @@ void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked( |
|
|
|
|
case GRPC_CHANNEL_SHUTDOWN: |
|
|
|
|
GPR_UNREACHABLE_CODE(break); |
|
|
|
|
} |
|
|
|
|
GRPC_ERROR_UNREF(error); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void PickFirst::PickFirstSubchannelData::ProcessUnselectedReadyLocked() { |
|
|
|
@ -509,7 +506,7 @@ void PickFirst::PickFirstSubchannelData::ProcessUnselectedReadyLocked() { |
|
|
|
|
// Cases 1 and 2.
|
|
|
|
|
p->selected_ = this; |
|
|
|
|
p->channel_control_helper()->UpdateState( |
|
|
|
|
GRPC_CHANNEL_READY, GRPC_ERROR_NONE, |
|
|
|
|
GRPC_CHANNEL_READY, |
|
|
|
|
UniquePtr<SubchannelPicker>(New<Picker>(connected_subchannel()->Ref()))); |
|
|
|
|
if (grpc_lb_pick_first_trace.enabled()) { |
|
|
|
|
gpr_log(GPR_INFO, "Pick First %p selected subchannel %p", p, subchannel()); |
|
|
|
@ -520,9 +517,7 @@ void PickFirst::PickFirstSubchannelData:: |
|
|
|
|
CheckConnectivityStateAndStartWatchingLocked() { |
|
|
|
|
PickFirst* p = static_cast<PickFirst*>(subchannel_list()->policy()); |
|
|
|
|
// Check current state.
|
|
|
|
|
grpc_error* error = GRPC_ERROR_NONE; |
|
|
|
|
grpc_connectivity_state current_state = CheckConnectivityStateLocked(&error); |
|
|
|
|
GRPC_ERROR_UNREF(error); |
|
|
|
|
grpc_connectivity_state current_state = CheckConnectivityStateLocked(); |
|
|
|
|
// Start watch.
|
|
|
|
|
StartConnectivityWatchLocked(); |
|
|
|
|
// If current state is READY, select the subchannel now, since we started
|
|
|
|
|