Search in sources :

Example 6 with CanCommitTransactionReply

use of org.opendaylight.controller.cluster.datastore.messages.CanCommitTransactionReply 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 7 with CanCommitTransactionReply

use of org.opendaylight.controller.cluster.datastore.messages.CanCommitTransactionReply in project controller by opendaylight.

the class ThreePhaseCommitCohortProxy method finishCanCommit.

private void finishCanCommit(final SettableFuture<Boolean> returnFuture) {
    LOG.debug("Tx {} finishCanCommit", transactionId);
    // For empty transactions return immediately
    if (cohorts.size() == 0) {
        LOG.debug("Tx {}: canCommit returning result true", transactionId);
        returnFuture.set(Boolean.TRUE);
        return;
    }
    commitOperationCallback = new TransactionRateLimitingCallback(actorContext);
    commitOperationCallback.run();
    final Iterator<CohortInfo> iterator = cohorts.iterator();
    final OnComplete<Object> onComplete = new OnComplete<Object>() {

        @Override
        public void onComplete(final Throwable failure, final Object response) {
            if (failure != null) {
                LOG.debug("Tx {}: a canCommit cohort Future failed", transactionId, failure);
                returnFuture.setException(failure);
                commitOperationCallback.failure();
                return;
            }
            // Only the first call to pause takes effect - subsequent calls before resume are no-ops. So
            // this means we'll only time the first transaction canCommit which should be fine.
            commitOperationCallback.pause();
            boolean result = true;
            if (CanCommitTransactionReply.isSerializedType(response)) {
                CanCommitTransactionReply reply = CanCommitTransactionReply.fromSerializable(response);
                LOG.debug("Tx {}: received {}", transactionId, response);
                if (!reply.getCanCommit()) {
                    result = false;
                }
            } else {
                LOG.error("Unexpected response type {}", response.getClass());
                returnFuture.setException(new IllegalArgumentException(String.format("Unexpected response type %s", response.getClass())));
                return;
            }
            if (iterator.hasNext() && result) {
                sendCanCommitTransaction(iterator.next(), this);
            } else {
                LOG.debug("Tx {}: canCommit returning result: {}", transactionId, result);
                returnFuture.set(Boolean.valueOf(result));
            }
        }
    };
    sendCanCommitTransaction(iterator.next(), onComplete);
}
Also used : OnComplete(akka.dispatch.OnComplete) CanCommitTransactionReply(org.opendaylight.controller.cluster.datastore.messages.CanCommitTransactionReply)

Example 8 with CanCommitTransactionReply

use of org.opendaylight.controller.cluster.datastore.messages.CanCommitTransactionReply in project controller by opendaylight.

the class ShardTest method testReadWriteCommitWithPersistenceDisabled.

@Test
public void testReadWriteCommitWithPersistenceDisabled() throws Exception {
    dataStoreContextBuilder.persistent(false);
    new ShardTestKit(getSystem()) {

        {
            final TestActorRef<Shard> shard = actorFactory.createTestActor(newShardProps().withDispatcher(Dispatchers.DefaultDispatcherId()), "testCommitWithPersistenceDisabled");
            waitUntilLeader(shard);
            // Setup a simulated transactions with a mock cohort.
            final FiniteDuration duration = duration("5 seconds");
            final TransactionIdentifier transactionID = nextTransactionId();
            final NormalizedNode<?, ?> containerNode = ImmutableNodes.containerNode(TestModel.TEST_QNAME);
            shard.tell(prepareBatchedModifications(transactionID, TestModel.TEST_PATH, containerNode, false), getRef());
            expectMsgClass(duration, ReadyTransactionReply.class);
            // Send the CanCommitTransaction message.
            shard.tell(new CanCommitTransaction(transactionID, CURRENT_VERSION).toSerializable(), getRef());
            final CanCommitTransactionReply canCommitReply = CanCommitTransactionReply.fromSerializable(expectMsgClass(duration, CanCommitTransactionReply.class));
            assertEquals("Can commit", true, canCommitReply.getCanCommit());
            // Send the CanCommitTransaction message.
            shard.tell(new CommitTransaction(transactionID, CURRENT_VERSION).toSerializable(), getRef());
            expectMsgClass(duration, CommitTransactionReply.class);
            final NormalizedNode<?, ?> actualNode = readStore(shard, TestModel.TEST_PATH);
            assertEquals(TestModel.TEST_QNAME.getLocalName(), containerNode, actualNode);
        }
    };
}
Also used : CanCommitTransaction(org.opendaylight.controller.cluster.datastore.messages.CanCommitTransaction) CommitTransaction(org.opendaylight.controller.cluster.datastore.messages.CommitTransaction) TransactionIdentifier(org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier) CanCommitTransaction(org.opendaylight.controller.cluster.datastore.messages.CanCommitTransaction) FiniteDuration(scala.concurrent.duration.FiniteDuration) CanCommitTransactionReply(org.opendaylight.controller.cluster.datastore.messages.CanCommitTransactionReply) Test(org.junit.Test)

