use of org.opendaylight.mdsal.dom.spi.store.DOMStoreThreePhaseCommitCohort in project controller by opendaylight.
the class DistributedDataStoreRemotingIntegrationTest method testTransactionChainWithMultipleShards.
@Test
public void testTransactionChainWithMultipleShards() throws Exception {
initDatastoresWithCarsAndPeople("testTransactionChainWithMultipleShards");
final DOMStoreTransactionChain txChain = followerDistributedDataStore.createTransactionChain();
DOMStoreWriteTransaction writeTx = txChain.newWriteOnlyTransaction();
assertNotNull("newWriteOnlyTransaction returned null", writeTx);
writeTx.write(CarsModel.BASE_PATH, CarsModel.emptyContainer());
writeTx.write(PeopleModel.BASE_PATH, PeopleModel.emptyContainer());
writeTx.write(CarsModel.CAR_LIST_PATH, CarsModel.newCarMapNode());
writeTx.write(PeopleModel.PERSON_LIST_PATH, PeopleModel.newPersonMapNode());
followerTestKit.doCommit(writeTx.ready());
final DOMStoreReadWriteTransaction readWriteTx = txChain.newReadWriteTransaction();
final MapEntryNode car = CarsModel.newCarEntry("optima", BigInteger.valueOf(20000));
final YangInstanceIdentifier carPath = CarsModel.newCarPath("optima");
readWriteTx.write(carPath, car);
final MapEntryNode person = PeopleModel.newPersonEntry("jack");
final YangInstanceIdentifier personPath = PeopleModel.newPersonPath("jack");
readWriteTx.merge(personPath, person);
Optional<NormalizedNode<?, ?>> optional = readWriteTx.read(carPath).get(5, TimeUnit.SECONDS);
assertEquals("isPresent", true, optional.isPresent());
assertEquals("Data node", car, optional.get());
optional = readWriteTx.read(personPath).get(5, TimeUnit.SECONDS);
assertEquals("isPresent", true, optional.isPresent());
assertEquals("Data node", person, optional.get());
final DOMStoreThreePhaseCommitCohort cohort2 = readWriteTx.ready();
writeTx = txChain.newWriteOnlyTransaction();
writeTx.delete(personPath);
final DOMStoreThreePhaseCommitCohort cohort3 = writeTx.ready();
followerTestKit.doCommit(cohort2);
followerTestKit.doCommit(cohort3);
txChain.close();
final DOMStoreReadTransaction readTx = followerDistributedDataStore.newReadOnlyTransaction();
verifyCars(readTx, car);
optional = readTx.read(personPath).get(5, TimeUnit.SECONDS);
assertEquals("isPresent", false, optional.isPresent());
}
use of org.opendaylight.mdsal.dom.spi.store.DOMStoreThreePhaseCommitCohort in project controller by opendaylight.
the class DistributedDataStoreRemotingIntegrationTest method testTransactionWithIsolatedLeader.
@Test
public void testTransactionWithIsolatedLeader() throws Exception {
// TODO remove when test passes also for ClientBackedDataStore
Assume.assumeTrue(testParameter.equals(DistributedDataStore.class));
// Set the isolated leader check interval high so we can control the switch to IsolatedLeader.
leaderDatastoreContextBuilder.shardIsolatedLeaderCheckIntervalInMillis(10000000);
final String testName = "testTransactionWithIsolatedLeader";
initDatastoresWithCars(testName);
// Tx that is submitted after the follower is stopped but before the leader transitions to IsolatedLeader.
final DOMStoreWriteTransaction preIsolatedLeaderWriteTx = leaderDistributedDataStore.newWriteOnlyTransaction();
preIsolatedLeaderWriteTx.write(CarsModel.BASE_PATH, CarsModel.emptyContainer());
// Tx that is submitted after the leader transitions to IsolatedLeader.
final DOMStoreWriteTransaction noShardLeaderWriteTx = leaderDistributedDataStore.newWriteOnlyTransaction();
noShardLeaderWriteTx.write(CarsModel.BASE_PATH, CarsModel.emptyContainer());
// Tx that is submitted after the follower is reinstated.
final DOMStoreWriteTransaction successWriteTx = leaderDistributedDataStore.newWriteOnlyTransaction();
successWriteTx.merge(CarsModel.BASE_PATH, CarsModel.emptyContainer());
// Stop the follower
followerTestKit.watch(followerDistributedDataStore.getActorContext().getShardManager());
followerDistributedDataStore.close();
followerTestKit.expectTerminated(followerDistributedDataStore.getActorContext().getShardManager());
// Submit the preIsolatedLeaderWriteTx so it's pending
final DOMStoreThreePhaseCommitCohort preIsolatedLeaderTxCohort = preIsolatedLeaderWriteTx.ready();
// Change the isolated leader check interval low so it changes to IsolatedLeader.
sendDatastoreContextUpdate(leaderDistributedDataStore, leaderDatastoreContextBuilder.shardIsolatedLeaderCheckIntervalInMillis(200));
MemberNode.verifyRaftState(leaderDistributedDataStore, "cars", raftState -> assertEquals("getRaftState", "IsolatedLeader", raftState.getRaftState()));
try {
leaderTestKit.doCommit(noShardLeaderWriteTx.ready());
fail("Expected NoShardLeaderException");
} catch (final ExecutionException e) {
assertEquals("getCause", NoShardLeaderException.class, Throwables.getRootCause(e).getClass());
}
sendDatastoreContextUpdate(leaderDistributedDataStore, leaderDatastoreContextBuilder.shardElectionTimeoutFactor(100));
final DOMStoreThreePhaseCommitCohort successTxCohort = successWriteTx.ready();
followerDistributedDataStore = followerTestKit.setupAbstractDataStore(testParameter, testName, MODULE_SHARDS_CARS_ONLY_1_2, false, CARS);
leaderTestKit.doCommit(preIsolatedLeaderTxCohort);
leaderTestKit.doCommit(successTxCohort);
}
use of org.opendaylight.mdsal.dom.spi.store.DOMStoreThreePhaseCommitCohort in project controller by opendaylight.
the class DistributedDataStoreRemotingIntegrationTest method testTransactionChainWithSingleShard.
@Test
public void testTransactionChainWithSingleShard() throws Exception {
initDatastoresWithCars("testTransactionChainWithSingleShard");
final DOMStoreTransactionChain txChain = followerDistributedDataStore.createTransactionChain();
// Add the top-level cars container with write-only.
final DOMStoreWriteTransaction writeTx = txChain.newWriteOnlyTransaction();
assertNotNull("newWriteOnlyTransaction returned null", writeTx);
writeTx.write(CarsModel.BASE_PATH, CarsModel.emptyContainer());
final DOMStoreThreePhaseCommitCohort writeTxReady = writeTx.ready();
// Verify the top-level cars container with read-only.
verifyNode(txChain.newReadOnlyTransaction(), CarsModel.BASE_PATH, CarsModel.emptyContainer());
// Perform car operations with read-write.
final DOMStoreReadWriteTransaction rwTx = txChain.newReadWriteTransaction();
verifyNode(rwTx, CarsModel.BASE_PATH, CarsModel.emptyContainer());
rwTx.merge(CarsModel.CAR_LIST_PATH, CarsModel.newCarMapNode());
final MapEntryNode car1 = CarsModel.newCarEntry("optima", BigInteger.valueOf(20000));
final YangInstanceIdentifier car1Path = CarsModel.newCarPath("optima");
rwTx.write(car1Path, car1);
verifyExists(rwTx, car1Path);
verifyCars(rwTx, car1);
final MapEntryNode car2 = CarsModel.newCarEntry("sportage", BigInteger.valueOf(25000));
rwTx.merge(CarsModel.newCarPath("sportage"), car2);
rwTx.delete(car1Path);
followerTestKit.doCommit(writeTxReady);
followerTestKit.doCommit(rwTx.ready());
txChain.close();
verifyCars(followerDistributedDataStore.newReadOnlyTransaction(), car2);
}
use of org.opendaylight.mdsal.dom.spi.store.DOMStoreThreePhaseCommitCohort in project controller by opendaylight.
the class DistributedDataStoreRemotingIntegrationTest method testTransactionForwardedToLeaderAfterRetry.
@Test
public void testTransactionForwardedToLeaderAfterRetry() throws Exception {
// TODO remove when test passes also for ClientBackedDataStore
Assume.assumeTrue(testParameter.equals(DistributedDataStore.class));
followerDatastoreContextBuilder.shardBatchedModificationCount(2);
leaderDatastoreContextBuilder.shardBatchedModificationCount(2);
initDatastoresWithCarsAndPeople("testTransactionForwardedToLeaderAfterRetry");
// Do an initial write to get the primary shard info cached.
final DOMStoreWriteTransaction initialWriteTx = followerDistributedDataStore.newWriteOnlyTransaction();
initialWriteTx.write(CarsModel.BASE_PATH, CarsModel.emptyContainer());
initialWriteTx.write(PeopleModel.BASE_PATH, PeopleModel.emptyContainer());
followerTestKit.doCommit(initialWriteTx.ready());
// Wait for the commit to be replicated to the follower.
MemberNode.verifyRaftState(followerDistributedDataStore, "cars", raftState -> assertEquals("getLastApplied", 1, raftState.getLastApplied()));
MemberNode.verifyRaftState(followerDistributedDataStore, "people", raftState -> assertEquals("getLastApplied", 1, raftState.getLastApplied()));
// Prepare, ready and canCommit a WO tx that writes to 2 shards. This will become the current tx in
// the leader shard.
final DOMStoreWriteTransaction writeTx1 = followerDistributedDataStore.newWriteOnlyTransaction();
writeTx1.write(CarsModel.CAR_LIST_PATH, CarsModel.newCarMapNode());
writeTx1.write(PeopleModel.BASE_PATH, PeopleModel.emptyContainer());
final DOMStoreThreePhaseCommitCohort writeTx1Cohort = writeTx1.ready();
final ListenableFuture<Boolean> writeTx1CanCommit = writeTx1Cohort.canCommit();
writeTx1CanCommit.get(5, TimeUnit.SECONDS);
// Prepare and ready another WO tx that writes to 2 shards but don't canCommit yet. This will be queued
// in the leader shard.
final DOMStoreWriteTransaction writeTx2 = followerDistributedDataStore.newWriteOnlyTransaction();
final LinkedList<MapEntryNode> cars = new LinkedList<>();
int carIndex = 1;
cars.add(CarsModel.newCarEntry("car" + carIndex, BigInteger.valueOf(carIndex)));
writeTx2.write(CarsModel.newCarPath("car" + carIndex), cars.getLast());
carIndex++;
NormalizedNode<?, ?> people = PeopleModel.newPersonMapNode();
writeTx2.write(PeopleModel.PERSON_LIST_PATH, people);
final DOMStoreThreePhaseCommitCohort writeTx2Cohort = writeTx2.ready();
// Prepare another WO that writes to a single shard and thus will be directly committed on ready. This
// tx writes 5 cars so 2 BatchedModidifications messages will be sent initially and cached in the
// leader shard (with shardBatchedModificationCount set to 2). The 3rd BatchedModidifications will be
// sent on ready.
final DOMStoreWriteTransaction writeTx3 = followerDistributedDataStore.newWriteOnlyTransaction();
for (int i = 1; i <= 5; i++, carIndex++) {
cars.add(CarsModel.newCarEntry("car" + carIndex, BigInteger.valueOf(carIndex)));
writeTx3.write(CarsModel.newCarPath("car" + carIndex), cars.getLast());
}
// Prepare another WO that writes to a single shard. This will send a single BatchedModidifications
// message on ready.
final DOMStoreWriteTransaction writeTx4 = followerDistributedDataStore.newWriteOnlyTransaction();
cars.add(CarsModel.newCarEntry("car" + carIndex, BigInteger.valueOf(carIndex)));
writeTx4.write(CarsModel.newCarPath("car" + carIndex), cars.getLast());
carIndex++;
// Prepare a RW tx that will create a tx actor and send a ForwardedReadyTransaciton message to the
// leader shard on ready.
final DOMStoreReadWriteTransaction readWriteTx = followerDistributedDataStore.newReadWriteTransaction();
cars.add(CarsModel.newCarEntry("car" + carIndex, BigInteger.valueOf(carIndex)));
readWriteTx.write(CarsModel.newCarPath("car" + carIndex), cars.getLast());
IntegrationTestKit.verifyShardStats(leaderDistributedDataStore, "cars", stats -> assertEquals("getReadWriteTransactionCount", 1, stats.getReadWriteTransactionCount()));
// Disable elections on the leader so it switches to follower.
sendDatastoreContextUpdate(leaderDistributedDataStore, leaderDatastoreContextBuilder.customRaftPolicyImplementation(DisableElectionsRaftPolicy.class.getName()).shardElectionTimeoutFactor(10));
leaderTestKit.waitUntilNoLeader(leaderDistributedDataStore.getActorContext(), "cars");
// Submit all tx's - the messages should get queued for retry.
final ListenableFuture<Boolean> writeTx2CanCommit = writeTx2Cohort.canCommit();
final DOMStoreThreePhaseCommitCohort writeTx3Cohort = writeTx3.ready();
final DOMStoreThreePhaseCommitCohort writeTx4Cohort = writeTx4.ready();
final DOMStoreThreePhaseCommitCohort rwTxCohort = readWriteTx.ready();
// Enable elections on the other follower so it becomes the leader, at which point the
// tx's should get forwarded from the previous leader to the new leader to complete the commits.
sendDatastoreContextUpdate(followerDistributedDataStore, followerDatastoreContextBuilder.customRaftPolicyImplementation(null).shardElectionTimeoutFactor(1));
IntegrationTestKit.findLocalShard(followerDistributedDataStore.getActorContext(), "cars").tell(TimeoutNow.INSTANCE, ActorRef.noSender());
IntegrationTestKit.findLocalShard(followerDistributedDataStore.getActorContext(), "people").tell(TimeoutNow.INSTANCE, ActorRef.noSender());
followerTestKit.doCommit(writeTx1CanCommit, writeTx1Cohort);
followerTestKit.doCommit(writeTx2CanCommit, writeTx2Cohort);
followerTestKit.doCommit(writeTx3Cohort);
followerTestKit.doCommit(writeTx4Cohort);
followerTestKit.doCommit(rwTxCohort);
DOMStoreReadTransaction readTx = leaderDistributedDataStore.newReadOnlyTransaction();
verifyCars(readTx, cars.toArray(new MapEntryNode[cars.size()]));
verifyNode(readTx, PeopleModel.PERSON_LIST_PATH, people);
}
use of org.opendaylight.mdsal.dom.spi.store.DOMStoreThreePhaseCommitCohort in project controller by opendaylight.
the class DataTreeCohortIntegrationTest method testFailedCanCommit.
@SuppressWarnings("unchecked")
@Test
public void testFailedCanCommit() throws Exception {
final DOMDataTreeCommitCohort failedCohort = mock(DOMDataTreeCommitCohort.class);
doReturn(FAILED_CAN_COMMIT_FUTURE).when(failedCohort).canCommit(any(Object.class), any(Collection.class), any(SchemaContext.class));
IntegrationTestKit kit = new IntegrationTestKit(getSystem(), datastoreContextBuilder);
try (AbstractDataStore dataStore = kit.setupAbstractDataStore(DistributedDataStore.class, "testFailedCanCommit", "test-1")) {
dataStore.registerCommitCohort(TEST_ID, failedCohort);
IntegrationTestKit.verifyShardState(dataStore, "test-1", state -> assertEquals("Cohort registrations", 1, state.getCommitCohortActors().size()));
DOMStoreWriteTransaction writeTx = dataStore.newWriteOnlyTransaction();
writeTx.write(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
DOMStoreThreePhaseCommitCohort dsCohort = writeTx.ready();
try {
dsCohort.canCommit().get(5, TimeUnit.SECONDS);
fail("Exception should be raised.");
} catch (ExecutionException e) {
assertSame(FAILED_CAN_COMMIT, Throwables.getRootCause(e));
}
}
}
Aggregations