Search in sources :

Example 71 with Transaction

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

the class IndexingScrubDangling method scrubIndexRangeOnly.

@Nonnull
private CompletableFuture<Boolean> scrubIndexRangeOnly(@Nonnull FDBRecordStore store, byte[] startBytes, byte[] endBytes, @Nonnull AtomicLong recordsScanned) {
    // return false when done
    Index index = common.getIndex();
    final RecordMetaData metaData = store.getRecordMetaData();
    final RecordMetaDataProvider recordMetaDataProvider = common.getRecordStoreBuilder().getMetaDataProvider();
    if (recordMetaDataProvider == null || !metaData.equals(recordMetaDataProvider.getRecordMetaData())) {
        throw new MetaDataException("Store does not have the same metadata");
    }
    final IndexMaintainer maintainer = store.getIndexMaintainer(index);
    // scrubbing only readable, VALUE, idempotence indexes (at least for now)
    validateOrThrowEx(maintainer.isIdempotent(), "scrubbed index is not idempotent");
    validateOrThrowEx(index.getType().equals(IndexTypes.VALUE) || scrubbingPolicy.ignoreIndexTypeCheck(), "scrubbed index is not a VALUE index");
    validateOrThrowEx(store.getIndexState(index) == IndexState.READABLE, "scrubbed index is not readable");
    RangeSet rangeSet = new RangeSet(indexScrubIndexRangeSubspace(store, index));
    AsyncIterator<Range> ranges = rangeSet.missingRanges(store.ensureContextActive(), startBytes, endBytes).iterator();
    final ExecuteProperties.Builder executeProperties = ExecuteProperties.newBuilder().setIsolationLevel(IsolationLevel.SNAPSHOT).setReturnedRowLimit(// always respectLimit 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)) {
            // Here: no more missing ranges - all done
            // To avoid stale metadata, we'll keep the scrubbed-ranges indicator empty until the next scrub call.
            Transaction tr = store.getContext().ensureActive();
            tr.clear(indexScrubIndexRangeSubspace(store, index).range());
            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<FDBIndexedRecord<Message>> cursor = store.scanIndexRecords(index.getName(), IndexScanType.BY_VALUE, tupleRange, null, IndexOrphanBehavior.RETURN, scanProperties);
        final AtomicBoolean hasMore = new AtomicBoolean(true);
        final AtomicReference<RecordCursorResult<FDBIndexedRecord<Message>>> lastResult = new AtomicReference<>(RecordCursorResult.exhausted());
        final long scanLimit = scrubbingPolicy.getEntriesScanLimit();
        return iterateRangeOnly(store, cursor, this::deleteIndexIfDangling, lastResult, hasMore, recordsScanned, true).thenApply(vignore -> hasMore.get() ? lastResult.get().get().getIndexEntry().getKey() : rangeEnd).thenCompose(cont -> rangeSet.insertRange(store.ensureContextActive(), packOrNull(rangeStart), packOrNull(cont), true).thenApply(ignore -> {
            if (scanLimit > 0) {
                scanCounter += recordsScanned.get();
                if (scanLimit <= scanCounter) {
                    return false;
                }
            }
            return !Objects.equals(cont, rangeEnd);
        }));
    });
}
Also used : IndexEntry(com.apple.foundationdb.record.IndexEntry) RecordMetaData(com.apple.foundationdb.record.RecordMetaData) 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) MetaDataException(com.apple.foundationdb.record.metadata.MetaDataException) RangeSet(com.apple.foundationdb.async.RangeSet) AtomicReference(java.util.concurrent.atomic.AtomicReference) Subspace(com.apple.foundationdb.subspace.Subspace) Transaction(com.apple.foundationdb.Transaction) ExecuteProperties(com.apple.foundationdb.record.ExecuteProperties) IndexScanType(com.apple.foundationdb.record.IndexScanType) Tuple(com.apple.foundationdb.tuple.Tuple) Range(com.apple.foundationdb.Range) RecordCursorResult(com.apple.foundationdb.record.RecordCursorResult) KeyValueLogMessage(com.apple.foundationdb.record.logging.KeyValueLogMessage) ScanProperties(com.apple.foundationdb.record.ScanProperties) IndexBuildProto(com.apple.foundationdb.record.IndexBuildProto) Nonnull(javax.annotation.Nonnull) Nullable(javax.annotation.Nullable) IsolationLevel(com.apple.foundationdb.record.IsolationLevel) Logger(org.slf4j.Logger) IndexState(com.apple.foundationdb.record.IndexState) TupleRange(com.apple.foundationdb.record.TupleRange) Objects(java.util.Objects) AtomicLong(java.util.concurrent.atomic.AtomicLong) List(java.util.List) RecordMetaDataProvider(com.apple.foundationdb.record.RecordMetaDataProvider) Index(com.apple.foundationdb.record.metadata.Index) Message(com.google.protobuf.Message) RecordCursor(com.apple.foundationdb.record.RecordCursor) IndexTypes(com.apple.foundationdb.record.metadata.IndexTypes) API(com.apple.foundationdb.annotation.API) RecordMetaData(com.apple.foundationdb.record.RecordMetaData) KeyValueLogMessage(com.apple.foundationdb.record.logging.KeyValueLogMessage) Message(com.google.protobuf.Message) RecordMetaDataProvider(com.apple.foundationdb.record.RecordMetaDataProvider) RangeSet(com.apple.foundationdb.async.RangeSet) Index(com.apple.foundationdb.record.metadata.Index) RecordCursorResult(com.apple.foundationdb.record.RecordCursorResult) AtomicReference(java.util.concurrent.atomic.AtomicReference) Range(com.apple.foundationdb.Range) TupleRange(com.apple.foundationdb.record.TupleRange) MetaDataException(com.apple.foundationdb.record.metadata.MetaDataException) ExecuteProperties(com.apple.foundationdb.record.ExecuteProperties) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Transaction(com.apple.foundationdb.Transaction) ScanProperties(com.apple.foundationdb.record.ScanProperties) TupleRange(com.apple.foundationdb.record.TupleRange) Tuple(com.apple.foundationdb.tuple.Tuple) Nonnull(javax.annotation.Nonnull)

