use of org.opendaylight.controller.cluster.datastore.messages.CanCommitTransactionReply in project controller by opendaylight.
the class ShardTest method testReadyLocalTransactionWithThreePhaseCommit.
@Test
public void testReadyLocalTransactionWithThreePhaseCommit() throws Exception {
new ShardTestKit(getSystem()) {
{
final TestActorRef<Shard> shard = actorFactory.createTestActor(newShardProps().withDispatcher(Dispatchers.DefaultDispatcherId()), "testReadyLocalTransactionWithThreePhaseCommit");
waitUntilLeader(shard);
final ShardDataTree dataStore = shard.underlyingActor().getDataStore();
final DataTreeModification modification = dataStore.newModification();
final ContainerNode writeData = ImmutableNodes.containerNode(TestModel.TEST_QNAME);
new WriteModification(TestModel.TEST_PATH, writeData).apply(modification);
final MapNode mergeData = ImmutableNodes.mapNodeBuilder(TestModel.OUTER_LIST_QNAME).build();
new MergeModification(TestModel.OUTER_LIST_PATH, mergeData).apply(modification);
final TransactionIdentifier txId = nextTransactionId();
modification.ready();
final ReadyLocalTransaction readyMessage = new ReadyLocalTransaction(txId, modification, false);
shard.tell(readyMessage, getRef());
expectMsgClass(ReadyTransactionReply.class);
// Send the CanCommitTransaction message.
shard.tell(new CanCommitTransaction(txId, CURRENT_VERSION).toSerializable(), getRef());
final CanCommitTransactionReply canCommitReply = CanCommitTransactionReply.fromSerializable(expectMsgClass(CanCommitTransactionReply.class));
assertEquals("Can commit", true, canCommitReply.getCanCommit());
// Send the CanCommitTransaction message.
shard.tell(new CommitTransaction(txId, CURRENT_VERSION).toSerializable(), getRef());
expectMsgClass(CommitTransactionReply.class);
final NormalizedNode<?, ?> actualNode = readStore(shard, TestModel.OUTER_LIST_PATH);
assertEquals(TestModel.OUTER_LIST_QNAME.getLocalName(), mergeData, actualNode);
}
};
}
use of org.opendaylight.controller.cluster.datastore.messages.CanCommitTransactionReply in project controller by opendaylight.
the class ShardTest method testBatchedModificationsWithNoCommitOnReady.
@Test
public void testBatchedModificationsWithNoCommitOnReady() throws Exception {
new ShardTestKit(getSystem()) {
{
final TestActorRef<Shard> shard = actorFactory.createTestActor(newShardProps().withDispatcher(Dispatchers.DefaultDispatcherId()), "testBatchedModificationsWithNoCommitOnReady");
waitUntilLeader(shard);
final TransactionIdentifier transactionID = nextTransactionId();
final FiniteDuration duration = duration("5 seconds");
// Send a BatchedModifications to start a transaction.
shard.tell(newBatchedModifications(transactionID, TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME), false, false, 1), getRef());
expectMsgClass(duration, BatchedModificationsReply.class);
// Send a couple more BatchedModifications.
shard.tell(newBatchedModifications(transactionID, TestModel.OUTER_LIST_PATH, ImmutableNodes.mapNodeBuilder(TestModel.OUTER_LIST_QNAME).build(), false, false, 2), getRef());
expectMsgClass(duration, BatchedModificationsReply.class);
shard.tell(newBatchedModifications(transactionID, YangInstanceIdentifier.builder(TestModel.OUTER_LIST_PATH).nodeWithKey(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, 1).build(), ImmutableNodes.mapEntry(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, 1), true, false, 3), 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 CommitTransaction message.
shard.tell(new CommitTransaction(transactionID, CURRENT_VERSION).toSerializable(), getRef());
expectMsgClass(duration, CommitTransactionReply.class);
// Verify data in the data store.
verifyOuterListEntry(shard, 1);
}
};
}
use of org.opendaylight.controller.cluster.datastore.messages.CanCommitTransactionReply in project controller by opendaylight.
the class ShardTest method testConcurrentThreePhaseCommits.
@Test
@SuppressWarnings("checkstyle:IllegalCatch")
public void testConcurrentThreePhaseCommits() throws Exception {
final AtomicReference<Throwable> caughtEx = new AtomicReference<>();
final CountDownLatch commitLatch = new CountDownLatch(2);
final long timeoutSec = 5;
final FiniteDuration duration = FiniteDuration.create(timeoutSec, TimeUnit.SECONDS);
final Timeout timeout = new Timeout(duration);
final TestActorRef<Shard> shard = actorFactory.createTestActor(newShardProps().withDispatcher(Dispatchers.DefaultDispatcherId()), "testConcurrentThreePhaseCommits");
class OnFutureComplete extends OnComplete<Object> {
private final Class<?> expRespType;
OnFutureComplete(final Class<?> expRespType) {
this.expRespType = expRespType;
}
@Override
public void onComplete(final Throwable error, final Object resp) {
if (error != null) {
caughtEx.set(new AssertionError(getClass().getSimpleName() + " failure", error));
} else {
try {
assertEquals("Commit response type", expRespType, resp.getClass());
onSuccess(resp);
} catch (final Exception e) {
caughtEx.set(e);
}
}
}
void onSuccess(final Object resp) throws Exception {
}
}
class OnCommitFutureComplete extends OnFutureComplete {
OnCommitFutureComplete() {
super(CommitTransactionReply.class);
}
@Override
public void onComplete(final Throwable error, final Object resp) {
super.onComplete(error, resp);
commitLatch.countDown();
}
}
class OnCanCommitFutureComplete extends OnFutureComplete {
private final TransactionIdentifier transactionID;
OnCanCommitFutureComplete(final TransactionIdentifier transactionID) {
super(CanCommitTransactionReply.class);
this.transactionID = transactionID;
}
@Override
void onSuccess(final Object resp) throws Exception {
final CanCommitTransactionReply canCommitReply = CanCommitTransactionReply.fromSerializable(resp);
assertEquals("Can commit", true, canCommitReply.getCanCommit());
final Future<Object> commitFuture = Patterns.ask(shard, new CommitTransaction(transactionID, CURRENT_VERSION).toSerializable(), timeout);
commitFuture.onComplete(new OnCommitFutureComplete(), getSystem().dispatcher());
}
}
new ShardTestKit(getSystem()) {
{
waitUntilLeader(shard);
final TransactionIdentifier transactionID1 = nextTransactionId();
final TransactionIdentifier transactionID2 = nextTransactionId();
final TransactionIdentifier transactionID3 = nextTransactionId();
final Map<TransactionIdentifier, CapturingShardDataTreeCohort> cohortMap = setupCohortDecorator(shard.underlyingActor(), transactionID1, transactionID2, transactionID3);
final CapturingShardDataTreeCohort cohort1 = cohortMap.get(transactionID1);
final CapturingShardDataTreeCohort cohort2 = cohortMap.get(transactionID2);
final CapturingShardDataTreeCohort cohort3 = cohortMap.get(transactionID3);
shard.tell(prepareBatchedModifications(transactionID1, TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME), false), getRef());
final ReadyTransactionReply readyReply = ReadyTransactionReply.fromSerializable(expectMsgClass(duration, ReadyTransactionReply.class));
assertEquals("Cohort path", shard.path().toString(), readyReply.getCohortPath());
// 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());
// Ready 2 more Tx's.
shard.tell(prepareBatchedModifications(transactionID2, TestModel.OUTER_LIST_PATH, ImmutableNodes.mapNodeBuilder(TestModel.OUTER_LIST_QNAME).build(), false), getRef());
expectMsgClass(duration, ReadyTransactionReply.class);
shard.tell(prepareBatchedModifications(transactionID3, YangInstanceIdentifier.builder(TestModel.OUTER_LIST_PATH).nodeWithKey(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, 1).build(), ImmutableNodes.mapEntry(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, 1), false), getRef());
expectMsgClass(duration, ReadyTransactionReply.class);
// Send the CanCommitTransaction message for the next 2 Tx's.
// These should get queued and
// processed after the first Tx completes.
final Future<Object> canCommitFuture1 = Patterns.ask(shard, new CanCommitTransaction(transactionID2, CURRENT_VERSION).toSerializable(), timeout);
final Future<Object> canCommitFuture2 = Patterns.ask(shard, new CanCommitTransaction(transactionID3, CURRENT_VERSION).toSerializable(), timeout);
// Send the CommitTransaction message for the first Tx. After it
// completes, it should
// trigger the 2nd Tx to proceed which should in turn then
// trigger the 3rd.
shard.tell(new CommitTransaction(transactionID1, CURRENT_VERSION).toSerializable(), getRef());
expectMsgClass(duration, CommitTransactionReply.class);
// Wait for the next 2 Tx's to complete.
canCommitFuture1.onComplete(new OnCanCommitFutureComplete(transactionID2), getSystem().dispatcher());
canCommitFuture2.onComplete(new OnCanCommitFutureComplete(transactionID3), getSystem().dispatcher());
final boolean done = commitLatch.await(timeoutSec, TimeUnit.SECONDS);
final Throwable t = caughtEx.get();
if (t != null) {
Throwables.propagateIfPossible(t, Exception.class);
throw new RuntimeException(t);
}
assertEquals("Commits complete", true, done);
// final InOrder inOrder = inOrder(cohort1.getCanCommit(), cohort1.getPreCommit(), cohort1.getCommit(),
// cohort2.getCanCommit(), cohort2.getPreCommit(), cohort2.getCommit(), cohort3.getCanCommit(),
// cohort3.getPreCommit(), cohort3.getCommit());
// inOrder.verify(cohort1.getCanCommit()).onSuccess(any(Void.class));
// inOrder.verify(cohort1.getPreCommit()).onSuccess(any(DataTreeCandidate.class));
// inOrder.verify(cohort2.getCanCommit()).onSuccess(any(Void.class));
// inOrder.verify(cohort2.getPreCommit()).onSuccess(any(DataTreeCandidate.class));
// inOrder.verify(cohort3.getCanCommit()).onSuccess(any(Void.class));
// inOrder.verify(cohort3.getPreCommit()).onSuccess(any(DataTreeCandidate.class));
// inOrder.verify(cohort1.getCommit()).onSuccess(any(UnsignedLong.class));
// inOrder.verify(cohort2.getCommit()).onSuccess(any(UnsignedLong.class));
// inOrder.verify(cohort3.getCommit()).onSuccess(any(UnsignedLong.class));
// Verify data in the data store.
verifyOuterListEntry(shard, 1);
verifyLastApplied(shard, 5);
}
};
}
use of org.opendaylight.controller.cluster.datastore.messages.CanCommitTransactionReply in project controller by opendaylight.
the class ShardTest method testAbortAfterCanCommit.
@Test
public void testAbortAfterCanCommit() throws Exception {
new ShardTestKit(getSystem()) {
{
final TestActorRef<Shard> shard = actorFactory.createTestActor(newShardProps().withDispatcher(Dispatchers.DefaultDispatcherId()), "testAbortAfterCanCommit");
waitUntilLeader(shard);
final FiniteDuration duration = duration("5 seconds");
final Timeout timeout = new Timeout(duration);
// Ready 2 transactions - the first one will be aborted.
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());
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 AbortTransaction message for the first Tx. This
// should trigger the 2nd
// Tx to proceed.
shard.tell(new AbortTransaction(transactionID1, CURRENT_VERSION).toSerializable(), getRef());
expectMsgClass(duration, AbortTransactionReply.class);
// Wait for the 2nd Tx to complete the canCommit phase.
canCommitReply = (CanCommitTransactionReply) Await.result(canCommitFuture, duration);
assertEquals("Can commit", true, canCommitReply.getCanCommit());
}
};
}
use of org.opendaylight.controller.cluster.datastore.messages.CanCommitTransactionReply 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));
}
};
}
Aggregations