Search in sources :

Example 11 with Range

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

the class IndexingByRecords method buildRange.

// Builds a range within a single transaction. It will look for the missing ranges within the given range and build those while
// updating the range set.
@Nonnull
private CompletableFuture<Void> buildRange(@Nonnull FDBRecordStore store, @Nullable Tuple start, @Nullable Tuple end, @Nullable AtomicLong recordsScanned) {
    RangeSet rangeSet = new RangeSet(store.indexRangeSubspace(common.getIndex()));
    AsyncIterator<Range> ranges = rangeSet.missingRanges(store.ensureContextActive(), packOrNull(start), packOrNull(end)).iterator();
    return ranges.onHasNext().thenCompose(hasAny -> {
        if (hasAny) {
            return AsyncUtil.whileTrue(() -> {
                Range range = ranges.next();
                Tuple rangeStart = RangeSet.isFirstKey(range.begin) ? null : Tuple.fromBytes(range.begin);
                Tuple rangeEnd = RangeSet.isFinalKey(range.end) ? null : Tuple.fromBytes(range.end);
                return CompletableFuture.allOf(// one long, respectively.
                buildRangeOnly(store, rangeStart, rangeEnd, false, recordsScanned), rangeSet.insertRange(store.ensureContextActive(), range, true)).thenCompose(vignore -> ranges.onHasNext());
            }, store.getExecutor());
        } else {
            return AsyncUtil.DONE;
        }
    });
}
Also used : RangeSet(com.apple.foundationdb.async.RangeSet) Range(com.apple.foundationdb.Range) TupleRange(com.apple.foundationdb.record.TupleRange) Tuple(com.apple.foundationdb.tuple.Tuple) Nonnull(javax.annotation.Nonnull)

Example 12 with Range

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

the class IndexingByRecords method buildRanges.

@Nonnull
private CompletableFuture<Void> buildRanges(SubspaceProvider subspaceProvider, @Nonnull Subspace subspace, RangeSet rangeSet, Queue<Range> rangeDeque) {
    return AsyncUtil.whileTrue(() -> {
        if (rangeDeque.isEmpty()) {
            // We're done.
            return CompletableFuture.completedFuture(false);
        }
        Range toBuild = rangeDeque.remove();
        // This only works if the things included within the rangeSet are serialized Tuples.
        Tuple startTuple = Tuple.fromBytes(toBuild.begin);
        Tuple endTuple = RangeSet.isFinalKey(toBuild.end) ? null : Tuple.fromBytes(toBuild.end);
        return buildUnbuiltRange(startTuple, endTuple).handle((realEnd, ex) -> handleBuiltRange(subspaceProvider, subspace, rangeSet, rangeDeque, startTuple, endTuple, realEnd, ex)).thenCompose(Function.identity());
    }, getRunner().getExecutor());
}
Also used : Arrays(java.util.Arrays) LogMessageKeys(com.apple.foundationdb.record.logging.LogMessageKeys) LoggerFactory(org.slf4j.LoggerFactory) AsyncIterator(com.apple.foundationdb.async.AsyncIterator) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) CompletableFuture(java.util.concurrent.CompletableFuture) AsyncUtil(com.apple.foundationdb.async.AsyncUtil) RangeSet(com.apple.foundationdb.async.RangeSet) AtomicReference(java.util.concurrent.atomic.AtomicReference) Function(java.util.function.Function) Subspace(com.apple.foundationdb.subspace.Subspace) ArrayList(java.util.ArrayList) Key(com.apple.foundationdb.record.metadata.Key) ExecuteProperties(com.apple.foundationdb.record.ExecuteProperties) Tuple(com.apple.foundationdb.tuple.Tuple) Range(com.apple.foundationdb.Range) RecordCursorResult(com.apple.foundationdb.record.RecordCursorResult) KeyValueLogMessage(com.apple.foundationdb.record.logging.KeyValueLogMessage) Lists(com.google.common.collect.Lists) Pair(org.apache.commons.lang3.tuple.Pair) EndpointType(com.apple.foundationdb.record.EndpointType) RecordCoreException(com.apple.foundationdb.record.RecordCoreException) ScanProperties(com.apple.foundationdb.record.ScanProperties) ReadTransactionContext(com.apple.foundationdb.ReadTransactionContext) IndexBuildProto(com.apple.foundationdb.record.IndexBuildProto) Nonnull(javax.annotation.Nonnull) Nullable(javax.annotation.Nullable) ByteArrayUtil2(com.apple.foundationdb.tuple.ByteArrayUtil2) IsolationLevel(com.apple.foundationdb.record.IsolationLevel) Logger(org.slf4j.Logger) TupleRange(com.apple.foundationdb.record.TupleRange) AtomicLong(java.util.concurrent.atomic.AtomicLong) List(java.util.List) RecordType(com.apple.foundationdb.record.metadata.RecordType) Index(com.apple.foundationdb.record.metadata.Index) Message(com.google.protobuf.Message) RecordCursor(com.apple.foundationdb.record.RecordCursor) API(com.apple.foundationdb.annotation.API) VisibleForTesting(com.google.common.annotations.VisibleForTesting) Queue(java.util.Queue) ArrayDeque(java.util.ArrayDeque) Collections(java.util.Collections) Range(com.apple.foundationdb.Range) TupleRange(com.apple.foundationdb.record.TupleRange) Tuple(com.apple.foundationdb.tuple.Tuple) Nonnull(javax.annotation.Nonnull)

