Split TransactionChainProxy.combineWithPriorReadOnlyTxFutures()
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / main / java / org / opendaylight / controller / cluster / datastore / TransactionChainProxy.java
index 7c36adb70e6f65cdd559f68ff524b56461bc14ff..4ef89b4684c907923274ee1fb4ef0ae6d554da27 100644 (file)
@@ -256,38 +256,42 @@ final class TransactionChainProxy extends AbstractTransactionContextFactory<Loca
 
     private <T> Future<T> combineFutureWithPossiblePriorReadOnlyTxFutures(final Future<T> future,
             final TransactionIdentifier txId) {
-        if (!priorReadOnlyTxPromises.containsKey(txId) && !priorReadOnlyTxPromises.isEmpty()) {
-            Collection<Entry<TransactionIdentifier, Promise<Object>>> priorReadOnlyTxPromiseEntries =
-                    new ArrayList<>(priorReadOnlyTxPromises.entrySet());
-            if (priorReadOnlyTxPromiseEntries.isEmpty()) {
-                return future;
-            }
+        return priorReadOnlyTxPromises.isEmpty() || priorReadOnlyTxPromises.containsKey(txId) ? future
+                // Tough luck, we need do some work
+                : combineWithPriorReadOnlyTxFutures(future, txId);
+    }
 
-            List<Future<Object>> priorReadOnlyTxFutures = new ArrayList<>(priorReadOnlyTxPromiseEntries.size());
-            for (Entry<TransactionIdentifier, Promise<Object>> entry: priorReadOnlyTxPromiseEntries) {
-                LOG.debug("Tx: {} - waiting on future for prior read-only Tx {}", txId, entry.getKey());
-                priorReadOnlyTxFutures.add(entry.getValue().future());
-            }
+    // Split out of the common path
+    private <T> Future<T> combineWithPriorReadOnlyTxFutures(final Future<T> future, final TransactionIdentifier txId) {
+        // Take a stable snapshot, and check if we raced
+        final List<Entry<TransactionIdentifier, Promise<Object>>> priorReadOnlyTxPromiseEntries =
+                new ArrayList<>(priorReadOnlyTxPromises.entrySet());
+        if (priorReadOnlyTxPromiseEntries.isEmpty()) {
+            return future;
+        }
 
-            Future<Iterable<Object>> combinedFutures = Futures.sequence(priorReadOnlyTxFutures,
-                    getActorUtils().getClientDispatcher());
+        final List<Future<Object>> priorReadOnlyTxFutures = new ArrayList<>(priorReadOnlyTxPromiseEntries.size());
+        for (Entry<TransactionIdentifier, Promise<Object>> entry: priorReadOnlyTxPromiseEntries) {
+            LOG.debug("Tx: {} - waiting on future for prior read-only Tx {}", txId, entry.getKey());
+            priorReadOnlyTxFutures.add(entry.getValue().future());
+        }
 
-            final Promise<T> returnPromise = Futures.promise();
-            final OnComplete<Iterable<Object>> onComplete = new OnComplete<Iterable<Object>>() {
-                @Override
-                public void onComplete(final Throwable failure, final Iterable<Object> notUsed) {
-                    LOG.debug("Tx: {} - prior read-only Tx futures complete", txId);
+        final Future<Iterable<Object>> combinedFutures = Futures.sequence(priorReadOnlyTxFutures,
+            getActorUtils().getClientDispatcher());
 
-                    // Complete the returned Promise with the original Future.
-                    returnPromise.completeWith(future);
-                }
-            };
+        final Promise<T> returnPromise = Futures.promise();
+        final OnComplete<Iterable<Object>> onComplete = new OnComplete<>() {
+            @Override
+            public void onComplete(final Throwable failure, final Iterable<Object> notUsed) {
+                LOG.debug("Tx: {} - prior read-only Tx futures complete", txId);
 
-            combinedFutures.onComplete(onComplete, getActorUtils().getClientDispatcher());
-            return returnPromise.future();
-        } else {
-            return future;
-        }
+                // Complete the returned Promise with the original Future.
+                returnPromise.completeWith(future);
+            }
+        };
+
+        combinedFutures.onComplete(onComplete, getActorUtils().getClientDispatcher());
+        return returnPromise.future();
     }
 
     @Override