1818
1919import  static  com .google .common .base .Preconditions .checkNotNull ;
2020import  static  io .grpc .ConnectivityState .TRANSIENT_FAILURE ;
21+ import  static  io .grpc .xds .XdsLbPolicies .CDS_POLICY_NAME ;
2122import  static  io .grpc .xds .XdsLbPolicies .CLUSTER_RESOLVER_POLICY_NAME ;
23+ import  static  io .grpc .xds .XdsLbPolicies .PRIORITY_POLICY_NAME ;
2224
23- import  com .google .common .annotations .VisibleForTesting ;
24- import  com .google .common .collect .ImmutableList ;
2525import  com .google .errorprone .annotations .CheckReturnValue ;
2626import  io .grpc .InternalLogId ;
2727import  io .grpc .LoadBalancer ;
3333import  io .grpc .xds .CdsLoadBalancerProvider .CdsConfig ;
3434import  io .grpc .xds .ClusterResolverLoadBalancerProvider .ClusterResolverConfig ;
3535import  io .grpc .xds .ClusterResolverLoadBalancerProvider .ClusterResolverConfig .DiscoveryMechanism ;
36+ import  io .grpc .xds .PriorityLoadBalancerProvider .PriorityLbConfig .PriorityChildConfig ;
3637import  io .grpc .xds .XdsClusterResource .CdsUpdate ;
3738import  io .grpc .xds .XdsClusterResource .CdsUpdate .ClusterType ;
3839import  io .grpc .xds .XdsConfig .Subscription ;
4142import  io .grpc .xds .XdsConfig .XdsClusterConfig .EndpointConfig ;
4243import  io .grpc .xds .client .XdsLogger ;
4344import  io .grpc .xds .client .XdsLogger .XdsLogLevel ;
44- import  java .util .ArrayList ;
4545import  java .util .Arrays ;
4646import  java .util .Collections ;
47+ import  java .util .HashMap ;
4748import  java .util .List ;
49+ import  java .util .Map ;
4850
4951/** 
5052 * Load balancer for cds_experimental LB policy. One instance per top-level cluster. 
@@ -55,19 +57,15 @@ final class CdsLoadBalancer2 extends LoadBalancer {
5557  private  final  XdsLogger  logger ;
5658  private  final  Helper  helper ;
5759  private  final  LoadBalancerRegistry  lbRegistry ;
60+   private  GracefulSwitchLoadBalancer  delegate ;
5861  // Following fields are effectively final. 
5962  private  String  clusterName ;
6063  private  Subscription  clusterSubscription ;
61-   private  LoadBalancer  childLb ;
6264
63-   CdsLoadBalancer2 (Helper  helper ) {
64-     this (helper , LoadBalancerRegistry .getDefaultRegistry ());
65-   }
66- 
67-   @ VisibleForTesting 
6865  CdsLoadBalancer2 (Helper  helper , LoadBalancerRegistry  lbRegistry ) {
6966    this .helper  = checkNotNull (helper , "helper" );
7067    this .lbRegistry  = checkNotNull (lbRegistry , "lbRegistry" );
68+     this .delegate  = new  GracefulSwitchLoadBalancer (helper );
7169    logger  = XdsLogger .withLogId (InternalLogId .allocate ("cds-lb" , helper .getAuthority ()));
7270    logger .log (XdsLogLevel .INFO , "Created" );
7371  }
@@ -91,7 +89,7 @@ public Status acceptResolvedAddresses(ResolvedAddresses resolvedAddresses) {
9189      if  (clusterSubscription  == null ) {
9290        // Should be impossible, because XdsDependencyManager wouldn't have generated this 
9391        return  fail (Status .INTERNAL .withDescription (
94-             errorPrefix () + "Unable to find non-dynamic root  cluster" ));
92+             errorPrefix () + "Unable to find non-dynamic cluster" ));
9593      }
9694      // The dynamic cluster must not have loaded yet 
9795      return  Status .OK ;
@@ -100,42 +98,25 @@ public Status acceptResolvedAddresses(ResolvedAddresses resolvedAddresses) {
10098      return  fail (clusterConfigOr .getStatus ());
10199    }
102100    XdsClusterConfig  clusterConfig  = clusterConfigOr .getValue ();
103-     List <String > leafNames ;
104-     if  (clusterConfig .getChildren () instanceof  AggregateConfig ) {
105-       leafNames  = ((AggregateConfig ) clusterConfig .getChildren ()).getLeafNames ();
106-     } else  if  (clusterConfig .getChildren () instanceof  EndpointConfig ) {
107-       leafNames  = ImmutableList .of (clusterName );
108-     } else  {
109-       return  fail (Status .INTERNAL .withDescription (
110-           errorPrefix () + "Unexpected cluster children type: " 
111-           + clusterConfig .getChildren ().getClass ()));
112-     }
113-     if  (leafNames .isEmpty ()) {
114-       // Should be impossible, because XdsClusterResource validated this 
115-       return  fail (Status .UNAVAILABLE .withDescription (
116-           errorPrefix () + "Zero leaf clusters for root cluster "  + clusterName ));
117-     }
118101
119-     Status  noneFoundError  = Status .INTERNAL 
120-         .withDescription (errorPrefix () + "No leaves and no error; this is a bug" );
121-     List <DiscoveryMechanism > instances  = new  ArrayList <>();
122-     for  (String  leafName  : leafNames ) {
123-       StatusOr <XdsClusterConfig > leafConfigOr  = xdsConfig .getClusters ().get (leafName );
124-       if  (!leafConfigOr .hasValue ()) {
125-         noneFoundError  = leafConfigOr .getStatus ();
126-         continue ;
127-       }
128-       if  (!(leafConfigOr .getValue ().getChildren () instanceof  EndpointConfig )) {
129-         noneFoundError  = Status .INTERNAL .withDescription (
130-             errorPrefix () + "Unexpected child "  + leafName  + " cluster children type: " 
131-             + leafConfigOr .getValue ().getChildren ().getClass ());
132-         continue ;
102+     NameResolver .ConfigOrError  configOrError ;
103+     Object  gracefulConfig ;
104+     if  (clusterConfig .getChildren () instanceof  EndpointConfig ) {
105+       // The LB policy config is provided in service_config.proto/JSON format. 
106+       configOrError  =
107+               GracefulSwitchLoadBalancer .parseLoadBalancingPolicyConfig (
108+                       Arrays .asList (clusterConfig .getClusterResource ().lbPolicyConfig ()),
109+                       lbRegistry );
110+       if  (configOrError .getError () != null ) {
111+         // Should be impossible, because XdsClusterResource validated this 
112+         return  fail (Status .INTERNAL .withDescription (
113+                 errorPrefix () + "Unable to parse the LB config: "  + configOrError .getError ()));
133114      }
134-       CdsUpdate  result  = leafConfigOr . getValue () .getClusterResource ();
115+       CdsUpdate  result  = clusterConfig .getClusterResource ();
135116      DiscoveryMechanism  instance ;
136117      if  (result .clusterType () == ClusterType .EDS ) {
137118        instance  = DiscoveryMechanism .forEds (
138-             leafName ,
119+             clusterName ,
139120            result .edsServiceName (),
140121            result .lrsServerInfo (),
141122            result .maxConcurrentRequests (),
@@ -144,45 +125,49 @@ public Status acceptResolvedAddresses(ResolvedAddresses resolvedAddresses) {
144125            result .outlierDetection ());
145126      } else  {
146127        instance  = DiscoveryMechanism .forLogicalDns (
147-             leafName ,
128+             clusterName ,
148129            result .dnsHostName (),
149130            result .lrsServerInfo (),
150131            result .maxConcurrentRequests (),
151132            result .upstreamTlsContext (),
152133            result .filterMetadata ());
153134      }
154-       instances .add (instance );
155-     }
156-     if  (instances .isEmpty ()) {
157-       return  fail (noneFoundError );
158-     }
159- 
160-     // The LB policy config is provided in service_config.proto/JSON format. 
161-     NameResolver .ConfigOrError  configOrError  =
162-         GracefulSwitchLoadBalancer .parseLoadBalancingPolicyConfig (
163-             Arrays .asList (clusterConfig .getClusterResource ().lbPolicyConfig ()), lbRegistry );
164-     if  (configOrError .getError () != null ) {
165-       // Should be impossible, because XdsClusterResource validated this 
135+       gracefulConfig  = GracefulSwitchLoadBalancer .createLoadBalancingPolicyConfig (
136+           lbRegistry .getProvider (CLUSTER_RESOLVER_POLICY_NAME ),
137+           new  ClusterResolverConfig (
138+               instance ,
139+               configOrError .getConfig (),
140+               clusterConfig .getClusterResource ().isHttp11ProxyAvailable ()));
141+     } else  if  (clusterConfig .getChildren () instanceof  AggregateConfig ) {
142+       Map <String , PriorityChildConfig > priorityChildConfigs  = new  HashMap <>();
143+       List <String > leafClusters  = ((AggregateConfig ) clusterConfig .getChildren ()).getLeafNames ();
144+       for  (String  childCluster : leafClusters ) {
145+         priorityChildConfigs .put (childCluster ,
146+                 new  PriorityChildConfig (
147+                         GracefulSwitchLoadBalancer .createLoadBalancingPolicyConfig (
148+                                 lbRegistry .getProvider (CDS_POLICY_NAME ),
149+                                 new  CdsConfig (childCluster )),
150+                         false ));
151+       }
152+       gracefulConfig  = GracefulSwitchLoadBalancer .createLoadBalancingPolicyConfig (
153+           lbRegistry .getProvider (PRIORITY_POLICY_NAME ),
154+           new  PriorityLoadBalancerProvider .PriorityLbConfig (
155+               Collections .unmodifiableMap (priorityChildConfigs ), leafClusters ));
156+     } else  {
166157      return  fail (Status .INTERNAL .withDescription (
167-           errorPrefix () + "Unable to parse the LB config: "  + configOrError .getError ()));
158+               errorPrefix () + "Unexpected cluster children type: " 
159+                       + clusterConfig .getChildren ().getClass ()));
168160    }
169161
170-     ClusterResolverConfig  config  = new  ClusterResolverConfig (
171-         Collections .unmodifiableList (instances ),
172-         configOrError .getConfig (),
173-         clusterConfig .getClusterResource ().isHttp11ProxyAvailable ());
174-     if  (childLb  == null ) {
175-       childLb  = lbRegistry .getProvider (CLUSTER_RESOLVER_POLICY_NAME ).newLoadBalancer (helper );
176-     }
177-     return  childLb .acceptResolvedAddresses (
178-         resolvedAddresses .toBuilder ().setLoadBalancingPolicyConfig (config ).build ());
162+     return  delegate .acceptResolvedAddresses (
163+         resolvedAddresses .toBuilder ().setLoadBalancingPolicyConfig (gracefulConfig ).build ());
179164  }
180165
181166  @ Override 
182167  public  void  handleNameResolutionError (Status  error ) {
183168    logger .log (XdsLogLevel .WARNING , "Received name resolution error: {0}" , error );
184-     if  (childLb  != null ) {
185-       childLb .handleNameResolutionError (error );
169+     if  (delegate  != null ) {
170+       delegate .handleNameResolutionError (error );
186171    } else  {
187172      helper .updateBalancingState (
188173          TRANSIENT_FAILURE , new  FixedResultPicker (PickResult .withError (error )));
@@ -192,10 +177,8 @@ public void handleNameResolutionError(Status error) {
192177  @ Override 
193178  public  void  shutdown () {
194179    logger .log (XdsLogLevel .INFO , "Shutdown" );
195-     if  (childLb  != null ) {
196-       childLb .shutdown ();
197-       childLb  = null ;
198-     }
180+     delegate .shutdown ();
181+     delegate  = new  GracefulSwitchLoadBalancer (helper );
199182    if  (clusterSubscription  != null ) {
200183      clusterSubscription .close ();
201184      clusterSubscription  = null ;
@@ -204,10 +187,7 @@ public void shutdown() {
204187
205188  @ CheckReturnValue  // don't forget to return up the stack after the fail call 
206189  private  Status  fail (Status  error ) {
207-     if  (childLb  != null ) {
208-       childLb .shutdown ();
209-       childLb  = null ;
210-     }
190+     delegate .shutdown ();
211191    helper .updateBalancingState (
212192        TRANSIENT_FAILURE , new  FixedResultPicker (PickResult .withError (error )));
213193    return  Status .OK ; // XdsNameResolver isn't a polling NR, so this value doesn't matter 
0 commit comments