use of org.apache.cassandra.utils.concurrent.Future in project cassandra by apache.
the class HintsService method excise.
/**
* Cleans up hints-related state after a node with id = hostId left.
*
* Dispatcher can not stop itself (isHostAlive() can not start returning false for the leaving host because this
* method is called by the same thread as gossip, which blocks gossip), so we can't simply wait for
* completion.
*
* We should also flush the buffer if there are any hints for the node there, and close the writer (if any),
* so that we don't leave any hint files lying around.
*
* Once that is done, we can simply delete all hint files and remove the host id from the catalog.
*
* The worst that can happen if we don't get everything right is a hints file (or two) remaining undeleted.
*
* @param hostId id of the node being excised
*/
public void excise(UUID hostId) {
HintsStore store = catalog.getNullable(hostId);
if (store == null)
return;
// flush the buffer and then close the writer for the excised host id, to make sure that no new files will appear
// for this host id after we are done
Future flushFuture = writeExecutor.flushBufferPool(bufferPool, Collections.singleton(store));
Future closeFuture = writeExecutor.closeWriter(store);
try {
flushFuture.get();
closeFuture.get();
} catch (InterruptedException e) {
throw new UncheckedInterruptedException(e);
} catch (ExecutionException e) {
throw new RuntimeException(e);
}
// interrupt the current dispatch session to end (if any), so that the currently dispatched file gets removed
dispatchExecutor.interruptDispatch(store.hostId);
// delete all the hints files and remove the HintsStore instance from the map in the catalog
catalog.exciseStore(hostId);
}
use of org.apache.cassandra.utils.concurrent.Future in project cassandra by apache.
the class PendingAntiCompactionTest method testRetries.
@Test
public void testRetries() throws InterruptedException, ExecutionException {
ColumnFamilyStore cfs = MockSchema.newCFS();
cfs.addSSTable(MockSchema.sstable(1, true, cfs));
CountDownLatch cdl = new CountDownLatch(5);
ExecutorPlus es = executorFactory().sequential("test");
CompactionInfo.Holder holder = new CompactionInfo.Holder() {
public CompactionInfo getCompactionInfo() {
return new CompactionInfo(cfs.metadata(), OperationType.ANTICOMPACTION, 0, 0, nextTimeUUID(), cfs.getLiveSSTables());
}
public boolean isGlobal() {
return false;
}
};
try {
PendingAntiCompaction.AntiCompactionPredicate acp = new PendingAntiCompaction.AntiCompactionPredicate(FULL_RANGE, nextTimeUUID()) {
@Override
public boolean apply(SSTableReader sstable) {
cdl.countDown();
if (cdl.getCount() > 0)
throw new PendingAntiCompaction.SSTableAcquisitionException("blah");
return true;
}
};
CompactionManager.instance.active.beginCompaction(holder);
PendingAntiCompaction.AcquisitionCallable acquisitionCallable = new PendingAntiCompaction.AcquisitionCallable(cfs, nextTimeUUID(), 10, 1, acp);
Future f = es.submit(acquisitionCallable);
cdl.await();
assertNotNull(f.get());
} finally {
es.shutdown();
CompactionManager.instance.active.finishCompaction(holder);
}
}
use of org.apache.cassandra.utils.concurrent.Future in project cassandra by apache.
the class PendingAntiCompactionTest method testRetriesTimeout.
@Test
public void testRetriesTimeout() throws InterruptedException, ExecutionException {
ColumnFamilyStore cfs = MockSchema.newCFS();
cfs.addSSTable(MockSchema.sstable(1, true, cfs));
ExecutorPlus es = executorFactory().sequential("test");
CompactionInfo.Holder holder = new CompactionInfo.Holder() {
public CompactionInfo getCompactionInfo() {
return new CompactionInfo(cfs.metadata(), OperationType.ANTICOMPACTION, 0, 0, nextTimeUUID(), cfs.getLiveSSTables());
}
public boolean isGlobal() {
return false;
}
};
try {
PendingAntiCompaction.AntiCompactionPredicate acp = new PendingAntiCompaction.AntiCompactionPredicate(FULL_RANGE, nextTimeUUID()) {
@Override
public boolean apply(SSTableReader sstable) {
throw new PendingAntiCompaction.SSTableAcquisitionException("blah");
}
};
CompactionManager.instance.active.beginCompaction(holder);
PendingAntiCompaction.AcquisitionCallable acquisitionCallable = new PendingAntiCompaction.AcquisitionCallable(cfs, nextTimeUUID(), 2, 1000, acp);
Future fut = es.submit(acquisitionCallable);
assertNull(fut.get());
} finally {
es.shutdown();
CompactionManager.instance.active.finishCompaction(holder);
}
}
use of org.apache.cassandra.utils.concurrent.Future 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();
TimeUUID 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.utils.concurrent.Future in project cassandra by apache.
the class RepairJob method run.
/**
* Runs repair job.
*
* This sets up necessary task and runs them on given {@code taskExecutor}.
* After submitting all tasks, waits until validation with replica completes.
*/
public void run() {
state.phase.start();
Keyspace ks = Keyspace.open(desc.keyspace);
ColumnFamilyStore cfs = ks.getColumnFamilyStore(desc.columnFamily);
cfs.metric.repairsStarted.inc();
List<InetAddressAndPort> allEndpoints = new ArrayList<>(session.state.commonRange.endpoints);
allEndpoints.add(FBUtilities.getBroadcastAddressAndPort());
Future<List<TreeResponse>> treeResponses;
Future<Void> paxosRepair;
if (paxosRepairEnabled() && ((useV2() && session.repairPaxos) || session.paxosOnly)) {
logger.info("{} {}.{} starting paxos repair", session.previewKind.logPrefix(session.getId()), desc.keyspace, desc.columnFamily);
TableMetadata metadata = Schema.instance.getTableMetadata(desc.keyspace, desc.columnFamily);
paxosRepair = PaxosCleanup.cleanup(allEndpoints, metadata, desc.ranges, session.state.commonRange.hasSkippedReplicas, taskExecutor);
} else {
logger.info("{} {}.{} not running paxos repair", session.previewKind.logPrefix(session.getId()), desc.keyspace, desc.columnFamily);
paxosRepair = ImmediateFuture.success(null);
}
if (session.paxosOnly) {
paxosRepair.addCallback(new FutureCallback<Void>() {
public void onSuccess(Void v) {
logger.info("{} {}.{} paxos repair completed", session.previewKind.logPrefix(session.getId()), desc.keyspace, desc.columnFamily);
trySuccess(new RepairResult(desc, Collections.emptyList()));
}
/**
* Snapshot, validation and sync failures are all handled here
*/
public void onFailure(Throwable t) {
logger.warn("{} {}.{} paxos repair failed", session.previewKind.logPrefix(session.getId()), desc.keyspace, desc.columnFamily);
tryFailure(t);
}
}, taskExecutor);
return;
}
// Create a snapshot at all nodes unless we're using pure parallel repairs
if (parallelismDegree != RepairParallelism.PARALLEL) {
Future<?> allSnapshotTasks;
if (session.isIncremental) {
// consistent repair does it's own "snapshotting"
allSnapshotTasks = paxosRepair.map(input -> allEndpoints);
} else {
// Request snapshot to all replica
allSnapshotTasks = paxosRepair.flatMap(input -> {
List<Future<InetAddressAndPort>> snapshotTasks = new ArrayList<>(allEndpoints.size());
state.phase.snapshotsSubmitted();
for (InetAddressAndPort endpoint : allEndpoints) {
SnapshotTask snapshotTask = new SnapshotTask(desc, endpoint);
snapshotTasks.add(snapshotTask);
taskExecutor.execute(snapshotTask);
}
return FutureCombiner.allOf(snapshotTasks).map(a -> {
state.phase.snapshotsCompleted();
return a;
});
});
}
// When all snapshot complete, send validation requests
treeResponses = allSnapshotTasks.flatMap(endpoints -> {
if (parallelismDegree == RepairParallelism.SEQUENTIAL)
return sendSequentialValidationRequest(allEndpoints);
else
return sendDCAwareValidationRequest(allEndpoints);
}, taskExecutor);
} else {
// If not sequential, just send validation request to all replica
treeResponses = paxosRepair.flatMap(input -> sendValidationRequest(allEndpoints));
}
treeResponses = treeResponses.map(a -> {
state.phase.validationCompleted();
return a;
});
// When all validations complete, submit sync tasks
Future<List<SyncStat>> syncResults = treeResponses.flatMap(session.optimiseStreams && !session.pullRepair ? this::optimisedSyncing : this::standardSyncing, taskExecutor);
// When all sync complete, set the final result
syncResults.addCallback(new FutureCallback<List<SyncStat>>() {
@Override
public void onSuccess(List<SyncStat> stats) {
state.phase.success();
if (!session.previewKind.isPreview()) {
logger.info("{} {}.{} is fully synced", session.previewKind.logPrefix(session.getId()), desc.keyspace, desc.columnFamily);
SystemDistributedKeyspace.successfulRepairJob(session.getId(), desc.keyspace, desc.columnFamily);
}
cfs.metric.repairsCompleted.inc();
trySuccess(new RepairResult(desc, stats));
}
/**
* Snapshot, validation and sync failures are all handled here
*/
@Override
public void onFailure(Throwable t) {
state.phase.fail(t);
// Make sure all validation tasks have cleaned up the off-heap Merkle trees they might contain.
validationTasks.forEach(ValidationTask::abort);
syncTasks.forEach(SyncTask::abort);
if (!session.previewKind.isPreview()) {
logger.warn("{} {}.{} sync failed", session.previewKind.logPrefix(session.getId()), desc.keyspace, desc.columnFamily);
SystemDistributedKeyspace.failedRepairJob(session.getId(), desc.keyspace, desc.columnFamily, t);
}
cfs.metric.repairsCompleted.inc();
tryFailure(t instanceof NoSuchRepairSessionExceptionWrapper ? ((NoSuchRepairSessionExceptionWrapper) t).wrapped : t);
}
}, taskExecutor);
}
Aggregations