Search in sources :

Example 11 with IndexEntry

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

the class BitmapValueIndexMaintainer method updateIndexKeys.

@Override
@Nonnull
protected <M extends Message> CompletableFuture<Void> updateIndexKeys(@Nonnull final FDBIndexableRecord<M> savedRecord, final boolean remove, @Nonnull final List<IndexEntry> indexEntries) {
    final int groupPrefixSize = getGroupingCount();
    final List<CompletableFuture<Void>> futures = unique && !remove ? new ArrayList<>(indexEntries.size()) : null;
    for (IndexEntry indexEntry : indexEntries) {
        final long startTime = System.nanoTime();
        final Tuple groupKey = TupleHelpers.subTuple(indexEntry.getKey(), 0, groupPrefixSize);
        Object positionObject = indexEntry.getKey().get(groupPrefixSize);
        if (positionObject == null) {
            continue;
        }
        if (!(positionObject instanceof Number)) {
            // This should be prevented by the checks in the meta-data builder, but just in case
            throw new RecordCoreException("position field in index entry is not a number").addLogInfo(LogMessageKeys.KEY, indexEntry.getKey(), LogMessageKeys.INDEX_NAME, state.index.getName(), LogMessageKeys.INDEX_TYPE, state.index.getType());
        }
        long position = ((Number) positionObject).longValue();
        final int offset = (int) Math.floorMod(position, (long) entrySize);
        position -= offset;
        final byte[] key = state.indexSubspace.pack(groupKey.add(position));
        // This has to be the same size every time, with all the unset bits, or else it gets truncated.
        // We really could use a new mutation that took a linear bit position to set / clear and only did length extension or something like that.
        final byte[] bitmap = new byte[(entrySize + 7) / 8];
        if (remove) {
            if (state.store.isIndexWriteOnly(state.index)) {
                // If the index isn't built, it's possible this key wasn't reached.
                // So initialize it to zeros (or leave it alone).
                state.transaction.mutate(MutationType.BIT_OR, key, bitmap);
            }
            // Otherwise the entry must already exist for us to be removing it,
            // so there is no danger that this will store all (but one) ones in a new key.
            Arrays.fill(bitmap, (byte) 0xFF);
            bitmap[offset / 8] &= ~(byte) (1 << (offset % 8));
            state.transaction.mutate(MutationType.BIT_AND, key, bitmap);
            Arrays.fill(bitmap, (byte) 0x00);
            state.transaction.mutate(MutationType.COMPARE_AND_CLEAR, key, bitmap);
        } else {
            if (unique) {
                // Snapshot read to see if the bit is already set.
                CompletableFuture<Void> future = state.transaction.snapshot().get(key).thenAccept(existing -> {
                    if (existing != null && (existing[offset / 8] & (byte) (1 << (offset % 8))) != 0) {
                        throw new RecordIndexUniquenessViolation(state.index, indexEntry, savedRecord.getPrimaryKey(), // Unfortunately, we don't know the other key.
                        null);
                    }
                });
                futures.add(future);
                // Then arrange to conflict for the position with any concurrent update.
                final byte[] conflictKey = new Subspace(key).pack(offset);
                state.transaction.addReadConflictKey(conflictKey);
                state.transaction.addWriteConflictKey(conflictKey);
            }
            bitmap[offset / 8] |= (byte) (1 << (offset % 8));
            state.transaction.mutate(MutationType.BIT_OR, key, bitmap);
        }
        if (state.store.getTimer() != null) {
            state.store.getTimer().recordSinceNanoTime(FDBStoreTimer.Events.MUTATE_INDEX_ENTRY, startTime);
        }
    }
    return futures != null ? AsyncUtil.whenAll(futures) : AsyncUtil.DONE;
}
Also used : IndexEntry(com.apple.foundationdb.record.IndexEntry) RecordCoreException(com.apple.foundationdb.record.RecordCoreException) CompletableFuture(java.util.concurrent.CompletableFuture) RecordIndexUniquenessViolation(com.apple.foundationdb.record.RecordIndexUniquenessViolation) Subspace(com.apple.foundationdb.subspace.Subspace) Tuple(com.apple.foundationdb.tuple.Tuple) Nonnull(javax.annotation.Nonnull)

Example 12 with IndexEntry

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

the class TimeWindowLeaderboardIndexMaintainer method scan.

