use of com.apple.foundationdb.Transaction in project fdb-record-layer by FoundationDB.
the class IndexingBase method rebuildIndexAsync.
// rebuildIndexAsync - builds the whole index inline (without committing)
@Nonnull
public CompletableFuture<Void> rebuildIndexAsync(@Nonnull FDBRecordStore store) {
return forEachTargetIndex(index -> store.clearAndMarkIndexWriteOnly(index).thenCompose(bignore -> {
// Insert the full range into the range set. (The internal rebuild method only indexes the records and
// does not update the range set.) This is important because if marking the index as readable fails (for
// example, because of uniqueness violations), we still want to record in the range set that the entire
// range was built so that future index builds don't re-scan the record data and so that non-idempotent
// indexes know to update the index on all record saves.
Transaction tr = store.ensureContextActive();
RangeSet rangeSet = new RangeSet(store.indexRangeSubspace(index));
return rangeSet.insertRange(tr, null, null);
})).thenCompose(vignore -> rebuildIndexInternalAsync(store));
}
use of com.apple.foundationdb.Transaction 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());
}
});
});
}
use of com.apple.foundationdb.Transaction in project fdb-record-layer by FoundationDB.
the class FDBSystemOperations method getPrimaryDatacenterAsync.
/**
* Get the primary datacenter of the underlying cluster. This will return the datacenter ID (if set)
* of the datacenter currently serving as the primary, which (by definition) is where the transaction
* subsystem will be recruited. This is mostly relevant for
* <a href="https://apple.github.io/foundationdb/configuration.html#configuring-regions">multi-region configurations</a>,
* where this value might change if the cluster decides that it needs to fail over to a secondary region. The returned
* datacenter ID will be {@code null} if the FDB cluster's datacenter has not been set.
*
* <p>
* Note that this operation must read this information from the database's storage and uses its own transaction.
* </p>
*
* @param runner a runner to use to perform the operation
* @return a future that will complete with the primary datacenter of the cluster for the database underlying {@code runner}
*/
@Nonnull
public static CompletableFuture<String> getPrimaryDatacenterAsync(@Nonnull FDBDatabaseRunner runner) {
return runner.runAsync(context -> {
final Transaction tr = context.ensureActive();
tr.options().setReadSystemKeys();
return tr.get(SystemKeyspace.PRIMARY_DATACENTER_KEY).thenApply(FDBSystemOperations::nullableUtf8);
}, Arrays.asList(LogMessageKeys.TRANSACTION_NAME, "FDBSystemOperations::getPrimaryDatacenterAsync"));
}
use of com.apple.foundationdb.Transaction in project fdb-record-layer by FoundationDB.
the class FDBDatabase method openContext.
/**
* Open a new record context with a new transaction begun on the underlying FDB database. Various
* options on the transaction will be informed based on the passed context.
*
* @param contextConfig a configuration object specifying various options on the returned context
* @return a new record context
* @see Database#createTransaction
*/
@Nonnull
@SuppressWarnings("PMD.CompareObjectsWithEquals")
public FDBRecordContext openContext(@Nonnull FDBRecordContextConfig contextConfig) {
openFDB();
final Executor executor = newContextExecutor(contextConfig.getMdcContext());
final Transaction transaction = createTransaction(contextConfig, executor);
// TODO: Compatibility with STABLE API.
if (transactionIsTracedSupplier.get()) {
contextConfig = contextConfig.toBuilder().setTrackOpen(true).setLogTransaction(true).setSaveOpenStackTrace(true).build();
}
FDBRecordContext context = new FDBRecordContext(this, transaction, contextConfig);
final WeakReadSemantics weakReadSemantics = context.getWeakReadSemantics();
if (isTrackLastSeenVersion() && (weakReadSemantics != null)) {
Pair<Long, Long> pair = lastSeenFDBVersion.get();
if (pair != initialVersionPair) {
long version = pair.getLeft();
long versionTimeMillis = pair.getRight();
// otherwise getReadVersion does not use the cached value and results in a GRV call to FDB
if (version >= weakReadSemantics.getMinVersion() && (System.currentTimeMillis() - versionTimeMillis) <= weakReadSemantics.getStalenessBoundMillis()) {
context.setReadVersion(version);
context.increment(FDBStoreTimer.Counts.SET_READ_VERSION_TO_LAST_SEEN);
}
}
}
if (warnAndCloseOpenContextsAfterSeconds > 0) {
warnAndCloseOldTrackedOpenContexts(warnAndCloseOpenContextsAfterSeconds);
}
if (contextConfig.isTrackOpen()) {
trackOpenContext(context);
}
return context;
}
use of com.apple.foundationdb.Transaction in project fdb-record-layer by FoundationDB.
the class BunchedMapScanTest method testScan.
private void testScan(int limit, boolean reverse, @Nonnull BiFunction<Transaction, byte[], BunchedMapIterator<Tuple, Tuple>> iteratorFunction) {
try (Transaction tr = db.createTransaction()) {
byte[] continuation = null;
List<Tuple> readKeys = new ArrayList<>();
Tuple lastKey = null;
do {
int returned = 0;
BunchedMapIterator<Tuple, Tuple> bunchedMapIterator = iteratorFunction.apply(tr, continuation);
while (bunchedMapIterator.hasNext()) {
Tuple toAdd = bunchedMapIterator.peek().getKey();
readKeys.add(toAdd);
assertEquals(toAdd, bunchedMapIterator.next().getKey());
if (lastKey != null) {
assertEquals(reverse ? 1 : -1, lastKey.compareTo(toAdd));
}
lastKey = toAdd;
returned += 1;
}
assertFalse(bunchedMapIterator.hasNext());
assertThrows(NoSuchElementException.class, bunchedMapIterator::peek);
assertThrows(NoSuchElementException.class, bunchedMapIterator::next);
continuation = bunchedMapIterator.getContinuation();
if (limit == ReadTransaction.ROW_LIMIT_UNLIMITED || returned < limit) {
assertNull(continuation);
} else {
assertNotNull(continuation);
}
} while (continuation != null);
if (reverse) {
readKeys = Lists.reverse(readKeys);
}
assertEquals(keys, readKeys);
tr.cancel();
}
}
Aggregations