use of org.apache.cassandra.utils.concurrent.Future in project cassandra by apache.
the class RepairJob method sendSequentialValidationRequest.
/**
* Creates {@link ValidationTask} and submit them to task executor so that tasks run sequentially.
*/
private Future<List<TreeResponse>> sendSequentialValidationRequest(Collection<InetAddressAndPort> endpoints) {
state.phase.validationSubmitted();
String message = String.format("Requesting merkle trees for %s (to %s)", desc.columnFamily, endpoints);
logger.info("{} {}", session.previewKind.logPrefix(desc.sessionId), message);
Tracing.traceRepair(message);
int nowInSec = getNowInSeconds();
List<Future<TreeResponse>> tasks = new ArrayList<>(endpoints.size());
Queue<InetAddressAndPort> requests = new LinkedList<>(endpoints);
InetAddressAndPort address = requests.poll();
ValidationTask firstTask = newValidationTask(address, nowInSec);
logger.info("{} Validating {}", session.previewKind.logPrefix(desc.sessionId), address);
session.trackValidationCompletion(Pair.create(desc, address), firstTask);
tasks.add(firstTask);
ValidationTask currentTask = firstTask;
while (requests.size() > 0) {
final InetAddressAndPort nextAddress = requests.poll();
final ValidationTask nextTask = newValidationTask(nextAddress, nowInSec);
tasks.add(nextTask);
currentTask.addCallback(new FutureCallback<TreeResponse>() {
public void onSuccess(TreeResponse result) {
logger.info("{} Validating {}", session.previewKind.logPrefix(desc.sessionId), nextAddress);
session.trackValidationCompletion(Pair.create(desc, nextAddress), nextTask);
taskExecutor.execute(nextTask);
}
// failure is handled at root of job chain
public void onFailure(Throwable t) {
}
});
currentTask = nextTask;
}
// start running tasks
taskExecutor.execute(firstTask);
return FutureCombiner.allOf(tasks);
}
use of org.apache.cassandra.utils.concurrent.Future in project cassandra by apache.
the class ActiveRepairService method repairPaxosForTopologyChange.
public Future<?> repairPaxosForTopologyChange(String ksName, Collection<Range<Token>> ranges, String reason) {
if (!paxosRepairEnabled()) {
logger.warn("Not running paxos repair for topology change because paxos repair has been disabled");
return ImmediateFuture.success(null);
}
if (ranges.isEmpty()) {
logger.warn("Not running paxos repair for topology change because there are no ranges to repair");
return ImmediateFuture.success(null);
}
List<TableMetadata> tables = Lists.newArrayList(Schema.instance.getKeyspaceMetadata(ksName).tables);
List<Future<Void>> futures = new ArrayList<>(ranges.size() * tables.size());
Keyspace keyspace = Keyspace.open(ksName);
AbstractReplicationStrategy replication = keyspace.getReplicationStrategy();
for (Range<Token> range : ranges) {
for (TableMetadata table : tables) {
Set<InetAddressAndPort> endpoints = replication.getNaturalReplicas(range.right).filter(FailureDetector.isReplicaAlive).endpoints();
if (!PaxosRepair.hasSufficientLiveNodesForTopologyChange(keyspace, range, endpoints)) {
Set<InetAddressAndPort> downEndpoints = replication.getNaturalReplicas(range.right).filter(e -> !endpoints.contains(e)).endpoints();
downEndpoints.removeAll(endpoints);
throw new RuntimeException(String.format("Insufficient live nodes to repair paxos for %s in %s for %s.\n" + "There must be enough live nodes to satisfy EACH_QUORUM, but the following nodes are down: %s\n" + "This check can be skipped by setting either the yaml property skip_paxos_repair_on_topology_change or " + "the system property cassandra.skip_paxos_repair_on_topology_change to false. The jmx property " + "StorageService.SkipPaxosRepairOnTopologyChange can also be set to false to temporarily disable without " + "restarting the node\n" + "Individual keyspaces can be skipped with the yaml property skip_paxos_repair_on_topology_change_keyspaces, the" + "system property cassandra.skip_paxos_repair_on_topology_change_keyspaces, or temporarily with the jmx" + "property StorageService.SkipPaxosRepairOnTopologyChangeKeyspaces\n" + "Skipping this check can lead to paxos correctness issues", range, ksName, reason, downEndpoints));
}
EndpointsForToken pending = StorageService.instance.getTokenMetadata().pendingEndpointsForToken(range.right, ksName);
if (pending.size() > 1 && !Boolean.getBoolean("cassandra.paxos_repair_allow_multiple_pending_unsafe")) {
throw new RuntimeException(String.format("Cannot begin paxos auto repair for %s in %s.%s, multiple pending endpoints exist for range (%s). " + "Set -Dcassandra.paxos_repair_allow_multiple_pending_unsafe=true to skip this check", range, table.keyspace, table.name, pending));
}
Future<Void> future = PaxosCleanup.cleanup(endpoints, table, Collections.singleton(range), false, repairCommandExecutor());
futures.add(future);
}
}
return FutureCombiner.allOf(futures);
}
use of org.apache.cassandra.utils.concurrent.Future in project cassandra by apache.
the class StorageService method drain.
protected synchronized void drain(boolean isFinalShutdown) throws IOException, InterruptedException, ExecutionException {
if (Stage.areMutationExecutorsTerminated()) {
if (!isFinalShutdown)
logger.warn("Cannot drain node (did it already happen?)");
return;
}
assert !isShutdown;
isShutdown = true;
Throwable preShutdownHookThrowable = Throwables.perform(null, preShutdownHooks.stream().map(h -> h::run));
if (preShutdownHookThrowable != null)
logger.error("Attempting to continue draining after pre-shutdown hooks returned exception", preShutdownHookThrowable);
try {
setMode(Mode.DRAINING, "starting drain process", !isFinalShutdown);
try {
/* not clear this is reasonable time, but propagated from prior embedded behaviour */
BatchlogManager.instance.shutdownAndWait(1L, MINUTES);
} catch (TimeoutException t) {
logger.error("Batchlog manager timed out shutting down", t);
}
snapshotManager.stop();
HintsService.instance.pauseDispatch();
if (daemon != null)
shutdownClientServers();
ScheduledExecutors.optionalTasks.shutdown();
Gossiper.instance.stop();
ActiveRepairService.instance.stop();
if (!isFinalShutdown)
setMode(Mode.DRAINING, "shutting down MessageService", false);
// before mutation stage, so we can get all the hints saved before shutting down.
try {
MessagingService.instance().shutdown();
} catch (Throwable t) {
// prevent messaging service timing out shutdown from aborting
// drain process; otherwise drain and/or shutdown might throw
logger.error("Messaging service timed out shutting down", t);
}
if (!isFinalShutdown)
setMode(Mode.DRAINING, "clearing mutation stage", false);
Stage.shutdownAndAwaitMutatingExecutors(false, DRAIN_EXECUTOR_TIMEOUT_MS.getInt(), TimeUnit.MILLISECONDS);
StorageProxy.instance.verifyNoHintsInProgress();
if (!isFinalShutdown)
setMode(Mode.DRAINING, "flushing column families", false);
// we don't want to start any new compactions while we are draining
disableAutoCompaction();
// count CFs first, since forceFlush could block for the flushWriter to get a queue slot empty
totalCFs = 0;
for (Keyspace keyspace : Keyspace.nonSystem()) totalCFs += keyspace.getColumnFamilyStores().size();
remainingCFs = totalCFs;
// flush
List<Future<?>> flushes = new ArrayList<>();
for (Keyspace keyspace : Keyspace.nonSystem()) {
for (ColumnFamilyStore cfs : keyspace.getColumnFamilyStores()) flushes.add(cfs.forceFlush(ColumnFamilyStore.FlushReason.DRAIN));
}
// thus make several short ones "instant" if we wait for them later.
for (Future f : flushes) {
try {
FBUtilities.waitOnFuture(f);
} catch (Throwable t) {
JVMStabilityInspector.inspectThrowable(t);
// don't let this stop us from shutting down the commitlog and other thread pools
logger.warn("Caught exception while waiting for memtable flushes during shutdown hook", t);
}
remainingCFs--;
}
// Interrupt ongoing compactions and shutdown CM to prevent further compactions.
CompactionManager.instance.forceShutdown();
// Flush the system tables after all other tables are flushed, just in case flushing modifies any system state
// like CASSANDRA-5151. Don't bother with progress tracking since system data is tiny.
// Flush system tables after stopping compactions since they modify
// system tables (for example compactions can obsolete sstables and the tidiers in SSTableReader update
// system tables, see SSTableReader.GlobalTidy)
flushes.clear();
for (Keyspace keyspace : Keyspace.system()) {
for (ColumnFamilyStore cfs : keyspace.getColumnFamilyStores()) flushes.add(cfs.forceFlush(ColumnFamilyStore.FlushReason.DRAIN));
}
FBUtilities.waitOnFutures(flushes);
SnapshotManager.shutdownAndWait(1L, MINUTES);
HintsService.instance.shutdownBlocking();
// Interrupt ongoing compactions and shutdown CM to prevent further compactions.
CompactionManager.instance.forceShutdown();
// whilst we've flushed all the CFs, which will have recycled all completed segments, we want to ensure
// there are no segments to replay, so we force the recycling of any remaining (should be at most one)
CommitLog.instance.forceRecycleAllSegments();
CommitLog.instance.shutdownBlocking();
// wait for miscellaneous tasks like sstable and commitlog segment deletion
ColumnFamilyStore.shutdownPostFlushExecutor();
try {
// we are not shutting down ScheduledExecutors#scheduledFastTasks to be still able to progress time
// fast-tasks executor is shut down in StorageService's shutdown hook added to Runtime
ExecutorUtils.shutdownNowAndWait(1, MINUTES, ScheduledExecutors.nonPeriodicTasks, ScheduledExecutors.scheduledTasks, ScheduledExecutors.optionalTasks);
} finally {
setMode(Mode.DRAINED, !isFinalShutdown);
}
} catch (Throwable t) {
logger.error("Caught an exception while draining ", t);
} finally {
Throwable postShutdownHookThrowable = Throwables.perform(null, postShutdownHooks.stream().map(h -> h::run));
if (postShutdownHookThrowable != null)
logger.error("Post-shutdown hooks returned exception", postShutdownHookThrowable);
}
}
use of org.apache.cassandra.utils.concurrent.Future in project cassandra by apache.
the class StorageService method startRepairPaxosForTopologyChange.
@VisibleForTesting
public Future<?> startRepairPaxosForTopologyChange(String reason) {
logger.info("repairing paxos for {}", reason);
List<Future<?>> futures = new ArrayList<>();
Keyspaces keyspaces = Schema.instance.getNonLocalStrategyKeyspaces();
for (String ksName : keyspaces.names()) {
if (SchemaConstants.REPLICATED_SYSTEM_KEYSPACE_NAMES.contains(ksName))
continue;
if (DatabaseDescriptor.skipPaxosRepairOnTopologyChangeKeyspaces().contains(ksName))
continue;
List<Range<Token>> ranges = getLocalAndPendingRanges(ksName);
futures.add(ActiveRepairService.instance.repairPaxosForTopologyChange(ksName, ranges, reason));
}
return FutureCombiner.allOf(futures);
}
use of org.apache.cassandra.utils.concurrent.Future in project cassandra by apache.
the class OnClusterLeave method performSimple.
public ActionList performSimple() {
IInvokableInstance leaveInstance = actions.cluster.get(leaving);
before(leaveInstance);
AtomicReference<Supplier<? extends Future<?>>> preparedUnbootstrap = new AtomicReference<>();
return ActionList.of(// setup the node's own gossip state for pending ownership, and return gossip actions to disseminate
new OnClusterUpdateGossip(actions, leaving, new OnInstanceSetLeaving(actions, leaving)), new SimulatedActionConsumer<>("Prepare unbootstrap on " + leaving, RELIABLE_NO_TIMEOUTS, RELIABLE_NO_TIMEOUTS, actions, leaveInstance, ref -> ref.set(StorageService.instance.prepareUnbootstrapStreaming()), preparedUnbootstrap), new OnInstanceTopologyChangePaxosRepair(actions, leaving, "Leave"), new SimulatedActionConsumer<>("Execute unbootstrap on " + leaving, RELIABLE_NO_TIMEOUTS, RELIABLE_NO_TIMEOUTS, actions, leaveInstance, ref -> ref.get().get().syncThrowUncheckedOnInterrupt(), preparedUnbootstrap), // setup the node's own gossip state for natural ownership, and return gossip actions to disseminate
new OnClusterUpdateGossip(actions, leaving, new OnInstanceSetLeft(actions, leaving)));
}
Aggregations