use of com.apple.foundationdb.record.IsolationLevel in project fdb-record-layer by FoundationDB.
the class BitmapValueIndexMaintainer method evaluateAggregateFunction.
@Override
@Nonnull
public CompletableFuture<Tuple> evaluateAggregateFunction(@Nonnull IndexAggregateFunction function, @Nonnull TupleRange range, @Nonnull IsolationLevel isolationveLevel) {
if (!function.getName().equals(AGGREGATE_FUNCTION_NAME)) {
throw new MetaDataException("this index does not support aggregate function: " + function);
}
final RecordCursor<IndexEntry> cursor = scan(IndexScanType.BY_GROUP, range, null, new ScanProperties(ExecuteProperties.newBuilder().setIsolationLevel(isolationveLevel).build()));
final int groupPrefixSize = getGroupingCount();
long startPosition = 0;
if (range.getLow() != null && range.getLow().size() > groupPrefixSize) {
startPosition = range.getLow().getLong(groupPrefixSize);
}
int size = entrySize;
if (range.getHigh() != null && range.getHigh().size() > groupPrefixSize) {
long endPosition = range.getHigh().getLong(groupPrefixSize);
if (size > endPosition - startPosition) {
// Narrow size to what can actually be passed through from scan.
size = (int) (endPosition - startPosition);
}
}
return cursor.reduce(new BitmapAggregator(startPosition, size), (combined, kv) -> combined.append(kv.getKey().getLong(kv.getKeySize() - 1), kv.getValue().getBytes(0))).thenApply(combined -> Tuple.from(combined.asByteArray()));
}
use of com.apple.foundationdb.record.IsolationLevel in project fdb-record-layer by FoundationDB.
the class IndexingByRecords method buildEndpoints.
@Nonnull
private CompletableFuture<TupleRange> buildEndpoints(@Nonnull FDBRecordStore store, @Nonnull RangeSet rangeSet, @Nullable AtomicLong recordsScanned) {
boolean isIdempotent = store.getIndexMaintainer(common.getIndex()).isIdempotent();
final IsolationLevel isolationLevel = isIdempotent ? // before this method's query) will be re-indexed.
IsolationLevel.SNAPSHOT : IsolationLevel.SERIALIZABLE;
final ExecuteProperties limit1 = ExecuteProperties.newBuilder().setReturnedRowLimit(1).setIsolationLevel(isolationLevel).build();
final ScanProperties forward = new ScanProperties(limit1);
RecordCursor<FDBStoredRecord<Message>> beginCursor = store.scanRecords(recordsRange, null, forward);
CompletableFuture<Tuple> begin = beginCursor.onNext().thenCompose(result -> {
if (result.hasNext()) {
Tuple firstTuple = result.get().getPrimaryKey();
return buildRange(store, null, firstTuple, recordsScanned).thenApply(vignore -> firstTuple);
} else {
// Empty range -- add the whole thing.
return rangeSet.insertRange(store.ensureContextActive(), null, null).thenApply(bignore -> null);
}
});
final ScanProperties backward = new ScanProperties(limit1, true);
RecordCursor<FDBStoredRecord<Message>> endCursor = store.scanRecords(recordsRange, null, backward);
CompletableFuture<Tuple> end = endCursor.onNext().thenCompose(result -> {
if (result.hasNext()) {
Tuple lastTuple = result.get().getPrimaryKey();
return buildRange(store, lastTuple, null, recordsScanned).thenApply(vignore -> lastTuple);
} else {
// by the above future, so this has nothing to do.
return CompletableFuture.completedFuture(null);
}
});
return begin.thenCombine(end, (firstTuple, lastTuple) -> {
if (firstTuple == null || firstTuple.equals(lastTuple)) {
return null;
} else {
return new TupleRange(firstTuple, lastTuple, EndpointType.RANGE_INCLUSIVE, EndpointType.RANGE_EXCLUSIVE);
}
});
}
use of com.apple.foundationdb.record.IsolationLevel in project fdb-record-layer by FoundationDB.
the class IndexingMultiTargetByRecords method buildRangeOnly.
@Nonnull
private CompletableFuture<Boolean> buildRangeOnly(@Nonnull FDBRecordStore store, byte[] startBytes, byte[] endBytes, @Nonnull AtomicLong recordsScanned) {
// return false when done
/* Multi target consistency:
* 1. Identify missing ranges from only the first index
* 2. Update all indexes' range sets as the indexes are built - each inserted range is validated as empty.
* 3. While each index as readable, we validate that its range is completely built.
*/
validateSameMetadataOrThrow(store);
RangeSet rangeSet = new RangeSet(store.indexRangeSubspace(common.getPrimaryIndex()));
AsyncIterator<Range> ranges = rangeSet.missingRanges(store.ensureContextActive(), startBytes, endBytes).iterator();
final List<Index> targetIndexes = common.getTargetIndexes();
final List<RangeSet> targetRangeSets = targetIndexes.stream().map(targetIndex -> new RangeSet(store.indexRangeSubspace(targetIndex))).collect(Collectors.toList());
final boolean isIdempotent = areTheyAllIdempotent(store, targetIndexes);
final IsolationLevel isolationLevel = isIdempotent ? IsolationLevel.SNAPSHOT : IsolationLevel.SERIALIZABLE;
final ExecuteProperties.Builder executeProperties = ExecuteProperties.newBuilder().setIsolationLevel(isolationLevel).setReturnedRowLimit(// always respect limit in this path; +1 allows a continuation item
getLimit() + 1);
final ScanProperties scanProperties = new ScanProperties(executeProperties.build());
return ranges.onHasNext().thenCompose(hasNext -> {
if (Boolean.FALSE.equals(hasNext)) {
// no more missing ranges - all done
return AsyncUtil.READY_FALSE;
}
final Range range = ranges.next();
final Tuple rangeStart = RangeSet.isFirstKey(range.begin) ? null : Tuple.fromBytes(range.begin);
final Tuple rangeEnd = RangeSet.isFinalKey(range.end) ? null : Tuple.fromBytes(range.end);
final TupleRange tupleRange = TupleRange.between(rangeStart, rangeEnd);
RecordCursor<FDBStoredRecord<Message>> cursor = store.scanRecords(tupleRange, null, scanProperties);
final AtomicReference<RecordCursorResult<FDBStoredRecord<Message>>> lastResult = new AtomicReference<>(RecordCursorResult.exhausted());
final AtomicBoolean hasMore = new AtomicBoolean(true);
return iterateRangeOnly(store, cursor, this::getRecordIfTypeMatch, lastResult, hasMore, recordsScanned, isIdempotent).thenApply(vignore -> hasMore.get() ? lastResult.get().get().getPrimaryKey() : rangeEnd).thenCompose(cont -> insertRanges(store.ensureContextActive(), targetRangeSets, packOrNull(rangeStart), packOrNull(cont)).thenApply(ignore -> !Objects.equals(cont, rangeEnd)));
});
}
use of com.apple.foundationdb.record.IsolationLevel in project fdb-record-layer by FoundationDB.
the class IndexingMultiTargetByRecords method rebuildRangeOnly.
@Nonnull
private CompletableFuture<Tuple> rebuildRangeOnly(@Nonnull FDBRecordStore store, Tuple cont, @Nonnull AtomicLong recordsScanned) {
validateSameMetadataOrThrow(store);
final boolean isIdempotent = areTheyAllIdempotent(store, common.getTargetIndexes());
final IsolationLevel isolationLevel = isIdempotent ? IsolationLevel.SNAPSHOT : IsolationLevel.SERIALIZABLE;
final ExecuteProperties.Builder executeProperties = ExecuteProperties.newBuilder().setIsolationLevel(isolationLevel);
final ScanProperties scanProperties = new ScanProperties(executeProperties.build());
final TupleRange tupleRange = TupleRange.between(cont, null);
RecordCursor<FDBStoredRecord<Message>> cursor = store.scanRecords(tupleRange, null, scanProperties);
final AtomicReference<RecordCursorResult<FDBStoredRecord<Message>>> lastResult = new AtomicReference<>(RecordCursorResult.exhausted());
final AtomicBoolean hasMore = new AtomicBoolean(true);
return iterateRangeOnly(store, cursor, this::getRecordIfTypeMatch, lastResult, hasMore, recordsScanned, isIdempotent).thenApply(vignore -> hasMore.get() ? lastResult.get().get().getPrimaryKey() : null);
}
use of com.apple.foundationdb.record.IsolationLevel in project fdb-record-layer by FoundationDB.
the class RecordQueryScoreForRankPlan method bindScores.
private <M extends Message> CompletableFuture<EvaluationContext> bindScores(@Nonnull FDBRecordStoreBase<M> store, @Nonnull EvaluationContext context, @Nonnull IsolationLevel isolationLevel) {
final List<CompletableFuture<Tuple>> scores = ranks.stream().map(r -> bindScore(store, context, r, isolationLevel)).collect(Collectors.toList());
return AsyncUtil.whenAll(scores).thenApply(vignore -> {
EvaluationContextBuilder builder = context.childBuilder();
for (int i = 0; i < scores.size(); i++) {
final ScoreForRank rank = ranks.get(i);
final Tuple score = store.getContext().joinNow(scores.get(i));
final Object binding;
if (score == null) {
binding = null;
} else if (score == RankedSetIndexHelper.COMPARISON_SKIPPED_SCORE) {
binding = Comparisons.COMPARISON_SKIPPED_BINDING;
} else {
binding = rank.bindingFunction.apply(score);
}
builder.setBinding(rank.bindingName, binding);
}
return builder.build();
});
}
Aggregations