BUG-8620: handle direct commit and disconnect correctly 41/59841/2
authorRobert Varga <robert.varga@pantheon.tech>
Wed, 7 Jun 2017 16:08:28 +0000 (18:08 +0200)
committerRobert Varga <nite@hq.sk>
Mon, 3 Jul 2017 11:08:16 +0000 (11:08 +0000)
Transactions committed directly can complete in a disconnected
fashion as we are skipping the back-and-forth communication of the
three-phase commit. This period may involve shard leadership changes
and so we may end up in a situation where we are replaying a direct
commit request to a transaction which already completed -- which
raises a RequestFailure to make sure we do not do anything untoward.

In the specific case of direct commit, though, this is perfectly fine
and so update the callback to account for this case happening.

Change-Id: Ic60e69f0f58cc7c5a3ac869386dc12f856aa1f74
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
(cherry picked from commit da42d2ffc8904b8dd24596cf6d918a0d30c8c521)

opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/databroker/actors/dds/AbstractProxyTransaction.java

index 3a463e51906ed7ded5a4e657f044e0b7915e2ce7..84546632f099bb3302938f6d0e8990c3f93e5e3b 100644 (file)
@@ -30,6 +30,7 @@ import javax.annotation.concurrent.GuardedBy;
 import javax.annotation.concurrent.NotThreadSafe;
 import org.opendaylight.controller.cluster.access.client.ConnectionEntry;
 import org.opendaylight.controller.cluster.access.commands.AbstractLocalTransactionRequest;
+import org.opendaylight.controller.cluster.access.commands.ClosedTransactionException;
 import org.opendaylight.controller.cluster.access.commands.IncrementTransactionSequenceRequest;
 import org.opendaylight.controller.cluster.access.commands.TransactionAbortRequest;
 import org.opendaylight.controller.cluster.access.commands.TransactionAbortSuccess;
@@ -463,7 +464,14 @@ abstract class AbstractProxyTransaction implements Identifiable<TransactionIdent
                     if (t instanceof TransactionCommitSuccess) {
                         ret.set(Boolean.TRUE);
                     } else if (t instanceof RequestFailure) {
-                        ret.setException(((RequestFailure<?, ?>) t).getCause().unwrap());
+                        final Throwable cause = ((RequestFailure<?, ?>) t).getCause().unwrap();
+                        if (cause instanceof ClosedTransactionException) {
+                            // This is okay, as it indicates the transaction has been completed. It can happen
+                            // when we lose connectivity with the backend after it has received the request.
+                            ret.set(Boolean.TRUE);
+                        } else {
+                            ret.setException(cause);
+                        }
                     } else {
                         ret.setException(new IllegalStateException("Unhandled response " + t.getClass()));
                     }