grpc 1.28.0.pre2 → 1.28.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of grpc might be problematic. Click here for more details.

@@ -71,6 +71,7 @@
71
71
  #include <grpc/support/time.h>
72
72
 
73
73
  #include "src/core/ext/filters/client_channel/client_channel.h"
74
+ #include "src/core/ext/filters/client_channel/lb_policy/child_policy_handler.h"
74
75
  #include "src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h"
75
76
  #include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h"
76
77
  #include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h"
@@ -296,14 +297,8 @@ class GrpcLb : public LoadBalancingPolicy {
296
297
  void RequestReresolution() override;
297
298
  void AddTraceEvent(TraceSeverity severity, StringView message) override;
298
299
 
299
- void set_child(LoadBalancingPolicy* child) { child_ = child; }
300
-
301
300
  private:
302
- bool CalledByPendingChild() const;
303
- bool CalledByCurrentChild() const;
304
-
305
301
  RefCountedPtr<GrpcLb> parent_;
306
- LoadBalancingPolicy* child_ = nullptr;
307
302
  };
308
303
 
309
304
  ~GrpcLb();
@@ -334,7 +329,7 @@ class GrpcLb : public LoadBalancingPolicy {
334
329
  grpc_channel_args* CreateChildPolicyArgsLocked(
335
330
  bool is_backend_from_grpclb_load_balancer);
336
331
  OrphanablePtr<LoadBalancingPolicy> CreateChildPolicyLocked(
337
- const char* name, const grpc_channel_args* args);
332
+ const grpc_channel_args* args);
338
333
  void CreateOrUpdateChildPolicyLocked();
339
334
 
340
335
  // Who the client is trying to communicate with.
