36
36
import io .grpc .xds .client .XdsClient .ResourceWatcher ;
37
37
import io .grpc .xds .client .XdsResourceType ;
38
38
import java .util .Collections ;
39
+ import java .util .EnumMap ;
39
40
import java .util .HashMap ;
40
41
import java .util .HashSet ;
41
42
import java .util .LinkedHashSet ;
53
54
* applies to a single data plane authority.
54
55
*/
55
56
final 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
+
58
70
private static final int MAX_CLUSTER_RECURSION_DEPTH = 16 ; // Specified by gRFC A37
59
71
private final String listenerName ;
60
72
private final XdsClient xdsClient ;
@@ -63,7 +75,8 @@ final class XdsDependencyManager implements XdsConfig.XdsClusterSubscriptionRegi
63
75
private XdsConfigWatcher xdsConfigWatcher ;
64
76
65
77
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 );
67
80
private final Set <ClusterSubscription > subscriptions = new HashSet <>();
68
81
69
82
XdsDependencyManager (XdsClient xdsClient ,
@@ -86,7 +99,7 @@ public void start(XdsConfigWatcher xdsConfigWatcher) {
86
99
checkState (this .xdsConfigWatcher == null , "dep manager may not be restarted" );
87
100
this .xdsConfigWatcher = checkNotNull (xdsConfigWatcher , "xdsConfigWatcher" );
88
101
// start the ball rolling
89
- syncContext .execute (() -> addWatcher (new LdsWatcher (listenerName )));
102
+ syncContext .execute (() -> addWatcher (LDS_TYPE , new LdsWatcher (listenerName )));
90
103
}
91
104
92
105
@ Override
@@ -96,7 +109,7 @@ public XdsConfig.Subscription subscribeToCluster(String clusterName) {
96
109
ClusterSubscription subscription = new ClusterSubscription (clusterName );
97
110
98
111
syncContext .execute (() -> {
99
- if (getWatchers (XdsListenerResource . getInstance () ).isEmpty ()) {
112
+ if (getWatchers (LDS_TYPE ).isEmpty ()) {
100
113
subscription .closed = true ;
101
114
return ; // shutdown() called
102
115
}
@@ -107,33 +120,28 @@ public XdsConfig.Subscription subscribeToCluster(String clusterName) {
107
120
return subscription ;
108
121
}
109
122
110
- private <T extends ResourceUpdate > void addWatcher (XdsWatcherBase <T > watcher ) {
123
+ private <T extends ResourceUpdate > void addWatcher (
124
+ TrackedWatcherType <T > watcherType , XdsWatcherBase <T > watcher ) {
111
125
syncContext .throwIfNotInThisSynchronizationContext ();
112
126
XdsResourceType <T > type = watcher .type ;
113
127
String resourceName = watcher .resourceName ;
114
128
115
- getWatchers (type ).put (resourceName , watcher );
129
+ getWatchers (watcherType ).put (resourceName , watcher );
116
130
xdsClient .watchXdsResource (type , resourceName , watcher , syncContext );
117
131
}
118
132
119
133
public void shutdown () {
120
134
syncContext .execute (() -> {
121
135
for (TypeWatchers <?> watchers : resourceWatchers .values ()) {
122
- shutdownWatchersForType (watchers );
136
+ for (TrackedWatcher <?> watcher : watchers .watchers .values ()) {
137
+ watcher .close ();
138
+ }
123
139
}
124
140
resourceWatchers .clear ();
125
141
subscriptions .clear ();
126
142
});
127
143
}
128
144
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
-
137
145
private void releaseSubscription (ClusterSubscription subscription ) {
138
146
checkNotNull (subscription , "subscription" );
139
147
syncContext .execute (() -> {
@@ -154,12 +162,12 @@ private void releaseSubscription(ClusterSubscription subscription) {
154
162
*/
155
163
private void maybePublishConfig () {
156
164
syncContext .throwIfNotInThisSynchronizationContext ();
157
- if (getWatchers (XdsListenerResource . getInstance () ).isEmpty ()) {
165
+ if (getWatchers (LDS_TYPE ).isEmpty ()) {
158
166
return ; // shutdown() called
159
167
}
160
168
boolean waitingOnResource = resourceWatchers .values ().stream ()
161
169
.flatMap (typeWatchers -> typeWatchers .watchers .values ().stream ())
162
- .anyMatch (XdsWatcherBase ::missingResult );
170
+ .anyMatch (TrackedWatcher ::missingResult );
163
171
if (waitingOnResource ) {
164
172
return ;
165
173
}
@@ -194,8 +202,8 @@ private static StatusOr<XdsConfig> buildUpdate(
194
202
195
203
// Iterate watchers and build the XdsConfig
196
204
197
- XdsWatcherBase <XdsListenerResource .LdsUpdate > ldsWatcher
198
- = tracer .getWatcher (XdsListenerResource . getInstance () , listenerName );
205
+ TrackedWatcher <XdsListenerResource .LdsUpdate > ldsWatcher
206
+ = tracer .getWatcher (LDS_TYPE , listenerName );
199
207
if (ldsWatcher == null ) {
200
208
return StatusOr .fromStatus (Status .UNAVAILABLE .withDescription (
201
209
"Bug: No listener watcher found for " + listenerName ));
@@ -241,14 +249,13 @@ private static StatusOr<XdsConfig> buildUpdate(
241
249
return StatusOr .fromValue (builder .build ());
242
250
}
243
251
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 );
247
254
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 );
250
257
}
251
- assert typeWatchers .resourceType == resourceType ;
258
+ assert typeWatchers .watcherType == watcherType ;
252
259
@ SuppressWarnings ("unchecked" )
253
260
TypeWatchers <T > tTypeWatchers = (TypeWatchers <T >) typeWatchers ;
254
261
return tTypeWatchers .watchers ;
@@ -275,7 +282,7 @@ private static void addConfigForCluster(
275
282
return ;
276
283
}
277
284
278
- CdsWatcher cdsWatcher = (CdsWatcher ) tracer .getWatcher (CLUSTER_RESOURCE , clusterName );
285
+ CdsWatcher cdsWatcher = (CdsWatcher ) tracer .getWatcher (CDS_TYPE , clusterName );
279
286
StatusOr <XdsClusterResource .CdsUpdate > cdsWatcherDataOr = cdsWatcher .getData ();
280
287
if (!cdsWatcherDataOr .hasValue ()) {
281
288
clusters .put (clusterName , StatusOr .fromStatus (cdsWatcherDataOr .getStatus ()));
@@ -318,8 +325,8 @@ private static void addConfigForCluster(
318
325
child = new AggregateConfig (ImmutableList .copyOf (leafNames ));
319
326
break ;
320
327
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 ());
323
330
if (edsWatcher != null ) {
324
331
child = new EndpointConfig (edsWatcher .getData ());
325
332
} else {
@@ -346,27 +353,27 @@ private static void addConfigForCluster(
346
353
}
347
354
348
355
private void addRdsWatcher (String resourceName ) {
349
- if (getWatchers (XdsRouteConfigureResource . getInstance () ).containsKey (resourceName )) {
356
+ if (getWatchers (RDS_TYPE ).containsKey (resourceName )) {
350
357
return ;
351
358
}
352
359
353
- addWatcher (new RdsWatcher (resourceName ));
360
+ addWatcher (RDS_TYPE , new RdsWatcher (resourceName ));
354
361
}
355
362
356
363
private void addEdsWatcher (String edsServiceName ) {
357
- if (getWatchers (XdsEndpointResource . getInstance () ).containsKey (edsServiceName )) {
364
+ if (getWatchers (EDS_TYPE ).containsKey (edsServiceName )) {
358
365
return ;
359
366
}
360
367
361
- addWatcher (new EdsWatcher (edsServiceName ));
368
+ addWatcher (EDS_TYPE , new EdsWatcher (edsServiceName ));
362
369
}
363
370
364
371
private void addClusterWatcher (String clusterName ) {
365
- if (getWatchers (CLUSTER_RESOURCE ).containsKey (clusterName )) {
372
+ if (getWatchers (CDS_TYPE ).containsKey (clusterName )) {
366
373
return ;
367
374
}
368
375
369
- addWatcher (new CdsWatcher (clusterName ));
376
+ addWatcher (CDS_TYPE , new CdsWatcher (clusterName ));
370
377
}
371
378
372
379
private void updateRoutes (List <VirtualHost > virtualHosts ) {
@@ -404,13 +411,13 @@ private static Set<String> getClusterNamesFromVirtualHost(VirtualHost virtualHos
404
411
return clusters ;
405
412
}
406
413
407
- private static class TypeWatchers <T extends ResourceUpdate > {
414
+ private static class TypeWatchers <T > {
408
415
// 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 ;
411
418
412
- TypeWatchers (XdsResourceType <T > resourceType ) {
413
- this .resourceType = resourceType ;
419
+ TypeWatchers (TrackedWatcherType <T > watcherType ) {
420
+ this .watcherType = checkNotNull ( watcherType , "watcherType" ) ;
414
421
}
415
422
}
416
423
@@ -442,48 +449,46 @@ public void close() {
442
449
443
450
/** State for tracing garbage collector. */
444
451
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 ;
447
454
448
- public WatcherTracer (Map <XdsResourceType <?> , TypeWatchers <?>> resourceWatchers ) {
455
+ public WatcherTracer (Map <TrackedWatcherTypeEnum , TypeWatchers <?>> resourceWatchers ) {
449
456
this .resourceWatchers = resourceWatchers ;
450
457
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 ));
454
461
}
455
462
}
456
463
457
- private static <T extends ResourceUpdate > TypeWatchers <T > newTypeWatchers (
458
- XdsResourceType <T > type ) {
464
+ private static <T > TypeWatchers <T > newTypeWatchers (TrackedWatcherType <T > type ) {
459
465
return new TypeWatchers <T >(type );
460
466
}
461
467
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 );
465
470
if (typeWatchers == null ) {
466
471
return null ;
467
472
}
468
- assert typeWatchers .resourceType == resourceType ;
473
+ assert typeWatchers .watcherType == watcherType ;
469
474
@ SuppressWarnings ("unchecked" )
470
475
TypeWatchers <T > tTypeWatchers = (TypeWatchers <T >) typeWatchers ;
471
- XdsWatcherBase <T > watcher = tTypeWatchers .watchers .get (name );
476
+ TrackedWatcher <T > watcher = tTypeWatchers .watchers .get (name );
472
477
if (watcher == null ) {
473
478
return null ;
474
479
}
475
480
@ SuppressWarnings ("unchecked" )
476
- TypeWatchers <T > usedTypeWatchers = (TypeWatchers <T >) usedWatchers .get (resourceType );
481
+ TypeWatchers <T > usedTypeWatchers = (TypeWatchers <T >) usedWatchers .get (watcherType . typeEnum );
477
482
usedTypeWatchers .watchers .put (name , watcher );
478
483
return watcher ;
479
484
}
480
485
481
486
/** Shut down unused watchers. */
482
487
public void closeUnusedWatchers () {
483
488
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 );
487
492
for (String name : orig .watchers .keySet ()) {
488
493
if (used .watchers .containsKey (name )) {
489
494
continue ;
@@ -498,8 +503,33 @@ public void closeUnusedWatchers() {
498
503
}
499
504
}
500
505
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
+
501
531
private abstract class XdsWatcherBase <T extends ResourceUpdate >
502
- implements ResourceWatcher <T > {
532
+ implements ResourceWatcher <T >, TrackedWatcher < T > {
503
533
private final XdsResourceType <T > type ;
504
534
private final String resourceName ;
505
535
boolean cancelled ;
@@ -554,24 +584,18 @@ public void onChanged(T update) {
554
584
555
585
protected abstract void subscribeToChildren (T update );
556
586
587
+ @ Override
557
588
public void close () {
558
589
cancelled = true ;
559
590
xdsClient .cancelXdsResourceWatch (type , resourceName , this );
560
591
}
561
592
562
- boolean missingResult () {
563
- return data == null ;
564
- }
565
-
593
+ @ Override
566
594
@ Nullable
567
- StatusOr <T > getData () {
595
+ public StatusOr <T > getData () {
568
596
return data ;
569
597
}
570
598
571
- boolean hasDataValue () {
572
- return data != null && data .hasValue ();
573
- }
574
-
575
599
public String toContextString () {
576
600
return toContextStr (type .typeName (), resourceName );
577
601
}
@@ -622,7 +646,7 @@ private RdsWatcher getRdsWatcher(XdsListenerResource.LdsUpdate update, WatcherTr
622
646
if (rdsName == null ) {
623
647
return null ;
624
648
}
625
- return (RdsWatcher ) tracer .getWatcher (XdsRouteConfigureResource . getInstance () , rdsName );
649
+ return (RdsWatcher ) tracer .getWatcher (RDS_TYPE , rdsName );
626
650
}
627
651
628
652
public RdsUpdateSupplier getRouteSource (WatcherTracer tracer ) {
@@ -688,7 +712,7 @@ public StatusOr<RdsUpdate> getRdsUpdate() {
688
712
689
713
private class CdsWatcher extends XdsWatcherBase <XdsClusterResource .CdsUpdate > {
690
714
CdsWatcher (String resourceName ) {
691
- super (CLUSTER_RESOURCE , checkNotNull (resourceName , "resourceName" ));
715
+ super (XdsClusterResource . getInstance () , checkNotNull (resourceName , "resourceName" ));
692
716
}
693
717
694
718
@ Override
@@ -721,7 +745,7 @@ public String getEdsServiceName() {
721
745
722
746
private class EdsWatcher extends XdsWatcherBase <XdsEndpointResource .EdsUpdate > {
723
747
private EdsWatcher (String resourceName ) {
724
- super (ENDPOINT_RESOURCE , checkNotNull (resourceName , "resourceName" ));
748
+ super (XdsEndpointResource . getInstance () , checkNotNull (resourceName , "resourceName" ));
725
749
}
726
750
727
751
@ Override
0 commit comments