diff --git a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc index c697ebb402b..3a0937015e7 100644 --- a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +++ b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc @@ -148,6 +148,7 @@ class RoundRobin : public LoadBalancingPolicy { void StartPickingLocked(); size_t GetNextReadySubchannelIndexLocked(); + bool DoPickLocked(PickState* pick); void UpdateLastReadySubchannelIndexLocked(size_t last_ready_index); void UpdateConnectivityStateLocked(grpc_connectivity_state state, grpc_error* error); @@ -351,6 +352,31 @@ void RoundRobin::ExitIdleLocked() { } } +bool RoundRobin::DoPickLocked(PickState* pick) { + const size_t next_ready_index = GetNextReadySubchannelIndexLocked(); + if (next_ready_index < subchannel_list_->num_subchannels()) { + /* readily available, report right away */ + RoundRobinSubchannelData* sd = + subchannel_list_->subchannel(next_ready_index); + pick->connected_subchannel = sd->connected_subchannel()->Ref(); + if (pick->user_data != nullptr) { + *pick->user_data = sd->user_data(); + } + if (grpc_lb_round_robin_trace.enabled()) { + gpr_log( + GPR_DEBUG, + "[RR %p] Picked target <-- Subchannel %p (connected %p) (sl %p, " + "index %" PRIuPTR ")", + this, sd->subchannel(), pick->connected_subchannel.get(), + sd->subchannel_list(), next_ready_index); + } + /* only advance the last picked pointer if the selection was used */ + UpdateLastReadySubchannelIndexLocked(next_ready_index); + return true; + } + return false; +} + bool RoundRobin::PickLocked(PickState* pick) { if (grpc_lb_round_robin_trace.enabled()) { gpr_log(GPR_DEBUG, "[RR %p] Trying to pick (shutdown: %d)", this, @@ -358,27 +384,7 @@ bool RoundRobin::PickLocked(PickState* pick) { } GPR_ASSERT(!shutdown_); if (subchannel_list_ != nullptr) { - const size_t next_ready_index = GetNextReadySubchannelIndexLocked(); - if (next_ready_index < subchannel_list_->num_subchannels()) { - /* readily available, report right away */ - RoundRobinSubchannelData* sd = - subchannel_list_->subchannel(next_ready_index); - pick->connected_subchannel = sd->connected_subchannel()->Ref(); - if (pick->user_data != nullptr) { - *pick->user_data = sd->user_data(); - } - if (grpc_lb_round_robin_trace.enabled()) { - gpr_log( - GPR_DEBUG, - "[RR %p] Picked target <-- Subchannel %p (connected %p) (sl %p, " - "index %" PRIuPTR ")", - this, sd->subchannel(), pick->connected_subchannel.get(), - sd->subchannel_list(), next_ready_index); - } - /* only advance the last picked pointer if the selection was used */ - UpdateLastReadySubchannelIndexLocked(next_ready_index); - return true; - } + if (DoPickLocked(pick)) return true; } /* no pick currently available. Save for later in list of pending picks */ if (!started_picking_) { @@ -548,32 +554,11 @@ void RoundRobin::RoundRobinSubchannelData::ProcessConnectivityChangeLocked( } p->subchannel_list_ = std::move(p->latest_pending_subchannel_list_); } - /* at this point we know there's at least one suitable subchannel. Go - * ahead and pick one and notify the pending suitors in - * p->pending_picks. This preemptively replicates rr_pick()'s actions. */ - const size_t next_ready_index = p->GetNextReadySubchannelIndexLocked(); - GPR_ASSERT(next_ready_index < p->subchannel_list_->num_subchannels()); - RoundRobinSubchannelData* selected = - p->subchannel_list_->subchannel(next_ready_index); - if (p->pending_picks_ != nullptr) { - // if the selected subchannel is going to be used for the pending - // picks, update the last picked pointer - p->UpdateLastReadySubchannelIndexLocked(next_ready_index); - } + // Drain pending picks. PickState* pick; while ((pick = p->pending_picks_)) { p->pending_picks_ = pick->next; - pick->connected_subchannel = selected->connected_subchannel()->Ref(); - if (pick->user_data != nullptr) { - *pick->user_data = selected->user_data(); - } - if (grpc_lb_round_robin_trace.enabled()) { - gpr_log(GPR_DEBUG, - "[RR %p] Fulfilling pending pick. Target <-- subchannel %p " - "(subchannel_list %p, index %" PRIuPTR ")", - p, selected->subchannel(), p->subchannel_list_.get(), - next_ready_index); - } + GPR_ASSERT(p->DoPickLocked(pick)); GRPC_CLOSURE_SCHED(pick->on_complete, GRPC_ERROR_NONE); } break;