Search in sources :

Example 41 with KeyValue

use of com.apple.foundationdb.KeyValue in project fdb-record-layer by FoundationDB.

the class FDBRecordStore method scanTypedRecords.

@Nonnull
public <M extends Message> RecordCursor<FDBStoredRecord<M>> scanTypedRecords(@Nonnull RecordSerializer<M> typedSerializer, @Nullable final Tuple low, @Nullable final Tuple high, @Nonnull final EndpointType lowEndpoint, @Nonnull final EndpointType highEndpoint, @Nullable byte[] continuation, @Nonnull ScanProperties scanProperties) {
    final RecordMetaData metaData = metaDataProvider.getRecordMetaData();
    final Subspace recordsSubspace = recordsSubspace();
    final SplitHelper.SizeInfo sizeInfo = new SplitHelper.SizeInfo();
    final RecordCursor<FDBRawRecord> rawRecords;
    if (metaData.isSplitLongRecords()) {
        RecordCursor<KeyValue> keyValues = KeyValueCursor.Builder.withSubspace(recordsSubspace).setContext(context).setContinuation(continuation).setLow(low, lowEndpoint).setHigh(high, highEndpoint).setScanProperties(scanProperties.with(ExecuteProperties::clearRowAndTimeLimits).with(ExecuteProperties::clearState)).build();
        rawRecords = new SplitHelper.KeyValueUnsplitter(context, recordsSubspace, keyValues, useOldVersionFormat(), sizeInfo, scanProperties.isReverse(), new CursorLimitManager(context, scanProperties.with(ExecuteProperties::clearReturnedRowLimit))).skip(scanProperties.getExecuteProperties().getSkip()).limitRowsTo(scanProperties.getExecuteProperties().getReturnedRowLimit());
    } else {
        KeyValueCursor.Builder keyValuesBuilder = KeyValueCursor.Builder.withSubspace(recordsSubspace).setContext(context).setContinuation(continuation).setLow(low, lowEndpoint).setHigh(high, highEndpoint);
        if (omitUnsplitRecordSuffix) {
            rawRecords = keyValuesBuilder.setScanProperties(scanProperties).build().map(kv -> {
                sizeInfo.set(kv);
                Tuple primaryKey = SplitHelper.unpackKey(recordsSubspace, kv);
                return new FDBRawRecord(primaryKey, kv.getValue(), null, sizeInfo);
            });
        } else {
            final ScanProperties finalScanProperties = scanProperties.with(executeProperties -> {
                final ExecuteProperties.Builder builder = executeProperties.toBuilder().clearTimeLimit().clearSkipAndAdjustLimit().clearState();
                int returnedRowLimit = builder.getReturnedRowLimitOrMax();
                if (returnedRowLimit != Integer.MAX_VALUE) {
                    // Adjust limit to twice the supplied limit in case there are versions in the records
                    builder.setReturnedRowLimit(2 * returnedRowLimit);
                }
                return builder.build();
            });
            rawRecords = new SplitHelper.KeyValueUnsplitter(context, recordsSubspace, keyValuesBuilder.setScanProperties(finalScanProperties).build(), useOldVersionFormat(), sizeInfo, scanProperties.isReverse(), new CursorLimitManager(context, scanProperties.with(ExecuteProperties::clearReturnedRowLimit))).skip(scanProperties.getExecuteProperties().getSkip()).limitRowsTo(scanProperties.getExecuteProperties().getReturnedRowLimit());
        }
    }
    RecordCursor<FDBStoredRecord<M>> result = rawRecords.mapPipelined(rawRecord -> {
        final Optional<CompletableFuture<FDBRecordVersion>> versionFutureOptional;
        if (useOldVersionFormat()) {
            // Older format versions: do a separate read to get the version.
            versionFutureOptional = loadRecordVersionAsync(rawRecord.getPrimaryKey(), scanProperties.getExecuteProperties().getIsolationLevel().isSnapshot());
        } else {
            // Newer format versions: the version is either in the record or it is not -- do not do another read.
            versionFutureOptional = Optional.empty();
        }
        return deserializeRecord(typedSerializer, rawRecord, metaData, versionFutureOptional);
    }, pipelineSizer.getPipelineSize(PipelineOperation.KEY_TO_RECORD));
    return context.instrument(FDBStoreTimer.Events.SCAN_RECORDS, result);
}
Also used : LogMessageKeys(com.apple.foundationdb.record.logging.LogMessageKeys) UnaryOperator(java.util.function.UnaryOperator) MetaDataException(com.apple.foundationdb.record.metadata.MetaDataException) RecordSerializer(com.apple.foundationdb.record.provider.common.RecordSerializer) Subspace(com.apple.foundationdb.subspace.Subspace) MutationType(com.apple.foundationdb.MutationType) RecordCoreException(com.apple.foundationdb.record.RecordCoreException) Map(java.util.Map) RecordIndexUniquenessViolation(com.apple.foundationdb.record.RecordIndexUniquenessViolation) QueryToKeyMatcher(com.apple.foundationdb.record.query.QueryToKeyMatcher) InvalidProtocolBufferException(com.google.protobuf.InvalidProtocolBufferException) Query(com.apple.foundationdb.record.query.expressions.Query) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) Set(java.util.Set) TupleRange(com.apple.foundationdb.record.TupleRange) KeySpacePath(com.apple.foundationdb.record.provider.foundationdb.keyspace.KeySpacePath) ByteOrder(java.nio.ByteOrder) SyntheticRecordType(com.apple.foundationdb.record.metadata.SyntheticRecordType) RecordMetaDataProvider(com.apple.foundationdb.record.RecordMetaDataProvider) RecordStoreState(com.apple.foundationdb.record.RecordStoreState) TupleHelpers(com.apple.foundationdb.tuple.TupleHelpers) API(com.apple.foundationdb.annotation.API) FunctionNames(com.apple.foundationdb.record.FunctionNames) RecordMetaData(com.apple.foundationdb.record.RecordMetaData) IndexAggregateFunction(com.apple.foundationdb.record.metadata.IndexAggregateFunction) AsyncUtil(com.apple.foundationdb.async.AsyncUtil) RecordQuery(com.apple.foundationdb.record.query.RecordQuery) RangeSet(com.apple.foundationdb.async.RangeSet) RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) Supplier(java.util.function.Supplier) FormerIndex(com.apple.foundationdb.record.metadata.FormerIndex) ArrayList(java.util.ArrayList) ByteScanLimiter(com.apple.foundationdb.record.ByteScanLimiter) ParameterRelationshipGraph(com.apple.foundationdb.record.query.ParameterRelationshipGraph) LoggableException(com.apple.foundationdb.util.LoggableException) CloseableAsyncIterator(com.apple.foundationdb.async.CloseableAsyncIterator) IndexRecordFunction(com.apple.foundationdb.record.metadata.IndexRecordFunction) Nullable(javax.annotation.Nullable) ByteArrayUtil2(com.apple.foundationdb.tuple.ByteArrayUtil2) IsolationLevel(com.apple.foundationdb.record.IsolationLevel) CursorLimitManager(com.apple.foundationdb.record.cursors.CursorLimitManager) ExecuteState(com.apple.foundationdb.record.ExecuteState) AtomicLong(java.util.concurrent.atomic.AtomicLong) RecordType(com.apple.foundationdb.record.metadata.RecordType) Index(com.apple.foundationdb.record.metadata.Index) DynamicMessageRecordSerializer(com.apple.foundationdb.record.provider.common.DynamicMessageRecordSerializer) SyntheticRecordPlanner(com.apple.foundationdb.record.query.plan.synthetic.SyntheticRecordPlanner) IndexEntry(com.apple.foundationdb.record.IndexEntry) LoggerFactory(org.slf4j.LoggerFactory) RecordCoreStorageException(com.apple.foundationdb.record.RecordCoreStorageException) ByteBuffer(java.nio.ByteBuffer) RecordQueryPlanner(com.apple.foundationdb.record.query.plan.RecordQueryPlanner) Transaction(com.apple.foundationdb.Transaction) Tuple(com.apple.foundationdb.tuple.Tuple) Range(com.apple.foundationdb.Range) KeyValueLogMessage(com.apple.foundationdb.record.logging.KeyValueLogMessage) PipelineOperation(com.apple.foundationdb.record.PipelineOperation) RecordMetaDataProto(com.apple.foundationdb.record.RecordMetaDataProto) ByteArrayUtil(com.apple.foundationdb.tuple.ByteArrayUtil) KeyValue(com.apple.foundationdb.KeyValue) ImmutableMap(com.google.common.collect.ImmutableMap) Predicate(java.util.function.Predicate) Collection(java.util.Collection) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) IndexQueryabilityFilter(com.apple.foundationdb.record.query.IndexQueryabilityFilter) AndComponent(com.apple.foundationdb.record.query.expressions.AndComponent) RecordCoreArgumentException(com.apple.foundationdb.record.RecordCoreArgumentException) Collectors(java.util.stream.Collectors) ByteString(com.google.protobuf.ByteString) List(java.util.List) EvaluationContext(com.apple.foundationdb.record.EvaluationContext) AggregateFunctionNotSupportedException(com.apple.foundationdb.record.AggregateFunctionNotSupportedException) RecordTypeKeyComparison(com.apple.foundationdb.record.query.expressions.RecordTypeKeyComparison) IndexTypes(com.apple.foundationdb.record.metadata.IndexTypes) Optional(java.util.Optional) MutableRecordStoreState(com.apple.foundationdb.record.MutableRecordStoreState) RecordTypeOrBuilder(com.apple.foundationdb.record.metadata.RecordTypeOrBuilder) SyntheticRecordFromStoredRecordPlan(com.apple.foundationdb.record.query.plan.synthetic.SyntheticRecordFromStoredRecordPlan) SpotBugsSuppressWarnings(com.apple.foundationdb.annotation.SpotBugsSuppressWarnings) Descriptors(com.google.protobuf.Descriptors) AsyncIterator(com.apple.foundationdb.async.AsyncIterator) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) AtomicReference(java.util.concurrent.atomic.AtomicReference) Function(java.util.function.Function) CursorStreamingMode(com.apple.foundationdb.record.CursorStreamingMode) Key(com.apple.foundationdb.record.metadata.Key) ExecuteProperties(com.apple.foundationdb.record.ExecuteProperties) EndpointType(com.apple.foundationdb.record.EndpointType) ScanProperties(com.apple.foundationdb.record.ScanProperties) Suppliers(com.google.common.base.Suppliers) LinkedList(java.util.LinkedList) Nonnull(javax.annotation.Nonnull) EmptyKeyExpression(com.apple.foundationdb.record.metadata.expressions.EmptyKeyExpression) MoreAsyncUtil(com.apple.foundationdb.async.MoreAsyncUtil) Logger(org.slf4j.Logger) Iterator(java.util.Iterator) IndexState(com.apple.foundationdb.record.IndexState) StoreRecordFunction(com.apple.foundationdb.record.metadata.StoreRecordFunction) ReadTransaction(com.apple.foundationdb.ReadTransaction) AsyncIterable(com.apple.foundationdb.async.AsyncIterable) FDBRecordStoreStateCache(com.apple.foundationdb.record.provider.foundationdb.storestate.FDBRecordStoreStateCache) Message(com.google.protobuf.Message) RecordCursor(com.apple.foundationdb.record.RecordCursor) QueryComponent(com.apple.foundationdb.record.query.expressions.QueryComponent) VisibleForTesting(com.google.common.annotations.VisibleForTesting) Collections(java.util.Collections) RecordMetaData(com.apple.foundationdb.record.RecordMetaData) KeyValue(com.apple.foundationdb.KeyValue) CursorLimitManager(com.apple.foundationdb.record.cursors.CursorLimitManager) ExecuteProperties(com.apple.foundationdb.record.ExecuteProperties) CompletableFuture(java.util.concurrent.CompletableFuture) ScanProperties(com.apple.foundationdb.record.ScanProperties) Subspace(com.apple.foundationdb.subspace.Subspace) Tuple(com.apple.foundationdb.tuple.Tuple) Nonnull(javax.annotation.Nonnull)