@@ -385,9 +380,6 @@ class GrpcLb : public LoadBalancingPolicy {
385
380
 
386
381
  // The child policy to use for the backends.
387
382
  OrphanablePtr<LoadBalancingPolicy> child_policy_;
388
- // When switching child policies, the new policy will be stored here
389
- // until it reports READY, at which point it will be moved to child_policy_.
390
- OrphanablePtr<LoadBalancingPolicy> pending_child_policy_;
391
383
  // The child policy config.
392
384
  RefCountedPtr<LoadBalancingPolicy::Config> child_policy_config_;
393
385
  // Child policy in state READY.
@@ -629,46 +621,15 @@ GrpcLb::PickResult GrpcLb::Picker::Pick(PickArgs args) {
629
621
  // GrpcLb::Helper
630
622
  //
631
623
 
632
- bool GrpcLb::Helper::CalledByPendingChild() const {
633
- GPR_ASSERT(child_ != nullptr);
634
- return child_ == parent_->pending_child_policy_.get();
635
- }
636
-
637
- bool GrpcLb::Helper::CalledByCurrentChild() const {
638
- GPR_ASSERT(child_ != nullptr);
639
- return child_ == parent_->child_policy_.get();
640
- }
641
-
642
624
  RefCountedPtr<SubchannelInterface> GrpcLb::Helper::CreateSubchannel(
643
625
  const grpc_channel_args& args) {
644
- if (parent_->shutting_down_ ||
645
- (!CalledByPendingChild() && !CalledByCurrentChild())) {
646
- return nullptr;
647
- }
626
+ if (parent_->shutting_down_) return nullptr;
648
627
  return parent_->channel_control_helper()->CreateSubchannel(args);
649
628
  }
650
629
 
651
630
  void GrpcLb::Helper::UpdateState(grpc_connectivity_state state,
652
631
  std::unique_ptr<SubchannelPicker> picker) {
653
632
  if (parent_->shutting_down_) return;
654
- // If this request is from the pending child policy, ignore it until
655
- // it reports READY, at which point we swap it into place.
656
- if (CalledByPendingChild()) {
657
- if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
658
- gpr_log(GPR_INFO,
659
- "[grpclb %p helper %p] pending child policy %p reports state=%s",
660
- parent_.get(), this, parent_->pending_child_policy_.get(),
661
- ConnectivityStateName(state));
662
- }
663
- if (state != GRPC_CHANNEL_READY) return;
664
- grpc_pollset_set_del_pollset_set(
665
- parent_->child_policy_->interested_parties(),
666
- parent_->interested_parties());
667
- parent_->child_policy_ = std::move(parent_->pending_child_policy_);
668
- } else if (!CalledByCurrentChild()) {
669
- // This request is from an outdated child, so ignore it.
670
- return;
671
- }
672
633
  // Record whether child policy reports READY.
673
634
  parent_->child_policy_ready_ = state == GRPC_CHANNEL_READY;
674
635
  // Enter fallback mode if needed.
@@ -721,16 +682,6 @@ void GrpcLb::Helper::UpdateState(grpc_connectivity_state state,
721
682
 
722
683
  void GrpcLb::Helper::RequestReresolution() {
723
684
  if (parent_->shutting_down_) return;
724
- const LoadBalancingPolicy* latest_child_policy =
725
- parent_->pending_child_policy_ != nullptr
726
- ? parent_->pending_child_policy_.get()
727
- : parent_->child_policy_.get();
728
- if (child_ != latest_child_policy) return;
729
- if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
730
- gpr_log(GPR_INFO,
731
- "[grpclb %p] Re-resolution requested from %schild policy (%p).",
732
- parent_.get(), CalledByPendingChild() ? "pending " : "", child_);
733
- }
734
685
  // If we are talking to a balancer, we expect to get updated addresses
735
686
  // from the balancer, so we can ignore the re-resolution request from
736
687
  // the child policy. Otherwise, pass the re-resolution request up to the
@@ -742,10 +693,7 @@ void GrpcLb::Helper::RequestReresolution() {
742
693
  }
743
694
 
744
695
  void GrpcLb::Helper::AddTraceEvent(TraceSeverity severity, StringView message) {
745
- if (parent_->shutting_down_ ||
746
- (!CalledByPendingChild() && !CalledByCurrentChild())) {
747
- return;
748
- }
696
+ if (parent_->shutting_down_) return;
749
697
  parent_->channel_control_helper()->AddTraceEvent(severity, message);
750
698
  }
751
699
 
@@ -1411,13 +1359,8 @@ void GrpcLb::ShutdownLocked() {
1411
1359
  if (child_policy_ != nullptr) {
1412
1360
  grpc_pollset_set_del_pollset_set(child_policy_->interested_parties(),
1413
1361
  interested_parties());
1362
+ child_policy_.reset();
1414
1363
  }
1415
- if (pending_child_policy_ != nullptr) {
1416
- grpc_pollset_set_del_pollset_set(
1417
- pending_child_policy_->interested_parties(), interested_parties());
1418
- }
1419
- child_policy_.reset();
1420
- pending_child_policy_.reset();
1421
1364
  // We destroy the LB channel here instead of in our destructor because
1422
1365
  // destroying the channel triggers a last callback to
1423
1366
  // OnBalancerChannelConnectivityChangedLocked(), and we need to be
@@ -1439,9 +1382,6 @@ void GrpcLb::ResetBackoffLocked() {
1439
1382
  if (child_policy_ != nullptr) {
1440
1383
  child_policy_->ResetBackoffLocked();
1441
1384
  }
1442
- if (pending_child_policy_ != nullptr) {
1443
- pending_child_policy_->ResetBackoffLocked();
1444
- }
1445
1385
  }
1446
1386
 
1447
1387
  void GrpcLb::UpdateLocked(UpdateArgs args) {
@@ -1727,25 +1667,17 @@ grpc_channel_args* GrpcLb::CreateChildPolicyArgsLocked(
1727
1667
  }
1728
1668
 
1729
1669
  OrphanablePtr<LoadBalancingPolicy> GrpcLb::CreateChildPolicyLocked(
1730
- const char* name, const grpc_channel_args* args) {
1731
- Helper* helper = new Helper(Ref());
1670
+ const grpc_channel_args* args) {
1732
1671
  LoadBalancingPolicy::Args lb_policy_args;
1733
1672
  lb_policy_args.combiner = combiner();
1734
1673
  lb_policy_args.args = args;
1735
- lb_policy_args.channel_control_helper =
1736
- std::unique_ptr<ChannelControlHelper>(helper);
1674
+ lb_policy_args.channel_control_helper = absl::make_unique<Helper>(Ref());
1737
1675
  OrphanablePtr<LoadBalancingPolicy> lb_policy =
1738
- LoadBalancingPolicyRegistry::CreateLoadBalancingPolicy(
1739
- name, std::move(lb_policy_args));
1740
- if (GPR_UNLIKELY(lb_policy == nullptr)) {
1741
- gpr_log(GPR_ERROR, "[grpclb %p] Failure creating child policy %s", this,
1742
- name);
1743
- return nullptr;
1744
- }
1745
- helper->set_child(lb_policy.get());
1676
+ MakeOrphanable<ChildPolicyHandler>(std::move(lb_policy_args),
1677
+ &grpc_lb_glb_trace);
1746
1678
  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
1747
- gpr_log(GPR_INFO, "[grpclb %p] Created new child policy %s (%p)", this,
1748
- name, lb_policy.get());
1679
+ gpr_log(GPR_INFO, "[grpclb %p] Created new child policy handler (%p)", this,
1680
+ lb_policy.get());
1749
1681
  }
1750
1682
  // Add the gRPC LB's interested_parties pollset_set to that of the newly
1751
1683
  // created child policy. This will make the child policy progress upon
@@ -1776,97 +1708,16 @@ void GrpcLb::CreateOrUpdateChildPolicyLocked() {
1776
1708
  CreateChildPolicyArgsLocked(is_backend_from_grpclb_load_balancer);
1777
1709
  GPR_ASSERT(update_args.args != nullptr);
1778
1710
  update_args.config = child_policy_config_;
1779
- // If the child policy name changes, we need to create a new child
1780
- // policy. When this happens, we leave child_policy_ as-is and store
1781
- // the new child policy in pending_child_policy_. Once the new child
1782
- // policy transitions into state READY, we swap it into child_policy_,
1783
- // replacing the original child policy. So pending_child_policy_ is
1784
- // non-null only between when we apply an update that changes the child
1785
- // policy name and when the new child reports state READY.
1786
- //
1787
- // Updates can arrive at any point during this transition. We always
1788
- // apply updates relative to the most recently created child policy,
1789
- // even if the most recent one is still in pending_child_policy_. This
1790
- // is true both when applying the updates to an existing child policy
1791
- // and when determining whether we need to create a new policy.
1792
- //
1793
- // As a result of this, there are several cases to consider here:
1794
- //
1795
- // 1. We have no existing child policy (i.e., we have started up but
1796
- // have not yet received a serverlist from the balancer or gone
1797
- // into fallback mode; in this case, both child_policy_ and
1798
- // pending_child_policy_ are null). In this case, we create a
1799
- // new child policy and store it in child_policy_.
1800
- //
1801
- // 2. We have an existing child policy and have no pending child policy
1802
- // from a previous update (i.e., either there has not been a
1803
- // previous update that changed the policy name, or we have already
1804
- // finished swapping in the new policy; in this case, child_policy_
1805
- // is non-null but pending_child_policy_ is null). In this case:
1806
- // a. If child_policy_->name() equals child_policy_name, then we
1807
- // update the existing child policy.
1808
- // b. If child_policy_->name() does not equal child_policy_name,
1809
- // we create a new policy. The policy will be stored in
1810
- // pending_child_policy_ and will later be swapped into
1811
- // child_policy_ by the helper when the new child transitions
1812
- // into state READY.
1813
- //
1814
- // 3. We have an existing child policy and have a pending child policy
1815
- // from a previous update (i.e., a previous update set
1816
- // pending_child_policy_ as per case 2b above and that policy has
1817
- // not yet transitioned into state READY and been swapped into
1818
- // child_policy_; in this case, both child_policy_ and
1819
- // pending_child_policy_ are non-null). In this case:
1820
- // a. If pending_child_policy_->name() equals child_policy_name,
1821
- // then we update the existing pending child policy.
1822
- // b. If pending_child_policy->name() does not equal
1823
- // child_policy_name, then we create a new policy. The new
1824
- // policy is stored in pending_child_policy_ (replacing the one
1825
- // that was there before, which will be immediately shut down)
1826
- // and will later be swapped into child_policy_ by the helper
1827
- // when the new child transitions into state READY.
1828
- const char* child_policy_name = child_policy_config_ == nullptr
1829
- ? "round_robin"
1830
- : child_policy_config_->name();
1831
- const bool create_policy =
1832
- // case 1
1833
- child_policy_ == nullptr ||
1834
- // case 2b
1835
- (pending_child_policy_ == nullptr &&
1836
- strcmp(child_policy_->name(), child_policy_name) != 0) ||
1837
- // case 3b
1838
- (pending_child_policy_ != nullptr &&
1839
- strcmp(pending_child_policy_->name(), child_policy_name) != 0);
1840
- LoadBalancingPolicy* policy_to_update = nullptr;
1841
- if (create_policy) {
1842
- // Cases 1, 2b, and 3b: create a new child policy.
1843
- // If child_policy_ is null, we set it (case 1), else we set
1844
- // pending_child_policy_ (cases 2b and 3b).
1845
- if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
1846
- gpr_log(GPR_INFO, "[grpclb %p] Creating new %schild policy %s", this,
1847
- child_policy_ == nullptr ? "" : "pending ", child_policy_name);
1848
- }
1849
- // Swap the policy into place.
1850
- auto& lb_policy =
1851
- child_policy_ == nullptr ? child_policy_ : pending_child_policy_;
1852
- lb_policy = CreateChildPolicyLocked(child_policy_name, update_args.args);
1853
- policy_to_update = lb_policy.get();
1854
- } else {
1855
- // Cases 2a and 3a: update an existing policy.
1856
- // If we have a pending child policy, send the update to the pending
1857
- // policy (case 3a), else send it to the current policy (case 2a).
1858
- policy_to_update = pending_child_policy_ != nullptr
1859
- ? pending_child_policy_.get()
1860
- : child_policy_.get();
1711
+ // Create child policy if needed.
1712
+ if (child_policy_ == nullptr) {
1713
+ child_policy_ = CreateChildPolicyLocked(update_args.args);
1861
1714
  }
1862
- GPR_ASSERT(policy_to_update != nullptr);
1863
1715
  // Update the policy.
1864
1716
  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
1865
- gpr_log(GPR_INFO, "[grpclb %p] Updating %schild policy %p", this,
1866
- policy_to_update == pending_child_policy_.get() ? "pending " : "",
1867
- policy_to_update);
1717
+ gpr_log(GPR_INFO, "[grpclb %p] Updating child policy handler %p", this,
1718
+ child_policy_.get());
1868
1719
  }
1869
- policy_to_update->UpdateLocked(std::move(update_args));
1720
+ child_policy_->UpdateLocked(std::move(update_args));
1870
1721
  }
1871
1722
 
1872
1723
  //
@@ -1889,21 +1740,29 @@ class GrpcLbFactory : public LoadBalancingPolicyFactory {
1889
1740
  return MakeRefCounted<GrpcLbConfig>(nullptr);
1890
1741
  }
1891
1742
  std::vector<grpc_error*> error_list;
1892
- RefCountedPtr<LoadBalancingPolicy::Config> child_policy;
1743
+ Json child_policy_config_json_tmp;
1744
+ const Json* child_policy_config_json;
1893
1745
  auto it = json.object_value().find("childPolicy");
1894
- if (it != json.object_value().end()) {
1895
- grpc_error* parse_error = GRPC_ERROR_NONE;
1896
- child_policy = LoadBalancingPolicyRegistry::ParseLoadBalancingConfig(
1897
- it->second, &parse_error);
1898
- if (parse_error != GRPC_ERROR_NONE) {
1899
- std::vector<grpc_error*> child_errors;
1900
- child_errors.push_back(parse_error);
1901
- error_list.push_back(
1902
- GRPC_ERROR_CREATE_FROM_VECTOR("field:childPolicy", &child_errors));
1903
- }
1746
+ if (it == json.object_value().end()) {
1747
+ child_policy_config_json_tmp = Json::Array{Json::Object{
1748
+ {"round_robin", Json::Object()},
1749
+ }};
1750
+ child_policy_config_json = &child_policy_config_json_tmp;
1751
+ } else {
1752
+ child_policy_config_json = &it->second;
1753
+ }
1754
+ grpc_error* parse_error = GRPC_ERROR_NONE;
1755
+ RefCountedPtr<LoadBalancingPolicy::Config> child_policy_config =
1756
+ LoadBalancingPolicyRegistry::ParseLoadBalancingConfig(
1757
+ *child_policy_config_json, &parse_error);
1758
+ if (parse_error != GRPC_ERROR_NONE) {
1759
+ std::vector<grpc_error*> child_errors;
1760
+ child_errors.push_back(parse_error);
1761
+ error_list.push_back(
1762
+ GRPC_ERROR_CREATE_FROM_VECTOR("field:childPolicy", &child_errors));
1904
1763
  }
1905
1764
  if (error_list.empty()) {
1906
- return MakeRefCounted<GrpcLbConfig>(std::move(child_policy));
1765
+ return MakeRefCounted<GrpcLbConfig>(std::move(child_policy_config));
1907
1766
  } else {
1908
1767
  *error = GRPC_ERROR_CREATE_FROM_VECTOR("GrpcLb Parser", &error_list);
1909
1768
  return nullptr;
@@ -113,8 +113,14 @@ class CdsLb : public LoadBalancingPolicy {
113
113
 
114
114
  void CdsLb::ClusterWatcher::OnClusterChanged(XdsApi::CdsUpdate cluster_data) {
115
115
  if (GRPC_TRACE_FLAG_ENABLED(grpc_cds_lb_trace)) {
116
- gpr_log(GPR_INFO, "[cdslb %p] received CDS update from xds client",
117
- parent_.get());
116
+ gpr_log(GPR_INFO,
117
+ "[cdslb %p] received CDS update from xds client %p: "
118
+ "eds_service_name=%s lrs_load_reporting_server_name=%s",
119
+ parent_.get(), parent_->xds_client_.get(),
120
+ cluster_data.eds_service_name.c_str(),
121
+ cluster_data.lrs_load_reporting_server_name.has_value()
122
+ ? cluster_data.lrs_load_reporting_server_name.value().c_str()
123
+ : "(unset)");
118
124
  }
119
125
  // Construct config for child policy.
120
126
  Json::Object child_config = {
@@ -152,9 +158,18 @@ void CdsLb::ClusterWatcher::OnClusterChanged(XdsApi::CdsUpdate cluster_data) {
152
158
  parent_->child_policy_ =
153
159
  LoadBalancingPolicyRegistry::CreateLoadBalancingPolicy(
154
160
  "xds_experimental", std::move(args));
161
+ if (parent_->child_policy_ == nullptr) {
162
+ OnError(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
163
+ "failed to create xds_experimental child policy"));
164
+ return;
165
+ }
155
166
  grpc_pollset_set_add_pollset_set(
156
167
  parent_->child_policy_->interested_parties(),
157
168
  parent_->interested_parties());
169
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_cds_lb_trace)) {
170
+ gpr_log(GPR_INFO, "[cdslb %p] created child policy xds_experimental (%p)",
171
+ parent_.get(), parent_->child_policy_.get());
172
+ }
158
173
  }
159
174
  // Update child policy.
160
175
  UpdateArgs args;
@@ -220,9 +235,9 @@ void CdsLb::Helper::AddTraceEvent(TraceSeverity severity, StringView message) {
220
235
  CdsLb::CdsLb(Args args)
221
236
  : LoadBalancingPolicy(std::move(args)),
222
237
  xds_client_(XdsClient::GetFromChannelArgs(*args.args)) {
223
- if (xds_client_ != nullptr && GRPC_TRACE_FLAG_ENABLED(grpc_cds_lb_trace)) {
224
- gpr_log(GPR_INFO, "[cdslb %p] Using xds client %p from channel", this,
225
- xds_client_.get());
238
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_cds_lb_trace)) {
239
+ gpr_log(GPR_INFO, "[cdslb %p] created -- using xds client %p from channel",
240
+ this, xds_client_.get());
226
241
  }
227
242
  }
228
243
 
@@ -245,6 +260,10 @@ void CdsLb::ShutdownLocked() {
245
260
  }
246
261
  if (xds_client_ != nullptr) {
247
262
  if (cluster_watcher_ != nullptr) {
263
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_cds_lb_trace)) {
264
+ gpr_log(GPR_INFO, "[cdslb %p] cancelling watch for cluster %s", this,
265
+ config_->cluster().c_str());
266
+ }
248
267
  xds_client_->CancelClusterDataWatch(
249
268
  StringView(config_->cluster().c_str()), cluster_watcher_);
250
269
  }
@@ -257,12 +276,13 @@ void CdsLb::ResetBackoffLocked() {
257
276
  }
258
277
 
259
278
  void CdsLb::UpdateLocked(UpdateArgs args) {
260
- if (GRPC_TRACE_FLAG_ENABLED(grpc_cds_lb_trace)) {
261
- gpr_log(GPR_INFO, "[cdslb %p] received update", this);
262
- }
263
279
  // Update config.
264
280
  auto old_config = std::move(config_);
265
281
  config_ = std::move(args.config);
282
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_cds_lb_trace)) {
283
+ gpr_log(GPR_INFO, "[cdslb %p] received update: cluster=%s", this,
284
+ config_->cluster().c_str());
285
+ }
266
286
  // Update args.
267
287
  grpc_channel_args_destroy(args_);
268
288
  args_ = args.args;
@@ -270,8 +290,17 @@ void CdsLb::UpdateLocked(UpdateArgs args) {
270
290
  // If cluster name changed, cancel watcher and restart.
271
291
  if (old_config == nullptr || old_config->cluster() != config_->cluster()) {
272
292
  if (old_config != nullptr) {
293
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_cds_lb_trace)) {
294
+ gpr_log(GPR_INFO, "[cdslb %p] cancelling watch for cluster %s", this,
295
+ old_config->cluster().c_str());
296
+ }
273
297
  xds_client_->CancelClusterDataWatch(
274
- StringView(old_config->cluster().c_str()), cluster_watcher_);
298
+ StringView(old_config->cluster().c_str()), cluster_watcher_,
299
+ /*delay_unsubscription=*/true);
300
+ }
301
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_cds_lb_trace)) {
302
+ gpr_log(GPR_INFO, "[cdslb %p] starting watch for cluster %s", this,
303
+ config_->cluster().c_str());
275
304
  }
276
305
  auto watcher = absl::make_unique<ClusterWatcher>(Ref());
277
306
  cluster_watcher_ = watcher.get();
@@ -25,6 +25,8 @@
25
25
  #include <limits.h>
26
26
  #include <string.h>
27
27
 
28
+ #include "absl/types/optional.h"
29
+
28
30
  #include <grpc/grpc.h>
29
31
  #include <grpc/support/alloc.h>
30
32
  #include <grpc/support/string_util.h>
@@ -32,6 +34,7 @@
32
34
 
33
35
  #include "src/core/ext/filters/client_channel/client_channel.h"
34
36
  #include "src/core/ext/filters/client_channel/lb_policy.h"
37
+ #include "src/core/ext/filters/client_channel/lb_policy/child_policy_handler.h"
35
38
  #include "src/core/ext/filters/client_channel/lb_policy/xds/xds.h"
36
39
  #include "src/core/ext/filters/client_channel/lb_policy_factory.h"
37
40
  #include "src/core/ext/filters/client_channel/lb_policy_registry.h"
@@ -68,7 +71,7 @@
68
71
 
69
72
  namespace grpc_core {
70
73
 
71
- TraceFlag grpc_lb_xds_trace(false, "xds");
74
+ TraceFlag grpc_lb_xds_trace(false, "xds_lb");
72
75
 
73
76
  namespace {
74
77
 
@@ -79,7 +82,7 @@ class XdsConfig : public LoadBalancingPolicy::Config {
79
82
  XdsConfig(RefCountedPtr<LoadBalancingPolicy::Config> child_policy,
80
83
  RefCountedPtr<LoadBalancingPolicy::Config> fallback_policy,
81
84
  std::string eds_service_name,
82
- Optional<std::string> lrs_load_reporting_server_name)
85
+ absl::optional<std::string> lrs_load_reporting_server_name)
83
86
  : child_policy_(std::move(child_policy)),
84
87
  fallback_policy_(std::move(fallback_policy)),
85
88
  eds_service_name_(std::move(eds_service_name)),
@@ -100,7 +103,7 @@ class XdsConfig : public LoadBalancingPolicy::Config {
100
103
  return eds_service_name_.empty() ? nullptr : eds_service_name_.c_str();
101
104
  };
102
105
 
103
- const Optional<std::string>& lrs_load_reporting_server_name() const {
106
+ const absl::optional<std::string>& lrs_load_reporting_server_name() const {
104
107
  return lrs_load_reporting_server_name_;
105
108
  };
106
109
 
@@ -108,7 +111,7 @@ class XdsConfig : public LoadBalancingPolicy::Config {
108
111
  RefCountedPtr<LoadBalancingPolicy::Config> child_policy_;
109
112
  RefCountedPtr<LoadBalancingPolicy::Config> fallback_policy_;
110
113
  std::string eds_service_name_;
111
- Optional<std::string> lrs_load_reporting_server_name_;
114
+ absl::optional<std::string> lrs_load_reporting_server_name_;
112
115
  };
113
116
 
114
117
  class XdsLb : public LoadBalancingPolicy {
@@ -198,14 +201,8 @@ class XdsLb : public LoadBalancingPolicy {
198
201
  void RequestReresolution() override;
199
202
  void AddTraceEvent(TraceSeverity severity, StringView message) override;
200
203
 
201
- void set_child(LoadBalancingPolicy* child) { child_ = child; }
202
-
203
204
  private:
204
- bool CalledByPendingFallback() const;
205
- bool CalledByCurrentFallback() const;
206
-
207
205
  RefCountedPtr<XdsLb> parent_;
208
- LoadBalancingPolicy* child_ = nullptr;
209
206
  };
210
207
 
211
208
  // Each LocalityMap holds a ref to the XdsLb.
@@ -262,19 +259,14 @@ class XdsLb : public LoadBalancingPolicy {
262
259
  // client, which is a watch-based API.
263
260
  void RequestReresolution() override {}
264
261
  void AddTraceEvent(TraceSeverity severity, StringView message) override;
265
- void set_child(LoadBalancingPolicy* child) { child_ = child; }
266
262
 
267
263
  private:
268
- bool CalledByPendingChild() const;
269
- bool CalledByCurrentChild() const;
270
-
271
264
  RefCountedPtr<Locality> locality_;
272
- LoadBalancingPolicy* child_ = nullptr;
273
265
  };
274
266
 
275
267
  // Methods for dealing with the child policy.
276
268
  OrphanablePtr<LoadBalancingPolicy> CreateChildPolicyLocked(
277
- const char* name, const grpc_channel_args* args);
269
+ const grpc_channel_args* args);
278
270
  grpc_channel_args* CreateChildPolicyArgsLocked(
279
271
  const grpc_channel_args* args);
280
272
 
@@ -291,7 +283,6 @@ class XdsLb : public LoadBalancingPolicy {
291
283
  RefCountedPtr<XdsLocalityName> name_;
292
284
  RefCountedPtr<XdsClusterLocalityStats> stats_;
293
285
  OrphanablePtr<LoadBalancingPolicy> child_policy_;
294
- OrphanablePtr<LoadBalancingPolicy> pending_child_policy_;
295
286
  RefCountedPtr<RefCountedEndpointPicker> picker_wrapper_;
296
287
  RefCountedPtr<LoadReportingPicker> load_reporting_picker_;
297
288
  grpc_connectivity_state connectivity_state_ = GRPC_CHANNEL_IDLE;
@@ -309,7 +300,7 @@ class XdsLb : public LoadBalancingPolicy {
309
300
  ~LocalityMap() { xds_policy_.reset(DEBUG_LOCATION, "LocalityMap"); }
310
301
 
311
302
  void UpdateLocked(
312
- const XdsApi::PriorityListUpdate::LocalityMap& locality_map_update,
303
+ const XdsApi::PriorityListUpdate::LocalityMap& priority_update,
313
304
  bool update_locality_stats);
314
305
  void ResetBackoffLocked();
315
306
  void UpdateXdsPickerLocked();
@@ -403,7 +394,7 @@ class XdsLb : public LoadBalancingPolicy {
403
394
  static void OnFallbackTimerLocked(void* arg, grpc_error* error);
404
395
  void UpdateFallbackPolicyLocked();
405
396
  OrphanablePtr<LoadBalancingPolicy> CreateFallbackPolicyLocked(
406
- const char* name, const grpc_channel_args* args);
397
+ const grpc_channel_args* args);
407
398
  void MaybeExitFallbackMode();
408
399
 
409
400
  // Server name from target URI.
@@ -445,7 +436,6 @@ class XdsLb : public LoadBalancingPolicy {
445
436
 
446
437
  // Non-null iff we are in fallback mode.
447
438
  OrphanablePtr<LoadBalancingPolicy> fallback_policy_;
448
- OrphanablePtr<LoadBalancingPolicy> pending_fallback_policy_;
449
439
 
450
440
  const grpc_millis locality_retention_interval_ms_;
451
441
  const grpc_millis locality_map_failover_timeout_ms_;
@@ -506,6 +496,16 @@ XdsLb::PickResult XdsLb::LocalityPicker::Pick(PickArgs args) {
506
496
  result.type = PickResult::PICK_COMPLETE;
507
497
  return result;
508
498
  }
499
+ // If we didn't drop, we better have some localities to pick from.
500
+ if (pickers_.empty()) { // Should never happen.
501
+ PickResult result;
502
+ result.type = PickResult::PICK_FAILED;
503
+ result.error =
504
+ grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
505
+ "xds picker not given any localities"),
506
+ GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_INTERNAL);
507
+ return result;
508
+ }
509
509
  // Generate a random number in [0, total weight).
510
510
  const uint32_t key = rand() % pickers_[pickers_.size() - 1].first;
511
511
  // Forward pick to whichever locality maps to the range in which the
@@ -539,71 +539,26 @@ XdsLb::PickResult XdsLb::LocalityPicker::PickFromLocality(const uint32_t key,
539
539
  // XdsLb::FallbackHelper
540
540
  //
541
541
 
542
- bool XdsLb::FallbackHelper::CalledByPendingFallback() const {
543
- GPR_ASSERT(child_ != nullptr);
544
- return child_ == parent_->pending_fallback_policy_.get();
545
- }
546
-
547
- bool XdsLb::FallbackHelper::CalledByCurrentFallback() const {
548
- GPR_ASSERT(child_ != nullptr);
549
- return child_ == parent_->fallback_policy_.get();
550
- }
551
-
552
542
  RefCountedPtr<SubchannelInterface> XdsLb::FallbackHelper::CreateSubchannel(
553
543
  const grpc_channel_args& args) {
554
- if (parent_->shutting_down_ ||
555
- (!CalledByPendingFallback() && !CalledByCurrentFallback())) {
556
- return nullptr;
557
- }
544
+ if (parent_->shutting_down_) return nullptr;
558
545
  return parent_->channel_control_helper()->CreateSubchannel(args);
559
546
  }
560
547
 
561
548
  void XdsLb::FallbackHelper::UpdateState(
562
549
  grpc_connectivity_state state, std::unique_ptr<SubchannelPicker> picker) {
563
550
  if (parent_->shutting_down_) return;
564
- // If this request is from the pending fallback policy, ignore it until
565
- // it reports READY, at which point we swap it into place.
566
- if (CalledByPendingFallback()) {
567
- if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
568
- gpr_log(
569
- GPR_INFO,
570
- "[xdslb %p helper %p] pending fallback policy %p reports state=%s",
571
- parent_.get(), this, parent_->pending_fallback_policy_.get(),
572
- ConnectivityStateName(state));
573
- }
574
- if (state != GRPC_CHANNEL_READY) return;
575
- grpc_pollset_set_del_pollset_set(
576
- parent_->fallback_policy_->interested_parties(),
577
- parent_->interested_parties());
578
- parent_->fallback_policy_ = std::move(parent_->pending_fallback_policy_);
579
- } else if (!CalledByCurrentFallback()) {
580
- // This request is from an outdated fallback policy, so ignore it.
581
- return;
582
- }
583
551
  parent_->channel_control_helper()->UpdateState(state, std::move(picker));
584
552
  }
585
553
 
586
554
  void XdsLb::FallbackHelper::RequestReresolution() {
587
555
  if (parent_->shutting_down_) return;
588
- const LoadBalancingPolicy* latest_fallback_policy =
589
- parent_->pending_fallback_policy_ != nullptr
590
- ? parent_->pending_fallback_policy_.get()
591
- : parent_->fallback_policy_.get();
592
- if (child_ != latest_fallback_policy) return;
593
- if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
594
- gpr_log(GPR_INFO,
595
- "[xdslb %p] Re-resolution requested from the fallback policy (%p).",
596
- parent_.get(), child_);
597
- }
598
556
  parent_->channel_control_helper()->RequestReresolution();
599
557
  }
600
558
 
601
559
  void XdsLb::FallbackHelper::AddTraceEvent(TraceSeverity severity,
602
560
  StringView message) {
603
- if (parent_->shutting_down_ ||
604
- (!CalledByPendingFallback() && !CalledByCurrentFallback())) {
605
- return;
606
- }
561
+ if (parent_->shutting_down_) return;
607
562
  parent_->channel_control_helper()->AddTraceEvent(severity, message);
608
563
  }
609
564
 
@@ -625,7 +580,7 @@ class XdsLb::EndpointWatcher : public XdsClient::EndpointWatcherInterface {
625
580
  }
626
581
  // If the balancer tells us to drop all the calls, we should exit fallback
627
582
  // mode immediately.
628
- if (update.drop_all) xds_policy_->MaybeExitFallbackMode();
583
+ if (update.drop_config->drop_all()) xds_policy_->MaybeExitFallbackMode();
629
584
  // Update the drop config.
630
585
  const bool drop_config_changed =
631
586
  xds_policy_->drop_config_ == nullptr ||
@@ -676,6 +631,9 @@ class XdsLb::EndpointWatcher : public XdsClient::EndpointWatcherInterface {
676
631
  if (strstr(grpc_error_string(error), "xds call failed")) {
677
632
  xds_policy_->channel_control_helper()->RequestReresolution();
678
633
  }
634
+ } else if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
635
+ gpr_log(GPR_INFO, "[xdslb %p] xds watcher reported error (ignoring): %s",
636
+ xds_policy_.get(), grpc_error_string(error));
679
637
  }
680
638
  GRPC_ERROR_UNREF(error);
681
639
  }
@@ -700,9 +658,8 @@ XdsLb::XdsLb(Args args)
700
658
  locality_map_failover_timeout_ms_(grpc_channel_args_find_integer(
701
659
  args.args, GRPC_ARG_XDS_FAILOVER_TIMEOUT_MS,
702
660
  {GRPC_XDS_DEFAULT_FAILOVER_TIMEOUT_MS, 0, INT_MAX})) {
703
- if (xds_client_from_channel_ != nullptr &&
704
- GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
705
- gpr_log(GPR_INFO, "[xdslb %p] Using xds client %p from channel", this,
661
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
662
+ gpr_log(GPR_INFO, "[xdslb %p] created -- xds client from channel: %p", this,
706
663
  xds_client_from_channel_.get());
707
664
  }
708
665
  // Record server name.
@@ -737,18 +694,17 @@ void XdsLb::ShutdownLocked() {
737
694
  if (fallback_policy_ != nullptr) {
738
695
  grpc_pollset_set_del_pollset_set(fallback_policy_->interested_parties(),
739
696
  interested_parties());
697
+ fallback_policy_.reset();
740
698
  }
741
- if (pending_fallback_policy_ != nullptr) {
742
- grpc_pollset_set_del_pollset_set(
743
- pending_fallback_policy_->interested_parties(), interested_parties());
744
- }
745
- fallback_policy_.reset();
746
- pending_fallback_policy_.reset();
747
699
  // Cancel the endpoint watch here instead of in our dtor if we are using the
748
700
  // XdsResolver, because the watcher holds a ref to us and we might not be
749
701
  // destroying the Xds client leading to a situation where the Xds lb policy is
750
702
  // never destroyed.
751
703
  if (xds_client_from_channel_ != nullptr) {
704
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
705
+ gpr_log(GPR_INFO, "[xdslb %p] cancelling watch for %s", this,
706
+ eds_service_name());
707
+ }
752
708
  xds_client()->CancelEndpointDataWatch(StringView(eds_service_name()),
753
709
  endpoint_watcher_);
754
710
  xds_client_from_channel_.reset();
@@ -771,9 +727,6 @@ void XdsLb::ResetBackoffLocked() {
771
727
  if (fallback_policy_ != nullptr) {
772
728
  fallback_policy_->ResetBackoffLocked();
773
729
  }
774
- if (pending_fallback_policy_ != nullptr) {
775
- pending_fallback_policy_->ResetBackoffLocked();
776
- }
777
730
  }
778
731
 
779
732
  void XdsLb::UpdateLocked(UpdateArgs args) {
@@ -782,7 +735,6 @@ void XdsLb::UpdateLocked(UpdateArgs args) {
782
735
  }
783
736
  const bool is_initial_update = args_ == nullptr;
784
737
  // Update config.
785
- const char* old_eds_service_name = eds_service_name();
786
738
  auto old_config = std::move(config_);
787
739
  config_ = std::move(args.config);
788
740
  // Update fallback address list.
@@ -830,30 +782,27 @@ void XdsLb::UpdateLocked(UpdateArgs args) {
830
782
  eds_service_name(), eds_service_name());
831
783
  }
832
784
  }
833
- // Update priority list.
834
- // Note that this comes after updating drop_stats_, since we want that
835
- // to be used by any new picker we create here.
836
- // No need to do this on the initial update, since there won't be any
837
- // priorities to update yet.
838
- if (!is_initial_update) {
839
- const bool update_locality_stats =
840
- config_->lrs_load_reporting_server_name() !=
841
- old_config->lrs_load_reporting_server_name() ||
842
- strcmp(old_eds_service_name, eds_service_name()) != 0;
843
- UpdatePrioritiesLocked(update_locality_stats);
844
- }
845
- // Update endpoint watcher if needed.
846
- if (is_initial_update ||
847
- strcmp(old_eds_service_name, eds_service_name()) != 0) {
848
- if (!is_initial_update) {
849
- xds_client()->CancelEndpointDataWatch(StringView(old_eds_service_name),
850
- endpoint_watcher_);
785
+ // On the initial update, create the endpoint watcher.
786
+ if (is_initial_update) {
787
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
788
+ gpr_log(GPR_INFO, "[xdslb %p] starting watch for %s", this,
789
+ eds_service_name());
851
790
  }
852
791
  auto watcher = absl::make_unique<EndpointWatcher>(
853
792
  Ref(DEBUG_LOCATION, "EndpointWatcher"));
854
793
  endpoint_watcher_ = watcher.get();
855
794
  xds_client()->WatchEndpointData(StringView(eds_service_name()),
856
795
  std::move(watcher));
796
+ } else {
797
+ // Update priority list.
798
+ // Note that this comes after updating drop_stats_, since we want that
799
+ // to be used by any new picker we create here.
800
+ // No need to do this on the initial update, since there won't be any
801
+ // priorities to update yet.
802
+ const bool update_locality_stats =
803
+ config_->lrs_load_reporting_server_name() !=
804
+ old_config->lrs_load_reporting_server_name();
805
+ UpdatePrioritiesLocked(update_locality_stats);
857
806
  }
858
807
  }
859
808
 
@@ -896,127 +845,37 @@ void XdsLb::OnFallbackTimerLocked(void* arg, grpc_error* error) {
896
845
 
897
846
  void XdsLb::UpdateFallbackPolicyLocked() {
898
847
  if (shutting_down_) return;
899
- // Construct update args.
848
+ // Create policy if needed.
849
+ if (fallback_policy_ == nullptr) {
850
+ fallback_policy_ = CreateFallbackPolicyLocked(args_);
851
+ GPR_ASSERT(fallback_policy_ != nullptr);
852
+ }
853
+ // Perform update.
900
854
  UpdateArgs update_args;
901
855
  update_args.addresses = fallback_backend_addresses_;
902
856
  update_args.config = config_->fallback_policy();
903
857
  update_args.args = grpc_channel_args_copy(args_);
904
- // If the child policy name changes, we need to create a new child
905
- // policy. When this happens, we leave child_policy_ as-is and store
906
- // the new child policy in pending_child_policy_. Once the new child
907
- // policy transitions into state READY, we swap it into child_policy_,
908
- // replacing the original child policy. So pending_child_policy_ is
909
- // non-null only between when we apply an update that changes the child
910
- // policy name and when the new child reports state READY.
911
- //
912
- // Updates can arrive at any point during this transition. We always
913
- // apply updates relative to the most recently created child policy,
914
- // even if the most recent one is still in pending_child_policy_. This
915
- // is true both when applying the updates to an existing child policy
916
- // and when determining whether we need to create a new policy.
917
- //
918
- // As a result of this, there are several cases to consider here:
919
- //
920
- // 1. We have no existing child policy (i.e., we have started up but
921
- // have not yet received a serverlist from the balancer or gone
922
- // into fallback mode; in this case, both child_policy_ and
923
- // pending_child_policy_ are null). In this case, we create a
924
- // new child policy and store it in child_policy_.
925
- //
926
- // 2. We have an existing child policy and have no pending child policy
927
- // from a previous update (i.e., either there has not been a
928
- // previous update that changed the policy name, or we have already
929
- // finished swapping in the new policy; in this case, child_policy_
930
- // is non-null but pending_child_policy_ is null). In this case:
931
- // a. If child_policy_->name() equals child_policy_name, then we
932
- // update the existing child policy.
933
- // b. If child_policy_->name() does not equal child_policy_name,
934
- // we create a new policy. The policy will be stored in
935
- // pending_child_policy_ and will later be swapped into
936
- // child_policy_ by the helper when the new child transitions
937
- // into state READY.
938
- //
939
- // 3. We have an existing child policy and have a pending child policy
940
- // from a previous update (i.e., a previous update set
941
- // pending_child_policy_ as per case 2b above and that policy has
942
- // not yet transitioned into state READY and been swapped into
943
- // child_policy_; in this case, both child_policy_ and
944
- // pending_child_policy_ are non-null). In this case:
945
- // a. If pending_child_policy_->name() equals child_policy_name,
946
- // then we update the existing pending child policy.
947
- // b. If pending_child_policy->name() does not equal
948
- // child_policy_name, then we create a new policy. The new
949
- // policy is stored in pending_child_policy_ (replacing the one
950
- // that was there before, which will be immediately shut down)
951
- // and will later be swapped into child_policy_ by the helper
952
- // when the new child transitions into state READY.
953
- const char* fallback_policy_name = update_args.config == nullptr
954
- ? "round_robin"
955
- : update_args.config->name();
956
- const bool create_policy =
957
- // case 1
958
- fallback_policy_ == nullptr ||
959
- // case 2b
960
- (pending_fallback_policy_ == nullptr &&
961
- strcmp(fallback_policy_->name(), fallback_policy_name) != 0) ||
962
- // case 3b
963
- (pending_fallback_policy_ != nullptr &&
964
- strcmp(pending_fallback_policy_->name(), fallback_policy_name) != 0);
965
- LoadBalancingPolicy* policy_to_update = nullptr;
966
- if (create_policy) {
967
- // Cases 1, 2b, and 3b: create a new child policy.
968
- // If child_policy_ is null, we set it (case 1), else we set
969
- // pending_child_policy_ (cases 2b and 3b).
970
- if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
971
- gpr_log(GPR_INFO, "[xdslb %p] Creating new %sfallback policy %s", this,
972
- fallback_policy_ == nullptr ? "" : "pending ",
973
- fallback_policy_name);
974
- }
975
- auto& lb_policy = fallback_policy_ == nullptr ? fallback_policy_
976
- : pending_fallback_policy_;
977
- lb_policy =
978
- CreateFallbackPolicyLocked(fallback_policy_name, update_args.args);
979
- policy_to_update = lb_policy.get();
980
- } else {
981
- // Cases 2a and 3a: update an existing policy.
982
- // If we have a pending child policy, send the update to the pending
983
- // policy (case 3a), else send it to the current policy (case 2a).
984
- policy_to_update = pending_fallback_policy_ != nullptr
985
- ? pending_fallback_policy_.get()
986
- : fallback_policy_.get();
987
- }
988
- GPR_ASSERT(policy_to_update != nullptr);
989
- // Update the policy.
990
858
  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
991
- gpr_log(
992
- GPR_INFO, "[xdslb %p] Updating %sfallback policy %p", this,
993
- policy_to_update == pending_fallback_policy_.get() ? "pending " : "",
994
- policy_to_update);
859
+ gpr_log(GPR_INFO, "[xdslb %p] Updating fallback child policy handler %p",
860
+ this, fallback_policy_.get());
995
861
  }
996
- policy_to_update->UpdateLocked(std::move(update_args));
862
+ fallback_policy_->UpdateLocked(std::move(update_args));
997
863
  }
998
864
 
999
865
  OrphanablePtr<LoadBalancingPolicy> XdsLb::CreateFallbackPolicyLocked(
1000
- const char* name, const grpc_channel_args* args) {
1001
- FallbackHelper* helper =
1002
- new FallbackHelper(Ref(DEBUG_LOCATION, "FallbackHelper"));
866
+ const grpc_channel_args* args) {
1003
867
  LoadBalancingPolicy::Args lb_policy_args;
1004
868
  lb_policy_args.combiner = combiner();
1005
869
  lb_policy_args.args = args;
1006
870
  lb_policy_args.channel_control_helper =
1007
- std::unique_ptr<ChannelControlHelper>(helper);
871
+ absl::make_unique<FallbackHelper>(Ref(DEBUG_LOCATION, "FallbackHelper"));
1008
872
  OrphanablePtr<LoadBalancingPolicy> lb_policy =
1009
- LoadBalancingPolicyRegistry::CreateLoadBalancingPolicy(
1010
- name, std::move(lb_policy_args));
1011
- if (GPR_UNLIKELY(lb_policy == nullptr)) {
1012
- gpr_log(GPR_ERROR, "[xdslb %p] Failure creating fallback policy %s", this,
1013
- name);
1014
- return nullptr;
1015
- }
1016
- helper->set_child(lb_policy.get());
873
+ MakeOrphanable<ChildPolicyHandler>(std::move(lb_policy_args),
874
+ &grpc_lb_xds_trace);
1017
875
  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
1018
- gpr_log(GPR_INFO, "[xdslb %p] Created new fallback policy %s (%p)", this,
1019
- name, lb_policy.get());
876
+ gpr_log(GPR_INFO,
877
+ "[xdslb %p] Created new fallback child policy handler (%p)", this,
878
+ lb_policy.get());
1020
879
  }
1021
880
  // Add the xDS's interested_parties pollset_set to that of the newly created
1022
881
  // child policy. This will make the child policy progress upon activity on xDS
@@ -1030,7 +889,6 @@ void XdsLb::MaybeExitFallbackMode() {
1030
889
  if (fallback_policy_ == nullptr) return;
1031
890
  gpr_log(GPR_INFO, "[xdslb %p] Exiting fallback mode", this);
1032
891
  fallback_policy_.reset();
1033
- pending_fallback_policy_.reset();
1034
892
  }
1035
893
 
1036
894
  //
@@ -1071,13 +929,24 @@ void XdsLb::UpdatePrioritiesLocked(bool update_locality_stats) {
1071
929
  void XdsLb::UpdateXdsPickerLocked() {
1072
930
  // If we are in fallback mode, don't generate an xds picker from localities.
1073
931
  if (fallback_policy_ != nullptr) return;
1074
- if (current_priority_ == UINT32_MAX) {
1075
- grpc_error* error = grpc_error_set_int(
1076
- GRPC_ERROR_CREATE_FROM_STATIC_STRING("no ready locality map"),
1077
- GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
932
+ // If we're dropping all calls, report READY, even though we won't
933
+ // have a selected priority.
934
+ if (drop_config_ != nullptr && drop_config_->drop_all()) {
1078
935
  channel_control_helper()->UpdateState(
1079
- GRPC_CHANNEL_TRANSIENT_FAILURE,
1080
- absl::make_unique<TransientFailurePicker>(error));
936
+ GRPC_CHANNEL_READY,
937
+ absl::make_unique<LocalityPicker>(this, LocalityPicker::PickerList{}));
938
+ return;
939
+ }
940
+ // If we don't have a selected priority, report TRANSIENT_FAILURE.
941
+ if (current_priority_ == UINT32_MAX) {
942
+ if (fallback_policy_ == nullptr) {
943
+ grpc_error* error = grpc_error_set_int(
944
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("no ready locality map"),
945
+ GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
946
+ channel_control_helper()->UpdateState(
947
+ GRPC_CHANNEL_TRANSIENT_FAILURE,
948
+ absl::make_unique<TransientFailurePicker>(error));
949
+ }
1081
950
  return;
1082
951
  }
1083
952
  priorities_[current_priority_]->UpdateXdsPickerLocked();
@@ -1139,7 +1008,16 @@ OrphanablePtr<XdsLb::LocalityMap::Locality> XdsLb::ExtractLocalityLocked(
1139
1008
  if (priority == exclude_priority) continue;
1140
1009
  LocalityMap* locality_map = priorities_[priority].get();
1141
1010
  auto locality = locality_map->ExtractLocalityLocked(name);
1142
- if (locality != nullptr) return locality;
1011
+ if (locality != nullptr) {
1012
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
1013
+ gpr_log(GPR_INFO,
1014
+ "[xdslb %p] moving locality %p %s to new priority (%" PRIu32
1015
+ " -> %" PRIu32 ")",
1016
+ this, locality.get(), name->AsHumanReadableString(),
1017
+ exclude_priority, priority);
1018
+ }
1019
+ return locality;
1020
+ }
1143
1021
  }
1144
1022
  return nullptr;
1145
1023
  }
@@ -1165,7 +1043,7 @@ XdsLb::LocalityMap::LocalityMap(RefCountedPtr<XdsLb> xds_policy,
1165
1043
  &on_failover_timer_);
1166
1044
  failover_timer_callback_pending_ = true;
1167
1045
  // This is the first locality map ever created, report CONNECTING.
1168
- if (priority_ == 0) {
1046
+ if (priority_ == 0 && xds_policy_->fallback_policy_ == nullptr) {
1169
1047
  xds_policy_->channel_control_helper()->UpdateState(
1170
1048
  GRPC_CHANNEL_CONNECTING,
1171
1049
  absl::make_unique<QueuePicker>(
@@ -1174,7 +1052,7 @@ XdsLb::LocalityMap::LocalityMap(RefCountedPtr<XdsLb> xds_policy,
1174
1052
  }
1175
1053
 
1176
1054
  void XdsLb::LocalityMap::UpdateLocked(
1177
- const XdsApi::PriorityListUpdate::LocalityMap& locality_map_update,
1055
+ const XdsApi::PriorityListUpdate::LocalityMap& priority_update,
1178
1056
  bool update_locality_stats) {
1179
1057
  if (xds_policy_->shutting_down_) return;
1180
1058
  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
@@ -1184,11 +1062,11 @@ void XdsLb::LocalityMap::UpdateLocked(
1184
1062
  // Maybe reactivate the locality map in case all the active locality maps have
1185
1063
  // failed.
1186
1064
  MaybeReactivateLocked();
1187
- // Remove (later) the localities not in locality_map_update.
1065
+ // Remove (later) the localities not in priority_update.
1188
1066
  for (auto iter = localities_.begin(); iter != localities_.end();) {
1189
1067
  const auto& name = iter->first;
1190
1068
  Locality* locality = iter->second.get();
1191
- if (locality_map_update.Contains(name)) {
1069
+ if (priority_update.Contains(name)) {
1192
1070
  ++iter;
1193
1071
  continue;
1194
1072
  }
@@ -1199,8 +1077,8 @@ void XdsLb::LocalityMap::UpdateLocked(
1199
1077
  ++iter;
1200
1078
  }
1201
1079
  }
1202
- // Add or update the localities in locality_map_update.
1203
- for (const auto& p : locality_map_update.localities) {
1080
+ // Add or update the localities in priority_update.
1081
+ for (const auto& p : priority_update.localities) {
1204
1082
  const auto& name = p.first;
1205
1083
  const auto& locality_update = p.second;
1206
1084
  OrphanablePtr<Locality>& locality = localities_[name];
@@ -1220,6 +1098,32 @@ void XdsLb::LocalityMap::UpdateLocked(
1220
1098
  locality->UpdateLocked(locality_update.lb_weight,
1221
1099
  locality_update.serverlist, update_locality_stats);
1222
1100
  }
1101
+ // If this is the current priority and we removed all of the READY
1102
+ // localities, go into state CONNECTING.
1103
+ // TODO(roth): Ideally, we should model this as a graceful policy
1104
+ // switch: we should keep using the old localities for a short period
1105
+ // of time, long enough to give the new localities a chance to get
1106
+ // connected. As part of refactoring this policy, we should try to
1107
+ // fix that.
1108
+ if (priority_ == xds_policy()->current_priority_) {
1109
+ bool found_ready = false;
1110
+ for (auto& p : localities_) {
1111
+ const auto& locality_name = p.first;
1112
+ Locality* locality = p.second.get();
1113
+ if (!locality_map_update()->Contains(locality_name)) continue;
1114
+ if (locality->connectivity_state() == GRPC_CHANNEL_READY) {
1115
+ found_ready = true;
1116
+ break;
1117
+ }
1118
+ }
1119
+ if (!found_ready) {
1120
+ xds_policy_->channel_control_helper()->UpdateState(
1121
+ GRPC_CHANNEL_CONNECTING,
1122
+ absl::make_unique<QueuePicker>(
1123
+ xds_policy_->Ref(DEBUG_LOCATION, "QueuePicker")));
1124
+ xds_policy_->current_priority_ = UINT32_MAX;
1125
+ }
1126
+ }
1223
1127
  }
1224
1128
 
1225
1129
  void XdsLb::LocalityMap::ResetBackoffLocked() {
@@ -1227,6 +1131,9 @@ void XdsLb::LocalityMap::ResetBackoffLocked() {
1227
1131
  }
1228
1132
 
1229
1133
  void XdsLb::LocalityMap::UpdateXdsPickerLocked() {
1134
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
1135
+ gpr_log(GPR_INFO, "[xdslb %p] constructing new picker", xds_policy());
1136
+ }
1230
1137
  // Construct a new xds picker which maintains a map of all locality pickers
1231
1138
  // that are ready. Each locality is represented by a portion of the range
1232
1139
  // proportional to its weight, such that the total range is the sum of the
@@ -1237,11 +1144,18 @@ void XdsLb::LocalityMap::UpdateXdsPickerLocked() {
1237
1144
  const auto& locality_name = p.first;
1238
1145
  Locality* locality = p.second.get();
1239
1146
  // Skip the localities that are not in the latest locality map update.
1240
- if (!locality_map_update()->Contains(locality_name)) continue;
1147
+ const auto* locality_update = locality_map_update();
1148
+ if (locality_update == nullptr) continue;
1149
+ if (!locality_update->Contains(locality_name)) continue;
1241
1150
  if (locality->connectivity_state() != GRPC_CHANNEL_READY) continue;
1242
1151
  end += locality->weight();
1243
1152
  picker_list.push_back(
1244
1153
  std::make_pair(end, locality->GetLoadReportingPicker()));
1154
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
1155
+ gpr_log(GPR_INFO, "[xdslb %p] locality=%s weight=%d picker=%p",
1156
+ xds_policy(), locality_name->AsHumanReadableString(),
1157
+ locality->weight(), picker_list.back().second.get());
1158
+ }
1245
1159
  }
1246
1160
  xds_policy()->channel_control_helper()->UpdateState(
1247
1161
  GRPC_CHANNEL_READY,
@@ -1263,6 +1177,10 @@ XdsLb::LocalityMap::ExtractLocalityLocked(
1263
1177
  }
1264
1178
 
1265
1179
  void XdsLb::LocalityMap::DeactivateLocked() {
1180
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
1181
+ gpr_log(GPR_INFO, "[xdslb %p] deactivating priority %" PRIu32, xds_policy(),
1182
+ priority_);
1183
+ }
1266
1184
  // If already deactivated, don't do it again.
1267
1185
  if (delayed_removal_timer_callback_pending_) return;
1268
1186
  MaybeCancelFailoverTimerLocked();
@@ -1287,6 +1205,10 @@ bool XdsLb::LocalityMap::MaybeReactivateLocked() {
1287
1205
  // Don't reactivate a priority that is not higher than the current one.
1288
1206
  if (priority_ >= xds_policy_->current_priority_) return false;
1289
1207
  // Reactivate this priority by cancelling deletion timer.
1208
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
1209
+ gpr_log(GPR_INFO, "[xdslb %p] reactivating priority %" PRIu32, xds_policy(),
1210
+ priority_);
1211
+ }
1290
1212
  if (delayed_removal_timer_callback_pending_) {
1291
1213
  grpc_timer_cancel(&delayed_removal_timer_);
1292
1214
  }
@@ -1513,27 +1435,19 @@ grpc_channel_args* XdsLb::LocalityMap::Locality::CreateChildPolicyArgsLocked(
1513
1435
 
1514
1436
  OrphanablePtr<LoadBalancingPolicy>
1515
1437
  XdsLb::LocalityMap::Locality::CreateChildPolicyLocked(
1516
- const char* name, const grpc_channel_args* args) {
1517
- Helper* helper = new Helper(this->Ref(DEBUG_LOCATION, "Helper"));
1438
+ const grpc_channel_args* args) {
1518
1439
  LoadBalancingPolicy::Args lb_policy_args;
1519
1440
  lb_policy_args.combiner = xds_policy()->combiner();
1520
1441
  lb_policy_args.args = args;
1521
1442
  lb_policy_args.channel_control_helper =
1522
- std::unique_ptr<ChannelControlHelper>(helper);
1443
+ absl::make_unique<Helper>(this->Ref(DEBUG_LOCATION, "Helper"));
1523
1444
  OrphanablePtr<LoadBalancingPolicy> lb_policy =
1524
- LoadBalancingPolicyRegistry::CreateLoadBalancingPolicy(
1525
- name, std::move(lb_policy_args));
1526
- if (GPR_UNLIKELY(lb_policy == nullptr)) {
1527
- gpr_log(GPR_ERROR,
1528
- "[xdslb %p] Locality %p %s: failure creating child policy %s",
1529
- xds_policy(), this, name_->AsHumanReadableString(), name);
1530
- return nullptr;
1531
- }
1532
- helper->set_child(lb_policy.get());
1445
+ MakeOrphanable<ChildPolicyHandler>(std::move(lb_policy_args),
1446
+ &grpc_lb_xds_trace);
1533
1447
  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
1534
1448
  gpr_log(GPR_INFO,
1535
- "[xdslb %p] Locality %p %s: Created new child policy %s (%p)",
1536
- xds_policy(), this, name_->AsHumanReadableString(), name,
1449
+ "[xdslb %p] Locality %p %s: Created new child policy handler (%p)",
1450
+ xds_policy(), this, name_->AsHumanReadableString(),
1537
1451
  lb_policy.get());
1538
1452
  }
1539
1453
  // Add the xDS's interested_parties pollset_set to that of the newly created
@@ -1551,6 +1465,10 @@ void XdsLb::LocalityMap::Locality::UpdateLocked(uint32_t locality_weight,
1551
1465
  // Update locality weight.
1552
1466
  weight_ = locality_weight;
1553
1467
  if (delayed_removal_timer_callback_pending_) {
1468
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
1469
+ gpr_log(GPR_INFO, "[xdslb %p] Locality %p %s: reactivating", xds_policy(),
1470
+ this, name_->AsHumanReadableString());
1471
+ }
1554
1472
  grpc_timer_cancel(&delayed_removal_timer_);
1555
1473
  }
1556
1474
  // Update locality stats.
@@ -1560,101 +1478,19 @@ void XdsLb::LocalityMap::Locality::UpdateLocked(uint32_t locality_weight,
1560
1478
  update_args.addresses = std::move(serverlist);
1561
1479
  update_args.config = xds_policy()->config_->child_policy();
1562
1480
  update_args.args = CreateChildPolicyArgsLocked(xds_policy()->args_);
1563
- // If the child policy name changes, we need to create a new child
1564
- // policy. When this happens, we leave child_policy_ as-is and store
1565
- // the new child policy in pending_child_policy_. Once the new child
1566
- // policy transitions into state READY, we swap it into child_policy_,
1567
- // replacing the original child policy. So pending_child_policy_ is
1568
- // non-null only between when we apply an update that changes the child
1569
- // policy name and when the new child reports state READY.
1570
- //
1571
- // Updates can arrive at any point during this transition. We always
1572
- // apply updates relative to the most recently created child policy,
1573
- // even if the most recent one is still in pending_child_policy_. This
1574
- // is true both when applying the updates to an existing child policy
1575
- // and when determining whether we need to create a new policy.
1576
- //
1577
- // As a result of this, there are several cases to consider here:
1578
- //
1579
- // 1. We have no existing child policy (i.e., we have started up but
1580
- // have not yet received a serverlist from the balancer or gone
1581
- // into fallback mode; in this case, both child_policy_ and
1582
- // pending_child_policy_ are null). In this case, we create a
1583
- // new child policy and store it in child_policy_.
1584
- //
1585
- // 2. We have an existing child policy and have no pending child policy
1586
- // from a previous update (i.e., either there has not been a
1587
- // previous update that changed the policy name, or we have already
1588
- // finished swapping in the new policy; in this case, child_policy_
1589
- // is non-null but pending_child_policy_ is null). In this case:
1590
- // a. If child_policy_->name() equals child_policy_name, then we
1591
- // update the existing child policy.
1592
- // b. If child_policy_->name() does not equal child_policy_name,
1593
- // we create a new policy. The policy will be stored in
1594
- // pending_child_policy_ and will later be swapped into
1595
- // child_policy_ by the helper when the new child transitions
1596
- // into state READY.
1597
- //
1598
- // 3. We have an existing child policy and have a pending child policy
1599
- // from a previous update (i.e., a previous update set
1600
- // pending_child_policy_ as per case 2b above and that policy has
1601
- // not yet transitioned into state READY and been swapped into
1602
- // child_policy_; in this case, both child_policy_ and
1603
- // pending_child_policy_ are non-null). In this case:
1604
- // a. If pending_child_policy_->name() equals child_policy_name,
1605
- // then we update the existing pending child policy.
1606
- // b. If pending_child_policy->name() does not equal
1607
- // child_policy_name, then we create a new policy. The new
1608
- // policy is stored in pending_child_policy_ (replacing the one
1609
- // that was there before, which will be immediately shut down)
1610
- // and will later be swapped into child_policy_ by the helper
1611
- // when the new child transitions into state READY.
1612
- // TODO(juanlishen): If the child policy is not configured via service config,
1613
- // use whatever algorithm is specified by the balancer.
1614
- const char* child_policy_name = update_args.config == nullptr
1615
- ? "round_robin"
1616
- : update_args.config->name();
1617
- const bool create_policy =
1618
- // case 1
1619
- child_policy_ == nullptr ||
1620
- // case 2b
1621
- (pending_child_policy_ == nullptr &&
1622
- strcmp(child_policy_->name(), child_policy_name) != 0) ||
1623
- // case 3b
1624
- (pending_child_policy_ != nullptr &&
1625
- strcmp(pending_child_policy_->name(), child_policy_name) != 0);
1626
- LoadBalancingPolicy* policy_to_update = nullptr;
1627
- if (create_policy) {
1628
- // Cases 1, 2b, and 3b: create a new child policy.
1629
- // If child_policy_ is null, we set it (case 1), else we set
1630
- // pending_child_policy_ (cases 2b and 3b).
1631
- if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
1632
- gpr_log(GPR_INFO,
1633
- "[xdslb %p] Locality %p %s: Creating new %schild policy %s",
1634
- xds_policy(), this, name_->AsHumanReadableString(),
1635
- child_policy_ == nullptr ? "" : "pending ", child_policy_name);
1636
- }
1637
- auto& lb_policy =
1638
- child_policy_ == nullptr ? child_policy_ : pending_child_policy_;
1639
- lb_policy = CreateChildPolicyLocked(child_policy_name, update_args.args);
1640
- policy_to_update = lb_policy.get();
1641
- } else {
1642
- // Cases 2a and 3a: update an existing policy.
1643
- // If we have a pending child policy, send the update to the pending
1644
- // policy (case 3a), else send it to the current policy (case 2a).
1645
- policy_to_update = pending_child_policy_ != nullptr
1646
- ? pending_child_policy_.get()
1647
- : child_policy_.get();
1648
- }
1649
- GPR_ASSERT(policy_to_update != nullptr);
1481
+ // Create child policy if needed.
1482
+ if (child_policy_ == nullptr) {
1483
+ child_policy_ = CreateChildPolicyLocked(update_args.args);
1484
+ GPR_ASSERT(child_policy_ != nullptr);
1485
+ }
1650
1486
  // Update the policy.
1651
1487
  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
1652
- gpr_log(GPR_INFO, "[xdslb %p] Locality %p %s: Updating %schild policy %p",
1488
+ gpr_log(GPR_INFO,
1489
+ "[xdslb %p] Locality %p %s: Updating child policy handler %p",
1653
1490
  xds_policy(), this, name_->AsHumanReadableString(),
1654
- policy_to_update == pending_child_policy_.get() ? "pending " : "",
1655
- policy_to_update);
1491
+ child_policy_.get());
1656
1492
  }
1657
- policy_to_update->UpdateLocked(std::move(update_args));
1493
+ child_policy_->UpdateLocked(std::move(update_args));
1658
1494
  }
1659
1495
 
1660
1496
  void XdsLb::LocalityMap::Locality::ShutdownLocked() {
@@ -1668,12 +1504,6 @@ void XdsLb::LocalityMap::Locality::ShutdownLocked() {
1668
1504
  grpc_pollset_set_del_pollset_set(child_policy_->interested_parties(),
1669
1505
  xds_policy()->interested_parties());
1670
1506
  child_policy_.reset();
1671
- if (pending_child_policy_ != nullptr) {
1672
- grpc_pollset_set_del_pollset_set(
1673
- pending_child_policy_->interested_parties(),
1674
- xds_policy()->interested_parties());
1675
- pending_child_policy_.reset();
1676
- }
1677
1507
  // Drop our ref to the child's picker, in case it's holding a ref to
1678
1508
  // the child.
1679
1509
  load_reporting_picker_.reset();
@@ -1686,9 +1516,6 @@ void XdsLb::LocalityMap::Locality::ShutdownLocked() {
1686
1516
 
1687
1517
  void XdsLb::LocalityMap::Locality::ResetBackoffLocked() {
1688
1518
  child_policy_->ResetBackoffLocked();
1689
- if (pending_child_policy_ != nullptr) {
1690
- pending_child_policy_->ResetBackoffLocked();
1691
- }
1692
1519
  }
1693
1520
 
1694
1521
  void XdsLb::LocalityMap::Locality::Orphan() {
@@ -1699,6 +1526,10 @@ void XdsLb::LocalityMap::Locality::Orphan() {
1699
1526
  void XdsLb::LocalityMap::Locality::DeactivateLocked() {
1700
1527
  // If already deactivated, don't do that again.
1701
1528
  if (weight_ == 0) return;
1529
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
1530
+ gpr_log(GPR_INFO, "[xdslb %p] Locality %p %s: deactivating", xds_policy(),
1531
+ this, name_->AsHumanReadableString());
1532
+ }
1702
1533
  // Set the locality weight to 0 so that future xds picker won't contain this
1703
1534
  // locality.
1704
1535
  weight_ = 0;
@@ -1736,23 +1567,10 @@ void XdsLb::LocalityMap::Locality::OnDelayedRemovalTimerLocked(
1736
1567
  // XdsLb::LocalityMap::Locality::Helper
1737
1568
  //
1738
1569
 
1739
- bool XdsLb::LocalityMap::Locality::Helper::CalledByPendingChild() const {
1740
- GPR_ASSERT(child_ != nullptr);
1741
- return child_ == locality_->pending_child_policy_.get();
1742
- }
1743
-
1744
- bool XdsLb::LocalityMap::Locality::Helper::CalledByCurrentChild() const {
1745
- GPR_ASSERT(child_ != nullptr);
1746
- return child_ == locality_->child_policy_.get();
1747
- }
1748
-
1749
1570
  RefCountedPtr<SubchannelInterface>
1750
1571
  XdsLb::LocalityMap::Locality::Helper::CreateSubchannel(
1751
1572
  const grpc_channel_args& args) {
1752
- if (locality_->xds_policy()->shutting_down_ ||
1753
- (!CalledByPendingChild() && !CalledByCurrentChild())) {
1754
- return nullptr;
1755
- }
1573
+ if (locality_->xds_policy()->shutting_down_) return nullptr;
1756
1574
  return locality_->xds_policy()->channel_control_helper()->CreateSubchannel(
1757
1575
  args);
1758
1576
  }
@@ -1760,24 +1578,11 @@ XdsLb::LocalityMap::Locality::Helper::CreateSubchannel(
1760
1578
  void XdsLb::LocalityMap::Locality::Helper::UpdateState(
1761
1579
  grpc_connectivity_state state, std::unique_ptr<SubchannelPicker> picker) {
1762
1580
  if (locality_->xds_policy()->shutting_down_) return;
1763
- // If this request is from the pending child policy, ignore it until
1764
- // it reports READY, at which point we swap it into place.
1765
- if (CalledByPendingChild()) {
1766
- if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
1767
- gpr_log(GPR_INFO,
1768
- "[xdslb %p helper %p] pending child policy %p reports state=%s",
1769
- locality_->xds_policy(), this,
1770
- locality_->pending_child_policy_.get(),
1771
- ConnectivityStateName(state));
1772
- }
1773
- if (state != GRPC_CHANNEL_READY) return;
1774
- grpc_pollset_set_del_pollset_set(
1775
- locality_->child_policy_->interested_parties(),
1776
- locality_->xds_policy()->interested_parties());
1777
- locality_->child_policy_ = std::move(locality_->pending_child_policy_);
1778
- } else if (!CalledByCurrentChild()) {
1779
- // This request is from an outdated child, so ignore it.
1780
- return;
1581
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
1582
+ gpr_log(GPR_INFO,
1583
+ "[xdslb %p helper %p] child policy handler %p reports state=%s",
1584
+ locality_->xds_policy(), this, locality_->child_policy_.get(),
1585
+ ConnectivityStateName(state));
1781
1586
  }
1782
1587
  // Cache the state and picker in the locality.
1783
1588
  locality_->connectivity_state_ = state;
@@ -1789,10 +1594,7 @@ void XdsLb::LocalityMap::Locality::Helper::UpdateState(
1789
1594
 
1790
1595
  void XdsLb::LocalityMap::Locality::Helper::AddTraceEvent(TraceSeverity severity,
1791
1596
  StringView message) {
1792
- if (locality_->xds_policy()->shutting_down_ ||
1793
- (!CalledByPendingChild() && !CalledByCurrentChild())) {
1794
- return;
1795
- }
1597
+ if (locality_->xds_policy()->shutting_down_) return;
1796
1598
  locality_->xds_policy()->channel_control_helper()->AddTraceEvent(severity,
1797
1599
  message);
1798
1600
  }
@@ -1805,7 +1607,7 @@ class XdsFactory : public LoadBalancingPolicyFactory {
1805
1607
  public:
1806
1608
  OrphanablePtr<LoadBalancingPolicy> CreateLoadBalancingPolicy(
1807
1609
  LoadBalancingPolicy::Args args) const override {
1808
- return MakeOrphanable<XdsLb>(std::move(args));
1610
+ return MakeOrphanable<XdsChildHandler>(std::move(args), &grpc_lb_xds_trace);
1809
1611
  }
1810
1612
 
1811
1613
  const char* name() const override { return kXds; }
@@ -1823,34 +1625,48 @@ class XdsFactory : public LoadBalancingPolicyFactory {
1823
1625
  }
1824
1626
  std::vector<grpc_error*> error_list;
1825
1627
  // Child policy.
1826
- RefCountedPtr<LoadBalancingPolicy::Config> child_policy;
1628
+ Json json_tmp;
1629
+ const Json* child_policy_json;
1827
1630
  auto it = json.object_value().find("childPolicy");
1828
- if (it != json.object_value().end()) {
1829
- grpc_error* parse_error = GRPC_ERROR_NONE;
1830
- child_policy = LoadBalancingPolicyRegistry::ParseLoadBalancingConfig(
1831
- it->second, &parse_error);
1832
- if (child_policy == nullptr) {
1833
- GPR_DEBUG_ASSERT(parse_error != GRPC_ERROR_NONE);
1834
- std::vector<grpc_error*> child_errors;
1835
- child_errors.push_back(parse_error);
1836
- error_list.push_back(
1837
- GRPC_ERROR_CREATE_FROM_VECTOR("field:childPolicy", &child_errors));
1838
- }
1631
+ if (it == json.object_value().end()) {
1632
+ json_tmp = Json::Array{Json::Object{
1633
+ {"round_robin", Json::Object()},
1634
+ }};
1635
+ child_policy_json = &json_tmp;
1636
+ } else {
1637
+ child_policy_json = &it->second;
1638
+ }
1639
+ grpc_error* parse_error = GRPC_ERROR_NONE;
1640
+ RefCountedPtr<LoadBalancingPolicy::Config> child_policy =
1641
+ LoadBalancingPolicyRegistry::ParseLoadBalancingConfig(
1642
+ *child_policy_json, &parse_error);
1643
+ if (child_policy == nullptr) {
1644
+ GPR_DEBUG_ASSERT(parse_error != GRPC_ERROR_NONE);
1645
+ std::vector<grpc_error*> child_errors;
1646
+ child_errors.push_back(parse_error);
1647
+ error_list.push_back(
1648
+ GRPC_ERROR_CREATE_FROM_VECTOR("field:childPolicy", &child_errors));
1839
1649
  }
1840
1650
  // Fallback policy.
1841
- RefCountedPtr<LoadBalancingPolicy::Config> fallback_policy;
1651
+ const Json* fallback_policy_json;
1842
1652
  it = json.object_value().find("fallbackPolicy");
1843
- if (it != json.object_value().end()) {
1844
- grpc_error* parse_error = GRPC_ERROR_NONE;
1845
- fallback_policy = LoadBalancingPolicyRegistry::ParseLoadBalancingConfig(
1846
- it->second, &parse_error);
1847
- if (fallback_policy == nullptr) {
1848
- GPR_DEBUG_ASSERT(parse_error != GRPC_ERROR_NONE);
1849
- std::vector<grpc_error*> child_errors;
1850
- child_errors.push_back(parse_error);
1851
- error_list.push_back(GRPC_ERROR_CREATE_FROM_VECTOR(
1852
- "field:fallbackPolicy", &child_errors));
1853
- }
1653
+ if (it == json.object_value().end()) {
1654
+ json_tmp = Json::Array{Json::Object{
1655
+ {"round_robin", Json::Object()},
1656
+ }};
1657
+ fallback_policy_json = &json_tmp;
1658
+ } else {
1659
+ fallback_policy_json = &it->second;
1660
+ }
1661
+ RefCountedPtr<LoadBalancingPolicy::Config> fallback_policy =
1662
+ LoadBalancingPolicyRegistry::ParseLoadBalancingConfig(
1663
+ *fallback_policy_json, &parse_error);
1664
+ if (fallback_policy == nullptr) {
1665
+ GPR_DEBUG_ASSERT(parse_error != GRPC_ERROR_NONE);
1666
+ std::vector<grpc_error*> child_errors;
1667
+ child_errors.push_back(parse_error);
1668
+ error_list.push_back(
1669
+ GRPC_ERROR_CREATE_FROM_VECTOR("field:fallbackPolicy", &child_errors));
1854
1670
  }
1855
1671
  // EDS service name.
1856
1672
  const char* eds_service_name = nullptr;
@@ -1875,7 +1691,7 @@ class XdsFactory : public LoadBalancingPolicyFactory {
1875
1691
  }
1876
1692
  }
1877
1693
  if (error_list.empty()) {
1878
- Optional<std::string> optional_lrs_load_reporting_server_name;
1694
+ absl::optional<std::string> optional_lrs_load_reporting_server_name;
1879
1695
  if (lrs_load_reporting_server_name != nullptr) {
1880
1696
  optional_lrs_load_reporting_server_name.emplace(
1881
1697
  std::string(lrs_load_reporting_server_name));
@@ -1889,6 +1705,36 @@ class XdsFactory : public LoadBalancingPolicyFactory {
1889
1705
  return nullptr;
1890
1706
  }
1891
1707
  }
1708
+
1709
+ private:
1710
+ class XdsChildHandler : public ChildPolicyHandler {
1711
+ public:
1712
+ XdsChildHandler(Args args, TraceFlag* tracer)
1713
+ : ChildPolicyHandler(std::move(args), tracer) {}
1714
+
1715
+ bool ConfigChangeRequiresNewPolicyInstance(
1716
+ LoadBalancingPolicy::Config* old_config,
1717
+ LoadBalancingPolicy::Config* new_config) const override {
1718
+ GPR_ASSERT(old_config->name() == kXds);
1719
+ GPR_ASSERT(new_config->name() == kXds);
1720
+ XdsConfig* old_xds_config = static_cast<XdsConfig*>(old_config);
1721
+ XdsConfig* new_xds_config = static_cast<XdsConfig*>(new_config);
1722
+ const char* old_eds_service_name =
1723
+ old_xds_config->eds_service_name() == nullptr
1724
+ ? ""
1725
+ : old_xds_config->eds_service_name();
1726
+ const char* new_eds_service_name =
1727
+ new_xds_config->eds_service_name() == nullptr
1728
+ ? ""
1729
+ : new_xds_config->eds_service_name();
1730
+ return strcmp(old_eds_service_name, new_eds_service_name) != 0;
1731
+ }
1732
+
1733
+ OrphanablePtr<LoadBalancingPolicy> CreateLoadBalancingPolicy(
1734
+ const char* name, LoadBalancingPolicy::Args args) const override {
1735
+ return MakeOrphanable<XdsLb>(std::move(args));
1736
+ }
1737
+ };
1892
1738
  };
1893
1739
 
1894
1740
  } // namespace