xds: Use getWatchers more often in XdsDepManager

This provides better type and missing-map handling. Note that
getWatchers() now implicitly creates the map if it doesn't exist,
instead of just returning an empty map. That makes it a bit easier to
use and more importantly avoids accidents where a bug tries to modify
the immutable map.
This commit is contained in:
Eric Anderson 2025-06-02 06:42:31 -07:00 committed by GitHub
parent 379fbaa380
commit 6bad600592
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 25 additions and 48 deletions

View File

@ -112,14 +112,7 @@ final class XdsDependencyManager implements XdsConfig.XdsClusterSubscriptionRegi
XdsResourceType<T> type = watcher.type; XdsResourceType<T> type = watcher.type;
String resourceName = watcher.resourceName; String resourceName = watcher.resourceName;
@SuppressWarnings("unchecked") getWatchers(type).put(resourceName, watcher);
TypeWatchers<T> typeWatchers = (TypeWatchers<T>)resourceWatchers.get(type);
if (typeWatchers == null) {
typeWatchers = new TypeWatchers<>(type);
resourceWatchers.put(type, typeWatchers);
}
typeWatchers.add(resourceName, watcher);
xdsClient.watchXdsResource(type, resourceName, watcher, syncContext); xdsClient.watchXdsResource(type, resourceName, watcher, syncContext);
} }
@ -158,16 +151,12 @@ final class XdsDependencyManager implements XdsConfig.XdsClusterSubscriptionRegi
XdsResourceType<T> type = watcher.type; XdsResourceType<T> type = watcher.type;
String resourceName = watcher.resourceName; String resourceName = watcher.resourceName;
@SuppressWarnings("unchecked") if (getWatchers(type).remove(resourceName) == null) {
TypeWatchers<T> typeWatchers = (TypeWatchers<T>)resourceWatchers.get(type); logger.log(DEBUG, "Trying to cancel watcher {0}, but it isn't watched", watcher);
if (typeWatchers == null) {
logger.log(DEBUG, "Trying to cancel watcher {0}, but type not watched", watcher);
return; return;
} }
typeWatchers.watchers.remove(resourceName);
xdsClient.cancelXdsResourceWatch(type, resourceName, watcher); xdsClient.cancelXdsResourceWatch(type, resourceName, watcher);
} }
private static void throwIfParentContextsNotEmpty(XdsWatcherBase<?> watcher) { private static void throwIfParentContextsNotEmpty(XdsWatcherBase<?> watcher) {
@ -213,8 +202,8 @@ final class XdsDependencyManager implements XdsConfig.XdsClusterSubscriptionRegi
return; return;
} }
subscription.closed = true; subscription.closed = true;
XdsWatcherBase<?> cdsWatcher = XdsWatcherBase<XdsClusterResource.CdsUpdate> cdsWatcher
resourceWatchers.get(CLUSTER_RESOURCE).watchers.get(clusterName); = getWatchers(CLUSTER_RESOURCE).get(clusterName);
if (cdsWatcher == null) { if (cdsWatcher == null) {
return; // shutdown() called return; // shutdown() called
} }
@ -236,14 +225,12 @@ final class XdsDependencyManager implements XdsConfig.XdsClusterSubscriptionRegi
switch (cdsUpdate.clusterType()) { switch (cdsUpdate.clusterType()) {
case EDS: case EDS:
String edsServiceName = root.getEdsServiceName(); String edsServiceName = root.getEdsServiceName();
EdsWatcher edsWatcher = EdsWatcher edsWatcher = (EdsWatcher) getWatchers(ENDPOINT_RESOURCE).get(edsServiceName);
(EdsWatcher) resourceWatchers.get(ENDPOINT_RESOURCE).watchers.get(edsServiceName);
cancelEdsWatcher(edsWatcher, root); cancelEdsWatcher(edsWatcher, root);
break; break;
case AGGREGATE: case AGGREGATE:
for (String cluster : cdsUpdate.prioritizedClusterNames()) { for (String cluster : cdsUpdate.prioritizedClusterNames()) {
CdsWatcher clusterWatcher = CdsWatcher clusterWatcher = (CdsWatcher) getWatchers(CLUSTER_RESOURCE).get(cluster);
(CdsWatcher) resourceWatchers.get(CLUSTER_RESOURCE).watchers.get(cluster);
if (clusterWatcher != null) { if (clusterWatcher != null) {
cancelClusterWatcherTree(clusterWatcher, root); cancelClusterWatcherTree(clusterWatcher, root);
} }
@ -348,7 +335,8 @@ final class XdsDependencyManager implements XdsConfig.XdsClusterSubscriptionRegi
XdsResourceType<T> resourceType) { XdsResourceType<T> resourceType) {
TypeWatchers<?> typeWatchers = resourceWatchers.get(resourceType); TypeWatchers<?> typeWatchers = resourceWatchers.get(resourceType);
if (typeWatchers == null) { if (typeWatchers == null) {
return Collections.emptyMap(); typeWatchers = new TypeWatchers<T>(resourceType);
resourceWatchers.put(resourceType, typeWatchers);
} }
assert typeWatchers.resourceType == resourceType; assert typeWatchers.resourceType == resourceType;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -470,25 +458,22 @@ final class XdsDependencyManager implements XdsConfig.XdsClusterSubscriptionRegi
// Returns true if the watcher was added, false if it already exists // Returns true if the watcher was added, false if it already exists
private boolean addEdsWatcher(String edsServiceName, CdsWatcher parentContext) { private boolean addEdsWatcher(String edsServiceName, CdsWatcher parentContext) {
TypeWatchers<?> typeWatchers = resourceWatchers.get(XdsEndpointResource.getInstance()); EdsWatcher watcher
if (typeWatchers == null || !typeWatchers.watchers.containsKey(edsServiceName)) { = (EdsWatcher) getWatchers(XdsEndpointResource.getInstance()).get(edsServiceName);
addWatcher(new EdsWatcher(edsServiceName, parentContext)); if (watcher != null) {
return true; watcher.addParentContext(parentContext); // Is a set, so don't need to check for existence
return false;
} }
EdsWatcher watcher = (EdsWatcher) typeWatchers.watchers.get(edsServiceName); addWatcher(new EdsWatcher(edsServiceName, parentContext));
watcher.addParentContext(parentContext); // Is a set, so don't need to check for existence return true;
return false;
} }
private void addClusterWatcher(String clusterName, Object parentContext, int depth) { private void addClusterWatcher(String clusterName, Object parentContext, int depth) {
TypeWatchers<?> clusterWatchers = resourceWatchers.get(CLUSTER_RESOURCE); CdsWatcher watcher = (CdsWatcher) getWatchers(CLUSTER_RESOURCE).get(clusterName);
if (clusterWatchers != null) { if (watcher != null) {
CdsWatcher watcher = (CdsWatcher) clusterWatchers.watchers.get(clusterName); watcher.parentContexts.put(parentContext, depth);
if (watcher != null) { return;
watcher.parentContexts.put(parentContext, depth);
return;
}
} }
addWatcher(new CdsWatcher(clusterName, parentContext, depth)); addWatcher(new CdsWatcher(clusterName, parentContext, depth));
@ -546,7 +531,7 @@ final class XdsDependencyManager implements XdsConfig.XdsClusterSubscriptionRegi
} }
private CdsWatcher getCluster(String clusterName) { private CdsWatcher getCluster(String clusterName) {
return (CdsWatcher) resourceWatchers.get(CLUSTER_RESOURCE).watchers.get(clusterName); return (CdsWatcher) getWatchers(CLUSTER_RESOURCE).get(clusterName);
} }
private static class TypeWatchers<T extends ResourceUpdate> { private static class TypeWatchers<T extends ResourceUpdate> {
@ -557,10 +542,6 @@ final class XdsDependencyManager implements XdsConfig.XdsClusterSubscriptionRegi
TypeWatchers(XdsResourceType<T> resourceType) { TypeWatchers(XdsResourceType<T> resourceType) {
this.resourceType = resourceType; this.resourceType = resourceType;
} }
public void add(String resourceName, XdsWatcherBase<T> watcher) {
watchers.put(resourceName, watcher);
}
} }
public interface XdsConfigWatcher { public interface XdsConfigWatcher {
@ -738,11 +719,11 @@ final class XdsDependencyManager implements XdsConfig.XdsClusterSubscriptionRegi
logger.log(XdsLogger.XdsLogLevel.DEBUG, "Stop watching RDS resource {0}", rdsName); logger.log(XdsLogger.XdsLogLevel.DEBUG, "Stop watching RDS resource {0}", rdsName);
// Cleanup clusters (as appropriate) that had the old rds watcher as a parent // Cleanup clusters (as appropriate) that had the old rds watcher as a parent
if (!oldRdsWatcher.hasDataValue() || resourceWatchers.get(CLUSTER_RESOURCE) == null) { if (!oldRdsWatcher.hasDataValue()) {
return; return;
} }
for (XdsWatcherBase<?> watcher : for (XdsWatcherBase<XdsClusterResource.CdsUpdate> watcher :
resourceWatchers.get(CLUSTER_RESOURCE).watchers.values()) { getWatchers(CLUSTER_RESOURCE).values()) {
cancelCdsWatcher((CdsWatcher) watcher, oldRdsWatcher); cancelCdsWatcher((CdsWatcher) watcher, oldRdsWatcher);
} }
} }
@ -752,11 +733,7 @@ final class XdsDependencyManager implements XdsConfig.XdsClusterSubscriptionRegi
if (rdsName == null) { if (rdsName == null) {
return null; return null;
} }
TypeWatchers<?> watchers = resourceWatchers.get(XdsRouteConfigureResource.getInstance()); return (RdsWatcher) getWatchers(XdsRouteConfigureResource.getInstance()).get(rdsName);
if (watchers == null) {
return null;
}
return (RdsWatcher) watchers.watchers.get(rdsName);
} }
public RdsUpdateSupplier getRouteSource() { public RdsUpdateSupplier getRouteSource() {