Search in sources :

Example 6 with DataTree

use of org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree in project controller by opendaylight.

the class ShardTest method testDataTreeCandidateRecovery.

@Test
public void testDataTreeCandidateRecovery() throws Exception {
    // Set up the InMemorySnapshotStore.
    final DataTree source = setupInMemorySnapshotStore();
    final DataTreeModification writeMod = source.takeSnapshot().newModification();
    writeMod.write(TestModel.OUTER_LIST_PATH, ImmutableNodes.mapNodeBuilder(TestModel.OUTER_LIST_QNAME).build());
    writeMod.ready();
    InMemoryJournal.addEntry(shardID.toString(), 0, DUMMY_DATA);
    // Set up the InMemoryJournal.
    InMemoryJournal.addEntry(shardID.toString(), 1, new SimpleReplicatedLogEntry(0, 1, payloadForModification(source, writeMod, nextTransactionId())));
    final int nListEntries = 16;
    final Set<Integer> listEntryKeys = new HashSet<>();
    // Add some ModificationPayload entries
    for (int i = 1; i <= nListEntries; i++) {
        listEntryKeys.add(Integer.valueOf(i));
        final YangInstanceIdentifier path = YangInstanceIdentifier.builder(TestModel.OUTER_LIST_PATH).nodeWithKey(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, i).build();
        final DataTreeModification mod = source.takeSnapshot().newModification();
        mod.merge(path, ImmutableNodes.mapEntry(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, i));
        mod.ready();
        InMemoryJournal.addEntry(shardID.toString(), i + 1, new SimpleReplicatedLogEntry(i, 1, payloadForModification(source, mod, nextTransactionId())));
    }
    InMemoryJournal.addEntry(shardID.toString(), nListEntries + 2, new ApplyJournalEntries(nListEntries));
    testRecovery(listEntryKeys);
}
Also used : DataTreeModification(org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification) DataTree(org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree) SimpleReplicatedLogEntry(org.opendaylight.controller.cluster.raft.persisted.SimpleReplicatedLogEntry) ApplyJournalEntries(org.opendaylight.controller.cluster.raft.persisted.ApplyJournalEntries) YangInstanceIdentifier(org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier) HashSet(java.util.HashSet) Test(org.junit.Test)

Example 7 with DataTree

use of org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree in project controller by opendaylight.

the class ShardTest method testCommitPhaseFailure.

@Test
public void testCommitPhaseFailure() throws Exception {
    new ShardTestKit(getSystem()) {

        {
            final DataTree dataTree = createDelegatingMockDataTree();
            final TestActorRef<Shard> shard = actorFactory.createTestActor(newShardBuilder().dataTree(dataTree).props().withDispatcher(Dispatchers.DefaultDispatcherId()), "testCommitPhaseFailure");
            waitUntilLeader(shard);
            final FiniteDuration duration = duration("5 seconds");
            final Timeout timeout = new Timeout(duration);
            // Setup 2 simulated transactions with mock cohorts. The first
            // one fails in the
            // commit phase.
            doThrow(new RuntimeException("mock commit failure")).when(dataTree).commit(any(DataTreeCandidate.class));
            final TransactionIdentifier transactionID1 = nextTransactionId();
            shard.tell(newBatchedModifications(transactionID1, TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME), true, false, 1), getRef());
            expectMsgClass(duration, ReadyTransactionReply.class);
            final TransactionIdentifier transactionID2 = nextTransactionId();
            shard.tell(newBatchedModifications(transactionID2, TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME), true, false, 1), getRef());
            expectMsgClass(duration, ReadyTransactionReply.class);
            // Send the CanCommitTransaction message for the first Tx.
            shard.tell(new CanCommitTransaction(transactionID1, CURRENT_VERSION).toSerializable(), getRef());
            final CanCommitTransactionReply canCommitReply = CanCommitTransactionReply.fromSerializable(expectMsgClass(duration, CanCommitTransactionReply.class));
            assertEquals("Can commit", true, canCommitReply.getCanCommit());
            // Send the CanCommitTransaction message for the 2nd Tx. This
            // should get queued and
            // processed after the first Tx completes.
            final Future<Object> canCommitFuture = Patterns.ask(shard, new CanCommitTransaction(transactionID2, CURRENT_VERSION).toSerializable(), timeout);
            // Send the CommitTransaction message for the first Tx. This
            // should send back an error
            // and trigger the 2nd Tx to proceed.
            shard.tell(new CommitTransaction(transactionID1, CURRENT_VERSION).toSerializable(), getRef());
            expectMsgClass(duration, akka.actor.Status.Failure.class);
            // Wait for the 2nd Tx to complete the canCommit phase.
            final CountDownLatch latch = new CountDownLatch(1);
            canCommitFuture.onComplete(new OnComplete<Object>() {

                @Override
                public void onComplete(final Throwable failure, final Object resp) {
                    latch.countDown();
                }
            }, getSystem().dispatcher());
            assertEquals("2nd CanCommit complete", true, latch.await(5, TimeUnit.SECONDS));
            final InOrder inOrder = inOrder(dataTree);
            inOrder.verify(dataTree).validate(any(DataTreeModification.class));
            inOrder.verify(dataTree).prepare(any(DataTreeModification.class));
            // FIXME: this invocation is done on the result of validate(). To test it, we need to make sure mock
            // validate performs wrapping and we capture that mock
            // inOrder.verify(dataTree).validate(any(DataTreeModification.class));
            inOrder.verify(dataTree).commit(any(DataTreeCandidate.class));
        }
    };
}
Also used : FollowerInitialSyncUpStatus(org.opendaylight.controller.cluster.raft.base.messages.FollowerInitialSyncUpStatus) DataTreeModification(org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification) InOrder(org.mockito.InOrder) Timeout(akka.util.Timeout) ElectionTimeout(org.opendaylight.controller.cluster.raft.base.messages.ElectionTimeout) FiniteDuration(scala.concurrent.duration.FiniteDuration) CountDownLatch(java.util.concurrent.CountDownLatch) CanCommitTransactionReply(org.opendaylight.controller.cluster.datastore.messages.CanCommitTransactionReply) DataTreeCandidate(org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate) CanCommitTransaction(org.opendaylight.controller.cluster.datastore.messages.CanCommitTransaction) CommitTransaction(org.opendaylight.controller.cluster.datastore.messages.CommitTransaction) DataTree(org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree) TransactionIdentifier(org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier) CanCommitTransaction(org.opendaylight.controller.cluster.datastore.messages.CanCommitTransaction) Test(org.junit.Test)