Example 9 with CanCommitTransactionReply

use of org.opendaylight.controller.cluster.datastore.messages.CanCommitTransactionReply in project controller by opendaylight.

the class ShardTest method testBatchedModificationsOnTransactionChain.

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

        {
            final TestActorRef<Shard> shard = actorFactory.createTestActor(newShardProps().withDispatcher(Dispatchers.DefaultDispatcherId()), "testBatchedModificationsOnTransactionChain");
            waitUntilLeader(shard);
            final LocalHistoryIdentifier historyId = nextHistoryId();
            final TransactionIdentifier transactionID1 = new TransactionIdentifier(historyId, 0);
            final TransactionIdentifier transactionID2 = new TransactionIdentifier(historyId, 1);
            final FiniteDuration duration = duration("5 seconds");
            // Send a BatchedModifications to start a chained write
            // transaction and ready it.
            final ContainerNode containerNode = ImmutableNodes.containerNode(TestModel.TEST_QNAME);
            final YangInstanceIdentifier path = TestModel.TEST_PATH;
            shard.tell(newBatchedModifications(transactionID1, path, containerNode, true, false, 1), getRef());
            expectMsgClass(duration, ReadyTransactionReply.class);
            // Create a read Tx on the same chain.
            shard.tell(new CreateTransaction(transactionID2, TransactionType.READ_ONLY.ordinal(), DataStoreVersions.CURRENT_VERSION).toSerializable(), getRef());
            final CreateTransactionReply createReply = expectMsgClass(duration("3 seconds"), CreateTransactionReply.class);
            getSystem().actorSelection(createReply.getTransactionPath()).tell(new ReadData(path, DataStoreVersions.CURRENT_VERSION), getRef());
            final ReadDataReply readReply = expectMsgClass(duration("3 seconds"), ReadDataReply.class);
            assertEquals("Read node", containerNode, readReply.getNormalizedNode());
            // Commit the write transaction.
            shard.tell(new CanCommitTransaction(transactionID1, CURRENT_VERSION).toSerializable(), getRef());
            final CanCommitTransactionReply canCommitReply = CanCommitTransactionReply.fromSerializable(expectMsgClass(duration, CanCommitTransactionReply.class));
            assertEquals("Can commit", true, canCommitReply.getCanCommit());
            shard.tell(new CommitTransaction(transactionID1, CURRENT_VERSION).toSerializable(), getRef());
            expectMsgClass(duration, CommitTransactionReply.class);
            // Verify data in the data store.
            final NormalizedNode<?, ?> actualNode = readStore(shard, path);
            assertEquals("Stored node", containerNode, actualNode);
        }
    };
}
Also used : CreateTransaction(org.opendaylight.controller.cluster.datastore.messages.CreateTransaction) FiniteDuration(scala.concurrent.duration.FiniteDuration) CreateTransactionReply(org.opendaylight.controller.cluster.datastore.messages.CreateTransactionReply) LocalHistoryIdentifier(org.opendaylight.controller.cluster.access.concepts.LocalHistoryIdentifier) YangInstanceIdentifier(org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier) CanCommitTransactionReply(org.opendaylight.controller.cluster.datastore.messages.CanCommitTransactionReply) CanCommitTransaction(org.opendaylight.controller.cluster.datastore.messages.CanCommitTransaction) CommitTransaction(org.opendaylight.controller.cluster.datastore.messages.CommitTransaction) TransactionIdentifier(org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier) CanCommitTransaction(org.opendaylight.controller.cluster.datastore.messages.CanCommitTransaction) ContainerNode(org.opendaylight.yangtools.yang.data.api.schema.ContainerNode) ReadDataReply(org.opendaylight.controller.cluster.datastore.messages.ReadDataReply) ReadData(org.opendaylight.controller.cluster.datastore.messages.ReadData) Test(org.junit.Test)

