Update DOMStoreThreePhaseCommitCohort design
[mdsal.git] / dom / mdsal-dom-inmemory-datastore / src / main / java / org / opendaylight / mdsal / dom / store / inmemory / InMemoryDOMStoreThreePhaseCommitCohort.java
index 68cc7b49b243b56e0e8c3e1f1a8017a7713acea6..ef1a61859134db94e985f4e7f8e8907662f1b4e2 100644 (file)
@@ -9,36 +9,45 @@
 package org.opendaylight.mdsal.dom.store.inmemory;
 
 import static com.google.common.base.Preconditions.checkState;
+import static java.util.Objects.requireNonNull;
 
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.mdsal.common.api.CommitInfo;
+import org.opendaylight.mdsal.common.api.OptimisticLockFailedException;
+import org.opendaylight.mdsal.common.api.TransactionCommitFailedException;
 import org.opendaylight.mdsal.dom.spi.store.AbstractDOMStoreTransaction;
 import org.opendaylight.mdsal.dom.spi.store.DOMStoreThreePhaseCommitCohort;
 import org.opendaylight.mdsal.dom.spi.store.SnapshotBackedWriteTransaction;
-
-import org.opendaylight.mdsal.common.api.OptimisticLockFailedException;
-import org.opendaylight.mdsal.common.api.TransactionCommitFailedException;
-import com.google.common.base.Preconditions;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.ConflictingModificationAppliedException;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException;
+import org.opendaylight.yangtools.yang.common.Empty;
+import org.opendaylight.yangtools.yang.data.tree.api.ConflictingModificationAppliedException;
+import org.opendaylight.yangtools.yang.data.tree.api.DataTreeCandidate;
+import org.opendaylight.yangtools.yang.data.tree.api.DataTreeModification;
+import org.opendaylight.yangtools.yang.data.tree.api.DataValidationFailedException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 class InMemoryDOMStoreThreePhaseCommitCohort implements DOMStoreThreePhaseCommitCohort {
     private static final Logger LOG = LoggerFactory.getLogger(InMemoryDOMStoreThreePhaseCommitCohort.class);
-    private static final ListenableFuture<Void> SUCCESSFUL_FUTURE = Futures.immediateFuture(null);
+    private static final ListenableFuture<Empty> SUCCESSFUL_FUTURE = Futures.immediateFuture(Empty.value());
     private static final ListenableFuture<Boolean> CAN_COMMIT_FUTURE = Futures.immediateFuture(Boolean.TRUE);
+
     private final SnapshotBackedWriteTransaction<String> transaction;
     private final DataTreeModification modification;
     private final InMemoryDOMDataStore store;
-    private DataTreeCandidate candidate;
-
-    public InMemoryDOMStoreThreePhaseCommitCohort(final InMemoryDOMDataStore store, final SnapshotBackedWriteTransaction<String> writeTransaction, final DataTreeModification modification) {
-        this.transaction = Preconditions.checkNotNull(writeTransaction);
-        this.modification = Preconditions.checkNotNull(modification);
-        this.store = Preconditions.checkNotNull(store);
+    private final Exception operationError;
+
+    @VisibleForTesting
+    DataTreeCandidate candidate;
+
+    InMemoryDOMStoreThreePhaseCommitCohort(final InMemoryDOMDataStore store,
+            final SnapshotBackedWriteTransaction<String> transaction, final DataTreeModification modification,
+            final Exception operationError) {
+        this.transaction = requireNonNull(transaction);
+        this.modification = requireNonNull(modification);
+        this.store = requireNonNull(store);
+        this.operationError = operationError;
     }
 
     private static void warnDebugContext(final AbstractDOMStoreTransaction<?> transaction) {
@@ -48,8 +57,13 @@ class InMemoryDOMStoreThreePhaseCommitCohort implements DOMStoreThreePhaseCommit
         }
     }
 
+    @SuppressWarnings("checkstyle:IllegalCatch")
     @Override
     public final ListenableFuture<Boolean> canCommit() {
+        if (operationError != null) {
+            return Futures.immediateFailedFuture(operationError);
+        }
+
         try {
             store.validate(modification);
             LOG.debug("Store Transaction: {} can be committed", getTransaction().getIdentifier());
@@ -66,17 +80,20 @@ class InMemoryDOMStoreThreePhaseCommitCohort implements DOMStoreThreePhaseCommit
 
             // For debugging purposes, allow dumping of the modification. Coupled with the above
             // precondition log, it should allow us to understand what went on.
-            LOG.trace("Store Tx: {} modifications: {} tree: {}", modification, store);
+            LOG.trace("Store Tx: {} modifications: {} tree: {}", getTransaction().getIdentifier(),
+                    modification, store);
 
-            return Futures.immediateFailedFuture(new TransactionCommitFailedException("Data did not pass validation.", e));
+            return Futures.immediateFailedFuture(
+                    new TransactionCommitFailedException("Data did not pass validation.", e));
         } catch (Exception e) {
             LOG.warn("Unexpected failure in validation phase", e);
             return Futures.immediateFailedFuture(e);
         }
     }
 
+    @SuppressWarnings("checkstyle:IllegalCatch")
     @Override
-    public final ListenableFuture<Void> preCommit() {
+    public final ListenableFuture<Empty> preCommit() {
         try {
             candidate = store.prepare(modification);
             return SUCCESSFUL_FUTURE;
@@ -87,7 +104,7 @@ class InMemoryDOMStoreThreePhaseCommitCohort implements DOMStoreThreePhaseCommit
     }
 
     @Override
-    public final ListenableFuture<Void> abort() {
+    public final ListenableFuture<Empty> abort() {
         candidate = null;
         return SUCCESSFUL_FUTURE;
     }
@@ -97,15 +114,12 @@ class InMemoryDOMStoreThreePhaseCommitCohort implements DOMStoreThreePhaseCommit
     }
 
     @Override
-    public ListenableFuture<Void> commit() {
+    public ListenableFuture<CommitInfo> commit() {
         checkState(candidate != null, "Proposed subtree must be computed");
 
-        /*
-         * The commit has to occur atomically with regard to listener
-         * registrations.
-         */
+        // The commit has to occur atomically with regard to listener registrations.
         store.commit(candidate);
-        return SUCCESSFUL_FUTURE;
+        return CommitInfo.emptyFluentFuture();
     }
 }