Example 8 with DataTree

use of org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree in project controller by opendaylight.

the class ShardTest method testImmediateCommitWithCanCommitPhaseFailure.

private void testImmediateCommitWithCanCommitPhaseFailure(final boolean readWrite) throws Exception {
    new ShardTestKit(getSystem()) {

        {
            final DataTree dataTree = createDelegatingMockDataTree();
            final TestActorRef<Shard> shard = actorFactory.createTestActor(newShardBuilder().dataTree(dataTree).props().withDispatcher(Dispatchers.DefaultDispatcherId()), "testImmediateCommitWithCanCommitPhaseFailure-" + readWrite);
            waitUntilLeader(shard);
            doThrow(new DataValidationFailedException(YangInstanceIdentifier.EMPTY, "mock canCommit failure")).doNothing().when(dataTree).validate(any(DataTreeModification.class));
            final FiniteDuration duration = duration("5 seconds");
            final TransactionIdentifier transactionID1 = nextTransactionId();
            if (readWrite) {
                shard.tell(prepareForwardedReadyTransaction(shard, transactionID1, TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME), true), getRef());
            } else {
                shard.tell(prepareBatchedModifications(transactionID1, TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME), true), getRef());
            }
            expectMsgClass(duration, akka.actor.Status.Failure.class);
            // Send another can commit to ensure the failed one got cleaned
            // up.
            final TransactionIdentifier transactionID2 = nextTransactionId();
            if (readWrite) {
                shard.tell(prepareForwardedReadyTransaction(shard, transactionID2, TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME), true), getRef());
            } else {
                shard.tell(prepareBatchedModifications(transactionID2, TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME), true), getRef());
            }
            expectMsgClass(duration, CommitTransactionReply.class);
        }
    };
}
Also used : DataTreeModification(org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification) FollowerInitialSyncUpStatus(org.opendaylight.controller.cluster.raft.base.messages.FollowerInitialSyncUpStatus) DataValidationFailedException(org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException) DataTree(org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree) TransactionIdentifier(org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier) FiniteDuration(scala.concurrent.duration.FiniteDuration)

Example 9 with DataTree

use of org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree in project controller by opendaylight.

the class ShardTest method testPreCommitPhaseFailure.