Example 13 with Range

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

the class IndexingByRecords method buildRange.

@Nonnull
private CompletableFuture<Void> buildRange(@Nonnull SubspaceProvider subspaceProvider, @Nullable Key.Evaluated start, @Nullable Key.Evaluated end) {
    return getRunner().runAsync(context -> context.getReadVersionAsync().thenCompose(vignore -> subspaceProvider.getSubspaceAsync(context).thenCompose(subspace -> {
        RangeSet rangeSet = new RangeSet(subspace.subspace(Tuple.from(FDBRecordStore.INDEX_RANGE_SPACE_KEY, common.getIndex().getSubspaceKey())));
        byte[] startBytes = packOrNull(convertOrNull(start));
        byte[] endBytes = packOrNull(convertOrNull(end));
        Queue<Range> rangeDeque = new ArrayDeque<>();
        ReadTransactionContext rtc = context.ensureActive();
        return rangeSet.missingRanges(rtc, startBytes, endBytes).thenAccept(rangeDeque::addAll).thenCompose(vignore2 -> buildRanges(subspaceProvider, subspace, rangeSet, rangeDeque));
    })));
}
Also used : Arrays(java.util.Arrays) LogMessageKeys(com.apple.foundationdb.record.logging.LogMessageKeys) LoggerFactory(org.slf4j.LoggerFactory) AsyncIterator(com.apple.foundationdb.async.AsyncIterator) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) CompletableFuture(java.util.concurrent.CompletableFuture) AsyncUtil(com.apple.foundationdb.async.AsyncUtil) RangeSet(com.apple.foundationdb.async.RangeSet) AtomicReference(java.util.concurrent.atomic.AtomicReference) Function(java.util.function.Function) Subspace(com.apple.foundationdb.subspace.Subspace) ArrayList(java.util.ArrayList) Key(com.apple.foundationdb.record.metadata.Key) ExecuteProperties(com.apple.foundationdb.record.ExecuteProperties) Tuple(com.apple.foundationdb.tuple.Tuple) Range(com.apple.foundationdb.Range) RecordCursorResult(com.apple.foundationdb.record.RecordCursorResult) KeyValueLogMessage(com.apple.foundationdb.record.logging.KeyValueLogMessage) Lists(com.google.common.collect.Lists) Pair(org.apache.commons.lang3.tuple.Pair) EndpointType(com.apple.foundationdb.record.EndpointType) RecordCoreException(com.apple.foundationdb.record.RecordCoreException) ScanProperties(com.apple.foundationdb.record.ScanProperties) ReadTransactionContext(com.apple.foundationdb.ReadTransactionContext) IndexBuildProto(com.apple.foundationdb.record.IndexBuildProto) Nonnull(javax.annotation.Nonnull) Nullable(javax.annotation.Nullable) ByteArrayUtil2(com.apple.foundationdb.tuple.ByteArrayUtil2) IsolationLevel(com.apple.foundationdb.record.IsolationLevel) Logger(org.slf4j.Logger) TupleRange(com.apple.foundationdb.record.TupleRange) AtomicLong(java.util.concurrent.atomic.AtomicLong) List(java.util.List) RecordType(com.apple.foundationdb.record.metadata.RecordType) Index(com.apple.foundationdb.record.metadata.Index) Message(com.google.protobuf.Message) RecordCursor(com.apple.foundationdb.record.RecordCursor) API(com.apple.foundationdb.annotation.API) VisibleForTesting(com.google.common.annotations.VisibleForTesting) Queue(java.util.Queue) ArrayDeque(java.util.ArrayDeque) Collections(java.util.Collections) ReadTransactionContext(com.apple.foundationdb.ReadTransactionContext) RangeSet(com.apple.foundationdb.async.RangeSet) Range(com.apple.foundationdb.Range) TupleRange(com.apple.foundationdb.record.TupleRange) ArrayDeque(java.util.ArrayDeque) Nonnull(javax.annotation.Nonnull)

