3636import  io .grpc .xds .client .XdsClient .ResourceWatcher ;
3737import  io .grpc .xds .client .XdsResourceType ;
3838import  java .util .Collections ;
39+ import  java .util .EnumMap ;
3940import  java .util .HashMap ;
4041import  java .util .HashSet ;
4142import  java .util .LinkedHashSet ;
5354 * applies to a single data plane authority. 
5455 */ 
5556final  class  XdsDependencyManager  implements  XdsConfig .XdsClusterSubscriptionRegistry  {
56-   public  static  final  XdsClusterResource  CLUSTER_RESOURCE  = XdsClusterResource .getInstance ();
57-   public  static  final  XdsEndpointResource  ENDPOINT_RESOURCE  = XdsEndpointResource .getInstance ();
57+   private  enum  TrackedWatcherTypeEnum  {
58+     LDS , RDS , CDS , EDS 
59+   }
60+ 
61+   private  static  final  TrackedWatcherType <XdsListenerResource .LdsUpdate > LDS_TYPE  =
62+       new  TrackedWatcherType <>(TrackedWatcherTypeEnum .LDS );
63+   private  static  final  TrackedWatcherType <RdsUpdate > RDS_TYPE  =
64+       new  TrackedWatcherType <>(TrackedWatcherTypeEnum .RDS );
65+   private  static  final  TrackedWatcherType <XdsClusterResource .CdsUpdate > CDS_TYPE  =
66+       new  TrackedWatcherType <>(TrackedWatcherTypeEnum .CDS );
67+   private  static  final  TrackedWatcherType <XdsEndpointResource .EdsUpdate > EDS_TYPE  =
68+       new  TrackedWatcherType <>(TrackedWatcherTypeEnum .EDS );
69+ 
5870  private  static  final  int  MAX_CLUSTER_RECURSION_DEPTH  = 16 ; // Specified by gRFC A37 
5971  private  final  String  listenerName ;
6072  private  final  XdsClient  xdsClient ;
@@ -63,7 +75,8 @@ final class XdsDependencyManager implements XdsConfig.XdsClusterSubscriptionRegi
6375  private  XdsConfigWatcher  xdsConfigWatcher ;
6476
6577  private  StatusOr <XdsConfig > lastUpdate  = null ;
66-   private  final  Map <XdsResourceType <?>, TypeWatchers <?>> resourceWatchers  = new  HashMap <>();
78+   private  final  Map <TrackedWatcherTypeEnum , TypeWatchers <?>> resourceWatchers  =
79+       new  EnumMap <>(TrackedWatcherTypeEnum .class );
6780  private  final  Set <ClusterSubscription > subscriptions  = new  HashSet <>();
6881
6982  XdsDependencyManager (XdsClient  xdsClient ,
@@ -86,7 +99,7 @@ public void start(XdsConfigWatcher xdsConfigWatcher) {
8699    checkState (this .xdsConfigWatcher  == null , "dep manager may not be restarted" );
87100    this .xdsConfigWatcher  = checkNotNull (xdsConfigWatcher , "xdsConfigWatcher" );
88101    // start the ball rolling 
89-     syncContext .execute (() -> addWatcher (new  LdsWatcher (listenerName )));
102+     syncContext .execute (() -> addWatcher (LDS_TYPE ,  new  LdsWatcher (listenerName )));
90103  }
91104
92105  @ Override 
@@ -96,7 +109,7 @@ public XdsConfig.Subscription subscribeToCluster(String clusterName) {
96109    ClusterSubscription  subscription  = new  ClusterSubscription (clusterName );
97110
98111    syncContext .execute (() -> {
99-       if  (getWatchers (XdsListenerResource . getInstance () ).isEmpty ()) {
112+       if  (getWatchers (LDS_TYPE ).isEmpty ()) {
100113        subscription .closed  = true ;
101114        return ; // shutdown() called 
102115      }
@@ -107,33 +120,28 @@ public XdsConfig.Subscription subscribeToCluster(String clusterName) {
107120    return  subscription ;
108121  }
109122
110-   private  <T  extends  ResourceUpdate > void  addWatcher (XdsWatcherBase <T > watcher ) {
123+   private  <T  extends  ResourceUpdate > void  addWatcher (
124+       TrackedWatcherType <T > watcherType , XdsWatcherBase <T > watcher ) {
111125    syncContext .throwIfNotInThisSynchronizationContext ();
112126    XdsResourceType <T > type  = watcher .type ;
113127    String  resourceName  = watcher .resourceName ;
114128
115-     getWatchers (type ).put (resourceName , watcher );
129+     getWatchers (watcherType ).put (resourceName , watcher );
116130    xdsClient .watchXdsResource (type , resourceName , watcher , syncContext );
117131  }
118132
119133  public  void  shutdown () {
120134    syncContext .execute (() -> {
121135      for  (TypeWatchers <?> watchers  : resourceWatchers .values ()) {
122-         shutdownWatchersForType (watchers );
136+         for  (TrackedWatcher <?> watcher  : watchers .watchers .values ()) {
137+           watcher .close ();
138+         }
123139      }
124140      resourceWatchers .clear ();
125141      subscriptions .clear ();
126142    });
127143  }
128144
129-   private  <T  extends  ResourceUpdate > void  shutdownWatchersForType (TypeWatchers <T > watchers ) {
130-     for  (Map .Entry <String , XdsWatcherBase <T >> watcherEntry  : watchers .watchers .entrySet ()) {
131-       xdsClient .cancelXdsResourceWatch (watchers .resourceType , watcherEntry .getKey (),
132-           watcherEntry .getValue ());
133-       watcherEntry .getValue ().cancelled  = true ;
134-     }
135-   }
136- 
137145  private  void  releaseSubscription (ClusterSubscription  subscription ) {
138146    checkNotNull (subscription , "subscription" );
139147    syncContext .execute (() -> {
@@ -154,12 +162,12 @@ private void releaseSubscription(ClusterSubscription subscription) {
154162   */ 
155163  private  void  maybePublishConfig () {
156164    syncContext .throwIfNotInThisSynchronizationContext ();
157-     if  (getWatchers (XdsListenerResource . getInstance () ).isEmpty ()) {
165+     if  (getWatchers (LDS_TYPE ).isEmpty ()) {
158166      return ; // shutdown() called 
159167    }
160168    boolean  waitingOnResource  = resourceWatchers .values ().stream ()
161169        .flatMap (typeWatchers  -> typeWatchers .watchers .values ().stream ())
162-         .anyMatch (XdsWatcherBase ::missingResult );
170+         .anyMatch (TrackedWatcher ::missingResult );
163171    if  (waitingOnResource ) {
164172      return ;
165173    }
@@ -194,8 +202,8 @@ private static StatusOr<XdsConfig> buildUpdate(
194202
195203    // Iterate watchers and build the XdsConfig 
196204
197-     XdsWatcherBase <XdsListenerResource .LdsUpdate > ldsWatcher 
198-         = tracer .getWatcher (XdsListenerResource . getInstance () , listenerName );
205+     TrackedWatcher <XdsListenerResource .LdsUpdate > ldsWatcher 
206+         = tracer .getWatcher (LDS_TYPE , listenerName );
199207    if  (ldsWatcher  == null ) {
200208      return  StatusOr .fromStatus (Status .UNAVAILABLE .withDescription (
201209          "Bug: No listener watcher found for "  + listenerName ));
@@ -241,14 +249,13 @@ private static StatusOr<XdsConfig> buildUpdate(
241249    return  StatusOr .fromValue (builder .build ());
242250  }
243251
244-   private  <T  extends  ResourceUpdate > Map <String , XdsWatcherBase <T >> getWatchers (
245-       XdsResourceType <T > resourceType ) {
246-     TypeWatchers <?> typeWatchers  = resourceWatchers .get (resourceType );
252+   private  <T > Map <String , TrackedWatcher <T >> getWatchers (TrackedWatcherType <T > watcherType ) {
253+     TypeWatchers <?> typeWatchers  = resourceWatchers .get (watcherType .typeEnum );
247254    if  (typeWatchers  == null ) {
248-       typeWatchers  = new  TypeWatchers <T >(resourceType );
249-       resourceWatchers .put (resourceType , typeWatchers );
255+       typeWatchers  = new  TypeWatchers <T >(watcherType );
256+       resourceWatchers .put (watcherType . typeEnum , typeWatchers );
250257    }
251-     assert  typeWatchers .resourceType  == resourceType ;
258+     assert  typeWatchers .watcherType  == watcherType ;
252259    @ SuppressWarnings ("unchecked" )
253260    TypeWatchers <T > tTypeWatchers  = (TypeWatchers <T >) typeWatchers ;
254261    return  tTypeWatchers .watchers ;
@@ -275,7 +282,7 @@ private static void addConfigForCluster(
275282      return ;
276283    }
277284
278-     CdsWatcher  cdsWatcher  = (CdsWatcher ) tracer .getWatcher (CLUSTER_RESOURCE , clusterName );
285+     CdsWatcher  cdsWatcher  = (CdsWatcher ) tracer .getWatcher (CDS_TYPE , clusterName );
279286    StatusOr <XdsClusterResource .CdsUpdate > cdsWatcherDataOr  = cdsWatcher .getData ();
280287    if  (!cdsWatcherDataOr .hasValue ()) {
281288      clusters .put (clusterName , StatusOr .fromStatus (cdsWatcherDataOr .getStatus ()));
@@ -318,8 +325,8 @@ private static void addConfigForCluster(
318325        child  = new  AggregateConfig (ImmutableList .copyOf (leafNames ));
319326        break ;
320327      case  EDS :
321-         XdsWatcherBase <XdsEndpointResource .EdsUpdate > edsWatcher  =
322-             tracer .getWatcher (ENDPOINT_RESOURCE , cdsWatcher .getEdsServiceName ());
328+         TrackedWatcher <XdsEndpointResource .EdsUpdate > edsWatcher  =
329+             tracer .getWatcher (EDS_TYPE , cdsWatcher .getEdsServiceName ());
323330        if  (edsWatcher  != null ) {
324331          child  = new  EndpointConfig (edsWatcher .getData ());
325332        } else  {
@@ -346,27 +353,27 @@ private static void addConfigForCluster(
346353  }
347354
348355  private  void  addRdsWatcher (String  resourceName ) {
349-     if  (getWatchers (XdsRouteConfigureResource . getInstance () ).containsKey (resourceName )) {
356+     if  (getWatchers (RDS_TYPE ).containsKey (resourceName )) {
350357      return ;
351358    }
352359
353-     addWatcher (new  RdsWatcher (resourceName ));
360+     addWatcher (RDS_TYPE ,  new  RdsWatcher (resourceName ));
354361  }
355362
356363  private  void  addEdsWatcher (String  edsServiceName ) {
357-     if  (getWatchers (XdsEndpointResource . getInstance () ).containsKey (edsServiceName )) {
364+     if  (getWatchers (EDS_TYPE ).containsKey (edsServiceName )) {
358365      return ;
359366    }
360367
361-     addWatcher (new  EdsWatcher (edsServiceName ));
368+     addWatcher (EDS_TYPE ,  new  EdsWatcher (edsServiceName ));
362369  }
363370
364371  private  void  addClusterWatcher (String  clusterName ) {
365-     if  (getWatchers (CLUSTER_RESOURCE ).containsKey (clusterName )) {
372+     if  (getWatchers (CDS_TYPE ).containsKey (clusterName )) {
366373      return ;
367374    }
368375
369-     addWatcher (new  CdsWatcher (clusterName ));
376+     addWatcher (CDS_TYPE ,  new  CdsWatcher (clusterName ));
370377  }
371378
372379  private  void  updateRoutes (List <VirtualHost > virtualHosts ) {
@@ -404,13 +411,13 @@ private static Set<String> getClusterNamesFromVirtualHost(VirtualHost virtualHos
404411    return  clusters ;
405412  }
406413
407-   private  static  class  TypeWatchers <T   extends   ResourceUpdate > {
414+   private  static  class  TypeWatchers <T > {
408415    // Key is resource name 
409-     final  Map <String , XdsWatcherBase <T >> watchers  = new  HashMap <>();
410-     final  XdsResourceType <T > resourceType ;
416+     final  Map <String , TrackedWatcher <T >> watchers  = new  HashMap <>();
417+     final  TrackedWatcherType <T > watcherType ;
411418
412-     TypeWatchers (XdsResourceType <T > resourceType ) {
413-       this .resourceType  = resourceType ;
419+     TypeWatchers (TrackedWatcherType <T > watcherType ) {
420+       this .watcherType  = checkNotNull ( watcherType ,  "watcherType" ) ;
414421    }
415422  }
416423
@@ -442,48 +449,46 @@ public void close() {
442449
443450  /** State for tracing garbage collector. */ 
444451  private  static  final  class  WatcherTracer  {
445-     private  final  Map <XdsResourceType <?> , TypeWatchers <?>> resourceWatchers ;
446-     private  final  Map <XdsResourceType <?> , TypeWatchers <?>> usedWatchers ;
452+     private  final  Map <TrackedWatcherTypeEnum , TypeWatchers <?>> resourceWatchers ;
453+     private  final  Map <TrackedWatcherTypeEnum , TypeWatchers <?>> usedWatchers ;
447454
448-     public  WatcherTracer (Map <XdsResourceType <?> , TypeWatchers <?>> resourceWatchers ) {
455+     public  WatcherTracer (Map <TrackedWatcherTypeEnum , TypeWatchers <?>> resourceWatchers ) {
449456      this .resourceWatchers  = resourceWatchers ;
450457
451-       this .usedWatchers  = new  HashMap <>();
452-       for  (XdsResourceType <?>  type  : resourceWatchers .keySet ()) {
453-         usedWatchers .put (type , newTypeWatchers (type ));
458+       this .usedWatchers  = new  EnumMap <>(TrackedWatcherTypeEnum . class );
459+       for  (Map . Entry < TrackedWatcherTypeEnum ,  TypeWatchers <?>>  me  : resourceWatchers .entrySet ()) {
460+         usedWatchers .put (me . getKey () , newTypeWatchers (me . getValue (). watcherType ));
454461      }
455462    }
456463
457-     private  static  <T  extends  ResourceUpdate > TypeWatchers <T > newTypeWatchers (
458-         XdsResourceType <T > type ) {
464+     private  static  <T > TypeWatchers <T > newTypeWatchers (TrackedWatcherType <T > type ) {
459465      return  new  TypeWatchers <T >(type );
460466    }
461467
462-     public  <T  extends  ResourceUpdate > XdsWatcherBase <T > getWatcher (
463-         XdsResourceType <T > resourceType , String  name ) {
464-       TypeWatchers <?> typeWatchers  = resourceWatchers .get (resourceType );
468+     public  <T > TrackedWatcher <T > getWatcher (TrackedWatcherType <T > watcherType , String  name ) {
469+       TypeWatchers <?> typeWatchers  = resourceWatchers .get (watcherType .typeEnum );
465470      if  (typeWatchers  == null ) {
466471        return  null ;
467472      }
468-       assert  typeWatchers .resourceType  == resourceType ;
473+       assert  typeWatchers .watcherType  == watcherType ;
469474      @ SuppressWarnings ("unchecked" )
470475      TypeWatchers <T > tTypeWatchers  = (TypeWatchers <T >) typeWatchers ;
471-       XdsWatcherBase <T > watcher  = tTypeWatchers .watchers .get (name );
476+       TrackedWatcher <T > watcher  = tTypeWatchers .watchers .get (name );
472477      if  (watcher  == null ) {
473478        return  null ;
474479      }
475480      @ SuppressWarnings ("unchecked" )
476-       TypeWatchers <T > usedTypeWatchers  = (TypeWatchers <T >) usedWatchers .get (resourceType );
481+       TypeWatchers <T > usedTypeWatchers  = (TypeWatchers <T >) usedWatchers .get (watcherType . typeEnum );
477482      usedTypeWatchers .watchers .put (name , watcher );
478483      return  watcher ;
479484    }
480485
481486    /** Shut down unused watchers. */ 
482487    public  void  closeUnusedWatchers () {
483488      boolean  changed  = false ; // Help out the GC by preferring old objects 
484-       for  (XdsResourceType <?>  type  : resourceWatchers .keySet ()) {
485-         TypeWatchers <?> orig  = resourceWatchers .get (type );
486-         TypeWatchers <?> used  = usedWatchers .get (type );
489+       for  (TrackedWatcherTypeEnum   key  : resourceWatchers .keySet ()) {
490+         TypeWatchers <?> orig  = resourceWatchers .get (key );
491+         TypeWatchers <?> used  = usedWatchers .get (key );
487492        for  (String  name  : orig .watchers .keySet ()) {
488493          if  (used .watchers .containsKey (name )) {
489494            continue ;
@@ -498,8 +503,33 @@ public void closeUnusedWatchers() {
498503    }
499504  }
500505
506+   @ SuppressWarnings ("UnusedTypeParameter" )
507+   private  static  final  class  TrackedWatcherType <T > {
508+     public  final  TrackedWatcherTypeEnum  typeEnum ;
509+ 
510+     public  TrackedWatcherType (TrackedWatcherTypeEnum  typeEnum ) {
511+       this .typeEnum  = checkNotNull (typeEnum , "typeEnum" );
512+     }
513+   }
514+ 
515+   private  interface  TrackedWatcher <T > {
516+     @ Nullable 
517+     StatusOr <T > getData ();
518+ 
519+     default  boolean  missingResult () {
520+       return  getData () == null ;
521+     }
522+ 
523+     default  boolean  hasDataValue () {
524+       StatusOr <T > data  = getData ();
525+       return  data  != null  && data .hasValue ();
526+     }
527+ 
528+     void  close ();
529+   }
530+ 
501531  private  abstract  class  XdsWatcherBase <T  extends  ResourceUpdate >
502-       implements  ResourceWatcher <T > {
532+       implements  ResourceWatcher <T >,  TrackedWatcher < T >  {
503533    private  final  XdsResourceType <T > type ;
504534    private  final  String  resourceName ;
505535    boolean  cancelled ;
@@ -554,24 +584,18 @@ public void onChanged(T update) {
554584
555585    protected  abstract  void  subscribeToChildren (T  update );
556586
587+     @ Override 
557588    public  void  close () {
558589      cancelled  = true ;
559590      xdsClient .cancelXdsResourceWatch (type , resourceName , this );
560591    }
561592
562-     boolean  missingResult () {
563-       return  data  == null ;
564-     }
565- 
593+     @ Override 
566594    @ Nullable 
567-     StatusOr <T > getData () {
595+     public   StatusOr <T > getData () {
568596      return  data ;
569597    }
570598
571-     boolean  hasDataValue () {
572-       return  data  != null  && data .hasValue ();
573-     }
574- 
575599    public  String  toContextString () {
576600      return  toContextStr (type .typeName (), resourceName );
577601    }
@@ -622,7 +646,7 @@ private RdsWatcher getRdsWatcher(XdsListenerResource.LdsUpdate update, WatcherTr
622646      if  (rdsName  == null ) {
623647        return  null ;
624648      }
625-       return  (RdsWatcher ) tracer .getWatcher (XdsRouteConfigureResource . getInstance () , rdsName );
649+       return  (RdsWatcher ) tracer .getWatcher (RDS_TYPE , rdsName );
626650    }
627651
628652    public  RdsUpdateSupplier  getRouteSource (WatcherTracer  tracer ) {
@@ -688,7 +712,7 @@ public StatusOr<RdsUpdate> getRdsUpdate() {
688712
689713  private  class  CdsWatcher  extends  XdsWatcherBase <XdsClusterResource .CdsUpdate > {
690714    CdsWatcher (String  resourceName ) {
691-       super (CLUSTER_RESOURCE , checkNotNull (resourceName , "resourceName" ));
715+       super (XdsClusterResource . getInstance () , checkNotNull (resourceName , "resourceName" ));
692716    }
693717
694718    @ Override 
@@ -721,7 +745,7 @@ public String getEdsServiceName() {
721745
722746  private  class  EdsWatcher  extends  XdsWatcherBase <XdsEndpointResource .EdsUpdate > {
723747    private  EdsWatcher (String  resourceName ) {
724-       super (ENDPOINT_RESOURCE , checkNotNull (resourceName , "resourceName" ));
748+       super (XdsEndpointResource . getInstance () , checkNotNull (resourceName , "resourceName" ));
725749    }
726750
727751    @ Override 
0 commit comments