Search in sources :

Example 1 with CommitTransactionPayload

use of org.opendaylight.controller.cluster.datastore.persisted.CommitTransactionPayload in project controller by opendaylight.

the class ShardDataTreeTest method testPipelinedTransactionsWithCoordinatedCommits.

@Test
public void testPipelinedTransactionsWithCoordinatedCommits() throws Exception {
    final ShardDataTreeCohort cohort1 = newShardDataTreeCohort(snapshot -> snapshot.write(CarsModel.BASE_PATH, CarsModel.emptyContainer()));
    final ShardDataTreeCohort cohort2 = newShardDataTreeCohort(snapshot -> snapshot.write(CarsModel.CAR_LIST_PATH, CarsModel.newCarMapNode()));
    NormalizedNode<?, ?> peopleNode = PeopleModel.create();
    final ShardDataTreeCohort cohort3 = newShardDataTreeCohort(snapshot -> snapshot.write(PeopleModel.BASE_PATH, peopleNode));
    YangInstanceIdentifier carPath = CarsModel.newCarPath("optima");
    MapEntryNode carNode = CarsModel.newCarEntry("optima", new BigInteger("100"));
    final ShardDataTreeCohort cohort4 = newShardDataTreeCohort(snapshot -> snapshot.write(carPath, carNode));
    immediateCanCommit(cohort1);
    final FutureCallback<Void> canCommitCallback2 = coordinatedCanCommit(cohort2);
    final FutureCallback<Void> canCommitCallback3 = coordinatedCanCommit(cohort3);
    final FutureCallback<Void> canCommitCallback4 = coordinatedCanCommit(cohort4);
    final FutureCallback<DataTreeCandidate> preCommitCallback1 = coordinatedPreCommit(cohort1);
    verify(preCommitCallback1).onSuccess(cohort1.getCandidate());
    verify(canCommitCallback2).onSuccess(null);
    final FutureCallback<DataTreeCandidate> preCommitCallback2 = coordinatedPreCommit(cohort2);
    verify(preCommitCallback2).onSuccess(cohort2.getCandidate());
    verify(canCommitCallback3).onSuccess(null);
    final FutureCallback<DataTreeCandidate> preCommitCallback3 = coordinatedPreCommit(cohort3);
    verify(preCommitCallback3).onSuccess(cohort3.getCandidate());
    verify(canCommitCallback4).onSuccess(null);
    final FutureCallback<DataTreeCandidate> preCommitCallback4 = coordinatedPreCommit(cohort4);
    verify(preCommitCallback4).onSuccess(cohort4.getCandidate());
    final FutureCallback<UnsignedLong> commitCallback2 = coordinatedCommit(cohort2);
    verify(mockShard, never()).persistPayload(eq(cohort1.getIdentifier()), any(CommitTransactionPayload.class), anyBoolean());
    verifyNoMoreInteractions(commitCallback2);
    final FutureCallback<UnsignedLong> commitCallback4 = coordinatedCommit(cohort4);
    verify(mockShard, never()).persistPayload(eq(cohort4.getIdentifier()), any(CommitTransactionPayload.class), anyBoolean());
    verifyNoMoreInteractions(commitCallback4);
    final FutureCallback<UnsignedLong> commitCallback1 = coordinatedCommit(cohort1);
    InOrder inOrder = inOrder(mockShard);
    inOrder.verify(mockShard).persistPayload(eq(cohort1.getIdentifier()), any(CommitTransactionPayload.class), eq(true));
    inOrder.verify(mockShard).persistPayload(eq(cohort2.getIdentifier()), any(CommitTransactionPayload.class), eq(false));
    verifyNoMoreInteractions(commitCallback1);
    verifyNoMoreInteractions(commitCallback2);
    final FutureCallback<UnsignedLong> commitCallback3 = coordinatedCommit(cohort3);
    inOrder = inOrder(mockShard);
    inOrder.verify(mockShard).persistPayload(eq(cohort3.getIdentifier()), any(CommitTransactionPayload.class), eq(true));
    inOrder.verify(mockShard).persistPayload(eq(cohort4.getIdentifier()), any(CommitTransactionPayload.class), eq(false));
    verifyNoMoreInteractions(commitCallback3);
    verifyNoMoreInteractions(commitCallback4);
    final ShardDataTreeCohort cohort5 = newShardDataTreeCohort(snapshot -> snapshot.merge(CarsModel.BASE_PATH, CarsModel.emptyContainer()));
    final FutureCallback<Void> canCommitCallback5 = coordinatedCanCommit(cohort5);
    // The payload instance doesn't matter - it just needs to be of type CommitTransactionPayload.
    CommitTransactionPayload mockPayload = CommitTransactionPayload.create(nextTransactionId(), cohort1.getCandidate());
    shardDataTree.applyReplicatedPayload(cohort1.getIdentifier(), mockPayload);
    shardDataTree.applyReplicatedPayload(cohort2.getIdentifier(), mockPayload);
    shardDataTree.applyReplicatedPayload(cohort3.getIdentifier(), mockPayload);
    shardDataTree.applyReplicatedPayload(cohort4.getIdentifier(), mockPayload);
    inOrder = inOrder(commitCallback1, commitCallback2, commitCallback3, commitCallback4);
    inOrder.verify(commitCallback1).onSuccess(any(UnsignedLong.class));
    inOrder.verify(commitCallback2).onSuccess(any(UnsignedLong.class));
    inOrder.verify(commitCallback3).onSuccess(any(UnsignedLong.class));
    inOrder.verify(commitCallback4).onSuccess(any(UnsignedLong.class));
    verify(canCommitCallback5).onSuccess(null);
    final DataTreeSnapshot snapshot = shardDataTree.newReadOnlyTransaction(nextTransactionId()).getSnapshot();
    Optional<NormalizedNode<?, ?>> optional = snapshot.readNode(carPath);
    assertEquals("Car node present", true, optional.isPresent());
    assertEquals("Car node", carNode, optional.get());
    optional = snapshot.readNode(PeopleModel.BASE_PATH);
    assertEquals("People node present", true, optional.isPresent());
    assertEquals("People node", peopleNode, optional.get());
}
Also used : InOrder(org.mockito.InOrder) UnsignedLong(com.google.common.primitives.UnsignedLong) MapEntryNode(org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode) YangInstanceIdentifier(org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier) DataTreeCandidate(org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate) BigInteger(java.math.BigInteger) CommitTransactionPayload(org.opendaylight.controller.cluster.datastore.persisted.CommitTransactionPayload) DataTreeSnapshot(org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeSnapshot) NormalizedNode(org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode) Test(org.junit.Test)

