use of com.apple.foundationdb.record.metadata.RecordType in project fdb-record-layer by FoundationDB.
the class FDBRecordStore method rebuildIndexes.
@Nonnull
protected CompletableFuture<Void> rebuildIndexes(@Nonnull Map<Index, List<RecordType>> indexes, @Nonnull Map<Index, CompletableFuture<IndexState>> newStates, @Nonnull List<CompletableFuture<Void>> work, @Nonnull RebuildIndexReason reason, @Nullable Integer oldMetaDataVersion) {
Iterator<Map.Entry<Index, List<RecordType>>> indexIter = indexes.entrySet().iterator();
return AsyncUtil.whileTrue(() -> {
Iterator<CompletableFuture<Void>> workIter = work.iterator();
while (workIter.hasNext()) {
CompletableFuture<Void> workItem = workIter.next();
if (workItem.isDone()) {
// Just for error handling.
context.asyncToSync(FDBStoreTimer.Waits.WAIT_ERROR_CHECK, workItem);
workIter.remove();
}
}
while (work.size() < MAX_PARALLEL_INDEX_REBUILD) {
if (indexIter.hasNext()) {
Map.Entry<Index, List<RecordType>> indexItem = indexIter.next();
Index index = indexItem.getKey();
List<RecordType> recordTypes = indexItem.getValue();
final CompletableFuture<Void> rebuildOrMarkIndexSafely = MoreAsyncUtil.handleOnException(() -> newStates.getOrDefault(index, READY_READABLE).thenCompose(indexState -> rebuildOrMarkIndex(index, indexState, recordTypes, reason, oldMetaDataVersion)), exception -> {
// If there is any issue, simply mark the index as disabled without blocking checkVersion
logExceptionAsWarn(KeyValueLogMessage.build("unable to build index", LogMessageKeys.INDEX_NAME, index.getName()), exception);
return markIndexDisabled(index).thenApply(b -> null);
});
work.add(rebuildOrMarkIndexSafely);
} else {
break;
}
}
if (work.isEmpty()) {
return AsyncUtil.READY_FALSE;
}
return AsyncUtil.whenAny(work).thenApply(v -> true);
}, getExecutor());
}
use of com.apple.foundationdb.record.metadata.RecordType in project fdb-record-layer by FoundationDB.
the class FDBRecordStore method getStatesForRebuildIndexes.
@Nonnull
protected Map<Index, CompletableFuture<IndexState>> getStatesForRebuildIndexes(@Nullable UserVersionChecker userVersionChecker, @Nonnull Map<Index, List<RecordType>> indexes, @Nonnull Supplier<CompletableFuture<Long>> lazyRecordCount, @Nonnull Supplier<CompletableFuture<Long>> lazyRecordsSize, boolean newStore, int oldMetaDataVersion, int oldFormatVersion) {
Map<Index, CompletableFuture<IndexState>> newStates = new HashMap<>();
for (Map.Entry<Index, List<RecordType>> entry : indexes.entrySet()) {
Index index = entry.getKey();
List<RecordType> recordTypes = entry.getValue();
boolean indexOnNewRecordTypes = areAllRecordTypesSince(recordTypes, oldMetaDataVersion);
CompletableFuture<IndexState> stateFuture = userVersionChecker == null ? lazyRecordCount.get().thenApply(recordCount -> FDBRecordStore.disabledIfTooManyRecordsForRebuild(recordCount, indexOnNewRecordTypes)) : userVersionChecker.needRebuildIndex(index, lazyRecordCount, lazyRecordsSize, indexOnNewRecordTypes);
if (index.getType().equals(IndexTypes.VERSION) && !newStore && oldFormatVersion < SAVE_VERSION_WITH_RECORD_FORMAT_VERSION && !useOldVersionFormat()) {
stateFuture = stateFuture.thenApply(state -> {
if (IndexState.READABLE.equals(state)) {
// build and some versions won't be indexed correctly.
return IndexState.DISABLED;
}
return state;
});
}
newStates.put(index, stateFuture);
}
return newStates;
}
use of com.apple.foundationdb.record.metadata.RecordType in project fdb-record-layer by FoundationDB.
the class FDBRecordStore method getSnapshotRecordCountForRecordType.
@Override
public CompletableFuture<Long> getSnapshotRecordCountForRecordType(@Nonnull String recordTypeName, @Nonnull IndexQueryabilityFilter indexQueryabilityFilter) {
// A COUNT index on this record type.
IndexAggregateFunction aggregateFunction = IndexFunctionHelper.count(EmptyKeyExpression.EMPTY);
Optional<IndexMaintainer> indexMaintainer = IndexFunctionHelper.indexMaintainerForAggregateFunction(this, aggregateFunction, Collections.singletonList(recordTypeName), indexQueryabilityFilter);
if (indexMaintainer.isPresent()) {
return indexMaintainer.get().evaluateAggregateFunction(aggregateFunction, TupleRange.ALL, IsolationLevel.SNAPSHOT).thenApply(tuple -> tuple.getLong(0));
}
// A universal COUNT index by record type.
// In fact, any COUNT index by record type that applied to this record type would work, no matter what other
// types it applied to.
aggregateFunction = IndexFunctionHelper.count(Key.Expressions.recordType());
indexMaintainer = IndexFunctionHelper.indexMaintainerForAggregateFunction(this, aggregateFunction, Collections.emptyList(), indexQueryabilityFilter);
if (indexMaintainer.isPresent()) {
RecordType recordType = getRecordMetaData().getRecordType(recordTypeName);
return indexMaintainer.get().evaluateAggregateFunction(aggregateFunction, TupleRange.allOf(recordType.getRecordTypeKeyTuple()), IsolationLevel.SNAPSHOT).thenApply(tuple -> tuple.getLong(0));
}
throw recordCoreException("Require a COUNT index on " + recordTypeName);
}
use of com.apple.foundationdb.record.metadata.RecordType in project fdb-record-layer by FoundationDB.
the class FDBRecordStore method singleRecordTypeWithPrefixKey.
@Nullable
@SuppressWarnings("PMD.CompareObjectsWithEquals")
protected RecordType singleRecordTypeWithPrefixKey(@Nonnull Map<Index, List<RecordType>> indexes) {
RecordType recordType = null;
for (List<RecordType> entry : indexes.values()) {
Collection<RecordType> types = entry != null ? entry : getRecordMetaData().getRecordTypes().values();
if (types.size() != 1) {
return null;
}
RecordType type1 = entry != null ? entry.get(0) : types.iterator().next();
if (recordType == null) {
if (!type1.primaryKeyHasRecordTypePrefix()) {
return null;
}
recordType = type1;
} else if (type1 != recordType) {
return null;
}
}
return recordType;
}
use of com.apple.foundationdb.record.metadata.RecordType in project fdb-record-layer by FoundationDB.
the class IndexingByRecords method computeRecordsRange.
@Nonnull
private TupleRange computeRecordsRange() {
Tuple low = null;
Tuple high = null;
for (RecordType recordType : common.getAllRecordTypes()) {
if (!recordType.primaryKeyHasRecordTypePrefix() || recordType.isSynthetic()) {
// If any of the types to build for does not have a prefix, give up.
return TupleRange.ALL;
}
Tuple prefix = recordType.getRecordTypeKeyTuple();
if (low == null) {
low = high = prefix;
} else {
if (low.compareTo(prefix) > 0) {
low = prefix;
}
if (high.compareTo(prefix) < 0) {
high = prefix;
}
}
}
if (low == null) {
return TupleRange.ALL;
} else {
// Both ends inclusive.
return new TupleRange(low, high, EndpointType.RANGE_INCLUSIVE, EndpointType.RANGE_INCLUSIVE);
}
}
Aggregations