@Test
public void testPreCommitPhaseFailure() throws Exception {
    new ShardTestKit(getSystem()) {

        {
            final DataTree dataTree = createDelegatingMockDataTree();
            final TestActorRef<Shard> shard = actorFactory.createTestActor(newShardBuilder().dataTree(dataTree).props().withDispatcher(Dispatchers.DefaultDispatcherId()), "testPreCommitPhaseFailure");
            waitUntilLeader(shard);
            final FiniteDuration duration = duration("5 seconds");
            final Timeout timeout = new Timeout(duration);
            doThrow(new RuntimeException("mock preCommit failure")).when(dataTree).prepare(any(DataTreeModification.class));
            final TransactionIdentifier transactionID1 = nextTransactionId();
            shard.tell(newBatchedModifications(transactionID1, TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME), true, false, 1), getRef());
            expectMsgClass(duration, ReadyTransactionReply.class);
            final TransactionIdentifier transactionID2 = nextTransactionId();
            shard.tell(newBatchedModifications(transactionID2, TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME), true, false, 1), getRef());
            expectMsgClass(duration, ReadyTransactionReply.class);
            // Send the CanCommitTransaction message for the first Tx.
            shard.tell(new CanCommitTransaction(transactionID1, CURRENT_VERSION).toSerializable(), getRef());
            final CanCommitTransactionReply canCommitReply = CanCommitTransactionReply.fromSerializable(expectMsgClass(duration, CanCommitTransactionReply.class));
            assertEquals("Can commit", true, canCommitReply.getCanCommit());
            // Send the CanCommitTransaction message for the 2nd Tx. This
            // should get queued and
            // processed after the first Tx completes.
            final Future<Object> canCommitFuture = Patterns.ask(shard, new CanCommitTransaction(transactionID2, CURRENT_VERSION).toSerializable(), timeout);
            // Send the CommitTransaction message for the first Tx. This
            // should send back an error
            // and trigger the 2nd Tx to proceed.
            shard.tell(new CommitTransaction(transactionID1, CURRENT_VERSION).toSerializable(), getRef());
            expectMsgClass(duration, akka.actor.Status.Failure.class);
            // Wait for the 2nd Tx to complete the canCommit phase.
            final CountDownLatch latch = new CountDownLatch(1);
            canCommitFuture.onComplete(new OnComplete<Object>() {

                @Override
                public void onComplete(final Throwable failure, final Object resp) {
                    latch.countDown();
                }
            }, getSystem().dispatcher());
            assertEquals("2nd CanCommit complete", true, latch.await(5, TimeUnit.SECONDS));
            final InOrder inOrder = inOrder(dataTree);
            inOrder.verify(dataTree).validate(any(DataTreeModification.class));
            inOrder.verify(dataTree).prepare(any(DataTreeModification.class));
            inOrder.verify(dataTree).validate(any(DataTreeModification.class));
        }
    };
}
Also used : DataTreeModification(org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification) FollowerInitialSyncUpStatus(org.opendaylight.controller.cluster.raft.base.messages.FollowerInitialSyncUpStatus) InOrder(org.mockito.InOrder) Timeout(akka.util.Timeout) ElectionTimeout(org.opendaylight.controller.cluster.raft.base.messages.ElectionTimeout) FiniteDuration(scala.concurrent.duration.FiniteDuration) CountDownLatch(java.util.concurrent.CountDownLatch) CanCommitTransactionReply(org.opendaylight.controller.cluster.datastore.messages.CanCommitTransactionReply) CanCommitTransaction(org.opendaylight.controller.cluster.datastore.messages.CanCommitTransaction) CommitTransaction(org.opendaylight.controller.cluster.datastore.messages.CommitTransaction) DataTree(org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree) TransactionIdentifier(org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier) CanCommitTransaction(org.opendaylight.controller.cluster.datastore.messages.CanCommitTransaction) Test(org.junit.Test)

Example 10 with DataTree

use of org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree in project controller by opendaylight.

the class DistributedDataStoreRemotingIntegrationTest method testForwardedReadyTransactionForwardedToLeader.