Example 2 with CommitTransactionPayload

use of org.opendaylight.controller.cluster.datastore.persisted.CommitTransactionPayload in project controller by opendaylight.

the class ShardDataTreeTest method testAbortWithPendingCommits.

@SuppressWarnings("unchecked")
@Test
public void testAbortWithPendingCommits() throws Exception {
    final ShardDataTreeCohort cohort1 = newShardDataTreeCohort(snapshot -> snapshot.write(CarsModel.BASE_PATH, CarsModel.emptyContainer()));
    final ShardDataTreeCohort cohort2 = newShardDataTreeCohort(snapshot -> snapshot.write(PeopleModel.BASE_PATH, PeopleModel.create()));
    final ShardDataTreeCohort cohort3 = newShardDataTreeCohort(snapshot -> snapshot.write(CarsModel.CAR_LIST_PATH, CarsModel.newCarMapNode()));
    YangInstanceIdentifier carPath = CarsModel.newCarPath("optima");
    MapEntryNode carNode = CarsModel.newCarEntry("optima", new BigInteger("100"));
    final ShardDataTreeCohort cohort4 = newShardDataTreeCohort(snapshot -> snapshot.write(carPath, carNode));
    coordinatedCanCommit(cohort2);
    immediateCanCommit(cohort1);
    coordinatedCanCommit(cohort3);
    coordinatedCanCommit(cohort4);
    coordinatedPreCommit(cohort1);
    coordinatedPreCommit(cohort2);
    coordinatedPreCommit(cohort3);
    FutureCallback<Void> mockAbortCallback = mock(FutureCallback.class);
    doNothing().when(mockAbortCallback).onSuccess(null);
    cohort2.abort(mockAbortCallback);
    verify(mockAbortCallback).onSuccess(null);
    coordinatedPreCommit(cohort4);
    coordinatedCommit(cohort1);
    coordinatedCommit(cohort3);
    coordinatedCommit(cohort4);
    InOrder inOrder = inOrder(mockShard);
    inOrder.verify(mockShard).persistPayload(eq(cohort1.getIdentifier()), any(CommitTransactionPayload.class), eq(false));
    inOrder.verify(mockShard).persistPayload(eq(cohort3.getIdentifier()), any(CommitTransactionPayload.class), eq(false));
    inOrder.verify(mockShard).persistPayload(eq(cohort4.getIdentifier()), any(CommitTransactionPayload.class), eq(false));
    // The payload instance doesn't matter - it just needs to be of type CommitTransactionPayload.
    CommitTransactionPayload mockPayload = CommitTransactionPayload.create(nextTransactionId(), cohort1.getCandidate());
    shardDataTree.applyReplicatedPayload(cohort1.getIdentifier(), mockPayload);
    shardDataTree.applyReplicatedPayload(cohort3.getIdentifier(), mockPayload);
    shardDataTree.applyReplicatedPayload(cohort4.getIdentifier(), mockPayload);
    final DataTreeSnapshot snapshot = shardDataTree.newReadOnlyTransaction(nextTransactionId()).getSnapshot();
    Optional<NormalizedNode<?, ?>> optional = snapshot.readNode(carPath);
    assertEquals("Car node present", true, optional.isPresent());
    assertEquals("Car node", carNode, optional.get());
}
Also used : InOrder(org.mockito.InOrder) BigInteger(java.math.BigInteger) CommitTransactionPayload(org.opendaylight.controller.cluster.datastore.persisted.CommitTransactionPayload) DataTreeSnapshot(org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeSnapshot) MapEntryNode(org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode) NormalizedNode(org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode) YangInstanceIdentifier(org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier) Test(org.junit.Test)

