Search in sources :

Example 66 with Transaction

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

the class FDBRecordStore method deleteStore.

/**
 * Delete the record store at the given {@link Subspace}. In addition to the store's
 * data this will delete the store's header and therefore will remove any evidence that
 * the store existed.
 *
 * <p>
 * This method does not read the underlying record store, so it does not validate
 * that a record store exists in the given subspace. As it might be the case that
 * this record store has a cacheable store state (see {@link #setStateCacheability(boolean)}),
 * this method resets the database's
 * {@linkplain FDBRecordContext#getMetaDataVersionStamp(IsolationLevel) meta-data version-stamp}.
 * As a result, calling this method may cause other clients to invalidate their caches needlessly.
 * </p>
 *
 * @param context the transactional context in which to delete the record store
 * @param subspace the subspace containing the record store
 */
public static void deleteStore(FDBRecordContext context, Subspace subspace) {
    // In theory, we only need to set the meta-data version stamp if the record store's
    // meta-data is cacheable, but we can't know that from here.
    context.setMetaDataVersionStamp();
    context.setDirtyStoreState(true);
    final Transaction transaction = context.ensureActive();
    transaction.clear(subspace.range());
}
Also used : Transaction(com.apple.foundationdb.Transaction) ReadTransaction(com.apple.foundationdb.ReadTransaction)

Example 67 with Transaction

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

the class FDBRecordStore method addRecordsReadConflict.

/**
 * Add a read conflict key for all records.
 */
private void addRecordsReadConflict() {
    if (recordsReadConflict) {
        return;
    }
    recordsReadConflict = true;
    Transaction tr = ensureContextActive();
    byte[] recordKey = getSubspace().pack(Tuple.from(RECORD_KEY));
    tr.addReadConflictRange(recordKey, ByteArrayUtil.strinc(recordKey));
}
Also used : Transaction(com.apple.foundationdb.Transaction) ReadTransaction(com.apple.foundationdb.ReadTransaction)

Example 68 with Transaction

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

the class FDBRecordStore method firstUnbuiltRange.

/**
 * Returns the first unbuilt range of an index that is currently being bulit.
 * If there is no range that is currently unbuilt, it will return an
 * empty {@link Optional}. If there is one, it will return an {@link Optional}
 * set to the first unbuilt range it finds.
 * @param index the index to check built state
 * @return a future that will contain the first unbuilt range if any
 */
@Nonnull
public CompletableFuture<Optional<Range>> firstUnbuiltRange(@Nonnull Index index) {
    if (!getRecordMetaData().hasIndex(index.getName())) {
        throw new MetaDataException("Index " + index.getName() + " does not exist in meta-data.");
    }
    Transaction tr = ensureContextActive();
    RangeSet rangeSet = new RangeSet(indexRangeSubspace(index));
    AsyncIterator<Range> missingRangeIterator = rangeSet.missingRanges(tr, null, null, 1).iterator();
    return missingRangeIterator.onHasNext().thenApply(hasFirst -> {
        if (hasFirst) {
            return Optional.of(missingRangeIterator.next());
        } else {
            return Optional.empty();
        }
    });
}
Also used : Transaction(com.apple.foundationdb.Transaction) ReadTransaction(com.apple.foundationdb.ReadTransaction) RangeSet(com.apple.foundationdb.async.RangeSet) TupleRange(com.apple.foundationdb.record.TupleRange) Range(com.apple.foundationdb.Range) MetaDataException(com.apple.foundationdb.record.metadata.MetaDataException) Nonnull(javax.annotation.Nonnull)

Example 69 with Transaction

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

the class IndexingBase method setIndexingTypeOrThrow.

@Nonnull
private CompletableFuture<Void> setIndexingTypeOrThrow(FDBRecordStore store, boolean continuedBuild) {
    // continuedBuild is set if this session isn't a continuation of a previous indexing
    Transaction transaction = store.getContext().ensureActive();
    IndexBuildProto.IndexBuildIndexingStamp indexingTypeStamp = getIndexingTypeStamp(store);
    return forEachTargetIndex(index -> setIndexingTypeOrThrow(store, continuedBuild, transaction, index, indexingTypeStamp));
}
Also used : Transaction(com.apple.foundationdb.Transaction) IndexBuildProto(com.apple.foundationdb.record.IndexBuildProto) Nonnull(javax.annotation.Nonnull)

