use of com.apple.foundationdb.record.IndexState in project fdb-record-layer by FoundationDB.
the class IndexingBase method handleStateAndDoBuildIndexAsync.
@Nonnull
private CompletableFuture<Void> handleStateAndDoBuildIndexAsync(boolean markReadable, KeyValueLogMessage message) {
/*
* Multi target:
* The primary and follower indexes must the same state.
* If the primary is disabled, a follower is write_only/readable, and the policy for write_only/readable is
* rebuild - the follower's state will be cleared.
* If the primary is cleared, all the followers are cleared (must match stamps/ranges).
* If the primary is write_only, and the followers' stamps/ranges do not match, it would be caught during indexing.
*/
final List<Index> targetIndexes = common.getTargetIndexes();
final Index primaryIndex = targetIndexes.get(0);
return getRunner().runAsync(context -> openRecordStore(context).thenCompose(store -> {
IndexState indexState = store.getIndexState(primaryIndex);
if (isScrubber) {
validateOrThrowEx(indexState == IndexState.READABLE, "Scrubber was called for a non-readable index. Index:" + primaryIndex.getName() + " State: " + indexState);
return setScrubberTypeOrThrow(store).thenApply(ignore -> true);
}
OnlineIndexer.IndexingPolicy.DesiredAction desiredAction = policy.getStateDesiredAction(indexState);
if (desiredAction == OnlineIndexer.IndexingPolicy.DesiredAction.ERROR) {
throw new ValidationException("Index state is not as expected", LogMessageKeys.INDEX_NAME, primaryIndex.getName(), LogMessageKeys.INDEX_VERSION, primaryIndex.getLastModifiedVersion(), LogMessageKeys.INDEX_STATE, indexState);
}
boolean shouldClear = desiredAction == OnlineIndexer.IndexingPolicy.DesiredAction.REBUILD;
boolean shouldBuild = shouldClear || indexState != IndexState.READABLE;
message.addKeyAndValue(LogMessageKeys.INITIAL_INDEX_STATE, indexState);
message.addKeyAndValue(LogMessageKeys.INDEXING_POLICY_DESIRED_ACTION, desiredAction);
message.addKeyAndValue(LogMessageKeys.SHOULD_BUILD_INDEX, shouldBuild);
message.addKeyAndValue(LogMessageKeys.SHOULD_CLEAR_EXISTING_DATA, shouldClear);
if (!shouldBuild) {
// do not index
return AsyncUtil.READY_FALSE;
}
List<Index> indexesToClear = new ArrayList<>(targetIndexes.size());
if (shouldClear) {
indexesToClear.add(primaryIndex);
// The code can work without this line, but it'll save probing the missing ranges
forceStampOverwrite = true;
}
boolean continuedBuild = !shouldClear && indexState == IndexState.WRITE_ONLY;
for (Index targetIndex : targetIndexes.subList(1, targetIndexes.size())) {
// Must follow the primary index' status
IndexState state = store.getIndexState(targetIndex);
if (state != indexState) {
if (policy.getStateDesiredAction(state) != OnlineIndexer.IndexingPolicy.DesiredAction.REBUILD || continuedBuild) {
throw new ValidationException("A target index state doesn't match the primary index state", LogMessageKeys.INDEX_NAME, primaryIndex.getName(), LogMessageKeys.INDEX_STATE, indexState, LogMessageKeys.TARGET_INDEX_NAME, targetIndex.getName(), LogMessageKeys.TARGET_INDEX_STATE, state);
}
// just clear this one, the primary is disabled
indexesToClear.add(targetIndex);
} else if (shouldClear) {
indexesToClear.add(targetIndex);
}
}
return AsyncUtil.whenAll(indexesToClear.stream().map(store::clearAndMarkIndexWriteOnly).collect(Collectors.toList())).thenCompose(vignore -> markIndexesWriteOnly(continuedBuild, store)).thenCompose(vignore -> setIndexingTypeOrThrow(store, continuedBuild)).thenApply(ignore -> true);
}), common.indexLogMessageKeyValues("IndexingBase::handleIndexingState")).thenCompose(doIndex -> doIndex ? buildIndexInternalAsync().thenApply(ignore -> markReadable) : AsyncUtil.READY_FALSE).thenCompose(this::markIndexReadable).thenApply(ignore -> null);
}
Aggregations