Example 14 with Range

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

the class IndexingByRecords method buildRange.

/**
 * Builds (transactionally) the index by adding records with primary keys within the given range.
 * This will look for gaps of keys within the given range that haven't yet been rebuilt and then
 * rebuild only those ranges. As a result, if this method is called twice, the first time, it will
 * build whatever needs to be built, and then the second time, it will notice that there are no ranges
 * that need to be built, so it will do nothing. In this way, it is idempotent and thus safe to
 * use in retry loops.
 *
 * This method will fail if there is too much work to be done in a single transaction. If one wants
 * to handle building a range that does not fit in a single transaction, one should use the
 * {@link #buildRange(Key.Evaluated, Key.Evaluated) buildRange()}
 * function that takes an {@link FDBDatabase} as its first parameter.
 *
 * @param store the record store in which to rebuild the range
 * @param start the (inclusive) beginning primary key of the range to build (or <code>null</code> to go to the end)
 * @param end the (exclusive) end primary key of the range to build (or <code>null</code> to go to the end)
 * @return a future that will be ready when the build has completed
 */
@Nonnull
public CompletableFuture<Void> buildRange(@Nonnull FDBRecordStore store, @Nullable Key.Evaluated start, @Nullable Key.Evaluated end) {
    RangeSet rangeSet = new RangeSet(store.indexRangeSubspace(common.getIndex()));
    byte[] startBytes = packOrNull(convertOrNull(start));
    byte[] endBytes = packOrNull(convertOrNull(end));
    AsyncIterator<Range> ranges = rangeSet.missingRanges(store.ensureContextActive(), startBytes, endBytes).iterator();
    return ranges.onHasNext().thenCompose(hasNext -> {
        if (hasNext) {
            return AsyncUtil.whileTrue(() -> {
                Range toBuild = ranges.next();
                Tuple startTuple = Tuple.fromBytes(toBuild.begin);
                Tuple endTuple = RangeSet.isFinalKey(toBuild.end) ? null : Tuple.fromBytes(toBuild.end);
                AtomicReference<Tuple> currStart = new AtomicReference<>(startTuple);
                return AsyncUtil.whileTrue(() -> buildUnbuiltRange(store, currStart.get(), endTuple, null).thenApply(realEnd -> {
                    if (realEnd != null && !realEnd.equals(endTuple)) {
                        currStart.set(realEnd);
                        return true;
                    } else {
                        return false;
                    }
                }), store.getExecutor()).thenCompose(vignore -> ranges.onHasNext());
            }, store.getExecutor());
        } else {
            return AsyncUtil.DONE;
        }
    });
}
Also used : RangeSet(com.apple.foundationdb.async.RangeSet) AtomicReference(java.util.concurrent.atomic.AtomicReference) Range(com.apple.foundationdb.Range) TupleRange(com.apple.foundationdb.record.TupleRange) Tuple(com.apple.foundationdb.tuple.Tuple) Nonnull(javax.annotation.Nonnull)

