X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;ds=sidebyside;f=opendaylight%2Fmd-sal%2Fcds-access-client%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fcluster%2Faccess%2Fclient%2FAbstractClientConnection.java;h=361027af1de299fab960c487c32b0c09e51bbdb1;hb=62cddd88e42e8f3c6a92bbf42c97b0d6806f44ae;hp=9fd75cc439b68499e13c463fbd419ae6b2d4704b;hpb=1819f12a7e562482d9328a8e4c4aeffd2b1a2c01;p=controller.git 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 9fd75cc439..361027af1d 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 @@ -7,11 +7,12 @@ */ package org.opendaylight.controller.cluster.access.client; +import static java.util.Objects.requireNonNull; + import akka.actor.ActorRef; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.MoreObjects; import com.google.common.base.MoreObjects.ToStringHelper; -import com.google.common.base.Preconditions; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.util.Collection; import java.util.Optional; @@ -20,9 +21,9 @@ import java.util.concurrent.TimeoutException; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import java.util.function.Consumer; -import javax.annotation.Nonnull; -import javax.annotation.concurrent.GuardedBy; -import javax.annotation.concurrent.NotThreadSafe; +import org.checkerframework.checker.lock.qual.GuardedBy; +import org.checkerframework.checker.lock.qual.Holding; +import org.eclipse.jdt.annotation.NonNull; import org.opendaylight.controller.cluster.access.concepts.Request; import org.opendaylight.controller.cluster.access.concepts.RequestException; import org.opendaylight.controller.cluster.access.concepts.Response; @@ -35,11 +36,10 @@ import scala.concurrent.duration.FiniteDuration; /** * Base class for a connection to the backend. Responsible to queueing and dispatch of requests toward the backend. * Can be in three conceptual states: Connecting, Connected and Reconnecting, which are represented by public final - * classes exposed from this package. + * classes exposed from this package. This class NOT thread-safe, not are its subclasses expected to be thread-safe. * * @author Robert Varga */ -@NotThreadSafe public abstract class AbstractClientConnection { private static final Logger LOG = LoggerFactory.getLogger(AbstractClientConnection.class); @@ -77,7 +77,8 @@ public abstract class AbstractClientConnection { private final ClientActorContext context; @GuardedBy("lock") private final TransmitQueue queue; - private final Long cookie; + private final @NonNull Long cookie; + private final String backendName; @GuardedBy("lock") private boolean haveTimer; @@ -90,19 +91,23 @@ public abstract class AbstractClientConnection { private volatile RequestException poisoned; // Private constructor to avoid code duplication. - private AbstractClientConnection(final AbstractClientConnection oldConn, final TransmitQueue newQueue) { - this.context = Preconditions.checkNotNull(oldConn.context); - this.cookie = Preconditions.checkNotNull(oldConn.cookie); - this.queue = Preconditions.checkNotNull(newQueue); + private AbstractClientConnection(final AbstractClientConnection oldConn, final TransmitQueue newQueue, + final String backendName) { + this.context = requireNonNull(oldConn.context); + this.cookie = requireNonNull(oldConn.cookie); + this.backendName = requireNonNull(backendName); + this.queue = requireNonNull(newQueue); // Will be updated in finishReplay if needed. this.lastReceivedTicks = oldConn.lastReceivedTicks; } // This constructor is only to be called by ConnectingClientConnection constructor. // Do not allow subclassing outside of this package - AbstractClientConnection(final ClientActorContext context, final Long cookie, final int queueDepth) { - this.context = Preconditions.checkNotNull(context); - this.cookie = Preconditions.checkNotNull(cookie); + AbstractClientConnection(final ClientActorContext context, final Long cookie, final String backendName, + final int queueDepth) { + this.context = requireNonNull(context); + this.cookie = requireNonNull(cookie); + this.backendName = requireNonNull(backendName); this.queue = new TransmitQueue.Halted(queueDepth); this.lastReceivedTicks = currentTime(); } @@ -110,21 +115,22 @@ public abstract class AbstractClientConnection { // This constructor is only to be called (indirectly) by ReconnectingClientConnection constructor. // Do not allow subclassing outside of this package AbstractClientConnection(final AbstractClientConnection oldConn) { - this(oldConn, new TransmitQueue.Halted(oldConn.queue, oldConn.currentTime())); + this(oldConn, new TransmitQueue.Halted(oldConn.queue, oldConn.currentTime()), oldConn.backendName); } // This constructor is only to be called (indirectly) by ConnectedClientConnection constructor. // Do not allow subclassing outside of this package - AbstractClientConnection(final AbstractClientConnection oldConn, final T newBackend, final int queueDepth) { + AbstractClientConnection(final AbstractClientConnection oldConn, final T newBackend, + final int queueDepth) { this(oldConn, new TransmitQueue.Transmitting(oldConn.queue, queueDepth, newBackend, oldConn.currentTime(), - Preconditions.checkNotNull(oldConn.context).messageSlicer())); + requireNonNull(oldConn.context).messageSlicer()), newBackend.getName()); } public final ClientActorContext context() { return context; } - public final @Nonnull Long cookie() { + public final @NonNull Long cookie() { return cookie; } @@ -191,7 +197,7 @@ public abstract class AbstractClientConnection { } } - @GuardedBy("lock") + @Holding("lock") private void commonEnqueue(final ConnectionEntry entry, final long now) { final RequestException maybePoison = poisoned; if (maybePoison != null) { @@ -216,7 +222,7 @@ public abstract class AbstractClientConnection { return queue.drain(); } - @GuardedBy("lock") + @Holding("lock") final void finishReplay(final ReconnectForwarder forwarder) { setForwarder(forwarder); @@ -236,12 +242,12 @@ public abstract class AbstractClientConnection { lock.unlock(); } - @GuardedBy("lock") + @Holding("lock") final void setForwarder(final ReconnectForwarder forwarder) { queue.setForwarder(forwarder, currentTime()); } - @GuardedBy("lock") + @Holding("lock") abstract ClientActorBehavior lockedReconnect(ClientActorBehavior current, RequestException runtimeRequestException); @@ -280,7 +286,7 @@ public abstract class AbstractClientConnection { * * @param delay Delay, in nanoseconds */ - @GuardedBy("lock") + @Holding("lock") private void scheduleTimer(final long delay) { if (haveTimer) { LOG.debug("{}: timer already scheduled on {}", context.persistenceId(), this); @@ -422,7 +428,8 @@ public abstract class AbstractClientConnection { context.executeInActor(current -> { final double time = beenOpen * 1.0 / 1_000_000_000; entry.complete(entry.getRequest().toRequestFailure( - new RequestTimeoutException("Timed out after " + time + " seconds"))); + new RequestTimeoutException(entry.getRequest() + " timed out after " + time + + " seconds. The backend for " + backendName + " is not available."))); return current; }); } @@ -436,7 +443,7 @@ public abstract class AbstractClientConnection { } } - @GuardedBy("lock") + @Holding("lock") private void lockedPoison(final RequestException cause) { poisoned = enrichPoison(cause); queue.poison(cause);