Example 42 with KeyValue

use of com.apple.foundationdb.KeyValue in project fdb-record-layer by FoundationDB.

the class FDBRecordStore method countRecords.

@Override
@Nonnull
public CompletableFuture<Integer> countRecords(@Nullable Tuple low, @Nullable Tuple high, @Nonnull EndpointType lowEndpoint, @Nonnull EndpointType highEndpoint, @Nullable byte[] continuation, @Nonnull ScanProperties scanProperties) {
    final Subspace recordsSubspace = recordsSubspace();
    RecordCursor<KeyValue> keyValues = KeyValueCursor.Builder.withSubspace(recordsSubspace).setContext(context).setLow(low, lowEndpoint).setHigh(high, highEndpoint).setContinuation(continuation).setScanProperties(scanProperties.with(ExecuteProperties::clearRowAndTimeLimits).with(ExecuteProperties::clearState)).build();
    if (getRecordMetaData().isSplitLongRecords()) {
        return new SplitHelper.KeyValueUnsplitter(context, recordsSubspace, keyValues, useOldVersionFormat(), null, scanProperties.isReverse(), new CursorLimitManager(context, scanProperties.with(ExecuteProperties::clearRowAndTimeLimits))).getCount();
    } else {
        return keyValues.getCount();
    }
}
Also used : ExecuteProperties(com.apple.foundationdb.record.ExecuteProperties) KeyValue(com.apple.foundationdb.KeyValue) Subspace(com.apple.foundationdb.subspace.Subspace) CursorLimitManager(com.apple.foundationdb.record.cursors.CursorLimitManager) Nonnull(javax.annotation.Nonnull)

