use of org.apache.cassandra.repair.CoordinatedRepairResult in project cassandra by apache.
the class CoordinatorMessagingTest method testMockedMessagingHappyPath.
@Test
public void testMockedMessagingHappyPath() throws InterruptedException, ExecutionException, TimeoutException, NoSuchRepairSessionException {
CountDownLatch prepareLatch = createLatch();
CountDownLatch finalizeLatch = createLatch();
MockMessagingSpy spyPrepare = createPrepareSpy(Collections.emptySet(), Collections.emptySet(), prepareLatch);
MockMessagingSpy spyFinalize = createFinalizeSpy(Collections.emptySet(), Collections.emptySet(), finalizeLatch);
MockMessagingSpy spyCommit = createCommitSpy();
UUID uuid = registerSession(cfs, true, true);
CoordinatorSession coordinator = ActiveRepairService.instance.consistent.coordinated.registerSession(uuid, PARTICIPANTS, false);
AtomicBoolean repairSubmitted = new AtomicBoolean(false);
Promise<CoordinatedRepairResult> repairFuture = AsyncPromise.uncancellable();
Supplier<Future<CoordinatedRepairResult>> sessionSupplier = () -> {
repairSubmitted.set(true);
return repairFuture;
};
// coordinator sends prepare requests to create local session and perform anticompaction
Assert.assertFalse(repairSubmitted.get());
// execute repair and start prepare phase
Future<CoordinatedRepairResult> sessionResult = coordinator.execute(sessionSupplier);
Assert.assertFalse(sessionResult.isDone());
// prepare completed
prepareLatch.countDown();
spyPrepare.interceptMessageOut(3).get(1, TimeUnit.SECONDS);
Assert.assertFalse(sessionResult.isDone());
// set result from local repair session
repairFuture.trySuccess(CoordinatedRepairResult.success(Lists.newArrayList(createResult(coordinator), createResult(coordinator), createResult(coordinator))));
// finalize phase
finalizeLatch.countDown();
spyFinalize.interceptMessageOut(3).get(1, TimeUnit.SECONDS);
// commit phase
spyCommit.interceptMessageOut(3).get(1, TimeUnit.SECONDS);
Assert.assertFalse(sessionResult.get().hasFailed());
// expect no other messages except from intercepted so far
spyPrepare.interceptNoMsg(100, TimeUnit.MILLISECONDS);
spyFinalize.interceptNoMsg(100, TimeUnit.MILLISECONDS);
spyCommit.interceptNoMsg(100, TimeUnit.MILLISECONDS);
Assert.assertEquals(ConsistentSession.State.FINALIZED, coordinator.getState());
Assert.assertFalse(ActiveRepairService.instance.consistent.local.isSessionInProgress(uuid));
}
use of org.apache.cassandra.repair.CoordinatedRepairResult in project cassandra by apache.
the class CoordinatorSessionTest method successCase.
/**
* Tests the complete coordinator side consistent repair cycle
*/
@Test
public void successCase() {
InstrumentedCoordinatorSession coordinator = createInstrumentedSession();
AtomicBoolean repairSubmitted = new AtomicBoolean(false);
Promise<CoordinatedRepairResult> repairFuture = AsyncPromise.uncancellable();
Supplier<Future<CoordinatedRepairResult>> sessionSupplier = () -> {
repairSubmitted.set(true);
return repairFuture;
};
// coordinator sends prepare requests to create local session and perform anticompaction
Assert.assertFalse(repairSubmitted.get());
Assert.assertTrue(coordinator.sentMessages.isEmpty());
Future<CoordinatedRepairResult> sessionResult = coordinator.execute(sessionSupplier);
for (InetAddressAndPort participant : PARTICIPANTS) {
RepairMessage expected = new PrepareConsistentRequest(coordinator.sessionID, COORDINATOR, new HashSet<>(PARTICIPANTS));
assertMessageSent(coordinator, participant, expected);
}
// participants respond to coordinator, and repair begins once all participants have responded with success
Assert.assertEquals(ConsistentSession.State.PREPARING, coordinator.getState());
coordinator.handlePrepareResponse(PARTICIPANT1, true);
Assert.assertEquals(ConsistentSession.State.PREPARING, coordinator.getState());
coordinator.handlePrepareResponse(PARTICIPANT2, true);
Assert.assertEquals(ConsistentSession.State.PREPARING, coordinator.getState());
// set the setRepairing callback to verify the correct state when it's called
Assert.assertFalse(coordinator.setRepairingCalled);
coordinator.onSetRepairing = () -> Assert.assertEquals(PREPARED, coordinator.getState());
coordinator.handlePrepareResponse(PARTICIPANT3, true);
Assert.assertTrue(coordinator.setRepairingCalled);
Assert.assertTrue(repairSubmitted.get());
Assert.assertEquals(ConsistentSession.State.REPAIRING, coordinator.getState());
ArrayList<RepairSessionResult> results = Lists.newArrayList(createResult(coordinator), createResult(coordinator), createResult(coordinator));
coordinator.sentMessages.clear();
repairFuture.trySuccess(CoordinatedRepairResult.success(results));
// propose messages should have been sent once all repair sessions completed successfully
for (InetAddressAndPort participant : PARTICIPANTS) {
RepairMessage expected = new FinalizePropose(coordinator.sessionID);
assertMessageSent(coordinator, participant, expected);
}
// finalize commit messages will be sent once all participants respond with a promize to finalize
coordinator.sentMessages.clear();
Assert.assertEquals(ConsistentSession.State.REPAIRING, coordinator.getState());
coordinator.handleFinalizePromise(PARTICIPANT1, true);
Assert.assertEquals(ConsistentSession.State.REPAIRING, coordinator.getState());
coordinator.handleFinalizePromise(PARTICIPANT2, true);
Assert.assertEquals(ConsistentSession.State.REPAIRING, coordinator.getState());
// set the finalizeCommit callback so we can verify the state when it's called
Assert.assertFalse(coordinator.finalizeCommitCalled);
coordinator.onFinalizeCommit = () -> Assert.assertEquals(FINALIZE_PROMISED, coordinator.getState());
coordinator.handleFinalizePromise(PARTICIPANT3, true);
Assert.assertTrue(coordinator.finalizeCommitCalled);
Assert.assertEquals(ConsistentSession.State.FINALIZED, coordinator.getState());
for (InetAddressAndPort participant : PARTICIPANTS) {
RepairMessage expected = new FinalizeCommit(coordinator.sessionID);
assertMessageSent(coordinator, participant, expected);
}
Assert.assertTrue(sessionResult.isDone());
sessionResult.syncUninterruptibly();
}
use of org.apache.cassandra.repair.CoordinatedRepairResult in project cassandra by apache.
the class CoordinatorSessionTest method failedPropose.
@Test
public void failedPropose() {
InstrumentedCoordinatorSession coordinator = createInstrumentedSession();
AtomicBoolean repairSubmitted = new AtomicBoolean(false);
Promise<CoordinatedRepairResult> repairFuture = AsyncPromise.uncancellable();
Supplier<Future<CoordinatedRepairResult>> sessionSupplier = () -> {
repairSubmitted.set(true);
return repairFuture;
};
// coordinator sends prepare requests to create local session and perform anticompaction
Assert.assertFalse(repairSubmitted.get());
Assert.assertTrue(coordinator.sentMessages.isEmpty());
Future<CoordinatedRepairResult> sessionResult = coordinator.execute(sessionSupplier);
for (InetAddressAndPort participant : PARTICIPANTS) {
RepairMessage expected = new PrepareConsistentRequest(coordinator.sessionID, COORDINATOR, new HashSet<>(PARTICIPANTS));
assertMessageSent(coordinator, participant, expected);
}
// participants respond to coordinator, and repair begins once all participants have responded with success
Assert.assertEquals(ConsistentSession.State.PREPARING, coordinator.getState());
coordinator.handlePrepareResponse(PARTICIPANT1, true);
Assert.assertEquals(ConsistentSession.State.PREPARING, coordinator.getState());
coordinator.handlePrepareResponse(PARTICIPANT2, true);
Assert.assertEquals(ConsistentSession.State.PREPARING, coordinator.getState());
// set the setRepairing callback to verify the correct state when it's called
Assert.assertFalse(coordinator.setRepairingCalled);
coordinator.onSetRepairing = () -> Assert.assertEquals(PREPARED, coordinator.getState());
coordinator.handlePrepareResponse(PARTICIPANT3, true);
Assert.assertTrue(coordinator.setRepairingCalled);
Assert.assertTrue(repairSubmitted.get());
Assert.assertEquals(ConsistentSession.State.REPAIRING, coordinator.getState());
ArrayList<RepairSessionResult> results = Lists.newArrayList(createResult(coordinator), createResult(coordinator), createResult(coordinator));
coordinator.sentMessages.clear();
repairFuture.trySuccess(CoordinatedRepairResult.success(results));
// propose messages should have been sent once all repair sessions completed successfully
for (InetAddressAndPort participant : PARTICIPANTS) {
RepairMessage expected = new FinalizePropose(coordinator.sessionID);
assertMessageSent(coordinator, participant, expected);
}
// finalize commit messages will be sent once all participants respond with a promize to finalize
coordinator.sentMessages.clear();
Assert.assertEquals(ConsistentSession.State.REPAIRING, coordinator.getState());
coordinator.handleFinalizePromise(PARTICIPANT1, true);
Assert.assertEquals(ConsistentSession.State.REPAIRING, coordinator.getState());
Assert.assertFalse(coordinator.failCalled);
coordinator.handleFinalizePromise(PARTICIPANT2, false);
Assert.assertEquals(ConsistentSession.State.FAILED, coordinator.getState());
Assert.assertTrue(coordinator.failCalled);
// additional success messages should be ignored
Assert.assertFalse(coordinator.finalizeCommitCalled);
coordinator.onFinalizeCommit = Assert::fail;
coordinator.handleFinalizePromise(PARTICIPANT3, true);
Assert.assertFalse(coordinator.finalizeCommitCalled);
Assert.assertEquals(ConsistentSession.State.FAILED, coordinator.getState());
// failure messages should have been sent to all participants
for (InetAddressAndPort participant : PARTICIPANTS) {
RepairMessage expected = new FailSession(coordinator.sessionID);
assertMessageSent(coordinator, participant, expected);
}
Assert.assertTrue(sessionResult.isDone());
Assert.assertNotNull(sessionResult.cause());
}
use of org.apache.cassandra.repair.CoordinatedRepairResult in project cassandra by apache.
the class CoordinatorSessionTest method failedRepairs.
@Test
public void failedRepairs() {
InstrumentedCoordinatorSession coordinator = createInstrumentedSession();
AtomicBoolean repairSubmitted = new AtomicBoolean(false);
Promise<CoordinatedRepairResult> repairFuture = AsyncPromise.uncancellable();
Supplier<Future<CoordinatedRepairResult>> sessionSupplier = () -> {
repairSubmitted.set(true);
return repairFuture;
};
// coordinator sends prepare requests to create local session and perform anticompaction
Assert.assertFalse(repairSubmitted.get());
Assert.assertTrue(coordinator.sentMessages.isEmpty());
Future<CoordinatedRepairResult> sessionResult = coordinator.execute(sessionSupplier);
for (InetAddressAndPort participant : PARTICIPANTS) {
PrepareConsistentRequest expected = new PrepareConsistentRequest(coordinator.sessionID, COORDINATOR, new HashSet<>(PARTICIPANTS));
assertMessageSent(coordinator, participant, expected);
}
// participants respond to coordinator, and repair begins once all participants have responded with success
Assert.assertEquals(ConsistentSession.State.PREPARING, coordinator.getState());
coordinator.handlePrepareResponse(PARTICIPANT1, true);
Assert.assertEquals(ConsistentSession.State.PREPARING, coordinator.getState());
coordinator.handlePrepareResponse(PARTICIPANT2, true);
Assert.assertEquals(ConsistentSession.State.PREPARING, coordinator.getState());
// set the setRepairing callback to verify the correct state when it's called
Assert.assertFalse(coordinator.setRepairingCalled);
coordinator.onSetRepairing = () -> Assert.assertEquals(PREPARED, coordinator.getState());
coordinator.handlePrepareResponse(PARTICIPANT3, true);
Assert.assertTrue(coordinator.setRepairingCalled);
Assert.assertTrue(repairSubmitted.get());
Assert.assertEquals(ConsistentSession.State.REPAIRING, coordinator.getState());
List<Collection<Range<Token>>> ranges = Arrays.asList(coordinator.ranges, coordinator.ranges, coordinator.ranges);
ArrayList<RepairSessionResult> results = Lists.newArrayList(createResult(coordinator), null, createResult(coordinator));
coordinator.sentMessages.clear();
Assert.assertFalse(coordinator.failCalled);
coordinator.onFail = () -> Assert.assertEquals(REPAIRING, coordinator.getState());
repairFuture.trySuccess(CoordinatedRepairResult.create(ranges, results));
Assert.assertTrue(coordinator.failCalled);
// all participants should have been notified of session failure
for (InetAddressAndPort participant : PARTICIPANTS) {
RepairMessage expected = new FailSession(coordinator.sessionID);
assertMessageSent(coordinator, participant, expected);
}
Assert.assertTrue(sessionResult.isDone());
Assert.assertNotNull(sessionResult.cause());
}
use of org.apache.cassandra.repair.CoordinatedRepairResult in project cassandra by apache.
the class CoordinatorSessionTest method failedPrepare.
@Test
public void failedPrepare() {
InstrumentedCoordinatorSession coordinator = createInstrumentedSession();
AtomicBoolean repairSubmitted = new AtomicBoolean(false);
Promise<CoordinatedRepairResult> repairFuture = AsyncPromise.uncancellable();
Supplier<Future<CoordinatedRepairResult>> sessionSupplier = () -> {
repairSubmitted.set(true);
return repairFuture;
};
// coordinator sends prepare requests to create local session and perform anticompaction
Assert.assertFalse(repairSubmitted.get());
Assert.assertTrue(coordinator.sentMessages.isEmpty());
Future<CoordinatedRepairResult> sessionResult = coordinator.execute(sessionSupplier);
for (InetAddressAndPort participant : PARTICIPANTS) {
PrepareConsistentRequest expected = new PrepareConsistentRequest(coordinator.sessionID, COORDINATOR, new HashSet<>(PARTICIPANTS));
assertMessageSent(coordinator, participant, expected);
}
coordinator.sentMessages.clear();
// participants respond to coordinator, and repair begins once all participants have responded
Assert.assertEquals(ConsistentSession.State.PREPARING, coordinator.getState());
coordinator.handlePrepareResponse(PARTICIPANT1, true);
Assert.assertEquals(ConsistentSession.State.PREPARING, coordinator.getState());
Assert.assertEquals(PREPARED, coordinator.getParticipantState(PARTICIPANT1));
Assert.assertFalse(sessionResult.isDone());
// participant 2 fails to prepare for consistent repair
Assert.assertFalse(coordinator.failCalled);
coordinator.handlePrepareResponse(PARTICIPANT2, false);
Assert.assertEquals(ConsistentSession.State.PREPARING, coordinator.getState());
// we should have sent failure messages to the other participants, but not yet marked them failed internally
assertMessageSent(coordinator, PARTICIPANT1, new FailSession(coordinator.sessionID));
assertMessageSent(coordinator, PARTICIPANT2, new FailSession(coordinator.sessionID));
assertMessageSent(coordinator, PARTICIPANT3, new FailSession(coordinator.sessionID));
Assert.assertEquals(FAILED, coordinator.getParticipantState(PARTICIPANT2));
Assert.assertEquals(PREPARED, coordinator.getParticipantState(PARTICIPANT1));
Assert.assertEquals(PREPARING, coordinator.getParticipantState(PARTICIPANT3));
Assert.assertFalse(sessionResult.isDone());
Assert.assertFalse(coordinator.failCalled);
coordinator.sentMessages.clear();
// last outstanding response should cause repair to complete in failed state
Assert.assertFalse(coordinator.setRepairingCalled);
coordinator.onSetRepairing = Assert::fail;
coordinator.handlePrepareResponse(PARTICIPANT3, true);
Assert.assertTrue(coordinator.failCalled);
Assert.assertFalse(coordinator.setRepairingCalled);
Assert.assertFalse(repairSubmitted.get());
// all participants that did not fail should have been notified of session failure
RepairMessage expected = new FailSession(coordinator.sessionID);
assertMessageSent(coordinator, PARTICIPANT1, expected);
assertMessageSent(coordinator, PARTICIPANT3, expected);
Assert.assertFalse(coordinator.sentMessages.containsKey(PARTICIPANT2));
Assert.assertTrue(sessionResult.isDone());
Assert.assertNotNull(sessionResult.cause());
}
Aggregations