Example 70 with Transaction

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

the class IndexingBase method iterateRangeOnly.

/**
 * iterate cursor's items and index them.
 *
 * @param store the record store.
 * @param cursor iteration items.
 * @param getRecordToIndex function to convert cursor's item to a record that should be indexed (or null, if inapplicable)
 * @param nextResultCont when return, if hasMore is true, holds the last cursored result - unprocessed - as a
 * continuation item.
 * @param hasMore when return, true if the cursor's source is not exhausted (not more items in range).
 * @param recordsScanned when return, number of scanned records.
 * @param isIdempotent are all the built indexes idempotent
 * @param <T> cursor result's type.
 *
 * @return hasMore, nextResultCont, and recordsScanned.
 */
protected <T> CompletableFuture<Void> iterateRangeOnly(@Nonnull FDBRecordStore store, @Nonnull RecordCursor<T> cursor, @Nonnull BiFunction<FDBRecordStore, RecordCursorResult<T>, CompletableFuture<FDBStoredRecord<Message>>> getRecordToIndex, @Nonnull AtomicReference<RecordCursorResult<T>> nextResultCont, @Nonnull AtomicBoolean hasMore, @Nullable AtomicLong recordsScanned, final boolean isIdempotent) {
    final FDBStoreTimer timer = getRunner().getTimer();
    final FDBRecordContext context = store.getContext();
    // Need to do this each transaction because other index enabled state might have changed. Could cache based on that.
    // Copying the state also guards against changes made by other online building from check version.
    AtomicLong recordsScannedCounter = new AtomicLong();
    final AtomicReference<RecordCursorResult<T>> nextResult = new AtomicReference<>(null);
    return AsyncUtil.whileTrue(() -> cursor.onNext().thenCompose(result -> {
        RecordCursorResult<T> currResult;
        final boolean isExhausted;
        if (result.hasNext()) {
            // has next, process one previous item (if exists)
            currResult = nextResult.get();
            nextResult.set(result);
            if (currResult == null) {
                // that was the first item, nothing to process
                return AsyncUtil.READY_TRUE;
            }
            isExhausted = false;
        } else {
            // end of the cursor list
            timerIncrement(timer, FDBStoreTimer.Counts.ONLINE_INDEX_BUILDER_RANGES_BY_COUNT);
            if (!result.getNoNextReason().isSourceExhausted()) {
                nextResultCont.set(nextResult.get());
                hasMore.set(true);
                return AsyncUtil.READY_FALSE;
            }
            // source is exhausted, fall down to handle the last item and return with hasMore=false
            currResult = nextResult.get();
            if (currResult == null) {
                // there was no data
                hasMore.set(false);
                return AsyncUtil.READY_FALSE;
            }
            // here, process the last item and return
            nextResult.set(null);
            isExhausted = true;
        }
        // here: currResult must have value
        timerIncrement(timer, FDBStoreTimer.Counts.ONLINE_INDEX_BUILDER_RECORDS_SCANNED);
        recordsScannedCounter.incrementAndGet();
        return getRecordToIndex.apply(store, currResult).thenCompose(rec -> {
            if (null == rec) {
                if (isExhausted) {
                    hasMore.set(false);
                    return AsyncUtil.READY_FALSE;
                }
                return AsyncUtil.READY_TRUE;
            }
            // This record should be indexed. Add it to the transaction.
            if (isIdempotent) {
                store.addRecordReadConflict(rec.getPrimaryKey());
            }
            timerIncrement(timer, FDBStoreTimer.Counts.ONLINE_INDEX_BUILDER_RECORDS_INDEXED);
            final CompletableFuture<Void> updateMaintainer = updateMaintainerBuilder(store, rec);
            if (isExhausted) {
                // we've just processed the last item
                hasMore.set(false);
                return updateMaintainer.thenApply(vignore -> false);
            }
            return updateMaintainer.thenCompose(vignore -> context.getApproximateTransactionSize().thenApply(size -> {
                if (size >= common.config.getMaxWriteLimitBytes()) {
                    // the transaction becomes too big - stop iterating
                    timerIncrement(timer, FDBStoreTimer.Counts.ONLINE_INDEX_BUILDER_RANGES_BY_SIZE);
                    nextResultCont.set(nextResult.get());
                    hasMore.set(true);
                    return false;
                }
                return true;
            }));
        });
    }), cursor.getExecutor()).thenApply(vignore -> {
        long recordsScannedInTransaction = recordsScannedCounter.get();
        if (recordsScanned != null) {
            recordsScanned.addAndGet(recordsScannedInTransaction);
        }
        if (common.isTrackProgress()) {
            for (Index index : common.getTargetIndexes()) {
                final Subspace scannedRecordsSubspace = indexBuildScannedRecordsSubspace(store, index);
                store.context.ensureActive().mutate(MutationType.ADD, scannedRecordsSubspace.getKey(), FDBRecordStore.encodeRecordCount(recordsScannedInTransaction));
            }
        }
        return null;
    });
}
Also used : RecordMetaData(com.apple.foundationdb.record.RecordMetaData) LogMessageKeys(com.apple.foundationdb.record.logging.LogMessageKeys) BiFunction(java.util.function.BiFunction) 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) Function(java.util.function.Function) Supplier(java.util.function.Supplier) Subspace(com.apple.foundationdb.subspace.Subspace) ArrayList(java.util.ArrayList) MutationType(com.apple.foundationdb.MutationType) Key(com.apple.foundationdb.record.metadata.Key) Transaction(com.apple.foundationdb.Transaction) Tuple(com.apple.foundationdb.tuple.Tuple) Range(com.apple.foundationdb.Range) RecordCursorResult(com.apple.foundationdb.record.RecordCursorResult) KeyValueLogMessage(com.apple.foundationdb.record.logging.KeyValueLogMessage) Pair(org.apache.commons.lang3.tuple.Pair) RecordCoreException(com.apple.foundationdb.record.RecordCoreException) BiConsumer(java.util.function.BiConsumer) IndexBuildProto(com.apple.foundationdb.record.IndexBuildProto) Nonnull(javax.annotation.Nonnull) Nullable(javax.annotation.Nullable) ByteArrayUtil2(com.apple.foundationdb.tuple.ByteArrayUtil2) MoreAsyncUtil(com.apple.foundationdb.async.MoreAsyncUtil) InvalidProtocolBufferException(com.google.protobuf.InvalidProtocolBufferException) Logger(org.slf4j.Logger) SynchronizedSessionRunner(com.apple.foundationdb.record.provider.foundationdb.synchronizedsession.SynchronizedSessionRunner) IndexState(com.apple.foundationdb.record.IndexState) Collectors(java.util.stream.Collectors) TimeUnit(java.util.concurrent.TimeUnit) AtomicLong(java.util.concurrent.atomic.AtomicLong) List(java.util.List) RecordMetaDataProvider(com.apple.foundationdb.record.RecordMetaDataProvider) Index(com.apple.foundationdb.record.metadata.Index) FDBException(com.apple.foundationdb.FDBException) Message(com.google.protobuf.Message) RecordCursor(com.apple.foundationdb.record.RecordCursor) API(com.apple.foundationdb.annotation.API) Collections(java.util.Collections) SyntheticRecordPlanner(com.apple.foundationdb.record.query.plan.synthetic.SyntheticRecordPlanner) SyntheticRecordFromStoredRecordPlan(com.apple.foundationdb.record.query.plan.synthetic.SyntheticRecordFromStoredRecordPlan) RecordCursorResult(com.apple.foundationdb.record.RecordCursorResult) AtomicReference(java.util.concurrent.atomic.AtomicReference) Index(com.apple.foundationdb.record.metadata.Index) AtomicLong(java.util.concurrent.atomic.AtomicLong) Subspace(com.apple.foundationdb.subspace.Subspace)

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