BUG-8219: optimize empty CompositeDataTreeCohort case 21/55821/3
authorRobert Varga <robert.varga@pantheon.tech>
Fri, 21 Apr 2017 16:04:23 +0000 (18:04 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Fri, 21 Apr 2017 16:08:23 +0000 (18:08 +0200)
The common case is when we do not have any user cohorts, in which
case these is nothing we need to do. Address the FIXME by adding
shortcuts which transition state directly without burdening the
global execution context.

Change-Id: I38e163a879949c3755322ed371db3bff5d28142f
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/CompositeDataTreeCohort.java

index 8115473a0565fb2c3865f4bc03e7216a8029a579..9d222bc2042c54413c77d2d424dac0274e38537e 100644 (file)
@@ -13,11 +13,11 @@ import akka.actor.Status.Failure;
 import akka.dispatch.ExecutionContexts;
 import akka.dispatch.Futures;
 import akka.dispatch.Recover;
-import akka.japi.Function;
 import akka.pattern.Patterns;
 import akka.util.Timeout;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Throwables;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
 import java.util.Collection;
 import java.util.Iterator;
@@ -91,7 +91,6 @@ class CompositeDataTreeCohort {
         }
     };
 
-
     private final DataTreeCohortActorRegistry registry;
     private final TransactionIdentifier txId;
     private final SchemaContext schema;
@@ -109,21 +108,26 @@ class CompositeDataTreeCohort {
 
     void canCommit(final DataTreeCandidate tip) throws ExecutionException, TimeoutException {
         Collection<CanCommit> messages = registry.createCanCommitMessages(txId, tip, schema);
-        // FIXME: Optimize empty collection list with pre-created futures, containing success.
-        Future<Iterable<Object>> canCommitsFuture =
-                Futures.traverse(messages, new Function<CanCommit, Future<Object>>() {
-                    @Override
-                    public Future<Object> apply(final CanCommit input) {
-                        return Patterns.ask(input.getCohort(), input, timeout).recover(EXCEPTION_TO_MESSAGE,
-                                ExecutionContexts.global());
-                    }
-                }, ExecutionContexts.global());
+        if (messages.isEmpty()) {
+            successfulFromPrevious = ImmutableList.of();
+            changeStateFrom(State.IDLE, State.CAN_COMMIT_SUCCESSFUL);
+            return;
+        }
+
+        Future<Iterable<Object>> canCommitsFuture = Futures.traverse(messages,
+            input -> Patterns.ask(input.getCohort(), input, timeout).recover(EXCEPTION_TO_MESSAGE,
+                ExecutionContexts.global()), ExecutionContexts.global());
         changeStateFrom(State.IDLE, State.CAN_COMMIT_SENT);
         processResponses(canCommitsFuture, State.CAN_COMMIT_SENT, State.CAN_COMMIT_SUCCESSFUL);
     }
 
     void preCommit() throws ExecutionException, TimeoutException {
         Preconditions.checkState(successfulFromPrevious != null);
+        if (isEmpty()) {
+            changeStateFrom(State.CAN_COMMIT_SUCCESSFUL, State.PRE_COMMIT_SUCCESSFUL);
+            return;
+        }
+
         Future<Iterable<Object>> preCommitFutures = sendMesageToSuccessful(new DataTreeCohortActor.PreCommit(txId));
         changeStateFrom(State.CAN_COMMIT_SUCCESSFUL, State.PRE_COMMIT_SENT);
         processResponses(preCommitFutures, State.PRE_COMMIT_SENT, State.PRE_COMMIT_SUCCESSFUL);
@@ -131,6 +135,11 @@ class CompositeDataTreeCohort {
 
     void commit() throws ExecutionException, TimeoutException {
         Preconditions.checkState(successfulFromPrevious != null);
+        if (isEmpty()) {
+            changeStateFrom(State.PRE_COMMIT_SUCCESSFUL, State.COMMITED);
+            return;
+        }
+
         Future<Iterable<Object>> commitsFuture = sendMesageToSuccessful(new DataTreeCohortActor.Commit(txId));
         changeStateFrom(State.PRE_COMMIT_SUCCESSFUL, State.COMMIT_SENT);
         processResponses(commitsFuture, State.COMMIT_SENT, State.COMMITED);
@@ -144,19 +153,17 @@ class CompositeDataTreeCohort {
         return Optional.empty();
     }
 
-    private Future<Iterable<Object>> sendMesageToSuccessful(final Object message) {
-        return Futures.traverse(successfulFromPrevious, new Function<DataTreeCohortActor.Success, Future<Object>>() {
-
-            @Override
-            public Future<Object> apply(final DataTreeCohortActor.Success cohortResponse) throws Exception {
-                return Patterns.ask(cohortResponse.getCohort(), message, timeout);
-            }
+    private boolean isEmpty() {
+        return successfulFromPrevious instanceof Collection && ((Collection<?>) successfulFromPrevious).isEmpty();
+    }
 
-        }, ExecutionContexts.global());
+    private Future<Iterable<Object>> sendMesageToSuccessful(final Object message) {
+        return Futures.traverse(successfulFromPrevious, cohortResponse -> Patterns.ask(cohortResponse.getCohort(),
+            message, timeout), ExecutionContexts.global());
     }
 
-    private void processResponses(final Future<Iterable<Object>> resultsFuture, final State currentState, final State afterState)
-            throws TimeoutException, ExecutionException {
+    private void processResponses(final Future<Iterable<Object>> resultsFuture, final State currentState,
+            final State afterState) throws TimeoutException, ExecutionException {
         final Iterable<Object> results;
         try {
             results = Await.result(resultsFuture, timeout.duration());
@@ -182,7 +189,7 @@ class CompositeDataTreeCohort {
         changeStateFrom(currentState, afterState);
     }
 
-    void changeStateFrom(final State expected, final State followup) {
+    private void changeStateFrom(final State expected, final State followup) {
         Preconditions.checkState(state == expected);
         state = followup;
     }