Example 43 with KeyValue

use of com.apple.foundationdb.KeyValue in project fdb-record-layer by FoundationDB.

the class BunchedMapIterator method onHasNext.

@Override
public CompletableFuture<Boolean> onHasNext() {
    if (done) {
        return AsyncUtil.READY_FALSE;
    }
    if (currEntryList != null && currEntryIndex >= 0 && currEntryIndex < currEntryList.size()) {
        return AsyncUtil.READY_TRUE;
    }
    if (hasNextFuture == null) {
        hasNextFuture = underlying.onHasNext().thenCompose(doesHaveNext -> {
            if (doesHaveNext) {
                return AsyncUtil.whileTrue(() -> {
                    KeyValue underlyingNext = underlying.peek();
                    if (!subspace.contains(underlyingNext.getKey())) {
                        if (ByteArrayUtil.compareUnsigned(underlyingNext.getKey(), subspaceKey) * (reverse ? -1 : 1) < 0) {
                            // We haven't gotten to this subspace yet, so try the next key.
                            underlying.next();
                            return underlying.onHasNext();
                        } else {
                            // We are done iterating through this subspace. Return
                            // without advancing the scan to support scanning
                            // over multiple subspaces.
                            done = true;
                            return AsyncUtil.READY_FALSE;
                        }
                    }
                    // Advance the underlying scan.
                    underlying.next();
                    final K boundaryKey = bunchedMap.getSerializer().deserializeKey(underlyingNext.getKey(), subspaceKey.length);
                    List<Map.Entry<K, V>> nextEntryList = bunchedMap.getSerializer().deserializeEntries(boundaryKey, underlyingNext.getValue());
                    if (nextEntryList.isEmpty()) {
                        // No entries in list. Try next key.
                        return underlying.onHasNext();
                    }
                    int nextItemIndex = reverse ? nextEntryList.size() - 1 : 0;
                    if (!continuationSatisfied) {
                        while (nextItemIndex >= 0 && nextItemIndex < nextEntryList.size() && bunchedMap.getKeyComparator().compare(continuationKey, nextEntryList.get(nextItemIndex).getKey()) * (reverse ? -1 : 1) >= 0) {
                            nextItemIndex += reverse ? -1 : 1;
                        }
                        if (nextItemIndex < 0 || nextItemIndex >= nextEntryList.size()) {
                            // through this entry. Move on to the next key in the database.
                            return underlying.onHasNext();
                        } else {
                            continuationSatisfied = true;
                        }
                    }
                    // TODO: We can be more exact about conflict ranges here.
                    currEntryIndex = nextItemIndex;
                    currEntryList = nextEntryList;
                    return AsyncUtil.READY_FALSE;
                }, tr.getExecutor()).thenApply(vignore -> {
                    if (currEntryList == null || currEntryIndex < 0 || currEntryIndex >= currEntryList.size()) {
                        done = true;
                    }
                    return !done;
                });
            } else {
                // Exhausted scan.
                done = true;
                return AsyncUtil.READY_FALSE;
            }
        });
    }
    return hasNextFuture;
}
Also used : ByteArrayUtil(com.apple.foundationdb.tuple.ByteArrayUtil) KeyValue(com.apple.foundationdb.KeyValue) CompletableFuture(java.util.concurrent.CompletableFuture) AsyncUtil(com.apple.foundationdb.async.AsyncUtil) ReadTransaction(com.apple.foundationdb.ReadTransaction) Subspace(com.apple.foundationdb.subspace.Subspace) List(java.util.List) Map(java.util.Map) API(com.apple.foundationdb.annotation.API) NoSuchElementException(java.util.NoSuchElementException) Nonnull(javax.annotation.Nonnull) Nullable(javax.annotation.Nullable) AsyncPeekIterator(com.apple.foundationdb.async.AsyncPeekIterator) KeyValue(com.apple.foundationdb.KeyValue)