@Nonnull
@Override
public RecordCursor<IndexEntry> scan(@Nonnull IndexScanBounds scanBounds, @Nullable byte[] continuation, @Nonnull ScanProperties scanProperties) {
    final IndexScanType scanType = scanBounds.getScanType();
    if (scanType != IndexScanType.BY_VALUE && scanType != IndexScanType.BY_RANK && scanType != IndexScanType.BY_TIME_WINDOW) {
        throw new RecordCoreException("Can only scan leaderboard index by time window, rank or value.");
    }
    // Decode range arguments.
    final int type;
    final long timestamp;
    final TupleRange leaderboardRange;
    if (scanType == IndexScanType.BY_TIME_WINDOW) {
        // Get oldest leaderboard of type containing timestamp.
        if (scanBounds instanceof TimeWindowScanRange) {
            TimeWindowScanRange scanRange = (TimeWindowScanRange) scanBounds;
            type = scanRange.getLeaderboardType();
            timestamp = scanRange.getLeaderboardTimestamp();
            leaderboardRange = scanRange.getScanRange();
        } else {
            // TODO: For compatibility, accept scan with BY_TIME_WINDOW and TupleRange for a while.
            // This code can be removed when we are confident all callers have been converted.
            IndexScanRange scanRange = (IndexScanRange) scanBounds;
            TupleRange rankRange = scanRange.getScanRange();
            final Tuple lowRank = rankRange.getLow();
            final Tuple highRank = rankRange.getHigh();
            type = (int) lowRank.getLong(0);
            timestamp = lowRank.getLong(1);
            leaderboardRange = new TupleRange(Tuple.fromList(lowRank.getItems().subList(2, lowRank.size())), Tuple.fromList(highRank.getItems().subList(2, highRank.size())), rankRange.getLowEndpoint(), rankRange.getHighEndpoint());
        }
    } else {
        // Get the all-time leaderboard for unqualified rank or value.
        IndexScanRange scanRange = (IndexScanRange) scanBounds;
        type = TimeWindowLeaderboard.ALL_TIME_LEADERBOARD_TYPE;
        // Any value would do.
        timestamp = 0;
        leaderboardRange = scanRange.getScanRange();
    }
    final int groupPrefixSize = getGroupingCount();
    final CompletableFuture<TimeWindowLeaderboard> leaderboardFuture = oldestLeaderboardMatching(type, timestamp);
    final CompletableFuture<TupleRange> scoreRangeFuture;
    if (scanType == IndexScanType.BY_VALUE) {
        scoreRangeFuture = leaderboardFuture.thenApply(leaderboard -> leaderboard == null ? null : leaderboardRange);
    } else {
        scoreRangeFuture = leaderboardFuture.thenCompose(leaderboard -> {
            if (leaderboard == null) {
                return CompletableFuture.completedFuture(null);
            }
            final Subspace extraSubspace = getSecondarySubspace();
            final Subspace leaderboardSubspace = extraSubspace.subspace(leaderboard.getSubspaceKey());
            final RankedSet.Config leaderboardConfig = config.toBuilder().setNLevels(leaderboard.getNLevels()).build();
            return RankedSetIndexHelper.rankRangeToScoreRange(state, groupPrefixSize, leaderboardSubspace, leaderboardConfig, leaderboardRange);
        });
    }
    // Add leaderboard's key to the front and take it off of the results.
    return RecordCursor.flatMapPipelined(ignore -> RecordCursor.fromFuture(getExecutor(), scoreRangeFuture), (scoreRange, ignore) -> {
        if (scoreRange == null) {
            return RecordCursor.empty(getExecutor());
        }
        // Already waited in scoreRangeFuture.
        final TimeWindowLeaderboard leaderboard = state.context.joinNow(leaderboardFuture);
        final CompletableFuture<Boolean> highStoreFirstFuture;
        if (scanType == IndexScanType.BY_VALUE) {
            final Tuple lowGroup = scoreRange.getLow() != null && scoreRange.getLow().size() > groupPrefixSize ? TupleHelpers.subTuple(scoreRange.getLow(), 0, groupPrefixSize) : null;
            final Tuple highGroup = scoreRange.getHigh() != null && scoreRange.getHigh().size() > groupPrefixSize ? TupleHelpers.subTuple(scoreRange.getHigh(), 0, groupPrefixSize) : null;
            if (lowGroup != null && lowGroup.equals(highGroup)) {
                highStoreFirstFuture = isHighScoreFirst(leaderboard.getDirectory(), lowGroup);
            } else {
                highStoreFirstFuture = CompletableFuture.completedFuture(leaderboard.getDirectory().isHighScoreFirst());
            }
        } else {
            highStoreFirstFuture = AsyncUtil.READY_FALSE;
        }
        if (highStoreFirstFuture.isDone()) {
            return scanLeaderboard(leaderboard, state.context.joinNow(highStoreFirstFuture), scoreRange, continuation, scanProperties);
        } else {
            return RecordCursor.flatMapPipelined(ignore2 -> RecordCursor.fromFuture(getExecutor(), highStoreFirstFuture), (highScoreFirst, ignore2) -> scanLeaderboard(leaderboard, highScoreFirst, scoreRange, continuation, scanProperties), null, 1);
        }
    }, null, 1).mapPipelined(kv -> getIndexEntry(kv, groupPrefixSize, state.context.joinNow(leaderboardFuture).getDirectory()), 1);
}
Also used : IndexEntry(com.apple.foundationdb.record.IndexEntry) LogMessageKeys(com.apple.foundationdb.record.logging.LogMessageKeys) StoreTimer(com.apple.foundationdb.record.provider.common.StoreTimer) IndexMaintainerState(com.apple.foundationdb.record.provider.foundationdb.IndexMaintainerState) FDBRecord(com.apple.foundationdb.record.provider.foundationdb.FDBRecord) LoggerFactory(org.slf4j.LoggerFactory) RecordCoreStorageException(com.apple.foundationdb.record.RecordCoreStorageException) MapUtils(com.apple.foundationdb.record.util.MapUtils) Subspace(com.apple.foundationdb.subspace.Subspace) MutationType(com.apple.foundationdb.MutationType) Transaction(com.apple.foundationdb.Transaction) IndexScanType(com.apple.foundationdb.record.IndexScanType) Tuple(com.apple.foundationdb.tuple.Tuple) KeyValueLogMessage(com.apple.foundationdb.record.logging.KeyValueLogMessage) Pair(org.apache.commons.lang3.tuple.Pair) RecordCoreException(com.apple.foundationdb.record.RecordCoreException) Map(java.util.Map) ByteArrayUtil(com.apple.foundationdb.tuple.ByteArrayUtil) InvalidProtocolBufferException(com.google.protobuf.InvalidProtocolBufferException) FDBIndexableRecord(com.apple.foundationdb.record.provider.foundationdb.FDBIndexableRecord) FDBStoreTimer(com.apple.foundationdb.record.provider.foundationdb.FDBStoreTimer) Collection(java.util.Collection) Set(java.util.Set) Collectors(java.util.stream.Collectors) TupleRange(com.apple.foundationdb.record.TupleRange) List(java.util.List) EvaluationContext(com.apple.foundationdb.record.EvaluationContext) TupleHelpers(com.apple.foundationdb.tuple.TupleHelpers) Optional(java.util.Optional) AtomicMutation(com.apple.foundationdb.record.provider.foundationdb.indexes.AtomicMutation) API(com.apple.foundationdb.annotation.API) FunctionNames(com.apple.foundationdb.record.FunctionNames) SpotBugsSuppressWarnings(com.apple.foundationdb.annotation.SpotBugsSuppressWarnings) IndexAggregateFunction(com.apple.foundationdb.record.metadata.IndexAggregateFunction) IndexOperation(com.apple.foundationdb.record.provider.foundationdb.IndexOperation) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) AsyncUtil(com.apple.foundationdb.async.AsyncUtil) TreeSet(java.util.TreeSet) ArrayList(java.util.ArrayList) TimeWindowLeaderboardProto(com.apple.foundationdb.record.TimeWindowLeaderboardProto) EndpointType(com.apple.foundationdb.record.EndpointType) ScanProperties(com.apple.foundationdb.record.ScanProperties) IndexScanBounds(com.apple.foundationdb.record.provider.foundationdb.IndexScanBounds) IndexScanRange(com.apple.foundationdb.record.provider.foundationdb.IndexScanRange) IndexRecordFunction(com.apple.foundationdb.record.metadata.IndexRecordFunction) Nonnull(javax.annotation.Nonnull) Nullable(javax.annotation.Nullable) ByteArrayUtil2(com.apple.foundationdb.tuple.ByteArrayUtil2) IndexOperationResult(com.apple.foundationdb.record.provider.foundationdb.IndexOperationResult) StandardIndexMaintainer(com.apple.foundationdb.record.provider.foundationdb.indexes.StandardIndexMaintainer) MoreAsyncUtil(com.apple.foundationdb.async.MoreAsyncUtil) IsolationLevel(com.apple.foundationdb.record.IsolationLevel) Logger(org.slf4j.Logger) Iterator(java.util.Iterator) RankedSetIndexHelper(com.apple.foundationdb.record.provider.foundationdb.indexes.RankedSetIndexHelper) RankedSet(com.apple.foundationdb.async.RankedSet) Message(com.google.protobuf.Message) RecordCursor(com.apple.foundationdb.record.RecordCursor) Collections(java.util.Collections) IndexScanRange(com.apple.foundationdb.record.provider.foundationdb.IndexScanRange) RecordCoreException(com.apple.foundationdb.record.RecordCoreException) CompletableFuture(java.util.concurrent.CompletableFuture) IndexScanType(com.apple.foundationdb.record.IndexScanType) Subspace(com.apple.foundationdb.subspace.Subspace) TupleRange(com.apple.foundationdb.record.TupleRange) Tuple(com.apple.foundationdb.tuple.Tuple) Nonnull(javax.annotation.Nonnull)