Example 3 with CommitTransactionPayload

use of org.opendaylight.controller.cluster.datastore.persisted.CommitTransactionPayload in project controller by opendaylight.

the class ShardDataTreeTest method testPipelinedTransactionsWithImmediateCommits.

@Test
public void testPipelinedTransactionsWithImmediateCommits() throws Exception {
    final ShardDataTreeCohort cohort1 = newShardDataTreeCohort(snapshot -> snapshot.write(CarsModel.BASE_PATH, CarsModel.emptyContainer()));
    final ShardDataTreeCohort cohort2 = newShardDataTreeCohort(snapshot -> snapshot.write(CarsModel.CAR_LIST_PATH, CarsModel.newCarMapNode()));
    YangInstanceIdentifier carPath = CarsModel.newCarPath("optima");
    MapEntryNode carNode = CarsModel.newCarEntry("optima", new BigInteger("100"));
    final ShardDataTreeCohort cohort3 = newShardDataTreeCohort(snapshot -> snapshot.write(carPath, carNode));
    final FutureCallback<UnsignedLong> commitCallback2 = immediate3PhaseCommit(cohort2);
    final FutureCallback<UnsignedLong> commitCallback3 = immediate3PhaseCommit(cohort3);
    final FutureCallback<UnsignedLong> commitCallback1 = immediate3PhaseCommit(cohort1);
    InOrder inOrder = inOrder(mockShard);
    inOrder.verify(mockShard).persistPayload(eq(cohort1.getIdentifier()), any(CommitTransactionPayload.class), eq(true));
    inOrder.verify(mockShard).persistPayload(eq(cohort2.getIdentifier()), any(CommitTransactionPayload.class), eq(true));
    inOrder.verify(mockShard).persistPayload(eq(cohort3.getIdentifier()), any(CommitTransactionPayload.class), eq(false));
    // The payload instance doesn't matter - it just needs to be of type CommitTransactionPayload.
    CommitTransactionPayload mockPayload = CommitTransactionPayload.create(nextTransactionId(), cohort1.getCandidate());
    shardDataTree.applyReplicatedPayload(cohort1.getIdentifier(), mockPayload);
    shardDataTree.applyReplicatedPayload(cohort2.getIdentifier(), mockPayload);
    shardDataTree.applyReplicatedPayload(cohort3.getIdentifier(), mockPayload);
    inOrder = inOrder(commitCallback1, commitCallback2, commitCallback3);
    inOrder.verify(commitCallback1).onSuccess(any(UnsignedLong.class));
    inOrder.verify(commitCallback2).onSuccess(any(UnsignedLong.class));
    inOrder.verify(commitCallback3).onSuccess(any(UnsignedLong.class));
    final DataTreeSnapshot snapshot = shardDataTree.newReadOnlyTransaction(nextTransactionId()).getSnapshot();
    Optional<NormalizedNode<?, ?>> optional = snapshot.readNode(carPath);
    assertEquals("Car node present", true, optional.isPresent());
    assertEquals("Car node", carNode, optional.get());
}
Also used : InOrder(org.mockito.InOrder) UnsignedLong(com.google.common.primitives.UnsignedLong) BigInteger(java.math.BigInteger) CommitTransactionPayload(org.opendaylight.controller.cluster.datastore.persisted.CommitTransactionPayload) DataTreeSnapshot(org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeSnapshot) MapEntryNode(org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode) NormalizedNode(org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode) YangInstanceIdentifier(org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier) Test(org.junit.Test)

Example 4 with CommitTransactionPayload

use of org.opendaylight.controller.cluster.datastore.persisted.CommitTransactionPayload in project controller by opendaylight.

the class ShardDataTree method applyReplicatedPayload.

/**
 * Apply a payload coming from the leader, which could actually be us. This method assumes the leader and follower
 * SchemaContexts match and does not perform any pruning.
 *
 * @param identifier Payload identifier as returned from RaftActor
 * @param payload Payload
 * @throws IOException when the snapshot fails to deserialize
 * @throws DataValidationFailedException when the snapshot fails to apply
 */