Example 10 with CanCommitTransactionReply

use of org.opendaylight.controller.cluster.datastore.messages.CanCommitTransactionReply in project controller by opendaylight.

the class ShardTest method testCommitWhenTransactionHasModifications.

private void testCommitWhenTransactionHasModifications(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()), "testCommitWhenTransactionHasModifications-" + readWrite);
            waitUntilLeader(shard);
            final FiniteDuration duration = duration("5 seconds");
            final TransactionIdentifier transactionID = nextTransactionId();
            if (readWrite) {
                shard.tell(prepareForwardedReadyTransaction(shard, transactionID, TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME), false), getRef());
            } else {
                shard.tell(prepareBatchedModifications(transactionID, TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME), false), getRef());
            }
            expectMsgClass(duration, ReadyTransactionReply.class);
            // Send the CanCommitTransaction message.
            shard.tell(new CanCommitTransaction(transactionID, CURRENT_VERSION).toSerializable(), getRef());
            final CanCommitTransactionReply canCommitReply = CanCommitTransactionReply.fromSerializable(expectMsgClass(duration, CanCommitTransactionReply.class));
            assertEquals("Can commit", true, canCommitReply.getCanCommit());
            shard.tell(new CommitTransaction(transactionID, CURRENT_VERSION).toSerializable(), getRef());
            expectMsgClass(duration, CommitTransactionReply.class);
            final InOrder inOrder = inOrder(dataTree);
            inOrder.verify(dataTree).validate(any(DataTreeModification.class));
            inOrder.verify(dataTree).prepare(any(DataTreeModification.class));
            inOrder.verify(dataTree).commit(any(DataTreeCandidate.class));
            // Purge request is scheduled as asynchronous, wait for two heartbeats to let it propagate into
            // the journal
            Thread.sleep(HEARTBEAT_MILLIS * 2);
            shard.tell(Shard.GET_SHARD_MBEAN_MESSAGE, getRef());
            final ShardStats shardStats = expectMsgClass(duration, ShardStats.class);
            // Use MBean for verification
            // Committed transaction count should increase as usual
            assertEquals(1, shardStats.getCommittedTransactionsCount());
            // Commit index should advance as we do not have an empty
            // modification
            assertEquals(1, shardStats.getCommitIndex());
        }
    };
}
Also used : DataTreeModification(org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification) ShardStats(org.opendaylight.controller.cluster.datastore.jmx.mbeans.shard.ShardStats) InOrder(org.mockito.InOrder) FiniteDuration(scala.concurrent.duration.FiniteDuration) 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)

Aggregations

CanCommitTransactionReply (org.opendaylight.controller.cluster.datastore.messages.CanCommitTransactionReply)11 TransactionIdentifier (org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier)10 CanCommitTransaction (org.opendaylight.controller.cluster.datastore.messages.CanCommitTransaction)10 Test (org.junit.Test)9 FiniteDuration (scala.concurrent.duration.FiniteDuration)9 CommitTransaction (org.opendaylight.controller.cluster.datastore.messages.CommitTransaction)8 DataTreeModification (org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification)5 Timeout (akka.util.Timeout)4 ElectionTimeout (org.opendaylight.controller.cluster.raft.base.messages.ElectionTimeout)4 DataTree (org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree)4 CountDownLatch (java.util.concurrent.CountDownLatch)3 InOrder (org.mockito.InOrder)3 FollowerInitialSyncUpStatus (org.opendaylight.controller.cluster.raft.base.messages.FollowerInitialSyncUpStatus)3 OnComplete (akka.dispatch.OnComplete)2 ContainerNode (org.opendaylight.yangtools.yang.data.api.schema.ContainerNode)2 DataTreeCandidate (org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate)2 DataValidationFailedException (org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException)2 IOException (java.io.IOException)1 AtomicReference (java.util.concurrent.atomic.AtomicReference)1 LocalHistoryIdentifier (org.opendaylight.controller.cluster.access.concepts.LocalHistoryIdentifier)1