Example 13 with IndexEntry

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

the class TimeWindowLeaderboardIndexMaintainer method timeWindowRankAndEntry.

@Nonnull
public <M extends Message> CompletableFuture<Pair<Long, Tuple>> timeWindowRankAndEntry(@Nonnull FDBRecord<M> record, int type, long timestamp) {
    final List<IndexEntry> indexEntries = evaluateIndex(record);
    final CompletableFuture<TimeWindowLeaderboard> leaderboardFuture = oldestLeaderboardMatching(type, timestamp);
    return leaderboardFuture.thenCompose(leaderboard -> {
        if (leaderboard == null) {
            return CompletableFuture.completedFuture(null);
        }
        return groupOrderedScoreIndexKeys(indexEntries, leaderboard.getDirectory(), true).thenCompose(groupedScores -> {
            if (groupedScores.isEmpty()) {
                return CompletableFuture.completedFuture(null);
            }
            if (groupedScores.size() > 1) {
                throw new RecordCoreException("Record has more than one group of scores");
            }
            Map.Entry<Tuple, Collection<OrderedScoreIndexKey>> groupEntry = groupedScores.entrySet().iterator().next();
            Optional<OrderedScoreIndexKey> bestContainedScore = groupEntry.getValue().stream().filter(score -> leaderboard.containsTimestamp(score.timestamp)).findFirst();
            if (!bestContainedScore.isPresent()) {
                return CompletableFuture.completedFuture(null);
            }
            // bestContainedScore should be the one stored in the leaderboard's ranked set; get its rank there.
            final Tuple groupKey = groupEntry.getKey();
            return isHighScoreFirst(leaderboard.getDirectory(), groupKey).thenCompose(highScoreFirst -> {
                final OrderedScoreIndexKey indexKey = bestContainedScore.get();
                final Tuple leaderboardGroupKey = leaderboard.getSubspaceKey().addAll(groupKey);
                final Subspace extraSubspace = getSecondarySubspace();
                final Subspace rankSubspace = extraSubspace.subspace(leaderboardGroupKey);
                final RankedSet.Config leaderboardConfig = config.toBuilder().setNLevels(leaderboard.getNLevels()).build();
                final RankedSet rankedSet = new RankedSetIndexHelper.InstrumentedRankedSet(state, rankSubspace, leaderboardConfig);
                // Undo any negation needed to find entry.
                final Tuple entry = highScoreFirst ? negateScoreForHighScoreFirst(indexKey.scoreKey, 0) : indexKey.scoreKey;
                return RankedSetIndexHelper.rankForScore(state, rankedSet, indexKey.scoreKey, true).thenApply(rank -> Pair.of(rank, entry));
            });
        });
    });
}
Also used : IndexEntry(com.apple.foundationdb.record.IndexEntry) LogMessageKeys(com.apple.foundationdb.record.logging.LogMessageKeys) StoreTimer(com.apple.foundationdb.record.provider.common.StoreTimer) IndexMaintainerState(com.apple.foundationdb.record.provider.foundationdb.IndexMaintainerState) FDBRecord(com.apple.foundationdb.record.provider.foundationdb.FDBRecord) LoggerFactory(org.slf4j.LoggerFactory) RecordCoreStorageException(com.apple.foundationdb.record.RecordCoreStorageException) MapUtils(com.apple.foundationdb.record.util.MapUtils) Subspace(com.apple.foundationdb.subspace.Subspace) MutationType(com.apple.foundationdb.MutationType) Transaction(com.apple.foundationdb.Transaction) IndexScanType(com.apple.foundationdb.record.IndexScanType) Tuple(com.apple.foundationdb.tuple.Tuple) KeyValueLogMessage(com.apple.foundationdb.record.logging.KeyValueLogMessage) Pair(org.apache.commons.lang3.tuple.Pair) RecordCoreException(com.apple.foundationdb.record.RecordCoreException) Map(java.util.Map) ByteArrayUtil(com.apple.foundationdb.tuple.ByteArrayUtil) InvalidProtocolBufferException(com.google.protobuf.InvalidProtocolBufferException) FDBIndexableRecord(com.apple.foundationdb.record.provider.foundationdb.FDBIndexableRecord) FDBStoreTimer(com.apple.foundationdb.record.provider.foundationdb.FDBStoreTimer) Collection(java.util.Collection) Set(java.util.Set) Collectors(java.util.stream.Collectors) TupleRange(com.apple.foundationdb.record.TupleRange) List(java.util.List) EvaluationContext(com.apple.foundationdb.record.EvaluationContext) TupleHelpers(com.apple.foundationdb.tuple.TupleHelpers) Optional(java.util.Optional) AtomicMutation(com.apple.foundationdb.record.provider.foundationdb.indexes.AtomicMutation) API(com.apple.foundationdb.annotation.API) FunctionNames(com.apple.foundationdb.record.FunctionNames) SpotBugsSuppressWarnings(com.apple.foundationdb.annotation.SpotBugsSuppressWarnings) IndexAggregateFunction(com.apple.foundationdb.record.metadata.IndexAggregateFunction) IndexOperation(com.apple.foundationdb.record.provider.foundationdb.IndexOperation) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) AsyncUtil(com.apple.foundationdb.async.AsyncUtil) TreeSet(java.util.TreeSet) ArrayList(java.util.ArrayList) TimeWindowLeaderboardProto(com.apple.foundationdb.record.TimeWindowLeaderboardProto) EndpointType(com.apple.foundationdb.record.EndpointType) ScanProperties(com.apple.foundationdb.record.ScanProperties) IndexScanBounds(com.apple.foundationdb.record.provider.foundationdb.IndexScanBounds) IndexScanRange(com.apple.foundationdb.record.provider.foundationdb.IndexScanRange) IndexRecordFunction(com.apple.foundationdb.record.metadata.IndexRecordFunction) Nonnull(javax.annotation.Nonnull) Nullable(javax.annotation.Nullable) ByteArrayUtil2(com.apple.foundationdb.tuple.ByteArrayUtil2) IndexOperationResult(com.apple.foundationdb.record.provider.foundationdb.IndexOperationResult) StandardIndexMaintainer(com.apple.foundationdb.record.provider.foundationdb.indexes.StandardIndexMaintainer) MoreAsyncUtil(com.apple.foundationdb.async.MoreAsyncUtil) IsolationLevel(com.apple.foundationdb.record.IsolationLevel) Logger(org.slf4j.Logger) Iterator(java.util.Iterator) RankedSetIndexHelper(com.apple.foundationdb.record.provider.foundationdb.indexes.RankedSetIndexHelper) RankedSet(com.apple.foundationdb.async.RankedSet) Message(com.google.protobuf.Message) RecordCursor(com.apple.foundationdb.record.RecordCursor) Collections(java.util.Collections) RankedSet(com.apple.foundationdb.async.RankedSet) IndexEntry(com.apple.foundationdb.record.IndexEntry) RecordCoreException(com.apple.foundationdb.record.RecordCoreException) Subspace(com.apple.foundationdb.subspace.Subspace) Collection(java.util.Collection) Map(java.util.Map) HashMap(java.util.HashMap) Tuple(com.apple.foundationdb.tuple.Tuple) Nonnull(javax.annotation.Nonnull)

