Bug 1430: Off-load notifications from single commit thread
[controller.git] / opendaylight / md-sal / sal-dom-broker / src / main / java / org / opendaylight / controller / md / sal / dom / broker / impl / DOMDataCommitCoordinatorImpl.java
index 13a0093d340b7ef3bc496cf6950d1118ad309ab5..521e2d0e731af06ac972ce2cce28f75a347ba490 100644 (file)
@@ -9,15 +9,14 @@ package org.opendaylight.controller.md.sal.dom.broker.impl;
 import java.util.List;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
+import java.util.concurrent.RejectedExecutionException;
 
 import javax.annotation.concurrent.GuardedBy;
 
-import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreThreePhaseCommitCohort;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.opendaylight.yangtools.util.concurrent.MappingCheckedFuture;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -82,18 +81,30 @@ public class DOMDataCommitCoordinatorImpl implements DOMDataCommitExecutor {
     }
 
     @Override
-    public ListenableFuture<RpcResult<TransactionStatus>> submit(final DOMDataWriteTransaction transaction,
+    public CheckedFuture<Void,TransactionCommitFailedException> submit(final DOMDataWriteTransaction transaction,
             final Iterable<DOMStoreThreePhaseCommitCohort> cohorts, final Optional<DOMDataCommitErrorListener> listener) {
         Preconditions.checkArgument(transaction != null, "Transaction must not be null.");
         Preconditions.checkArgument(cohorts != null, "Cohorts must not be null.");
         Preconditions.checkArgument(listener != null, "Listener must not be null");
         LOG.debug("Tx: {} is submitted for execution.", transaction.getIdentifier());
-        ListenableFuture<RpcResult<TransactionStatus>> commitFuture = executor.submit(new CommitCoordinationTask(
-                transaction, cohorts, listener));
+
+        ListenableFuture<Void> commitFuture = null;
+        try {
+            commitFuture = executor.submit(new CommitCoordinationTask(transaction, cohorts, listener));
+        } catch(RejectedExecutionException e) {
+            LOG.error("The commit executor's queue is full - submit task was rejected. \n" +
+                      executor, e);
+            return Futures.immediateFailedCheckedFuture(
+                    new TransactionCommitFailedException(
+                        "Could not submit the commit task - the commit queue capacity has been exceeded.", e));
+        }
+
         if (listener.isPresent()) {
             Futures.addCallback(commitFuture, new DOMDataCommitErrorInvoker(transaction, listener.get()));
         }
-        return commitFuture;
+
+        return MappingCheckedFuture.create(commitFuture,
+                TransactionCommitFailedExceptionMapper.COMMIT_ERROR_MAPPER);
     }
 
     /**
@@ -139,7 +150,7 @@ public class DOMDataCommitCoordinatorImpl implements DOMDataCommitExecutor {
      * support of cancelation.
      *
      */
-    private static class CommitCoordinationTask implements Callable<RpcResult<TransactionStatus>> {
+    private static class CommitCoordinationTask implements Callable<Void> {
 
         private final DOMDataWriteTransaction tx;
         private final Iterable<DOMStoreThreePhaseCommitCohort> cohorts;
@@ -156,12 +167,13 @@ public class DOMDataCommitCoordinatorImpl implements DOMDataCommitExecutor {
         }
 
         @Override
-        public RpcResult<TransactionStatus> call() throws TransactionCommitFailedException {
+        public Void call() throws TransactionCommitFailedException {
 
             try {
                 canCommitBlocking();
                 preCommitBlocking();
-                return commitBlocking();
+                commitBlocking();
+                return null;
             } catch (TransactionCommitFailedException e) {
                 LOG.warn("Tx: {} Error during phase {}, starting Abort", tx.getIdentifier(), currentPhase, e);
                 abortBlocking(e);
@@ -217,9 +229,8 @@ public class DOMDataCommitCoordinatorImpl implements DOMDataCommitExecutor {
          *             If one of cohorts failed preCommit
          *
          */
-        private RpcResult<TransactionStatus> commitBlocking() throws TransactionCommitFailedException {
+        private void commitBlocking() throws TransactionCommitFailedException {
             commitAll().checkedGet();
-            return RpcResultBuilder.<TransactionStatus>success(TransactionStatus.COMMITED).build();
         }
 
         /**
@@ -287,7 +298,8 @@ public class DOMDataCommitCoordinatorImpl implements DOMDataCommitExecutor {
              */
             @SuppressWarnings({ "unchecked", "rawtypes" })
             ListenableFuture<Void> compositeResult = (ListenableFuture) Futures.allAsList(ops.build());
-            return Futures.makeChecked(compositeResult, TransactionCommitFailedExceptionMapper.PRE_COMMIT_MAPPER);
+            return MappingCheckedFuture.create(compositeResult,
+                                         TransactionCommitFailedExceptionMapper.PRE_COMMIT_MAPPER);
         }
 
         /**
@@ -318,7 +330,8 @@ public class DOMDataCommitCoordinatorImpl implements DOMDataCommitExecutor {
              */
             @SuppressWarnings({ "unchecked", "rawtypes" })
             ListenableFuture<Void> compositeResult = (ListenableFuture) Futures.allAsList(ops.build());
-            return Futures.makeChecked(compositeResult, TransactionCommitFailedExceptionMapper.COMMIT_ERROR_MAPPER);
+            return MappingCheckedFuture.create(compositeResult,
+                                     TransactionCommitFailedExceptionMapper.COMMIT_ERROR_MAPPER);
         }
 
         /**
@@ -344,8 +357,8 @@ public class DOMDataCommitCoordinatorImpl implements DOMDataCommitExecutor {
             }
             ListenableFuture<List<Boolean>> allCanCommits = Futures.allAsList(canCommitOperations.build());
             ListenableFuture<Boolean> allSuccessFuture = Futures.transform(allCanCommits, AND_FUNCTION);
-            return Futures
-                    .makeChecked(allSuccessFuture, TransactionCommitFailedExceptionMapper.CAN_COMMIT_ERROR_MAPPER);
+            return MappingCheckedFuture.create(allSuccessFuture,
+                                       TransactionCommitFailedExceptionMapper.CAN_COMMIT_ERROR_MAPPER);
 
         }