Do not assert seal transition on forward path
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / main / java / org / opendaylight / controller / cluster / databroker / actors / dds / AbstractProxyTransaction.java
index 51f528150d22a717034cc4281618591645cca92f..132ebbf34ba1a124241d6a2c77f36a2c25f712f1 100644 (file)
@@ -9,16 +9,16 @@ package org.opendaylight.controller.cluster.databroker.actors.dds;
 
 import akka.actor.ActorRef;
 import com.google.common.base.MoreObjects;
-import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Verify;
 import com.google.common.collect.Iterables;
-import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.FluentFuture;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.SettableFuture;
 import java.util.ArrayDeque;
 import java.util.Deque;
 import java.util.Iterator;
+import java.util.Optional;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
 import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
@@ -45,7 +45,6 @@ import org.opendaylight.controller.cluster.access.concepts.Request;
 import org.opendaylight.controller.cluster.access.concepts.RequestFailure;
 import org.opendaylight.controller.cluster.access.concepts.Response;
 import org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier;
-import org.opendaylight.mdsal.common.api.ReadFailedException;
 import org.opendaylight.yangtools.concepts.Identifiable;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
@@ -305,12 +304,12 @@ abstract class AbstractProxyTransaction implements Identifiable<TransactionIdent
         doWrite(path, data);
     }
 
-    final CheckedFuture<Boolean, ReadFailedException> exists(final YangInstanceIdentifier path) {
+    final FluentFuture<Boolean> exists(final YangInstanceIdentifier path) {
         checkNotSealed();
         return doExists(path);
     }
 
-    final CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> read(final YangInstanceIdentifier path) {
+    final FluentFuture<Optional<NormalizedNode<?, ?>>> read(final YangInstanceIdentifier path) {
         checkNotSealed();
         return doRead(path);
     }
@@ -335,7 +334,7 @@ abstract class AbstractProxyTransaction implements Identifiable<TransactionIdent
         final boolean success = markSealed();
         Preconditions.checkState(success, "Proxy %s was already sealed", getIdentifier());
 
-        if (!sealAndSend(Optional.absent())) {
+        if (!sealAndSend(Optional.empty())) {
             sealSuccessor();
         }
     }
@@ -359,15 +358,19 @@ abstract class AbstractProxyTransaction implements Identifiable<TransactionIdent
     }
 
     private void predecessorSealed() {
-        if (markSealed() && !sealAndSend(Optional.absent())) {
+        if (markSealed() && !sealAndSend(Optional.empty())) {
             sealSuccessor();
         }
     }
 
-    void sealOnly() {
-        parent.onTransactionSealed(this);
-        final boolean success = STATE_UPDATER.compareAndSet(this, OPEN, SEALED);
-        Verify.verify(success, "Attempted to replay seal on %s", this);
+    /**
+     * Seal this transaction. If this method reports false, the caller needs to deal with propagating the seal operation
+     * towards the successor.
+     *
+     * @return True if seal operation was successful, false if this proxy has a successor.
+     */
+    boolean sealOnly() {
+        return sealState();
     }
 
     /**
@@ -378,8 +381,11 @@ abstract class AbstractProxyTransaction implements Identifiable<TransactionIdent
      * @return True if seal operation was successful, false if this proxy has a successor.
      */
     boolean sealAndSend(final Optional<Long> enqueuedTicks) {
-        parent.onTransactionSealed(this);
+        return sealState();
+    }
 
+    private boolean sealState() {
+        parent.onTransactionSealed(this);
         // Transition internal state to sealed and detect presence of a successor
         return STATE_UPDATER.compareAndSet(this, OPEN, SEALED);
     }
@@ -413,7 +419,7 @@ abstract class AbstractProxyTransaction implements Identifiable<TransactionIdent
         }
     }
 
-    final void recordSuccessfulRequest(final @Nonnull TransactionRequest<?> req) {
+    final void recordSuccessfulRequest(@Nonnull final TransactionRequest<?> req) {
         successfulRequests.add(Verify.verifyNotNull(req));
     }
 
@@ -449,7 +455,7 @@ abstract class AbstractProxyTransaction implements Identifiable<TransactionIdent
             } else if (t instanceof RequestFailure) {
                 ret.voteNo(((RequestFailure<?, ?>) t).getCause().unwrap());
             } else {
-                ret.voteNo(new IllegalStateException("Unhandled response " + t.getClass()));
+                ret.voteNo(unhandledResponseException(t));
             }
 
             // This is a terminal request, hence we do not need to record it
@@ -507,7 +513,7 @@ abstract class AbstractProxyTransaction implements Identifiable<TransactionIdent
                             ret.setException(cause);
                         }
                     } else {
-                        ret.setException(new IllegalStateException("Unhandled response " + t.getClass()));
+                        ret.setException(unhandledResponseException(t));
                     }
 
                     // This is a terminal request, hence we do not need to record it