Example 15 with Range

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

the class IndexingBase method setScrubberTypeOrThrow.

@Nonnull
private CompletableFuture<Void> setScrubberTypeOrThrow(FDBRecordStore store) {
    // HERE: The index must be readable, checked by the caller
    // if scrubber had already run and still have missing ranges, do nothing
    // else: clear ranges and overwrite type-stamp
    Transaction tr = store.getContext().ensureActive();
    IndexBuildProto.IndexBuildIndexingStamp indexingTypeStamp = getIndexingTypeStamp(store);
    validateOrThrowEx(indexingTypeStamp.getMethod().equals(IndexBuildProto.IndexBuildIndexingStamp.Method.SCRUB_REPAIR), "Not a scrubber type-stamp");
    // Note: the scrubbers do not support multi target (yet)
    final Index index = common.getIndex();
    final Subspace indexesRangeSubspace = indexScrubIndexRangeSubspace(store, index);
    final Subspace recordsRangeSubspace = indexScrubRecordsRangeSubspace(store, index);
    RangeSet indexRangeSet = new RangeSet(indexesRangeSubspace);
    RangeSet recordsRangeSet = new RangeSet(recordsRangeSubspace);
    AsyncIterator<Range> indexRanges = indexRangeSet.missingRanges(tr).iterator();
    AsyncIterator<Range> recordsRanges = recordsRangeSet.missingRanges(tr).iterator();
    return indexRanges.onHasNext().thenCompose(hasNextIndex -> {
        if (Boolean.FALSE.equals(hasNextIndex)) {
            // erase the 'ranges' data to allow a fresh index re-scrubbing.
            if (LOGGER.isInfoEnabled()) {
                LOGGER.info(KeyValueLogMessage.build("Reset scrubber's index range").addKeysAndValues(common.indexLogMessageKeyValues()).toString());
            }
            tr.clear(indexesRangeSubspace.range());
        }
        return recordsRanges.onHasNext().thenAccept(hasNextRecord -> {
            if (Boolean.FALSE.equals(hasNextRecord)) {
                // erase the 'ranges' data to allow a fresh records re-scrubbing.
                if (LOGGER.isInfoEnabled()) {
                    LOGGER.info(KeyValueLogMessage.build("Reset scrubber's records range").addKeysAndValues(common.indexLogMessageKeyValues()).toString());
                }
                tr.clear(recordsRangeSubspace.range());
            }
        });
    });
}
Also used : Transaction(com.apple.foundationdb.Transaction) IndexBuildProto(com.apple.foundationdb.record.IndexBuildProto) Subspace(com.apple.foundationdb.subspace.Subspace) RangeSet(com.apple.foundationdb.async.RangeSet) Index(com.apple.foundationdb.record.metadata.Index) Range(com.apple.foundationdb.Range) Nonnull(javax.annotation.Nonnull)

Aggregations

Range (com.apple.foundationdb.Range)38 Nonnull (javax.annotation.Nonnull)28 TupleRange (com.apple.foundationdb.record.TupleRange)26 Tuple (com.apple.foundationdb.tuple.Tuple)24 List (java.util.List)23 RangeSet (com.apple.foundationdb.async.RangeSet)22 CompletableFuture (java.util.concurrent.CompletableFuture)22 Index (com.apple.foundationdb.record.metadata.Index)21 Subspace (com.apple.foundationdb.subspace.Subspace)19 AsyncUtil (com.apple.foundationdb.async.AsyncUtil)18 LogMessageKeys (com.apple.foundationdb.record.logging.LogMessageKeys)18 IsolationLevel (com.apple.foundationdb.record.IsolationLevel)17 RecordCoreException (com.apple.foundationdb.record.RecordCoreException)17 Message (com.google.protobuf.Message)17 Collectors (java.util.stream.Collectors)17 Nullable (javax.annotation.Nullable)17 Transaction (com.apple.foundationdb.Transaction)16 AsyncIterator (com.apple.foundationdb.async.AsyncIterator)16 RecordCursor (com.apple.foundationdb.record.RecordCursor)16 ExecuteProperties (com.apple.foundationdb.record.ExecuteProperties)15