Fix transaction replay logic 69/86269/15
authorRobert Varga <robert.varga@pantheon.tech>
Fri, 6 Dec 2019 13:53:44 +0000 (14:53 +0100)
committerStephen Kitt <skitt@redhat.com>
Tue, 7 Jan 2020 16:04:52 +0000 (16:04 +0000)
After adding disambiguation (previous patch), it clear there is
a day-0 Obi-Wan bug in the code, which would cause the last
command to not be replayed.

Looking at the pending queue, if the transaction failing is second,
the second and third transactions should be replayed, not just
the second.

JIRA: OVSDB-428
Change-Id: Ifbdf5ba8bad5be6103e4666d95afd615ae7d1ab9
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/transactions/md/TransactionInvokerImpl.java
southbound/southbound-impl/src/test/java/org/opendaylight/ovsdb/southbound/transactions/md/TransactionInvokerImplTest.java

index 72ab103a5b657223a5e2ebb603eea04cf8cef414..1bd39f7eb58cc88fd6094924dc7ed2a9fe2fde6a 100644 (file)
@@ -163,9 +163,7 @@ public class TransactionInvokerImpl implements TransactionInvoker,TransactionCha
         List<TransactionCommand> commands = new ArrayList<>();
         if (transaction != null) {
             int index = pendingTransactions.lastIndexOf(transaction);
-            List<ReadWriteTransaction> transactions =
-                    pendingTransactions.subList(index, pendingTransactions.size() - 1);
-            for (ReadWriteTransaction tx: transactions) {
+            for (ReadWriteTransaction tx : pendingTransactions.subList(index, pendingTransactions.size())) {
                 commands.add(transactionToCommand.get(tx));
             }
             resetTransactionQueue();
index 1196679a255c7fcd60ce2d035989ac48e00c1757..64b97551d1f22c2592ca87cd4cf7c52bdb7b6b44 100644 (file)
@@ -17,6 +17,7 @@ import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.powermock.reflect.Whitebox.getInternalState;
 
+import com.google.common.collect.ImmutableList;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -81,25 +82,26 @@ public class TransactionInvokerImplTest {
 
     @Test
     public void testExtractResubmitCommands() {
-        final ReadWriteTransaction transaction = mock(ReadWriteTransaction.class);
         final ReadWriteTransaction tx1 = mock(ReadWriteTransaction.class);
         final ReadWriteTransaction tx2 = mock(ReadWriteTransaction.class);
-
-        final List<ReadWriteTransaction> pendingTransactions = new ArrayList<>();
-        pendingTransactions.add(tx1);
-        pendingTransactions.add(transaction);
-        pendingTransactions.add(tx2);
+        final ReadWriteTransaction tx3 = mock(ReadWriteTransaction.class);
 
         final Map<ReadWriteTransaction,TransactionCommand> transactionToCommand = new HashMap<>();
-        final TransactionCommand txCommand = mock(TransactionCommand.class);
         transactionToCommand.put(tx1, mock(TransactionCommand.class));
-        transactionToCommand.put(tx2, mock(TransactionCommand.class));
-        transactionToCommand.put(transaction, txCommand);
-
-        final TransactionInvokerImpl invoker = new TransactionInvokerImpl(db, pendingTransactions,
-            Collections.singletonList(transaction), transactionToCommand);
-
-        assertEquals(Collections.singletonList(txCommand), invoker.extractResubmitCommands());
+        final TransactionCommand cmd2 = mock(TransactionCommand.class);
+        transactionToCommand.put(tx2, cmd2);
+        final TransactionCommand cmd3 = mock(TransactionCommand.class);
+        transactionToCommand.put(tx3, cmd3);
+
+        final TransactionInvokerImpl invoker = new TransactionInvokerImpl(db,
+            // Given pending transaction order ...
+            ImmutableList.of(tx1, tx2, tx3),
+            // .. if tx2 fails ...
+            Collections.singletonList(tx2),
+            transactionToCommand);
+
+        // .. we want to replay tx2 and tx3
+        assertEquals(ImmutableList.of(cmd2, cmd3), invoker.extractResubmitCommands());
     }
 
     @Test