@@ -538,7 +544,7 @@ abstract class AbstractProxyTransaction implements Identifiable<TransactionIdent
                     } else if (t instanceof RequestFailure) {
                         ret.voteNo(((RequestFailure<?, ?>) t).getCause().unwrap());
                     } else {
-                        ret.voteNo(new IllegalStateException("Unhandled response " + t.getClass()));
+                        ret.voteNo(unhandledResponseException(t));
                     }
 
                     recordSuccessfulRequest(req);
@@ -569,7 +575,7 @@ abstract class AbstractProxyTransaction implements Identifiable<TransactionIdent
             } else if (t instanceof RequestFailure) {
                 ret.voteNo(((RequestFailure<?, ?>) t).getCause().unwrap());
             } else {
-                ret.voteNo(new IllegalStateException("Unhandled response " + t.getClass()));
+                ret.voteNo(unhandledResponseException(t));
             }
 
             onPreCommitComplete(req);
@@ -602,7 +608,7 @@ abstract class AbstractProxyTransaction implements Identifiable<TransactionIdent
             } else if (t instanceof RequestFailure) {
                 ret.voteNo(((RequestFailure<?, ?>) t).getCause().unwrap());
             } else {
-                ret.voteNo(new IllegalStateException("Unhandled response " + t.getClass()));
+                ret.voteNo(unhandledResponseException(t));
             }
 
             LOG.debug("Transaction {} doCommit completed", this);
@@ -687,13 +693,13 @@ abstract class AbstractProxyTransaction implements Identifiable<TransactionIdent
             for (Object obj : successfulRequests) {
                 if (obj instanceof TransactionRequest) {
                     LOG.debug("Forwarding successful request {} to successor {}", obj, successor);
-                    successor.doReplayRequest((TransactionRequest<?>) obj, resp -> { }, now);
+                    successor.doReplayRequest((TransactionRequest<?>) obj, resp -> { /*NOOP*/ }, now);
                 } else {
                     Verify.verify(obj instanceof IncrementSequence);
                     final IncrementSequence increment = (IncrementSequence) obj;
                     successor.doReplayRequest(new IncrementTransactionSequenceRequest(getIdentifier(),
-                        increment.getSequence(), localActor(), isSnapshotOnly(), increment.getDelta()), resp -> { },
-                        now);
+                        increment.getSequence(), localActor(), isSnapshotOnly(),
+                        increment.getDelta()), resp -> { /*NOOP*/ }, now);
                     LOG.debug("Incrementing sequence {} to successor {}", obj, successor);
                 }
             }
@@ -797,9 +803,9 @@ abstract class AbstractProxyTransaction implements Identifiable<TransactionIdent
 
     abstract void doWrite(YangInstanceIdentifier path, NormalizedNode<?, ?> data);
 
-    abstract CheckedFuture<Boolean, ReadFailedException> doExists(YangInstanceIdentifier path);
+    abstract FluentFuture<Boolean> doExists(YangInstanceIdentifier path);
 
-    abstract CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> doRead(YangInstanceIdentifier path);
+    abstract FluentFuture<Optional<NormalizedNode<?, ?>>> doRead(YangInstanceIdentifier path);
 
     @GuardedBy("this")
     abstract java.util.Optional<ModifyTransactionRequest> flushState();
@@ -846,6 +852,10 @@ abstract class AbstractProxyTransaction implements Identifiable<TransactionIdent
     abstract void handleReplayedRemoteRequest(TransactionRequest<?> request,
             @Nullable Consumer<Response<?, ?>> callback, long enqueuedTicks);
 
+    private static IllegalStateException unhandledResponseException(Response<?, ?> resp) {
+        return new IllegalStateException("Unhandled response " + resp.getClass());
+    }
+
     @Override
     public final String toString() {
         return MoreObjects.toStringHelper(this).add("identifier", getIdentifier()).add("state", state).toString();