Example 72 with Transaction

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

the class FDBStoreBase method addConflictForSubspace.

public void addConflictForSubspace(boolean write) {
    final Range range = getSubspace().range();
    final Transaction tr = context.ensureActive();
    if (write) {
        tr.addWriteConflictRange(range.begin, range.end);
    } else {
        tr.addReadConflictRange(range.begin, range.end);
    }
}
Also used : Transaction(com.apple.foundationdb.Transaction) Range(com.apple.foundationdb.Range)

Example 73 with Transaction

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

the class FDBDatabase method createTransaction.

/**
 * Creates a new transaction against the database.
 *
 * @param executor the executor to be used for asynchronous operations
 * @return newly created transaction
 */
private Transaction createTransaction(@Nonnull FDBRecordContextConfig config, @Nonnull Executor executor) {
    final TransactionListener listener = config.getTransactionListener() == null ? factory.getTransactionListener() : config.getTransactionListener();
    final StoreTimer timer = listener != null ? new StoreSubTimer(config.getTimer()) : config.getTimer();
    boolean enableAssertions = config.areAssertionsEnabled();
    // noinspection ConstantConditions
    Transaction transaction = database.createTransaction(executor, new EventKeeperTranslator(timer));
    if (timer != null || enableAssertions) {
        transaction = new InstrumentedTransaction(timer, this, listener, transaction, enableAssertions);
    }
    return transaction;
}
Also used : StoreTimer(com.apple.foundationdb.record.provider.common.StoreTimer) Transaction(com.apple.foundationdb.Transaction) StoreSubTimer(com.apple.foundationdb.record.provider.common.StoreSubTimer)

Example 74 with Transaction

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

the class FDBDatabase method performNoOpAsync.

