|
|
|
@ -210,6 +210,7 @@ class WeightedTargetLb : public LoadBalancingPolicy { |
|
|
|
|
|
|
|
|
|
// Internal state.
|
|
|
|
|
bool shutting_down_ = false; |
|
|
|
|
bool update_in_progress_ = false; |
|
|
|
|
|
|
|
|
|
// Children.
|
|
|
|
|
std::map<std::string, OrphanablePtr<WeightedChild>> targets_; |
|
|
|
@ -281,6 +282,7 @@ void WeightedTargetLb::UpdateLocked(UpdateArgs args) { |
|
|
|
|
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_weighted_target_trace)) { |
|
|
|
|
gpr_log(GPR_INFO, "[weighted_target_lb %p] Received update", this); |
|
|
|
|
} |
|
|
|
|
update_in_progress_ = true; |
|
|
|
|
// Update config.
|
|
|
|
|
config_ = std::move(args.config); |
|
|
|
|
// Deactivate the targets not in the new config.
|
|
|
|
@ -291,38 +293,37 @@ void WeightedTargetLb::UpdateLocked(UpdateArgs args) { |
|
|
|
|
child->DeactivateLocked(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
// Create any children that don't already exist.
|
|
|
|
|
// Note that we add all children before updating any of them, because
|
|
|
|
|
// an update may trigger a child to immediately update its
|
|
|
|
|
// connectivity state (e.g., reporting TRANSIENT_FAILURE immediately when
|
|
|
|
|
// receiving an empty address list), and we don't want to return an
|
|
|
|
|
// overall state with incomplete data.
|
|
|
|
|
for (const auto& p : config_->target_map()) { |
|
|
|
|
const std::string& name = p.first; |
|
|
|
|
auto it = targets_.find(name); |
|
|
|
|
if (it == targets_.end()) { |
|
|
|
|
targets_.emplace(name, MakeOrphanable<WeightedChild>( |
|
|
|
|
Ref(DEBUG_LOCATION, "WeightedChild"), name)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
// Update all children.
|
|
|
|
|
absl::StatusOr<HierarchicalAddressMap> address_map = |
|
|
|
|
MakeHierarchicalAddressMap(args.addresses); |
|
|
|
|
for (const auto& p : config_->target_map()) { |
|
|
|
|
const std::string& name = p.first; |
|
|
|
|
const WeightedTargetLbConfig::ChildConfig& config = p.second; |
|
|
|
|
auto& target = targets_[name]; |
|
|
|
|
// Create child if it does not already exist.
|
|
|
|
|
if (target == nullptr) { |
|
|
|
|
target = MakeOrphanable<WeightedChild>( |
|
|
|
|
Ref(DEBUG_LOCATION, "WeightedChild"), name); |
|
|
|
|
} |
|
|
|
|
absl::StatusOr<ServerAddressList> addresses; |
|
|
|
|
if (address_map.ok()) { |
|
|
|
|
addresses = std::move((*address_map)[name]); |
|
|
|
|
} else { |
|
|
|
|
addresses = address_map.status(); |
|
|
|
|
} |
|
|
|
|
targets_[name]->UpdateLocked(config, std::move(addresses), args.args); |
|
|
|
|
target->UpdateLocked(config, std::move(addresses), args.args); |
|
|
|
|
} |
|
|
|
|
update_in_progress_ = false; |
|
|
|
|
UpdateStateLocked(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void WeightedTargetLb::UpdateStateLocked() { |
|
|
|
|
// If we're in the process of propagating an update from our parent to
|
|
|
|
|
// our children, ignore any updates that come from the children. We
|
|
|
|
|
// will instead return a new picker once the update has been seen by
|
|
|
|
|
// all children. This avoids unnecessary picker churn while an update
|
|
|
|
|
// is being propagated to our children.
|
|
|
|
|
if (update_in_progress_) return; |
|
|
|
|
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_weighted_target_trace)) { |
|
|
|
|
gpr_log(GPR_INFO, |
|
|
|
|
"[weighted_target_lb %p] scanning children to determine " |
|
|
|
@ -356,6 +357,7 @@ void WeightedTargetLb::UpdateStateLocked() { |
|
|
|
|
} |
|
|
|
|
switch (child->connectivity_state()) { |
|
|
|
|
case GRPC_CHANNEL_READY: { |
|
|
|
|
GPR_ASSERT(child->weight() > 0); |
|
|
|
|
end += child->weight(); |
|
|
|
|
picker_list.push_back(std::make_pair(end, child->picker_wrapper())); |
|
|
|
|
break; |
|
|
|
|