@SuppressWarnings("unchecked")
@Test
public void testForwardedReadyTransactionForwardedToLeader() throws Exception {
    initDatastoresWithCars("testForwardedReadyTransactionForwardedToLeader");
    followerTestKit.waitUntilLeader(followerDistributedDataStore.getActorContext(), "cars");
    final Optional<ActorRef> carsFollowerShard = followerDistributedDataStore.getActorContext().findLocalShard("cars");
    assertEquals("Cars follower shard found", true, carsFollowerShard.isPresent());
    carsFollowerShard.get().tell(GetShardDataTree.INSTANCE, followerTestKit.getRef());
    final DataTree dataTree = followerTestKit.expectMsgClass(DataTree.class);
    // Send a tx with immediate commit.
    DataTreeModification modification = dataTree.takeSnapshot().newModification();
    new WriteModification(CarsModel.BASE_PATH, CarsModel.emptyContainer()).apply(modification);
    new MergeModification(CarsModel.CAR_LIST_PATH, CarsModel.newCarMapNode()).apply(modification);
    final MapEntryNode car1 = CarsModel.newCarEntry("optima", BigInteger.valueOf(20000));
    new WriteModification(CarsModel.newCarPath("optima"), car1).apply(modification);
    ForwardedReadyTransaction forwardedReady = new ForwardedReadyTransaction(tx1, DataStoreVersions.CURRENT_VERSION, new ReadWriteShardDataTreeTransaction(Mockito.mock(ShardDataTreeTransactionParent.class), tx1, modification), true);
    carsFollowerShard.get().tell(forwardedReady, followerTestKit.getRef());
    Object resp = followerTestKit.expectMsgClass(Object.class);
    if (resp instanceof akka.actor.Status.Failure) {
        throw new AssertionError("Unexpected failure response", ((akka.actor.Status.Failure) resp).cause());
    }
    assertEquals("Response type", CommitTransactionReply.class, resp.getClass());
    verifyCars(leaderDistributedDataStore.newReadOnlyTransaction(), car1);
    // Send another tx without immediate commit.
    modification = dataTree.takeSnapshot().newModification();
    MapEntryNode car2 = CarsModel.newCarEntry("sportage", BigInteger.valueOf(30000));
    new WriteModification(CarsModel.newCarPath("sportage"), car2).apply(modification);
    forwardedReady = new ForwardedReadyTransaction(tx2, DataStoreVersions.CURRENT_VERSION, new ReadWriteShardDataTreeTransaction(Mockito.mock(ShardDataTreeTransactionParent.class), tx2, modification), false);
    carsFollowerShard.get().tell(forwardedReady, followerTestKit.getRef());
    resp = followerTestKit.expectMsgClass(Object.class);
    if (resp instanceof akka.actor.Status.Failure) {
        throw new AssertionError("Unexpected failure response", ((akka.actor.Status.Failure) resp).cause());
    }
    assertEquals("Response type", ReadyTransactionReply.class, resp.getClass());
    ActorSelection txActor = leaderDistributedDataStore.getActorContext().actorSelection(((ReadyTransactionReply) resp).getCohortPath());
    final Supplier<Short> versionSupplier = Mockito.mock(Supplier.class);
    Mockito.doReturn(DataStoreVersions.CURRENT_VERSION).when(versionSupplier).get();
    final ThreePhaseCommitCohortProxy cohort = new ThreePhaseCommitCohortProxy(leaderDistributedDataStore.getActorContext(), Arrays.asList(new ThreePhaseCommitCohortProxy.CohortInfo(Futures.successful(txActor), versionSupplier)), tx2);
    cohort.canCommit().get(5, TimeUnit.SECONDS);
    cohort.preCommit().get(5, TimeUnit.SECONDS);
    cohort.commit().get(5, TimeUnit.SECONDS);
    verifyCars(leaderDistributedDataStore.newReadOnlyTransaction(), car1, car2);
}
Also used : DataTreeModification(org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification) WriteModification(org.opendaylight.controller.cluster.datastore.modification.WriteModification) ActorRef(akka.actor.ActorRef) MapEntryNode(org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode) MergeModification(org.opendaylight.controller.cluster.datastore.modification.MergeModification) ActorSelection(akka.actor.ActorSelection) GetShardDataTree(org.opendaylight.controller.cluster.datastore.messages.GetShardDataTree) DataTree(org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree) ForwardedReadyTransaction(org.opendaylight.controller.cluster.datastore.messages.ForwardedReadyTransaction) Test(org.junit.Test)

Aggregations

DataTree (org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree)33 Test (org.junit.Test)21 DataTreeModification (org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification)19 InMemoryDataTreeFactory (org.opendaylight.yangtools.yang.data.impl.schema.tree.InMemoryDataTreeFactory)14 ActorRef (akka.actor.ActorRef)7 TransactionIdentifier (org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier)7 MetadataShardDataTreeSnapshot (org.opendaylight.controller.cluster.datastore.persisted.MetadataShardDataTreeSnapshot)7 ShardSnapshotState (org.opendaylight.controller.cluster.datastore.persisted.ShardSnapshotState)6 AddressFromURIString (akka.actor.AddressFromURIString)5 DataTreeSnapshot (org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeSnapshot)5 FiniteDuration (scala.concurrent.duration.FiniteDuration)5 TestActorRef (akka.testkit.TestActorRef)4 CanCommitTransaction (org.opendaylight.controller.cluster.datastore.messages.CanCommitTransaction)4 CanCommitTransactionReply (org.opendaylight.controller.cluster.datastore.messages.CanCommitTransactionReply)4 GetShardDataTree (org.opendaylight.controller.cluster.datastore.messages.GetShardDataTree)4 LocalPrimaryShardFound (org.opendaylight.controller.cluster.datastore.messages.LocalPrimaryShardFound)4 ContainerNode (org.opendaylight.yangtools.yang.data.api.schema.ContainerNode)4 TestKit (akka.testkit.javadsl.TestKit)3 Timeout (akka.util.Timeout)3 InOrder (org.mockito.InOrder)3