Fix more transport error and shutdown scenarios.

Previously, if the active transport had failed but there were still other running transports, we would claim to be shutdown before we actually were (and would end up calling notifyStopped twice).

Also, if a transport immediately failed during startup, we could end up setting activeTransport to the already-failed transport, which meant we would perpetually try to use that broken transport.
-------------
Created by MOE: http://code.google.com/p/moe-java
MOE_MIGRATED_REVID=74339777
This commit is contained in:
ejona 2014-08-28 14:21:40 -07:00 committed by Eric Anderson
parent 4a3b5d1edd
commit 4e315e0110
1 changed files with 12 additions and 9 deletions

View File

@ -52,12 +52,14 @@ public final class ChannelImpl extends AbstractService implements Channel {
@Override
protected synchronized void doStop() {
if (activeTransport != null) {
activeTransport.stopAsync();
activeTransport = null;
// The last TransportListener will call notifyStopped().
} else {
if (transports.isEmpty()) {
notifyStopped();
} else {
// The last TransportListener will call notifyStopped().
if (activeTransport != null) {
activeTransport.stopAsync();
activeTransport = null;
}
}
}
@ -72,13 +74,14 @@ public final class ChannelImpl extends AbstractService implements Channel {
throw new IllegalStateException("Not running");
}
ClientTransport newTransport = transportFactory.newClientTransport();
activeTransport = newTransport;
transports.add(newTransport);
// activeTransport reference can be changed during calls to the transport, even if we hold the
// lock, due to reentrancy.
newTransport.addListener(
new TransportListener(newTransport), MoreExecutors.directExecutor());
transports.add(newTransport);
// activeTransport reference can be changed during this call, even if we hold the lock, due to
// reentrancy.
newTransport.startAsync();
activeTransport = newTransport;
return newTransport;
}
return activeTransport;
}