From: Robert Varga Date: Fri, 14 Apr 2017 18:45:20 +0000 (+0200) Subject: BUG-5280: handle NotLeaderException X-Git-Tag: release/nitrogen~311 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=bab94bcc7f46edf23ef666dbcd389f7b5ea1ca0a BUG-5280: handle NotLeaderException NotLeaderException is indicative of leader movement, in which case we need to tear down the connection and resolve the new leader. Change-Id: I068e97f9a7feb75cc30afb5f5449f0adf00aa217 Signed-off-by: Robert Varga (cherry picked from commit 8265c26f7692086677fa943976824966f32eecf6) --- diff --git a/opendaylight/md-sal/cds-access-client/src/main/java/org/opendaylight/controller/cluster/access/client/AbstractClientConnection.java b/opendaylight/md-sal/cds-access-client/src/main/java/org/opendaylight/controller/cluster/access/client/AbstractClientConnection.java index 69deb01910..28d8a1b422 100644 --- a/opendaylight/md-sal/cds-access-client/src/main/java/org/opendaylight/controller/cluster/access/client/AbstractClientConnection.java +++ b/opendaylight/md-sal/cds-access-client/src/main/java/org/opendaylight/controller/cluster/access/client/AbstractClientConnection.java @@ -124,7 +124,7 @@ public abstract class AbstractClientConnection { } @GuardedBy("lock") - abstract ClientActorBehavior reconnectConnection(ClientActorBehavior current); + abstract ClientActorBehavior lockedReconnect(ClientActorBehavior current); private long readTime() { return context.ticker().read(); @@ -152,6 +152,15 @@ public abstract class AbstractClientConnection { } } + final ClientActorBehavior reconnect(final ClientActorBehavior current) { + lock.lock(); + try { + return lockedReconnect(current); + } finally { + lock.unlock(); + } + } + /** * Schedule a timer to fire on the actor thread after a delay. * @@ -204,7 +213,7 @@ public abstract class AbstractClientConnection { delay = lockedCheckTimeout(now); if (delay == null) { // We have timed out. There is no point in scheduling a timer - return reconnectConnection(current); + return lockedReconnect(current); } if (delay.isPresent()) { diff --git a/opendaylight/md-sal/cds-access-client/src/main/java/org/opendaylight/controller/cluster/access/client/ClientActorBehavior.java b/opendaylight/md-sal/cds-access-client/src/main/java/org/opendaylight/controller/cluster/access/client/ClientActorBehavior.java index 896d85b713..5233c0795a 100644 --- a/opendaylight/md-sal/cds-access-client/src/main/java/org/opendaylight/controller/cluster/access/client/ClientActorBehavior.java +++ b/opendaylight/md-sal/cds-access-client/src/main/java/org/opendaylight/controller/cluster/access/client/ClientActorBehavior.java @@ -17,6 +17,7 @@ import java.util.concurrent.TimeoutException; import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.annotation.concurrent.GuardedBy; +import org.opendaylight.controller.cluster.access.commands.NotLeaderException; import org.opendaylight.controller.cluster.access.concepts.ClientIdentifier; import org.opendaylight.controller.cluster.access.concepts.FailureEnvelope; import org.opendaylight.controller.cluster.access.concepts.LocalHistoryIdentifier; @@ -105,6 +106,11 @@ public abstract class ClientActorBehavior extends } } + private AbstractClientConnection getConnection(final ResponseEnvelope response) { + // Always called from actor context: no locking required + return connections.get(extractCookie(response.getMessage().getTarget())); + } + @SuppressWarnings("unchecked") @Override final ClientActorBehavior onReceiveCommand(final Object command) { @@ -132,8 +138,7 @@ public abstract class ClientActorBehavior extends } private void onResponse(final ResponseEnvelope response) { - final long cookie = extractCookie(response.getMessage().getTarget()); - final AbstractClientConnection connection = connections.get(cookie); + final AbstractClientConnection connection = getConnection(response); if (connection != null) { connection.receiveResponse(response); } else { @@ -160,6 +165,16 @@ public abstract class ClientActorBehavior extends poison(cause); return null; } + if (cause instanceof NotLeaderException) { + final AbstractClientConnection conn = getConnection(command); + if (conn instanceof ReconnectingClientConnection) { + // Already reconnecting, do not churn the logs + return this; + } else if (conn != null) { + LOG.info("{}: connection {} indicated no leadership, reconnecting it", persistenceId(), conn, cause); + return conn.reconnect(this); + } + } return onRequestFailure(command); } diff --git a/opendaylight/md-sal/cds-access-client/src/main/java/org/opendaylight/controller/cluster/access/client/ConnectedClientConnection.java b/opendaylight/md-sal/cds-access-client/src/main/java/org/opendaylight/controller/cluster/access/client/ConnectedClientConnection.java index 9198d8fe12..cade27f77d 100644 --- a/opendaylight/md-sal/cds-access-client/src/main/java/org/opendaylight/controller/cluster/access/client/ConnectedClientConnection.java +++ b/opendaylight/md-sal/cds-access-client/src/main/java/org/opendaylight/controller/cluster/access/client/ConnectedClientConnection.java @@ -18,7 +18,7 @@ public final class ConnectedClientConnection extends Abst } @Override - ClientActorBehavior reconnectConnection(final ClientActorBehavior current) { + ClientActorBehavior lockedReconnect(final ClientActorBehavior current) { final ReconnectingClientConnection next = new ReconnectingClientConnection<>(this); setForwarder(new SimpleReconnectForwarder(next)); current.reconnectConnection(this, next); diff --git a/opendaylight/md-sal/cds-access-client/src/main/java/org/opendaylight/controller/cluster/access/client/ConnectingClientConnection.java b/opendaylight/md-sal/cds-access-client/src/main/java/org/opendaylight/controller/cluster/access/client/ConnectingClientConnection.java index aa986873d5..12c520bb17 100644 --- a/opendaylight/md-sal/cds-access-client/src/main/java/org/opendaylight/controller/cluster/access/client/ConnectingClientConnection.java +++ b/opendaylight/md-sal/cds-access-client/src/main/java/org/opendaylight/controller/cluster/access/client/ConnectingClientConnection.java @@ -30,7 +30,7 @@ public final class ConnectingClientConnection extends Abs } @Override - ClientActorBehavior reconnectConnection(final ClientActorBehavior current) { + ClientActorBehavior lockedReconnect(final ClientActorBehavior current) { throw new UnsupportedOperationException("Attempted to reconnect a connecting connection"); } } diff --git a/opendaylight/md-sal/cds-access-client/src/main/java/org/opendaylight/controller/cluster/access/client/ReconnectingClientConnection.java b/opendaylight/md-sal/cds-access-client/src/main/java/org/opendaylight/controller/cluster/access/client/ReconnectingClientConnection.java index a67b7ed3be..0aac7f4663 100644 --- a/opendaylight/md-sal/cds-access-client/src/main/java/org/opendaylight/controller/cluster/access/client/ReconnectingClientConnection.java +++ b/opendaylight/md-sal/cds-access-client/src/main/java/org/opendaylight/controller/cluster/access/client/ReconnectingClientConnection.java @@ -25,7 +25,7 @@ public final class ReconnectingClientConnection extends A } @Override - ClientActorBehavior reconnectConnection(final ClientActorBehavior current) { + ClientActorBehavior lockedReconnect(final ClientActorBehavior current) { // Intentional no-op LOG.debug("Skipping reconnect of already-reconnecting connection {}", this); return current; diff --git a/opendaylight/md-sal/cds-access-client/src/test/java/org/opendaylight/controller/cluster/access/client/ConnectedClientConnectionTest.java b/opendaylight/md-sal/cds-access-client/src/test/java/org/opendaylight/controller/cluster/access/client/ConnectedClientConnectionTest.java index 60cdc3acc8..2c1159ef93 100644 --- a/opendaylight/md-sal/cds-access-client/src/test/java/org/opendaylight/controller/cluster/access/client/ConnectedClientConnectionTest.java +++ b/opendaylight/md-sal/cds-access-client/src/test/java/org/opendaylight/controller/cluster/access/client/ConnectedClientConnectionTest.java @@ -28,7 +28,7 @@ public class ConnectedClientConnectionTest @Test public void testReconnectConnection() throws Exception { final ClientActorBehavior behavior = mock(ClientActorBehavior.class); - connection.reconnectConnection(behavior); + connection.lockedReconnect(behavior); verify(behavior).reconnectConnection(same(connection), any(ReconnectingClientConnection.class)); } diff --git a/opendaylight/md-sal/cds-access-client/src/test/java/org/opendaylight/controller/cluster/access/client/ReconnectingClientConnectionTest.java b/opendaylight/md-sal/cds-access-client/src/test/java/org/opendaylight/controller/cluster/access/client/ReconnectingClientConnectionTest.java index b2ff72368c..142e948820 100644 --- a/opendaylight/md-sal/cds-access-client/src/test/java/org/opendaylight/controller/cluster/access/client/ReconnectingClientConnectionTest.java +++ b/opendaylight/md-sal/cds-access-client/src/test/java/org/opendaylight/controller/cluster/access/client/ReconnectingClientConnectionTest.java @@ -41,7 +41,7 @@ public class ReconnectingClientConnectionTest @Test public void testReconnectConnection() throws Exception { final ClientActorBehavior behavior = mock(ClientActorBehavior.class); - Assert.assertSame(behavior, connection.reconnectConnection(behavior)); + Assert.assertSame(behavior, connection.lockedReconnect(behavior)); } @Override