Example 14 with IndexEntry

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

the class TimeWindowLeaderboardIndexMaintainer method updateIndexKeys.

@Override
protected <M extends Message> CompletableFuture<Void> updateIndexKeys(@Nonnull final FDBIndexableRecord<M> savedRecord, final boolean remove, @Nonnull final List<IndexEntry> indexEntries) {
    final Subspace extraSubspace = getSecondarySubspace();
    // The value for the index key cannot vary from entry-to-entry, so get the value only from the first entry.
    final Tuple entryValue = indexEntries.isEmpty() ? TupleHelpers.EMPTY : indexEntries.get(0).getValue();
    return loadDirectory().thenCompose(directory -> {
        if (directory == null) {
            return AsyncUtil.DONE;
        }
        return groupOrderedScoreIndexKeys(indexEntries, directory, true).thenCompose(groupedScores -> {
            final List<CompletableFuture<Void>> futures = new ArrayList<>();
            for (Iterable<TimeWindowLeaderboard> directoryEntry : directory.getLeaderboards().values()) {
                for (TimeWindowLeaderboard leaderboard : directoryEntry) {
                    for (Map.Entry<Tuple, Collection<OrderedScoreIndexKey>> groupEntry : groupedScores.entrySet()) {
                        final Optional<OrderedScoreIndexKey> bestContainedScore = groupEntry.getValue().stream().filter(score -> leaderboard.containsTimestamp(score.timestamp)).findFirst();
                        if (bestContainedScore.isPresent()) {
                            final Tuple groupKey = groupEntry.getKey();
                            final OrderedScoreIndexKey indexKey = bestContainedScore.get();
                            final Tuple leaderboardGroupKey = leaderboard.getSubspaceKey().addAll(groupKey);
                            // Update the ordinary B-tree for this leaderboard.
                            final Tuple entryKey = leaderboardGroupKey.addAll(indexKey.scoreKey);
                            CompletableFuture<Void> updateOrdinaryIndex = updateOneKeyAsync(savedRecord, remove, new IndexEntry(state.index, entryKey, entryValue));
                            if (!MoreAsyncUtil.isCompletedNormally(updateOrdinaryIndex)) {
                                futures.add(updateOrdinaryIndex);
                            }
                            // Update the corresponding rankset for this leaderboard.
                            // Notice that as each leaderboard has its own subspace key and at most one score
                            // per record is chosen per leaderboard, this is the only time this record will be
                            // indexed in this rankSubspace. Compare/contrast: RankIndexMaintainer::updateIndexKeys
                            final Subspace rankSubspace = extraSubspace.subspace(leaderboardGroupKey);
                            final RankedSet.Config leaderboardConfig = config.toBuilder().setNLevels(leaderboard.getNLevels()).build();
                            futures.add(RankedSetIndexHelper.updateRankedSet(state, rankSubspace, leaderboardConfig, entryKey, indexKey.scoreKey, remove));
                        }
                    }
                }
            }
            Optional<Long> latestTimestamp = groupedScores.values().stream().flatMap(Collection::stream).map(OrderedScoreIndexKey::getTimestamp).max(Long::compareTo);
            if (latestTimestamp.isPresent()) {
                // Keep track of the latest timestamp for any indexed entry.
                // Then, if time window update adds an index that starts before then, we have to index existing records.
                state.transaction.mutate(MutationType.MAX, state.indexSubspace.getKey(), AtomicMutation.Standard.encodeSignedLong(latestTimestamp.get()));
            }
            return AsyncUtil.whenAll(futures);
        });
    });
}
Also used : IndexEntry(com.apple.foundationdb.record.IndexEntry) LogMessageKeys(com.apple.foundationdb.record.logging.LogMessageKeys) StoreTimer(com.apple.foundationdb.record.provider.common.StoreTimer) IndexMaintainerState(com.apple.foundationdb.record.provider.foundationdb.IndexMaintainerState) FDBRecord(com.apple.foundationdb.record.provider.foundationdb.FDBRecord) LoggerFactory(org.slf4j.LoggerFactory) RecordCoreStorageException(com.apple.foundationdb.record.RecordCoreStorageException) MapUtils(com.apple.foundationdb.record.util.MapUtils) Subspace(com.apple.foundationdb.subspace.Subspace) MutationType(com.apple.foundationdb.MutationType) Transaction(com.apple.foundationdb.Transaction) IndexScanType(com.apple.foundationdb.record.IndexScanType) Tuple(com.apple.foundationdb.tuple.Tuple) KeyValueLogMessage(com.apple.foundationdb.record.logging.KeyValueLogMessage) Pair(org.apache.commons.lang3.tuple.Pair) RecordCoreException(com.apple.foundationdb.record.RecordCoreException) Map(java.util.Map) ByteArrayUtil(com.apple.foundationdb.tuple.ByteArrayUtil) InvalidProtocolBufferException(com.google.protobuf.InvalidProtocolBufferException) FDBIndexableRecord(com.apple.foundationdb.record.provider.foundationdb.FDBIndexableRecord) FDBStoreTimer(com.apple.foundationdb.record.provider.foundationdb.FDBStoreTimer) Collection(java.util.Collection) Set(java.util.Set) Collectors(java.util.stream.Collectors) TupleRange(com.apple.foundationdb.record.TupleRange) List(java.util.List) EvaluationContext(com.apple.foundationdb.record.EvaluationContext) TupleHelpers(com.apple.foundationdb.tuple.TupleHelpers) Optional(java.util.Optional) AtomicMutation(com.apple.foundationdb.record.provider.foundationdb.indexes.AtomicMutation) API(com.apple.foundationdb.annotation.API) FunctionNames(com.apple.foundationdb.record.FunctionNames) SpotBugsSuppressWarnings(com.apple.foundationdb.annotation.SpotBugsSuppressWarnings) IndexAggregateFunction(com.apple.foundationdb.record.metadata.IndexAggregateFunction) IndexOperation(com.apple.foundationdb.record.provider.foundationdb.IndexOperation) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) AsyncUtil(com.apple.foundationdb.async.AsyncUtil) TreeSet(java.util.TreeSet) ArrayList(java.util.ArrayList) TimeWindowLeaderboardProto(com.apple.foundationdb.record.TimeWindowLeaderboardProto) EndpointType(com.apple.foundationdb.record.EndpointType) ScanProperties(com.apple.foundationdb.record.ScanProperties) IndexScanBounds(com.apple.foundationdb.record.provider.foundationdb.IndexScanBounds) IndexScanRange(com.apple.foundationdb.record.provider.foundationdb.IndexScanRange) IndexRecordFunction(com.apple.foundationdb.record.metadata.IndexRecordFunction) Nonnull(javax.annotation.Nonnull) Nullable(javax.annotation.Nullable) ByteArrayUtil2(com.apple.foundationdb.tuple.ByteArrayUtil2) IndexOperationResult(com.apple.foundationdb.record.provider.foundationdb.IndexOperationResult) StandardIndexMaintainer(com.apple.foundationdb.record.provider.foundationdb.indexes.StandardIndexMaintainer) MoreAsyncUtil(com.apple.foundationdb.async.MoreAsyncUtil) IsolationLevel(com.apple.foundationdb.record.IsolationLevel) Logger(org.slf4j.Logger) Iterator(java.util.Iterator) RankedSetIndexHelper(com.apple.foundationdb.record.provider.foundationdb.indexes.RankedSetIndexHelper) RankedSet(com.apple.foundationdb.async.RankedSet) Message(com.google.protobuf.Message) RecordCursor(com.apple.foundationdb.record.RecordCursor) Collections(java.util.Collections) ArrayList(java.util.ArrayList) RankedSet(com.apple.foundationdb.async.RankedSet) IndexEntry(com.apple.foundationdb.record.IndexEntry) CompletableFuture(java.util.concurrent.CompletableFuture) Subspace(com.apple.foundationdb.subspace.Subspace) Collection(java.util.Collection) Map(java.util.Map) HashMap(java.util.HashMap) Tuple(com.apple.foundationdb.tuple.Tuple)