Example 44 with KeyValue

use of com.apple.foundationdb.KeyValue in project fdb-record-layer by FoundationDB.

the class BunchedMapMultiIterator method getNextMapIterator.

private CompletableFuture<Boolean> getNextMapIterator() {
    return underlying.onHasNext().thenCompose(doesHaveNext -> {
        if (doesHaveNext) {
            KeyValue nextKv = underlying.peek();
            if (!subspace.contains(nextKv.getKey())) {
                if (ByteArrayUtil.compareUnsigned(nextKv.getKey(), subspaceKey) * (reverse ? -1 : 1) > 0) {
                    // We have already gone past the end of the subspace. We are done.
                    underlying.cancel();
                    return AsyncUtil.READY_FALSE;
                } else {
                    // much reading, and it shouldn't make too many recursive calls.
                    return AsyncUtil.whileTrue(() -> {
                        KeyValue kv = underlying.peek();
                        if (ByteArrayUtil.compareUnsigned(kv.getKey(), subspaceKey) * (reverse ? -1 : 1) >= 0) {
                            return AsyncUtil.READY_FALSE;
                        } else {
                            underlying.next();
                            return underlying.onHasNext();
                        }
                    }, tr.getExecutor()).thenCompose(vignore -> getNextMapIterator());
                }
            }
            Subspace nextSubspace = splitter.subspaceOf(nextKv.getKey());
            byte[] nextSubspaceKey = nextSubspace.getKey();
            byte[] nextSubspaceSuffix = Arrays.copyOfRange(nextSubspaceKey, subspaceKey.length, nextSubspaceKey.length);
            K continuationKey = null;
            if (!continuationSatisfied) {
                if (ByteArrayUtil.startsWith(continuation, nextSubspaceSuffix)) {
                    continuationKey = bunchedMap.getSerializer().deserializeKey(continuation, nextSubspaceSuffix.length);
                    continuationSatisfied = true;
                } else if (ByteArrayUtil.compareUnsigned(nextSubspaceSuffix, continuation) * (reverse ? -1 : 1) > 0) {
                    // We have already satisfied the continuation, so we are can just say it is satisfied
                    continuationSatisfied = true;
                    continuationKey = null;
                } else {
                    // current subspace.
                    return AsyncUtil.whileTrue(() -> {
                        KeyValue kv = underlying.peek();
                        if (nextSubspace.contains(kv.getKey())) {
                            underlying.next();
                            return underlying.onHasNext();
                        } else {
                            return AsyncUtil.READY_FALSE;
                        }
                    }, tr.getExecutor()).thenCompose(vignore -> getNextMapIterator());
                }
            }
            BunchedMapIterator<K, V> nextMapIterator = new BunchedMapIterator<>(underlying, tr, nextSubspace, nextSubspaceKey, bunchedMap, continuationKey, (limit == ReadTransaction.ROW_LIMIT_UNLIMITED) ? ReadTransaction.ROW_LIMIT_UNLIMITED : limit - returned, reverse);
            final T nextSubspaceTag = splitter.subspaceTag(nextSubspace);
            return nextMapIterator.onHasNext().thenCompose(mapHasNext -> {
                if (mapHasNext) {
                    currentSubspace = nextSubspace;
                    currentSubspaceKey = nextSubspaceKey;
                    currentSubspaceSuffix = nextSubspaceSuffix;
                    currentSubspaceTag = nextSubspaceTag;
                    mapIterator = nextMapIterator;
                    Map.Entry<K, V> mapEntry = mapIterator.next();
                    nextEntry = new BunchedMapScanEntry<>(currentSubspace, currentSubspaceTag, mapEntry.getKey(), mapEntry.getValue());
                    return AsyncUtil.READY_TRUE;
                } else {
                    // we will only be recursing down a finite amount.
                    return getNextMapIterator();
                }
            });
        } else {
            done = true;
            return AsyncUtil.READY_FALSE;
        }
    });
}
Also used : ByteArrayUtil(com.apple.foundationdb.tuple.ByteArrayUtil) Arrays(java.util.Arrays) KeyValue(com.apple.foundationdb.KeyValue) CompletableFuture(java.util.concurrent.CompletableFuture) AsyncUtil(com.apple.foundationdb.async.AsyncUtil) ReadTransaction(com.apple.foundationdb.ReadTransaction) Subspace(com.apple.foundationdb.subspace.Subspace) Map(java.util.Map) API(com.apple.foundationdb.annotation.API) NoSuchElementException(java.util.NoSuchElementException) Nonnull(javax.annotation.Nonnull) Nullable(javax.annotation.Nullable) AsyncPeekIterator(com.apple.foundationdb.async.AsyncPeekIterator) KeyValue(com.apple.foundationdb.KeyValue) Subspace(com.apple.foundationdb.subspace.Subspace) Map(java.util.Map)