void applyReplicatedPayload(final Identifier identifier, final Payload payload) throws IOException, DataValidationFailedException {
    /*
         * This is a bit more involved than it needs to be due to to the fact we do not want to be touching the payload
         * if we are the leader and it has originated with us.
         *
         * The identifier will only ever be non-null when we were the leader which achieved consensus. Unfortunately,
         * though, this may not be the case anymore, as we are being called some time afterwards and we may not be
         * acting in that capacity anymore.
         *
         * In any case, we know that this is an entry coming from replication, hence we can be sure we will not observe
         * pre-Boron state -- which limits the number of options here.
         */
    if (payload instanceof CommitTransactionPayload) {
        final TransactionIdentifier txId;
        if (identifier == null) {
            final Entry<TransactionIdentifier, DataTreeCandidate> e = ((CommitTransactionPayload) payload).getCandidate();
            txId = e.getKey();
            applyReplicatedCandidate(txId, e.getValue());
        } else {
            Verify.verify(identifier instanceof TransactionIdentifier);
            txId = (TransactionIdentifier) identifier;
            payloadReplicationComplete(txId);
        }
        allMetadataCommittedTransaction(txId);
    } else if (payload instanceof AbortTransactionPayload) {
        if (identifier != null) {
            payloadReplicationComplete((AbortTransactionPayload) payload);
        }
        allMetadataAbortedTransaction(((AbortTransactionPayload) payload).getIdentifier());
    } else if (payload instanceof PurgeTransactionPayload) {
        if (identifier != null) {
            payloadReplicationComplete((PurgeTransactionPayload) payload);
        }
        allMetadataPurgedTransaction(((PurgeTransactionPayload) payload).getIdentifier());
    } else if (payload instanceof CloseLocalHistoryPayload) {
        if (identifier != null) {
            payloadReplicationComplete((CloseLocalHistoryPayload) payload);
        }
        allMetadataClosedLocalHistory(((CloseLocalHistoryPayload) payload).getIdentifier());
    } else if (payload instanceof CreateLocalHistoryPayload) {
        if (identifier != null) {
            payloadReplicationComplete((CreateLocalHistoryPayload) payload);
        }
        allMetadataCreatedLocalHistory(((CreateLocalHistoryPayload) payload).getIdentifier());
    } else if (payload instanceof PurgeLocalHistoryPayload) {
        if (identifier != null) {
            payloadReplicationComplete((PurgeLocalHistoryPayload) payload);
        }
        allMetadataPurgedLocalHistory(((PurgeLocalHistoryPayload) payload).getIdentifier());
    } else {
        LOG.warn("{}: ignoring unhandled identifier {} payload {}", logContext, identifier, payload);
    }
}
Also used : DataTreeCandidate(org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate) CreateLocalHistoryPayload(org.opendaylight.controller.cluster.datastore.persisted.CreateLocalHistoryPayload) CloseLocalHistoryPayload(org.opendaylight.controller.cluster.datastore.persisted.CloseLocalHistoryPayload) TransactionIdentifier(org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier) PurgeTransactionPayload(org.opendaylight.controller.cluster.datastore.persisted.PurgeTransactionPayload) CommitTransactionPayload(org.opendaylight.controller.cluster.datastore.persisted.CommitTransactionPayload) PurgeLocalHistoryPayload(org.opendaylight.controller.cluster.datastore.persisted.PurgeLocalHistoryPayload) AbortTransactionPayload(org.opendaylight.controller.cluster.datastore.persisted.AbortTransactionPayload)

Aggregations

CommitTransactionPayload (org.opendaylight.controller.cluster.datastore.persisted.CommitTransactionPayload)4 BigInteger (java.math.BigInteger)3 Test (org.junit.Test)3 InOrder (org.mockito.InOrder)3 YangInstanceIdentifier (org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier)3 MapEntryNode (org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode)3 NormalizedNode (org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode)3 DataTreeSnapshot (org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeSnapshot)3 UnsignedLong (com.google.common.primitives.UnsignedLong)2 DataTreeCandidate (org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate)2 TransactionIdentifier (org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier)1 AbortTransactionPayload (org.opendaylight.controller.cluster.datastore.persisted.AbortTransactionPayload)1 CloseLocalHistoryPayload (org.opendaylight.controller.cluster.datastore.persisted.CloseLocalHistoryPayload)1 CreateLocalHistoryPayload (org.opendaylight.controller.cluster.datastore.persisted.CreateLocalHistoryPayload)1 PurgeLocalHistoryPayload (org.opendaylight.controller.cluster.datastore.persisted.PurgeLocalHistoryPayload)1 PurgeTransactionPayload (org.opendaylight.controller.cluster.datastore.persisted.PurgeTransactionPayload)1