/**
 * Perform a no-op against FDB to check network thread liveness. This operation will not change the underlying data
 * in any way, nor will it perform any I/O against the FDB cluster. However, it will schedule some amount of work
 * onto the FDB client and wait for it to complete. The FoundationDB client operates by scheduling onto an event
 * queue that is then processed by a single thread (the "network thread"). This method can be used to determine if
 * the network thread has entered a state where it is no longer processing requests or if its time to process
 * requests has increased. If the network thread is busy, this operation may take some amount of time to complete,
 * which is why this operation returns a future.
 *
 * <p>
 * If the provided {@link FDBStoreTimer} is not {@code null}, then this will update the {@link FDBStoreTimer.Events#PERFORM_NO_OP}
 * operation with related timing information. This can then be monitored to detect instances of client saturation
 * where the performance bottleneck lies in scheduling work to run on the FDB event queue.
 * </p>
 *
 * @param mdcContext logger context to set in running threads
 * @param timer the timer to use for instrumentation
 * @return a future that will complete after being run by the FDB network thread
 */
@Nonnull
public CompletableFuture<Void> performNoOpAsync(@Nullable Map<String, String> mdcContext, @Nullable FDBStoreTimer timer) {
    final FDBRecordContext context = openContext(mdcContext, timer);
    boolean futureStarted = false;
    try {
        // Set the read version of the transaction, then read it back. This requires no I/O, but it does
        // require the network thread be running. The exact value used for the read version is unimportant.
        // Note that this calls setReadVersion and getReadVersion on the Transaction object, *not* on the
        // FDBRecordContext. This is because the FDBRecordContext will cache the value of setReadVersion to
        // avoid having to go back to the FDB network thread, but we do not want that for instrumentation.
        final Transaction tr = context.ensureActive();
        final long startTime = System.nanoTime();
        tr.setReadVersion(1066L);
        CompletableFuture<Long> future = tr.getReadVersion();
        if (timer != null) {
            future = context.instrument(FDBStoreTimer.Events.PERFORM_NO_OP, future, startTime);
        }
        futureStarted = true;
        return future.thenAccept(ignore -> {
        }).whenComplete((vignore, err) -> {
            context.close();
            if (err != null) {
                logNoOpFailure(err);
            }
        });
    } catch (RuntimeException e) {
        logNoOpFailure(e);
        CompletableFuture<Void> errFuture = new CompletableFuture<>();
        errFuture.completeExceptionally(e);
        return errFuture;
    } finally {
        if (!futureStarted) {
            context.close();
        }
    }
}
Also used : LogMessageKeys(com.apple.foundationdb.record.logging.LogMessageKeys) StoreTimer(com.apple.foundationdb.record.provider.common.StoreTimer) ScopedValue(com.apple.foundationdb.record.provider.foundationdb.keyspace.ScopedValue) ResolverResult(com.apple.foundationdb.record.provider.foundationdb.keyspace.ResolverResult) LoggerFactory(org.slf4j.LoggerFactory) TimeoutException(java.util.concurrent.TimeoutException) CompletableFuture(java.util.concurrent.CompletableFuture) Database(com.apple.foundationdb.Database) LocatableResolver(com.apple.foundationdb.record.provider.foundationdb.keyspace.LocatableResolver) AtomicReference(java.util.concurrent.atomic.AtomicReference) Function(java.util.function.Function) Supplier(java.util.function.Supplier) AsyncLoadingCache(com.apple.foundationdb.record.AsyncLoadingCache) Transaction(com.apple.foundationdb.Transaction) PassThroughRecordStoreStateCache(com.apple.foundationdb.record.provider.foundationdb.storestate.PassThroughRecordStoreStateCache) Tuple(com.apple.foundationdb.tuple.Tuple) KeyValueLogMessage(com.apple.foundationdb.record.logging.KeyValueLogMessage) RecordCoreRetriableTransactionException(com.apple.foundationdb.record.RecordCoreRetriableTransactionException) Pair(org.apache.commons.lang3.tuple.Pair) RecordCoreException(com.apple.foundationdb.record.RecordCoreException) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Map(java.util.Map) NoSuchElementException(java.util.NoSuchElementException) Nonnull(javax.annotation.Nonnull) Nullable(javax.annotation.Nullable) LoggableTimeoutException(com.apple.foundationdb.record.LoggableTimeoutException) Logger(org.slf4j.Logger) Executor(java.util.concurrent.Executor) NavigableMap(java.util.NavigableMap) ImmutablePair(org.apache.commons.lang3.tuple.ImmutablePair) ExecutionException(java.util.concurrent.ExecutionException) TimeUnit(java.util.concurrent.TimeUnit) List(java.util.List) ConcurrentSkipListMap(java.util.concurrent.ConcurrentSkipListMap) FDBException(com.apple.foundationdb.FDBException) StoreSubTimer(com.apple.foundationdb.record.provider.common.StoreSubTimer) FDBRecordStoreStateCache(com.apple.foundationdb.record.provider.foundationdb.storestate.FDBRecordStoreStateCache) API(com.apple.foundationdb.annotation.API) VisibleForTesting(com.google.common.annotations.VisibleForTesting) CacheBuilder(com.google.common.cache.CacheBuilder) Cache(com.google.common.cache.Cache) ResolverStateProto(com.apple.foundationdb.record.ResolverStateProto) CacheStats(com.google.common.cache.CacheStats) CompletableFuture(java.util.concurrent.CompletableFuture) Transaction(com.apple.foundationdb.Transaction) Nonnull(javax.annotation.Nonnull)