Example 45 with KeyValue

use of com.apple.foundationdb.KeyValue in project fdb-record-layer by FoundationDB.

the class RankedSet method toDebugString.

protected String toDebugString(ReadTransactionContext tc) {
    return tc.read(tr -> {
        final StringBuilder str = new StringBuilder();
        final int nlevels = config.getNLevels();
        for (int level = 0; level < nlevels; ++level) {
            if (level > 0) {
                str.setLength(str.length() - 2);
                str.append("\n");
            }
            str.append("L").append(level).append(": ");
            for (KeyValue kv : tr.getRange(subspace.range(Tuple.from(level)))) {
                byte[] key = subspace.unpack(kv.getKey()).getBytes(1);
                long count = decodeLong(kv.getValue());
                str.append("'").append(ByteArrayUtil2.loggable(key)).append("': ").append(count).append(", ");
            }
        }
        return str.toString();
    });
}
Also used : KeyValue(com.apple.foundationdb.KeyValue)

Aggregations

KeyValue (com.apple.foundationdb.KeyValue)51 Test (org.junit.jupiter.api.Test)23 Subspace (com.apple.foundationdb.subspace.Subspace)22 Nonnull (javax.annotation.Nonnull)22 CompletableFuture (java.util.concurrent.CompletableFuture)19 List (java.util.List)18 AsyncUtil (com.apple.foundationdb.async.AsyncUtil)16 ArrayList (java.util.ArrayList)16 Transaction (com.apple.foundationdb.Transaction)15 ScanProperties (com.apple.foundationdb.record.ScanProperties)15 Tuple (com.apple.foundationdb.tuple.Tuple)14 Map (java.util.Map)14 Collectors (java.util.stream.Collectors)12 Nullable (javax.annotation.Nullable)12 ByteArrayUtil (com.apple.foundationdb.tuple.ByteArrayUtil)11 AtomicReference (java.util.concurrent.atomic.AtomicReference)11 AsyncIterator (com.apple.foundationdb.async.AsyncIterator)10 ExecuteProperties (com.apple.foundationdb.record.ExecuteProperties)10 Collections (java.util.Collections)10 ReadTransaction (com.apple.foundationdb.ReadTransaction)9