use of org.apache.cassandra.utils.TimeUUID in project cassandra by apache.
the class LocalSessions method handleFinalizeProposeMessage.
public void handleFinalizeProposeMessage(InetAddressAndPort from, FinalizePropose propose) {
logger.trace("received {} from {}", propose, from);
TimeUUID sessionID = propose.sessionID;
LocalSession session = getSession(sessionID);
if (session == null) {
logger.info("Received FinalizePropose message for unknown repair session {}, responding with failure", sessionID);
sendMessage(from, Message.out(FAILED_SESSION_MSG, new FailSession(sessionID)));
return;
}
try {
setStateAndSave(session, FINALIZE_PROMISED);
/*
Flushing the repairs table here, *before* responding to the coordinator prevents a scenario where we respond
with a promise to the coordinator, but there is a failure before the commit log mutation with the
FINALIZE_PROMISED status is synced to disk. This could cause the state for this session to revert to an
earlier status on startup, which would prevent the failure recovery mechanism from ever being able to promote
this session to FINALIZED, likely creating inconsistencies in the repaired data sets across nodes.
*/
syncTable();
sendMessage(from, Message.out(FINALIZE_PROMISE_MSG, new FinalizePromise(sessionID, getBroadcastAddressAndPort(), true)));
logger.info("Received FinalizePropose message for incremental repair session {}, responded with FinalizePromise", sessionID);
} catch (IllegalArgumentException e) {
logger.error("Error handling FinalizePropose message for {}", session, e);
failSession(sessionID);
}
}
use of org.apache.cassandra.utils.TimeUUID in project cassandra by apache.
the class LocalSessions method start.
/**
* Loads sessions out of the repairs table and sets state to started
*/
public synchronized void start() {
Preconditions.checkArgument(!started, "LocalSessions.start can only be called once");
Preconditions.checkArgument(sessions.isEmpty(), "No sessions should be added before start");
UntypedResultSet rows = QueryProcessor.executeInternalWithPaging(String.format("SELECT * FROM %s.%s", keyspace, table), 1000);
Map<TimeUUID, LocalSession> loadedSessions = new HashMap<>();
Map<TableId, List<RepairedState.Level>> initialLevels = new HashMap<>();
for (UntypedResultSet.Row row : rows) {
try {
LocalSession session = load(row);
loadedSessions.put(session.sessionID, session);
if (shouldStoreSession(session)) {
for (TableId tid : session.tableIds) initialLevels.computeIfAbsent(tid, (t) -> new ArrayList<>()).add(new RepairedState.Level(session.ranges, session.repairedAt));
}
} catch (IllegalArgumentException | NullPointerException e) {
logger.warn("Unable to load malformed repair session {}, removing", row.has("parent_id") ? row.getTimeUUID("parent_id") : null);
if (row.has("parent_id"))
deleteRow(row.getTimeUUID("parent_id"));
}
}
for (Map.Entry<TableId, List<RepairedState.Level>> entry : initialLevels.entrySet()) getRepairedState(entry.getKey()).addAll(entry.getValue());
sessions = ImmutableMap.copyOf(loadedSessions);
failOngoingRepairs();
started = true;
}
use of org.apache.cassandra.utils.TimeUUID in project cassandra by apache.
the class LocalSessions method cleanup.
public CleanupSummary cleanup(TableId tid, Collection<Range<Token>> ranges, boolean force) {
Iterable<LocalSession> candidates = Iterables.filter(sessions.values(), ls -> ls.isCompleted() && ls.tableIds.contains(tid) && Range.intersects(ls.ranges, ranges));
ColumnFamilyStore cfs = Schema.instance.getColumnFamilyStoreInstance(tid);
Set<TimeUUID> sessionIds = Sets.newHashSet(Iterables.transform(candidates, s -> s.sessionID));
return cfs.releaseRepairData(sessionIds, force);
}
use of org.apache.cassandra.utils.TimeUUID in project cassandra by apache.
the class LocalSessions method handleFinalizeCommitMessage.
/**
* Finalizes the repair session, completing it as successful.
*
* This only changes the state of the session, it doesn't promote the siloed sstables to repaired. That will happen
* as part of the compaction process, and avoids having to worry about in progress compactions interfering with the
* promotion.
*/
public void handleFinalizeCommitMessage(InetAddressAndPort from, FinalizeCommit commit) {
logger.trace("received {} from {}", commit, from);
TimeUUID sessionID = commit.sessionID;
LocalSession session = getSession(sessionID);
if (session == null) {
logger.warn("Ignoring FinalizeCommit message for unknown repair session {}", sessionID);
return;
}
setStateAndSave(session, FINALIZED);
logger.info("Finalized local repair session {}", sessionID);
}
use of org.apache.cassandra.utils.TimeUUID in project cassandra by apache.
the class LocalSessions method handlePrepareMessage.
/**
* The PrepareConsistentRequest promotes the parent repair session to a consistent incremental
* session, and isolates the data to be repaired from the rest of the table's data
*
* No response is sent to the repair coordinator until the data preparation / isolation has completed
* successfully. If the data preparation fails, a failure message is sent to the coordinator,
* cancelling the session.
*/
public void handlePrepareMessage(InetAddressAndPort from, PrepareConsistentRequest request) {
logger.trace("received {} from {}", request, from);
TimeUUID sessionID = request.parentSession;
InetAddressAndPort coordinator = request.coordinator;
Set<InetAddressAndPort> peers = request.participants;
ActiveRepairService.ParentRepairSession parentSession;
try {
parentSession = getParentRepairSession(sessionID);
} catch (Throwable e) {
logger.error("Error retrieving ParentRepairSession for session {}, responding with failure", sessionID);
sendMessage(coordinator, Message.out(PREPARE_CONSISTENT_RSP, new PrepareConsistentResponse(sessionID, getBroadcastAddressAndPort(), false)));
return;
}
LocalSession session = createSessionUnsafe(sessionID, parentSession, peers);
putSessionUnsafe(session);
logger.info("Beginning local incremental repair session {}", session);
ExecutorService executor = executorFactory().pooled("Repair-" + sessionID, parentSession.getColumnFamilyStores().size());
KeyspaceRepairManager repairManager = parentSession.getKeyspace().getRepairManager();
RangesAtEndpoint tokenRanges = filterLocalRanges(parentSession.getKeyspace().getName(), parentSession.getRanges());
Future<List<Void>> repairPreparation = prepareSession(repairManager, sessionID, parentSession.getColumnFamilyStores(), tokenRanges, executor, () -> session.getState() != PREPARING);
repairPreparation.addCallback(new FutureCallback<List<Void>>() {
public void onSuccess(@Nullable List<Void> result) {
try {
logger.info("Prepare phase for incremental repair session {} completed", sessionID);
if (!prepareSessionExceptFailed(session))
logger.info("Session {} failed before anticompaction completed", sessionID);
Message<PrepareConsistentResponse> message = Message.out(PREPARE_CONSISTENT_RSP, new PrepareConsistentResponse(sessionID, getBroadcastAddressAndPort(), session.getState() != FAILED));
sendMessage(coordinator, message);
} finally {
executor.shutdown();
}
}
public void onFailure(Throwable t) {
try {
if (Throwables.anyCauseMatches(t, (throwable) -> throwable instanceof CompactionInterruptedException))
logger.info("Anticompaction interrupted for session {}: {}", sessionID, t.getMessage());
else if (Throwables.anyCauseMatches(t, (throwable) -> throwable instanceof NoSuchRepairSessionException))
logger.warn("No such repair session: {}", sessionID);
else
logger.error("Prepare phase for incremental repair session {} failed", sessionID, t);
sendMessage(coordinator, Message.out(PREPARE_CONSISTENT_RSP, new PrepareConsistentResponse(sessionID, getBroadcastAddressAndPort(), false)));
failSession(sessionID, false);
} finally {
executor.shutdown();
}
}
});
}
Aggregations