Example 75 with Transaction

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

the class FDBRecordStore method rebuildAllIndexes.

/**
 * Rebuild all of this store's indexes. All indexes will then be marked as {@linkplain IndexState#READABLE readable}
 * when this function completes. Note that this will attempt to read all of the records within
 * this store in a single transaction, so for large record stores, this can run up against transaction
 * time and size limits. For larger stores, one should use the {@link OnlineIndexer} to build
 * each index instead.
 *
 * @return a future that will complete when all of the indexes are built
 */
@Nonnull
public CompletableFuture<Void> rebuildAllIndexes() {
    Transaction tr = ensureContextActive();
    // Note that index states are *not* cleared, as rebuilding the indexes resets each state
    tr.clear(getSubspace().range(Tuple.from(INDEX_KEY)));
    tr.clear(getSubspace().range(Tuple.from(INDEX_SECONDARY_SPACE_KEY)));
    tr.clear(getSubspace().range(Tuple.from(INDEX_RANGE_SPACE_KEY)));
    tr.clear(getSubspace().range(Tuple.from(INDEX_UNIQUENESS_VIOLATIONS_KEY)));
    List<CompletableFuture<Void>> work = new LinkedList<>();
    addRebuildRecordCountsJob(work);
    return rebuildIndexes(getRecordMetaData().getIndexesToBuildSince(-1), Collections.emptyMap(), work, RebuildIndexReason.REBUILD_ALL, null);
}
Also used : CompletableFuture(java.util.concurrent.CompletableFuture) Transaction(com.apple.foundationdb.Transaction) ReadTransaction(com.apple.foundationdb.ReadTransaction) LinkedList(java.util.LinkedList) Nonnull(javax.annotation.Nonnull)

Aggregations

Transaction (com.apple.foundationdb.Transaction)84 ReadTransaction (com.apple.foundationdb.ReadTransaction)34 Tuple (com.apple.foundationdb.tuple.Tuple)34 Test (org.junit.jupiter.api.Test)33 Nonnull (javax.annotation.Nonnull)28 ArrayList (java.util.ArrayList)26 List (java.util.List)26 CompletableFuture (java.util.concurrent.CompletableFuture)26 AsyncUtil (com.apple.foundationdb.async.AsyncUtil)22 Subspace (com.apple.foundationdb.subspace.Subspace)21 Collectors (java.util.stream.Collectors)19 Nullable (javax.annotation.Nullable)19 KeyValue (com.apple.foundationdb.KeyValue)18 Map (java.util.Map)18 KeyValueLogMessage (com.apple.foundationdb.record.logging.KeyValueLogMessage)17 Range (com.apple.foundationdb.Range)16 RecordCoreException (com.apple.foundationdb.record.RecordCoreException)16 AtomicReference (java.util.concurrent.atomic.AtomicReference)16 Collections (java.util.Collections)15 RecordCursor (com.apple.foundationdb.record.RecordCursor)14