Example 15 with IndexEntry

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

the class FDBRecordStoreIndexTest method scanIndexWithValue.

/**
 * Verify that explicit (i.e. bypassing the planner) index scans work .
 */
@Test
public void scanIndexWithValue() throws Exception {
    RecordMetaDataHook hook = metaData -> {
        metaData.removeIndex("MySimpleRecord$num_value_unique");
        metaData.addIndex("MySimpleRecord", new Index("multi_index_value", Key.Expressions.field("num_value_unique"), Key.Expressions.field("num_value_2"), IndexTypes.VALUE, IndexOptions.UNIQUE_OPTIONS));
    };
    complexQuerySetup(hook);
    try (FDBRecordContext context = openContext()) {
        openSimpleRecordStore(context, hook);
        int i = 0;
        try (RecordCursorIterator<IndexEntry> cursor = recordStore.scanIndex(recordStore.getRecordMetaData().getIndex("multi_index_value"), IndexScanType.BY_VALUE, new TupleRange(Tuple.from(900L), Tuple.from(950L), EndpointType.RANGE_INCLUSIVE, EndpointType.RANGE_INCLUSIVE), null, ScanProperties.FORWARD_SCAN).asIterator()) {
            while (cursor.hasNext()) {
                IndexEntry tuples = cursor.next();
                Tuple key = tuples.getKey();
                Tuple value = tuples.getValue();
                assertEquals(2, key.size());
                assertEquals(1, value.size());
                assertTrue(key.getLong(0) >= 900);
                assertTrue(key.getLong(0) <= 950);
                assertTrue(value.getLong(0) == (999 - i) % 3);
                i++;
            }
        }
        assertEquals(50, i);
        assertDiscardedNone(context);
    }
}
Also used : IndexEntry(com.apple.foundationdb.record.IndexEntry) Arrays(java.util.Arrays) Descriptors(com.google.protobuf.Descriptors) FDBRecordContext(com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext) RecordQuery(com.apple.foundationdb.record.query.RecordQuery) Function(java.util.function.Function) Key(com.apple.foundationdb.record.metadata.Key) TestHelpers.assertDiscardedNone(com.apple.foundationdb.record.TestHelpers.assertDiscardedNone) IndexScanType(com.apple.foundationdb.record.IndexScanType) Tuple(com.apple.foundationdb.tuple.Tuple) TestHelpers(com.apple.foundationdb.record.TestHelpers) EndpointType(com.apple.foundationdb.record.EndpointType) ScanProperties(com.apple.foundationdb.record.ScanProperties) TestHelpers.assertDiscardedAtLeast(com.apple.foundationdb.record.TestHelpers.assertDiscardedAtLeast) RecordCursorIterator(com.apple.foundationdb.record.RecordCursorIterator) Tag(org.junit.jupiter.api.Tag) Assertions.assertEquals(org.junit.jupiter.api.Assertions.assertEquals) Nullable(javax.annotation.Nullable) FDBRecordStoreBase(com.apple.foundationdb.record.provider.foundationdb.FDBRecordStoreBase) TestRecords4Proto(com.apple.foundationdb.record.TestRecords4Proto) Query(com.apple.foundationdb.record.query.expressions.Query) TestRecords1Proto(com.apple.foundationdb.record.TestRecords1Proto) IndexOptions(com.apple.foundationdb.record.metadata.IndexOptions) FDBStoreTimer(com.apple.foundationdb.record.provider.foundationdb.FDBStoreTimer) Tags(com.apple.test.Tags) TupleRange(com.apple.foundationdb.record.TupleRange) Test(org.junit.jupiter.api.Test) Objects(java.util.Objects) Index(com.apple.foundationdb.record.metadata.Index) Assertions.assertTrue(org.junit.jupiter.api.Assertions.assertTrue) Message(com.google.protobuf.Message) IndexTypes(com.apple.foundationdb.record.metadata.IndexTypes) FDBRecordContext(com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext) IndexEntry(com.apple.foundationdb.record.IndexEntry) Index(com.apple.foundationdb.record.metadata.Index) TupleRange(com.apple.foundationdb.record.TupleRange) Tuple(com.apple.foundationdb.tuple.Tuple) Test(org.junit.jupiter.api.Test)

Aggregations

IndexEntry (com.apple.foundationdb.record.IndexEntry)74 Tuple (com.apple.foundationdb.tuple.Tuple)41 Nonnull (javax.annotation.Nonnull)37 Index (com.apple.foundationdb.record.metadata.Index)34 Test (org.junit.jupiter.api.Test)34 FDBRecordContext (com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext)32 Message (com.google.protobuf.Message)32 ScanProperties (com.apple.foundationdb.record.ScanProperties)29 ArrayList (java.util.ArrayList)29 RecordCoreException (com.apple.foundationdb.record.RecordCoreException)28 TupleRange (com.apple.foundationdb.record.TupleRange)28 List (java.util.List)28 Nullable (javax.annotation.Nullable)27 IndexScanType (com.apple.foundationdb.record.IndexScanType)24 RecordCursor (com.apple.foundationdb.record.RecordCursor)22 CompletableFuture (java.util.concurrent.CompletableFuture)21 Collectors (java.util.stream.Collectors)21 ExecuteProperties (com.apple.foundationdb.record.ExecuteProperties)20 TupleHelpers (com.apple.foundationdb.tuple.TupleHelpers)20 FDBStoreTimer (com.apple.foundationdb.record.provider.foundationdb.FDBStoreTimer)19