X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fmd-sal%2Fsal-distributed-datastore%2Fsrc%2Ftest%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fcluster%2Fdatastore%2FConcurrentDOMDataBrokerTest.java;h=7f481019ae853591b5d2d20434ec0ad0f91baa77;hp=80e25a167d49deef34b2bb2c0abdb0448a4528f5;hb=20e100c1377799a60976c4153e4f664578896cb9;hpb=107324809285bfbb9890cba38ffa18390f8de4bd diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ConcurrentDOMDataBrokerTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ConcurrentDOMDataBrokerTest.java index 80e25a167d..7f481019ae 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ConcurrentDOMDataBrokerTest.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ConcurrentDOMDataBrokerTest.java @@ -8,6 +8,7 @@ package org.opendaylight.controller.cluster.datastore; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -31,6 +32,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; @@ -42,6 +44,8 @@ import org.junit.Test; import org.mockito.InOrder; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; +import org.opendaylight.controller.cluster.datastore.exceptions.NoShardLeaderException; +import org.opendaylight.controller.md.sal.common.api.data.DataStoreUnavailableException; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener; import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; @@ -78,7 +82,7 @@ public class ConcurrentDOMDataBrokerTest { doReturn("tx").when(transaction).getIdentifier(); DOMStore store = new InMemoryDOMDataStore("OPER", - MoreExecutors.sameThreadExecutor()); + MoreExecutors.newDirectExecutorService()); coordinator = new ConcurrentDOMDataBroker(ImmutableMap.of(LogicalDatastoreType.OPERATIONAL, store), futureExecutor); } @@ -184,7 +188,7 @@ public class ConcurrentDOMDataBrokerTest { assertFailure(future, null, mockCohort1, mockCohort2, mockCohort3); } - private void assertFailure(final CheckedFuture future, + private static void assertFailure(final CheckedFuture future, final Exception expCause, final DOMStoreThreePhaseCommitCohort... mockCohorts) throws Exception { try { @@ -192,7 +196,7 @@ public class ConcurrentDOMDataBrokerTest { fail("Expected TransactionCommitFailedException"); } catch (TransactionCommitFailedException e) { if(expCause != null) { - assertSame("Expected cause", expCause, e.getCause()); + assertSame("Expected cause", expCause.getClass(), e.getCause().getClass()); } InOrder inOrder = inOrder((Object[])mockCohorts); @@ -219,6 +223,21 @@ public class ConcurrentDOMDataBrokerTest { assertFailure(future, cause, mockCohort1, mockCohort2); } + @Test + public void testSubmitWithCanCommitDataStoreUnavailableException() throws Exception { + doReturn(Futures.immediateFuture(true)).when(mockCohort1).canCommit(); + doReturn(Futures.immediateFuture(null)).when(mockCohort1).abort(); + NoShardLeaderException rootCause = new NoShardLeaderException("mock"); + DataStoreUnavailableException cause = new DataStoreUnavailableException(rootCause.getMessage(), rootCause); + doReturn(Futures.immediateFailedFuture(rootCause)).when(mockCohort2).canCommit(); + doReturn(Futures.immediateFuture(null)).when(mockCohort2).abort(); + + CheckedFuture future = coordinator.submit( + transaction, Arrays.asList(mockCohort1, mockCohort2)); + + assertFailure(future, cause, mockCohort1, mockCohort2); + } + @Test public void testSubmitWithPreCommitException() throws Exception { doReturn(Futures.immediateFuture(true)).when(mockCohort1).canCommit(); @@ -287,32 +306,37 @@ public class ConcurrentDOMDataBrokerTest { @Test public void testCreateReadWriteTransaction(){ DOMStore domStore = mock(DOMStore.class); - ConcurrentDOMDataBroker dataBroker = new ConcurrentDOMDataBroker(ImmutableMap.of(LogicalDatastoreType.OPERATIONAL, - domStore, LogicalDatastoreType.CONFIGURATION, domStore), futureExecutor); - dataBroker.newReadWriteTransaction(); + try (ConcurrentDOMDataBroker dataBroker = new ConcurrentDOMDataBroker(ImmutableMap.of( + LogicalDatastoreType.OPERATIONAL, domStore, LogicalDatastoreType.CONFIGURATION, domStore), + futureExecutor)) { + dataBroker.newReadWriteTransaction(); - verify(domStore, never()).newReadWriteTransaction(); + verify(domStore, never()).newReadWriteTransaction(); + } } - @Test public void testCreateWriteOnlyTransaction(){ DOMStore domStore = mock(DOMStore.class); - ConcurrentDOMDataBroker dataBroker = new ConcurrentDOMDataBroker(ImmutableMap.of(LogicalDatastoreType.OPERATIONAL, - domStore, LogicalDatastoreType.CONFIGURATION, domStore), futureExecutor); - dataBroker.newWriteOnlyTransaction(); + try (ConcurrentDOMDataBroker dataBroker = new ConcurrentDOMDataBroker(ImmutableMap.of( + LogicalDatastoreType.OPERATIONAL, domStore, LogicalDatastoreType.CONFIGURATION, domStore), + futureExecutor)) { + dataBroker.newWriteOnlyTransaction(); - verify(domStore, never()).newWriteOnlyTransaction(); + verify(domStore, never()).newWriteOnlyTransaction(); + } } @Test public void testCreateReadOnlyTransaction(){ DOMStore domStore = mock(DOMStore.class); - ConcurrentDOMDataBroker dataBroker = new ConcurrentDOMDataBroker(ImmutableMap.of(LogicalDatastoreType.OPERATIONAL, - domStore, LogicalDatastoreType.CONFIGURATION, domStore), futureExecutor); - dataBroker.newReadOnlyTransaction(); + try (ConcurrentDOMDataBroker dataBroker = new ConcurrentDOMDataBroker(ImmutableMap.of( + LogicalDatastoreType.OPERATIONAL, domStore, LogicalDatastoreType.CONFIGURATION, domStore), + futureExecutor)) { + dataBroker.newReadOnlyTransaction(); - verify(domStore, never()).newReadOnlyTransaction(); + verify(domStore, never()).newReadOnlyTransaction(); + } } @Test @@ -324,21 +348,23 @@ public class ConcurrentDOMDataBrokerTest { doReturn(storeTxn).when(operationalDomStore).newReadWriteTransaction(); doReturn(storeTxn).when(configDomStore).newReadWriteTransaction(); - ConcurrentDOMDataBroker dataBroker = new ConcurrentDOMDataBroker(ImmutableMap.of(LogicalDatastoreType.OPERATIONAL, - operationalDomStore, LogicalDatastoreType.CONFIGURATION, configDomStore), futureExecutor); - DOMDataReadWriteTransaction dataTxn = dataBroker.newReadWriteTransaction(); + try (ConcurrentDOMDataBroker dataBroker = new ConcurrentDOMDataBroker(ImmutableMap.of( + LogicalDatastoreType.OPERATIONAL, operationalDomStore, LogicalDatastoreType.CONFIGURATION, + configDomStore), futureExecutor)) { + DOMDataReadWriteTransaction dataTxn = dataBroker.newReadWriteTransaction(); - dataTxn.put(LogicalDatastoreType.OPERATIONAL, YangInstanceIdentifier.builder().build(), mock(NormalizedNode.class)); - dataTxn.put(LogicalDatastoreType.OPERATIONAL, YangInstanceIdentifier.builder().build(), mock(NormalizedNode.class)); - dataTxn.read(LogicalDatastoreType.OPERATIONAL, YangInstanceIdentifier.builder().build()); + dataTxn.put(LogicalDatastoreType.OPERATIONAL, YangInstanceIdentifier.builder().build(), mock(NormalizedNode.class)); + dataTxn.put(LogicalDatastoreType.OPERATIONAL, YangInstanceIdentifier.builder().build(), mock(NormalizedNode.class)); + dataTxn.read(LogicalDatastoreType.OPERATIONAL, YangInstanceIdentifier.builder().build()); - verify(configDomStore, never()).newReadWriteTransaction(); - verify(operationalDomStore, times(1)).newReadWriteTransaction(); + verify(configDomStore, never()).newReadWriteTransaction(); + verify(operationalDomStore, times(1)).newReadWriteTransaction(); - dataTxn.put(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.builder().build(), mock(NormalizedNode.class)); + dataTxn.put(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.builder().build(), mock(NormalizedNode.class)); - verify(configDomStore, times(1)).newReadWriteTransaction(); - verify(operationalDomStore, times(1)).newReadWriteTransaction(); + verify(configDomStore, times(1)).newReadWriteTransaction(); + verify(operationalDomStore, times(1)).newReadWriteTransaction(); + } } @@ -351,24 +377,24 @@ public class ConcurrentDOMDataBrokerTest { doReturn(storeTxn).when(operationalDomStore).newWriteOnlyTransaction(); doReturn(storeTxn).when(configDomStore).newWriteOnlyTransaction(); - ConcurrentDOMDataBroker dataBroker = new ConcurrentDOMDataBroker(ImmutableMap.of(LogicalDatastoreType.OPERATIONAL, - operationalDomStore, LogicalDatastoreType.CONFIGURATION, configDomStore), futureExecutor); - DOMDataWriteTransaction dataTxn = dataBroker.newWriteOnlyTransaction(); + try (ConcurrentDOMDataBroker dataBroker = new ConcurrentDOMDataBroker(ImmutableMap.of( + LogicalDatastoreType.OPERATIONAL, operationalDomStore, LogicalDatastoreType.CONFIGURATION, + configDomStore), futureExecutor)) { + DOMDataWriteTransaction dataTxn = dataBroker.newWriteOnlyTransaction(); - dataTxn.put(LogicalDatastoreType.OPERATIONAL, YangInstanceIdentifier.builder().build(), mock(NormalizedNode.class)); - dataTxn.put(LogicalDatastoreType.OPERATIONAL, YangInstanceIdentifier.builder().build(), mock(NormalizedNode.class)); + dataTxn.put(LogicalDatastoreType.OPERATIONAL, YangInstanceIdentifier.builder().build(), mock(NormalizedNode.class)); + dataTxn.put(LogicalDatastoreType.OPERATIONAL, YangInstanceIdentifier.builder().build(), mock(NormalizedNode.class)); - verify(configDomStore, never()).newWriteOnlyTransaction(); - verify(operationalDomStore, times(1)).newWriteOnlyTransaction(); + verify(configDomStore, never()).newWriteOnlyTransaction(); + verify(operationalDomStore, times(1)).newWriteOnlyTransaction(); - dataTxn.put(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.builder().build(), mock(NormalizedNode.class)); - - verify(configDomStore, times(1)).newWriteOnlyTransaction(); - verify(operationalDomStore, times(1)).newWriteOnlyTransaction(); + dataTxn.put(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.builder().build(), mock(NormalizedNode.class)); + verify(configDomStore, times(1)).newWriteOnlyTransaction(); + verify(operationalDomStore, times(1)).newWriteOnlyTransaction(); + } } - @Test public void testLazySubTransactionCreationForReadOnlyTransactions(){ DOMStore configDomStore = mock(DOMStore.class); @@ -378,21 +404,22 @@ public class ConcurrentDOMDataBrokerTest { doReturn(storeTxn).when(operationalDomStore).newReadOnlyTransaction(); doReturn(storeTxn).when(configDomStore).newReadOnlyTransaction(); - ConcurrentDOMDataBroker dataBroker = new ConcurrentDOMDataBroker(ImmutableMap.of(LogicalDatastoreType.OPERATIONAL, - operationalDomStore, LogicalDatastoreType.CONFIGURATION, configDomStore), futureExecutor); - DOMDataReadOnlyTransaction dataTxn = dataBroker.newReadOnlyTransaction(); + try (ConcurrentDOMDataBroker dataBroker = new ConcurrentDOMDataBroker(ImmutableMap.of( + LogicalDatastoreType.OPERATIONAL, operationalDomStore, LogicalDatastoreType.CONFIGURATION, + configDomStore), futureExecutor)) { + DOMDataReadOnlyTransaction dataTxn = dataBroker.newReadOnlyTransaction(); - dataTxn.read(LogicalDatastoreType.OPERATIONAL, YangInstanceIdentifier.builder().build()); - dataTxn.read(LogicalDatastoreType.OPERATIONAL, YangInstanceIdentifier.builder().build()); + dataTxn.read(LogicalDatastoreType.OPERATIONAL, YangInstanceIdentifier.builder().build()); + dataTxn.read(LogicalDatastoreType.OPERATIONAL, YangInstanceIdentifier.builder().build()); - verify(configDomStore, never()).newReadOnlyTransaction(); - verify(operationalDomStore, times(1)).newReadOnlyTransaction(); + verify(configDomStore, never()).newReadOnlyTransaction(); + verify(operationalDomStore, times(1)).newReadOnlyTransaction(); - dataTxn.read(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.builder().build()); - - verify(configDomStore, times(1)).newReadOnlyTransaction(); - verify(operationalDomStore, times(1)).newReadOnlyTransaction(); + dataTxn.read(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.builder().build()); + verify(configDomStore, times(1)).newReadOnlyTransaction(); + verify(operationalDomStore, times(1)).newReadOnlyTransaction(); + } } @Test @@ -408,26 +435,28 @@ public class ConcurrentDOMDataBrokerTest { doReturn(Futures.immediateFuture(null)).when(mockCohort).abort(); final CountDownLatch latch = new CountDownLatch(1); - final List commitCohorts = new ArrayList(); + final List commitCohorts = new ArrayList<>(); - ConcurrentDOMDataBroker dataBroker = new ConcurrentDOMDataBroker(ImmutableMap.of(LogicalDatastoreType.OPERATIONAL, - operationalDomStore, LogicalDatastoreType.CONFIGURATION, configDomStore), futureExecutor) { + try (ConcurrentDOMDataBroker dataBroker = new ConcurrentDOMDataBroker(ImmutableMap.of( + LogicalDatastoreType.OPERATIONAL, operationalDomStore, LogicalDatastoreType.CONFIGURATION, + configDomStore), futureExecutor) { @Override public CheckedFuture submit(DOMDataWriteTransaction transaction, Collection cohorts) { commitCohorts.addAll(cohorts); latch.countDown(); return super.submit(transaction, cohorts); } - }; - DOMDataReadWriteTransaction domDataReadWriteTransaction = dataBroker.newReadWriteTransaction(); + }) { + DOMDataReadWriteTransaction domDataReadWriteTransaction = dataBroker.newReadWriteTransaction(); - domDataReadWriteTransaction.delete(LogicalDatastoreType.OPERATIONAL, YangInstanceIdentifier.builder().build()); + domDataReadWriteTransaction.delete(LogicalDatastoreType.OPERATIONAL, YangInstanceIdentifier.builder().build()); - domDataReadWriteTransaction.submit(); + domDataReadWriteTransaction.submit(); - latch.await(10, TimeUnit.SECONDS); + latch.await(10, TimeUnit.SECONDS); - assertTrue(commitCohorts.size() == 1); + assertTrue(commitCohorts.size() == 1); + } } @Test @@ -450,62 +479,88 @@ public class ConcurrentDOMDataBrokerTest { doReturn(Futures.immediateFuture(false)).when(mockCohortConfig).canCommit(); doReturn(Futures.immediateFuture(null)).when(mockCohortConfig).abort(); - final CountDownLatch latch = new CountDownLatch(1); - final List commitCohorts = new ArrayList(); + final List commitCohorts = new ArrayList<>(); - ConcurrentDOMDataBroker dataBroker = new ConcurrentDOMDataBroker(ImmutableMap.of(LogicalDatastoreType.OPERATIONAL, - operationalDomStore, LogicalDatastoreType.CONFIGURATION, configDomStore), futureExecutor) { + try (ConcurrentDOMDataBroker dataBroker = new ConcurrentDOMDataBroker(ImmutableMap.of( + LogicalDatastoreType.OPERATIONAL, operationalDomStore, LogicalDatastoreType.CONFIGURATION, + configDomStore), futureExecutor) { @Override public CheckedFuture submit(DOMDataWriteTransaction transaction, Collection cohorts) { commitCohorts.addAll(cohorts); latch.countDown(); return super.submit(transaction, cohorts); } - }; - DOMDataReadWriteTransaction domDataReadWriteTransaction = dataBroker.newReadWriteTransaction(); + }) { + DOMDataReadWriteTransaction domDataReadWriteTransaction = dataBroker.newReadWriteTransaction(); - domDataReadWriteTransaction.put(LogicalDatastoreType.OPERATIONAL, YangInstanceIdentifier.builder().build(), mock(NormalizedNode.class)); - domDataReadWriteTransaction.merge(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.builder().build(), mock(NormalizedNode.class)); + domDataReadWriteTransaction.put(LogicalDatastoreType.OPERATIONAL, YangInstanceIdentifier.builder().build(), mock(NormalizedNode.class)); + domDataReadWriteTransaction.merge(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.builder().build(), mock(NormalizedNode.class)); - domDataReadWriteTransaction.submit(); + domDataReadWriteTransaction.submit(); - latch.await(10, TimeUnit.SECONDS); + latch.await(10, TimeUnit.SECONDS); - assertTrue(commitCohorts.size() == 2); + assertTrue(commitCohorts.size() == 2); + } } @Test public void testCreateTransactionChain(){ DOMStore domStore = mock(DOMStore.class); - ConcurrentDOMDataBroker dataBroker = new ConcurrentDOMDataBroker(ImmutableMap.of(LogicalDatastoreType.OPERATIONAL, - domStore, LogicalDatastoreType.CONFIGURATION, domStore), futureExecutor); + try (ConcurrentDOMDataBroker dataBroker = new ConcurrentDOMDataBroker(ImmutableMap.of( + LogicalDatastoreType.OPERATIONAL, domStore, LogicalDatastoreType.CONFIGURATION, domStore), + futureExecutor)) { - dataBroker.createTransactionChain(mock(TransactionChainListener.class)); + dataBroker.createTransactionChain(mock(TransactionChainListener.class)); - verify(domStore, times(2)).createTransactionChain(); + verify(domStore, times(2)).createTransactionChain(); + } } @Test public void testCreateTransactionOnChain(){ DOMStore domStore = mock(DOMStore.class); - ConcurrentDOMDataBroker dataBroker = new ConcurrentDOMDataBroker(ImmutableMap.of(LogicalDatastoreType.OPERATIONAL, - domStore, LogicalDatastoreType.CONFIGURATION, domStore), futureExecutor); + try (ConcurrentDOMDataBroker dataBroker = new ConcurrentDOMDataBroker(ImmutableMap.of( + LogicalDatastoreType.OPERATIONAL, domStore, LogicalDatastoreType.CONFIGURATION, domStore), + futureExecutor)) { - DOMStoreReadWriteTransaction operationalTransaction = mock(DOMStoreReadWriteTransaction.class); - DOMStoreTransactionChain mockChain = mock(DOMStoreTransactionChain.class); + DOMStoreReadWriteTransaction operationalTransaction = mock(DOMStoreReadWriteTransaction.class); + DOMStoreTransactionChain mockChain = mock(DOMStoreTransactionChain.class); + + doReturn(mockChain).when(domStore).createTransactionChain(); + doReturn(operationalTransaction).when(mockChain).newWriteOnlyTransaction(); - doReturn(mockChain).when(domStore).createTransactionChain(); - doReturn(operationalTransaction).when(mockChain).newWriteOnlyTransaction(); + DOMTransactionChain transactionChain = dataBroker.createTransactionChain(mock(TransactionChainListener.class)); - DOMTransactionChain transactionChain = dataBroker.createTransactionChain(mock(TransactionChainListener.class)); + DOMDataWriteTransaction domDataWriteTransaction = transactionChain.newWriteOnlyTransaction(); - DOMDataWriteTransaction domDataWriteTransaction = transactionChain.newWriteOnlyTransaction(); + verify(mockChain, never()).newWriteOnlyTransaction(); - verify(mockChain, never()).newWriteOnlyTransaction(); + domDataWriteTransaction.put(LogicalDatastoreType.OPERATIONAL, YangInstanceIdentifier.builder().build(), mock(NormalizedNode.class)); + } + } - domDataWriteTransaction.put(LogicalDatastoreType.OPERATIONAL, YangInstanceIdentifier.builder().build(), mock(NormalizedNode.class)); + @Test + public void testEmptyTransactionSubmitSucceeds() throws ExecutionException, InterruptedException { + DOMStore domStore = mock(DOMStore.class); + try (ConcurrentDOMDataBroker dataBroker = new ConcurrentDOMDataBroker(ImmutableMap.of( + LogicalDatastoreType.OPERATIONAL, domStore, LogicalDatastoreType.CONFIGURATION, domStore), + futureExecutor)) { + + CheckedFuture submit1 = dataBroker.newWriteOnlyTransaction().submit(); + + assertNotNull(submit1); + + submit1.get(); + + CheckedFuture submit2 = dataBroker.newReadWriteTransaction().submit(); + + assertNotNull(submit2); + + submit2.get(); + } } }