use of org.apache.cassandra.index.Index.IndexBuildingSupport in project cassandra by apache.
the class SecondaryIndexManager method buildIndexesBlocking.
/**
* Performs a blocking (re)indexing/recovery of the specified SSTables for the specified indexes.
*
* If the index doesn't support ALL {@link Index.LoadType} it performs a recovery {@link Index#getRecoveryTaskSupport()}
* instead of a build {@link Index#getBuildTaskSupport()}
*
* @param sstables the SSTables to be (re)indexed
* @param indexes the indexes to be (re)built for the specifed SSTables
* @param isFullRebuild True if this method is invoked as a full index rebuild, false otherwise
*/
@SuppressWarnings({ "unchecked" })
private void buildIndexesBlocking(Collection<SSTableReader> sstables, Set<Index> indexes, boolean isFullRebuild) {
if (indexes.isEmpty())
return;
// Mark all indexes as building: this step must happen first, because if any index can't be marked, the whole
// process needs to abort
markIndexesBuilding(indexes, isFullRebuild, false);
// Build indexes in a try/catch, so that any index not marked as either built or failed will be marked as failed:
final Set<Index> builtIndexes = Sets.newConcurrentHashSet();
final Set<Index> unbuiltIndexes = Sets.newConcurrentHashSet();
// Any exception thrown during index building that could be suppressed by the finally block
Exception accumulatedFail = null;
try {
logger.info("Submitting index {} of {} for data in {}", isFullRebuild ? "recovery" : "build", indexes.stream().map(i -> i.getIndexMetadata().name).collect(Collectors.joining(",")), sstables.stream().map(SSTableReader::toString).collect(Collectors.joining(",")));
// Group all building tasks
Map<Index.IndexBuildingSupport, Set<Index>> byType = new HashMap<>();
for (Index index : indexes) {
IndexBuildingSupport buildOrRecoveryTask = isFullRebuild ? index.getBuildTaskSupport() : index.getRecoveryTaskSupport();
Set<Index> stored = byType.computeIfAbsent(buildOrRecoveryTask, i -> new HashSet<>());
stored.add(index);
}
// Schedule all index building tasks with a callback to mark them as built or failed
List<Future<?>> futures = new ArrayList<>(byType.size());
byType.forEach((buildingSupport, groupedIndexes) -> {
SecondaryIndexBuilder builder = buildingSupport.getIndexBuildTask(baseCfs, groupedIndexes, sstables);
final AsyncPromise<Object> build = new AsyncPromise<>();
CompactionManager.instance.submitIndexBuild(builder).addCallback(new FutureCallback() {
@Override
public void onFailure(Throwable t) {
logAndMarkIndexesFailed(groupedIndexes, t, false);
unbuiltIndexes.addAll(groupedIndexes);
build.tryFailure(t);
}
@Override
public void onSuccess(Object o) {
groupedIndexes.forEach(i -> markIndexBuilt(i, isFullRebuild));
logger.info("Index build of {} completed", getIndexNames(groupedIndexes));
builtIndexes.addAll(groupedIndexes);
build.trySuccess(o);
}
});
futures.add(build);
});
// Finally wait for the index builds to finish and flush the indexes that built successfully
FBUtilities.waitOnFutures(futures);
} catch (Exception e) {
accumulatedFail = e;
throw e;
} finally {
try {
// Fail any indexes that couldn't be marked
Set<Index> failedIndexes = Sets.difference(indexes, Sets.union(builtIndexes, unbuiltIndexes));
if (!failedIndexes.isEmpty()) {
logAndMarkIndexesFailed(failedIndexes, accumulatedFail, false);
}
// Flush all built indexes with an aynchronous callback to log the success or failure of the flush
flushIndexesBlocking(builtIndexes, new FutureCallback() {
String indexNames = StringUtils.join(builtIndexes.stream().map(i -> i.getIndexMetadata().name).collect(Collectors.toList()), ',');
@Override
public void onFailure(Throwable ignored) {
logger.info("Index flush of {} failed", indexNames);
}
@Override
public void onSuccess(Object ignored) {
logger.info("Index flush of {} completed", indexNames);
}
});
} catch (Exception e) {
if (accumulatedFail != null) {
accumulatedFail.addSuppressed(e);
} else {
throw e;
}
}
}
}
Aggregations