FDBRecordContext extends FDBTransactionContext implements AutoCloseable { @SpotBugsSuppressWarnings(value = "UG_SYNC_SET_UNSYNC_GET", justification = "read only one field and avoid blocking in setReadVersion") public long getReadVersion() { if (hasReadVersion()) { return readVersion; } return asyncToSync(FDBStoreTimer.Waits.WAIT_GET_READ_VERSION, getReadVersionAsync()); } protected  FDBRecordContext(@Nonnull FDBDatabase fdb,
                               @Nonnull Transaction transaction,
                               @Nonnull FDBRecordContextConfig config); @Nullable String getTransactionId(); long getTimeoutMillis(); final void logTransaction(); boolean isLogged(); @API(API.Status.INTERNAL) @VisibleForTesting long getTrackOpenTimeNanos(); boolean isClosed(); @Override void close(); void commit(); CompletableFuture<Void> commitAsync(); @Override @Nonnull Transaction ensureActive(); synchronized long setReadVersion(long readVersion); @Nonnull synchronized CompletableFuture<Long> getReadVersionAsync(); @SpotBugsSuppressWarnings(value = "UG_SYNC_SET_UNSYNC_GET", justification = "read only one field and avoid blocking in setReadVersion") long getReadVersion(); boolean hasReadVersion(); @Nonnull ReadTransaction readTransaction(boolean snapshot); long getTransactionAge(); long getTransactionCreateTime(); @API(API.Status.INTERNAL) void setDirtyStoreState(boolean dirtyStoreState); @API(API.Status.INTERNAL) boolean hasDirtyStoreState(); synchronized void addCommitCheck(@Nonnull CommitCheckAsync check); synchronized void addCommitCheck(@Nonnull CompletableFuture<Void> check); @Nonnull CompletableFuture<Void> runCommitChecks(); @Nonnull PostCommit getOrCreatePostCommit(@Nonnull String name, @Nonnull Function<String, PostCommit> ifNotExists); @Nullable PostCommit getPostCommit(@Nonnull String name); void addPostCommit(@Nonnull String name, @Nonnull PostCommit postCommit); void addPostCommit(@Nonnull PostCommit postCommit); @Nullable PostCommit removePostCommit(@Nonnull String name); void addAfterCommit(@Nonnull AfterCommit afterCommit); @Deprecated @API(API.Status.DEPRECATED) void runAfterCommits(); long getCommittedVersion(); @Nullable @SpotBugsSuppressWarnings(value = {"EI"}, justification = "avoids copy") byte[] getVersionStamp(); @Nonnull CompletableFuture<byte[]> getMetaDataVersionStampAsync(@Nonnull IsolationLevel isolationLevel); @Nullable byte[] getMetaDataVersionStamp(@Nonnull IsolationLevel isolationLevel); void setMetaDataVersionStamp(); @Nullable T asyncToSync(FDBStoreTimer.Wait event, @Nonnull CompletableFuture<T> async); T join(CompletableFuture<T> future); T joinNow(CompletableFuture<T> future); T get(CompletableFuture<T> future); void timeReadSampleKey(byte[] key); @Nullable Map<String, String> getMdcContext(); @Nonnull FDBDatabaseRunner newRunner(); int claimLocalVersion(); @Deprecated @Nullable byte[] addVersionMutation(@Nonnull byte[] key, @Nonnull byte[] value); @Nullable byte[] addVersionMutation(@Nonnull MutationType mutationType, @Nonnull byte[] key, @Nonnull byte[] value); @Nullable byte[] removeVersionMutation(@Nonnull byte[] key); @Nullable byte[] updateVersionMutation(@Nonnull MutationType mutationType, @Nonnull byte[] key, @Nonnull byte[] value,
                                        @Nonnull BiFunction<byte[], byte[], byte[]> remappingFunction); @Nullable FDBDatabase.WeakReadSemantics getWeakReadSemantics(); @Nonnull FDBTransactionPriority getPriority(); void setHookForAsyncToSync(@Nonnull Consumer<FDBStoreTimer.Wait> hook); boolean hasHookForAsyncToSync(); static final int MAX_TR_ID_SIZE; }
@Test public void getReadVersionTwice() { final FDBStoreTimer timer = new FDBStoreTimer(); try (FDBRecordContext context = fdb.openContext(null, timer)) { long readVersion1 = context.getReadVersion(); assertEquals(1, timer.getCount(FDBStoreTimer.Events.GET_READ_VERSION)); long grvNanos = timer.getTimeNanos(FDBStoreTimer.Events.GET_READ_VERSION); long readVersion2 = context.getReadVersion(); assertEquals(readVersion1, readVersion2); assertEquals(1, timer.getCount(FDBStoreTimer.Events.GET_READ_VERSION)); assertEquals(grvNanos, timer.getTimeNanos(FDBStoreTimer.Events.GET_READ_VERSION)); } }
@Test public void getReadVersionTimingWithInjectedLatency() { final FDBStoreTimer timer = new FDBStoreTimer(); FDBDatabaseFactory factory = fdb.getFactory(); Function<FDBLatencySource, Long> oldLatencyInjector = factory.getLatencyInjector(); factory.setLatencyInjector(latencySource -> { if (latencySource.equals(FDBLatencySource.GET_READ_VERSION)) { return 50L; } else { return 10L; } }); factory.clear(); fdb = factory.getDatabase(fdb.getClusterFile()); try { try (FDBRecordContext context = fdb.openContext(null, timer)) { context.getReadVersion(); } assertEquals(1, timer.getCount(FDBStoreTimer.Waits.WAIT_GET_READ_VERSION)); assertEquals(1, timer.getCount(FDBStoreTimer.Events.GET_READ_VERSION)); assertEquals(1, timer.getCount(FDBStoreTimer.Events.INJECTED_GET_READ_VERSION_LATENCY)); long waitNanos = timer.getTimeNanos(FDBStoreTimer.Waits.WAIT_GET_READ_VERSION); long grvNanos = timer.getTimeNanos(FDBStoreTimer.Events.GET_READ_VERSION); long injectedNanos = timer.getTimeNanos(FDBStoreTimer.Events.INJECTED_GET_READ_VERSION_LATENCY); assertThat(injectedNanos, lessThanOrEqualTo(grvNanos)); assertThat(waitNanos, greaterThan(0L)); } finally { factory.setLatencyInjector(oldLatencyInjector); factory.clear(); } }
@Test public void getReadVersionWithWeakReadSemantics() { fdb.setTrackLastSeenVersion(true); long firstReadVersion; try (FDBRecordContext context = fdb.openContext()) { firstReadVersion = context.getReadVersion(); } final FDBStoreTimer timer = new FDBStoreTimer(); try (FDBRecordContext context = fdb.openContext(null, timer, UNLIMITED_STALE_READ)) { assertEquals(firstReadVersion, context.getReadVersion()); assertEquals(0, timer.getCount(FDBStoreTimer.Events.GET_READ_VERSION)); } }
@Test public void getReadVersionAtBatch() { final FDBStoreTimer timer = new FDBStoreTimer(); try (FDBRecordContext context = fdb.openContext(null, timer, null, FDBTransactionPriority.BATCH)) { context.getReadVersion(); assertEquals(1, timer.getCount(FDBStoreTimer.Events.BATCH_GET_READ_VERSION)); assertEquals(0, timer.getCount(FDBStoreTimer.Events.GET_READ_VERSION)); } }