use of com.apple.foundationdb.record.RecordCursor in project fdb-record-layer by FoundationDB.
the class ComposedBitmapIndexCursor method create.
@Nonnull
public static ComposedBitmapIndexCursor create(@Nonnull List<Function<byte[], RecordCursor<IndexEntry>>> cursorFunctions, @Nonnull Composer composer, @Nullable byte[] byteContinuation, @Nullable FDBStoreTimer timer) {
if (cursorFunctions.size() < 2) {
throw new RecordCoreArgumentException("not enough child cursors provided to ComposedBitmapIndexCursor").addLogInfo(LogMessageKeys.CHILD_COUNT, cursorFunctions.size());
}
final List<MergeCursorState<IndexEntry>> cursorStates = new ArrayList<>(cursorFunctions.size());
final ComposedBitmapIndexContinuation continuation = ComposedBitmapIndexContinuation.from(byteContinuation, cursorFunctions.size());
int i = 0;
for (Function<byte[], RecordCursor<IndexEntry>> cursorFunction : cursorFunctions) {
cursorStates.add(MergeCursorState.from(cursorFunction, continuation.getContinuation(i)));
i++;
}
return new ComposedBitmapIndexCursor(cursorStates, timer, composer);
}
use of com.apple.foundationdb.record.RecordCursor in project fdb-record-layer by FoundationDB.
the class ComposedBitmapIndexQueryPlan method executePlan.
@Nonnull
@Override
public <M extends Message> RecordCursor<QueryResult> executePlan(@Nonnull final FDBRecordStoreBase<M> store, @Nonnull final EvaluationContext context, @Nullable final byte[] continuation, @Nonnull final ExecuteProperties executeProperties) {
final ExecuteProperties scanExecuteProperties = executeProperties.getSkip() > 0 ? executeProperties.clearSkipAndAdjustLimit() : executeProperties;
final List<Function<byte[], RecordCursor<IndexEntry>>> cursorFunctions = indexPlans.stream().map(RecordQueryCoveringIndexPlan::getIndexPlan).map(scan -> (Function<byte[], RecordCursor<IndexEntry>>) childContinuation -> scan.executeEntries(store, context, childContinuation, scanExecuteProperties)).collect(Collectors.toList());
return ComposedBitmapIndexCursor.create(cursorFunctions, composer, continuation, store.getTimer()).filter(indexEntry -> indexEntry.getValue().get(0) != null).map(indexPlans.get(0).indexEntryToQueriedRecord(store)).map(QueryResult::of);
}
use of com.apple.foundationdb.record.RecordCursor in project fdb-record-layer by FoundationDB.
the class RecordQueryUnionPlanBase method executePlan.
@Nonnull
@Override
public <M extends Message> RecordCursor<QueryResult> executePlan(@Nonnull final FDBRecordStoreBase<M> store, @Nonnull final EvaluationContext context, @Nullable final byte[] continuation, @Nonnull final ExecuteProperties executeProperties) {
final ExecuteProperties childExecuteProperties;
// Can pass the limit down to all sides, since that is the most we'll take total.
if (executeProperties.getSkip() > 0) {
childExecuteProperties = executeProperties.clearSkipAndAdjustLimit();
} else {
childExecuteProperties = executeProperties;
}
final List<Function<byte[], RecordCursor<FDBQueriedRecord<M>>>> childCursorFunctions = getChildStream().map(childPlan -> (Function<byte[], RecordCursor<FDBQueriedRecord<M>>>) ((byte[] childContinuation) -> childPlan.executePlan(store, context, childContinuation, childExecuteProperties).map(result -> result.getQueriedRecord(0)))).collect(Collectors.toList());
return createUnionCursor(store, childCursorFunctions, continuation).skipThenLimit(executeProperties.getSkip(), executeProperties.getReturnedRowLimit()).map(QueryResult::of);
}
use of com.apple.foundationdb.record.RecordCursor in project fdb-record-layer by FoundationDB.
the class StandardIndexMaintainer method validateMissingEntries.
/**
* Validate entries in the index. It scans the records and checks if the index entries associated with each record
* exist. Note that it may not work for indexes on synthetic record types (e.g., join indexes).
* @param continuation any continuation from a previous validation invocation
* @param scanProperties skip, limit and other properties of the validation
* @return a cursor over records that have no associated index entries including the reason
*/
@Nonnull
protected RecordCursor<InvalidIndexEntry> validateMissingEntries(@Nullable byte[] continuation, @Nonnull ScanProperties scanProperties) {
final Collection<RecordType> recordTypes = state.store.getRecordMetaData().recordTypesForIndex(state.index);
final FDBRecordStoreBase.PipelineSizer pipelineSizer = state.store.getPipelineSizer();
return RecordCursor.flatMapPipelined(cont -> state.store.scanRecords(TupleRange.ALL, cont, scanProperties).filter(rec -> recordTypes.contains(rec.getRecordType())), (record, cont) -> {
List<IndexEntry> filteredIndexEntries = filteredIndexEntries(record);
return RecordCursor.fromList(filteredIndexEntries == null ? Collections.emptyList() : filteredIndexEntries.stream().map(indexEntryWithoutPrimaryKey -> new IndexEntry(indexEntryWithoutPrimaryKey.getIndex(), indexEntryKey(indexEntryWithoutPrimaryKey.getKey(), record.getPrimaryKey()), indexEntryWithoutPrimaryKey.getValue())).map(indexEntry -> Pair.of(indexEntry, record)).collect(Collectors.toList()), cont);
}, continuation, pipelineSizer.getPipelineSize(PipelineOperation.RECORD_FUNCTION)).filterAsync(indexEntryRecordPair -> {
final byte[] keyBytes = state.indexSubspace.pack(indexEntryRecordPair.getLeft().getKey());
return state.transaction.get(keyBytes).thenApply(Objects::isNull);
}, pipelineSizer.getPipelineSize(PipelineOperation.INDEX_ASYNC_FILTER)).map(indexEntryKeyRecordPair -> InvalidIndexEntry.newMissing(indexEntryKeyRecordPair.getLeft(), indexEntryKeyRecordPair.getRight()));
}
use of com.apple.foundationdb.record.RecordCursor in project fdb-record-layer by FoundationDB.
the class ResolverMappingReplicator method copyInternal.
private CompletableFuture<Void> copyInternal(@Nonnull final LocatableResolver replica, @Nonnull final LongAccumulator accumulator, @Nonnull final AtomicInteger counter) {
ExecuteProperties executeProperties = ExecuteProperties.newBuilder().setReturnedRowLimit(transactionRowLimit).setTimeLimit(transactionTimeLimitMillis).setIsolationLevel(IsolationLevel.SNAPSHOT).build();
final AtomicReference<byte[]> continuation = new AtomicReference<>(null);
return AsyncUtil.whileTrue(() -> {
final FDBRecordContext context = runner.openContext();
return primary.getMappingSubspaceAsync().thenCompose(primaryMappingSubspace -> {
RecordCursor<KeyValue> cursor = KeyValueCursor.Builder.withSubspace(primaryMappingSubspace).setScanProperties(new ScanProperties(executeProperties)).setContext(context).setContinuation(continuation.get()).build();
return cursor.forEachResultAsync(result -> {
KeyValue kv = result.get();
final String mappedString = primaryMappingSubspace.unpack(kv.getKey()).getString(0);
final ResolverResult mappedValue = valueDeserializer.apply(kv.getValue());
accumulator.accumulate(mappedValue.getValue());
counter.incrementAndGet();
return replica.setMapping(context, mappedString, mappedValue);
}).thenCompose(lastResult -> context.commitAsync().thenRun(() -> {
byte[] nextContinuationBytes = lastResult.getContinuation().toBytes();
if (LOGGER.isInfoEnabled()) {
LOGGER.info(KeyValueLogMessage.of("committing batch", LogMessageKeys.SCANNED_SO_FAR, counter.get(), LogMessageKeys.NEXT_CONTINUATION, ByteArrayUtil2.loggable(nextContinuationBytes)));
}
continuation.set(nextContinuationBytes);
})).whenComplete((vignore, eignore) -> cursor.close()).thenApply(vignore -> Objects.nonNull(continuation.get()));
});
}, runner.getExecutor());
}
Aggregations