Skip to content

Commit

Permalink
core: re-organize RealChannel with updateConfigSelector()
Browse files Browse the repository at this point in the history
As mentioned in #7413 (comment) `RealChannel` did not manage `configSelector`, and therefore `configSelector.get()`, `configSelector.set()` and `drainPendingCalls()` were scattered everywhere in `ManagedChannelImpl`. This PR re-organizes `RealChannel` to manage `configSelector`.
  • Loading branch information
dapengzhang0 committed Sep 11, 2020
1 parent 73dd367 commit 234125e
Showing 1 changed file with 24 additions and 23 deletions.
47 changes: 24 additions & 23 deletions core/src/main/java/io/grpc/internal/ManagedChannelImpl.java
Expand Up @@ -263,10 +263,6 @@ public void uncaughtException(Thread t, Throwable e) {
// Must be mutated and read from constructor or syncContext
// used for channel tracing when value changed
private ManagedChannelServiceConfig lastServiceConfig = EMPTY_SERVICE_CONFIG;
// Reference to null if no config selector is available from resolution result
// Reference must be set() from syncContext
private final AtomicReference<InternalConfigSelector> configSelector =
new AtomicReference<>(INITIAL_PENDING_SELECTOR);

@Nullable
private final ManagedChannelServiceConfig defaultServiceConfig;
Expand Down Expand Up @@ -750,7 +746,7 @@ static NameResolver getNameResolver(String target, NameResolver.Factory nameReso

@VisibleForTesting
InternalConfigSelector getConfigSelector() {
return configSelector.get();
return realChannel.configSelector.get();
}

/**
Expand Down Expand Up @@ -891,6 +887,10 @@ private Executor getCallExecutor(CallOptions callOptions) {
}

private class RealChannel extends Channel {
// Reference to null if no config selector is available from resolution result
// Reference must be set() from syncContext
private final AtomicReference<InternalConfigSelector> configSelector =
new AtomicReference<>(INITIAL_PENDING_SELECTOR);
// Set when the NameResolver is initially created. When we create a new NameResolver for the
// same target, the new instance must have the same value.
private final String authority;
Expand Down Expand Up @@ -954,12 +954,20 @@ public void run() {
}

// Must run in SynchronizationContext.
private void drainPendingCalls() {
if (pendingCalls == null) {
return;
void updateConfigSelector(@Nullable InternalConfigSelector config) {
InternalConfigSelector prevConfig = configSelector.get();
configSelector.set(config);
if (prevConfig == INITIAL_PENDING_SELECTOR && pendingCalls != null) {
for (RealChannel.PendingCall<?, ?> pendingCall : pendingCalls) {
pendingCall.reprocess();
}
}
for (RealChannel.PendingCall<?, ?> pendingCall : pendingCalls) {
pendingCall.reprocess();
}

// Must run in SynchronizationContext.
void onConfigError() {
if (configSelector.get() == INITIAL_PENDING_SELECTOR) {
updateConfigSelector(null);
}
}

Expand Down Expand Up @@ -1568,7 +1576,6 @@ public void run() {
Status serviceConfigError = configOrError != null ? configOrError.getError() : null;

ManagedChannelServiceConfig effectiveServiceConfig;
InternalConfigSelector prevConfigSelector = configSelector.get();
if (!lookUpServiceConfig) {
if (validServiceConfig != null) {
channelLogger.log(
Expand All @@ -1582,26 +1589,26 @@ public void run() {
ChannelLogLevel.INFO,
"Config selector from name resolver discarded by channel settings");
}
configSelector.set(effectiveServiceConfig.getDefaultConfigSelector());
realChannel.updateConfigSelector(effectiveServiceConfig.getDefaultConfigSelector());
} else {
// Try to use config if returned from name resolver
// Otherwise, try to use the default config if available
if (validServiceConfig != null) {
effectiveServiceConfig = validServiceConfig;
if (resolvedConfigSelector != null) {
configSelector.set(resolvedConfigSelector);
realChannel.updateConfigSelector(resolvedConfigSelector);
if (effectiveServiceConfig.getDefaultConfigSelector() != null) {
channelLogger.log(
ChannelLogLevel.DEBUG,
"Method configs in service config will be discarded due to presence of"
+ "config-selector");
}
} else {
configSelector.set(effectiveServiceConfig.getDefaultConfigSelector());
realChannel.updateConfigSelector(effectiveServiceConfig.getDefaultConfigSelector());
}
} else if (defaultServiceConfig != null) {
effectiveServiceConfig = defaultServiceConfig;
configSelector.set(effectiveServiceConfig.getDefaultConfigSelector());
realChannel.updateConfigSelector(effectiveServiceConfig.getDefaultConfigSelector());
channelLogger.log(
ChannelLogLevel.INFO,
"Received no service config, using default service config");
Expand All @@ -1618,7 +1625,7 @@ public void run() {
}
} else {
effectiveServiceConfig = EMPTY_SERVICE_CONFIG;
configSelector.set(null);
realChannel.updateConfigSelector(null);
}
if (!effectiveServiceConfig.equals(lastServiceConfig)) {
channelLogger.log(
Expand All @@ -1640,9 +1647,6 @@ public void run() {
re);
}
}
if (prevConfigSelector == INITIAL_PENDING_SELECTOR) {
realChannel.drainPendingCalls();
}

Attributes effectiveAttrs = resolutionResult.getAttributes();
// Call LB only if it's not shutdown. If LB is shutdown, lbHelper won't match.
Expand Down Expand Up @@ -1690,10 +1694,7 @@ public void run() {
private void handleErrorInSyncContext(Status error) {
logger.log(Level.WARNING, "[{0}] Failed to resolve name. status={1}",
new Object[] {getLogId(), error});
if (configSelector.get() == INITIAL_PENDING_SELECTOR) {
configSelector.set(null);
realChannel.drainPendingCalls();
}
realChannel.onConfigError();
if (lastResolutionState != ResolutionState.ERROR) {
channelLogger.log(ChannelLogLevel.WARNING, "Failed to resolve name: {0}", error);
lastResolutionState = ResolutionState.ERROR;
Expand Down

0 comments on commit 234125e

Please sign in to comment.