use of com.apple.foundationdb.record.provider.foundationdb.FDBStoreTimer in project fdb-record-layer by FoundationDB.
the class LocatableResolverTest method testDirectoryCache.
@Test
public void testDirectoryCache() {
FDBDatabaseFactory factory = FDBDatabaseFactory.instance();
factory.setDirectoryCacheSize(10);
FDBStoreTimer timer = new FDBStoreTimer();
FDBDatabase fdb = factory.getDatabase();
// Make sure cache is fresh.
fdb.close();
String key = "world";
Long value;
try (FDBRecordContext context = fdb.openContext()) {
context.setTimer(timer);
value = context.asyncToSync(FDBStoreTimer.Waits.WAIT_DIRECTORY_RESOLVE, globalScope.resolve(context.getTimer(), key));
}
int initialReads = timer.getCount(FDBStoreTimer.Events.DIRECTORY_READ);
assertThat(initialReads, is(greaterThanOrEqualTo(1)));
for (int i = 0; i < 10; i++) {
try (FDBRecordContext context = fdb.openContext()) {
context.setTimer(timer);
assertThat("we continue to resolve the same value", context.asyncToSync(FDBStoreTimer.Waits.WAIT_DIRECTORY_RESOLVE, globalScope.resolve(context.getTimer(), key)), is(value));
}
}
assertEquals(timer.getCount(FDBStoreTimer.Events.DIRECTORY_READ), initialReads);
}
use of com.apple.foundationdb.record.provider.foundationdb.FDBStoreTimer in project fdb-record-layer by FoundationDB.
the class LocatableResolverTest method testVersionIncrementInvalidatesCache.
@Test
public void testVersionIncrementInvalidatesCache() {
FDBDatabaseFactory factory = FDBDatabaseFactory.instance();
factory.setDirectoryCacheSize(10);
FDBStoreTimer timer = new FDBStoreTimer();
FDBDatabase fdb = factory.getDatabase();
// Make sure cache is fresh, and resets version
fdb.close();
fdb.setResolverStateRefreshTimeMillis(100);
String key = "some-key";
Long value;
try (FDBRecordContext context = fdb.openContext()) {
context.setTimer(timer);
value = context.asyncToSync(FDBStoreTimer.Waits.WAIT_DIRECTORY_RESOLVE, globalScope.resolve(context.getTimer(), key));
}
assertThat(timer.getCount(FDBStoreTimer.Events.DIRECTORY_READ), is(greaterThanOrEqualTo(1)));
timer.reset();
consistently("we hit the cached value", () -> {
try (FDBRecordContext context = fdb.openContext()) {
context.setTimer(timer);
assertThat("the resolved value is still the same", globalScope.resolve(context.getTimer(), key).join(), is(value));
}
return timer.getCount(FDBStoreTimer.Events.DIRECTORY_READ);
}, is(0), 200, 10);
globalScope.incrementVersion().join();
timer.reset();
eventually("we see the version change and invalidate the cache", () -> {
try (FDBRecordContext context = fdb.openContext()) {
context.setTimer(timer);
assertThat("the resolved value is still the same", globalScope.resolve(context.getTimer(), key).join(), is(value));
}
return timer.getCount(FDBStoreTimer.Events.DIRECTORY_READ);
}, is(1), 120, 10);
timer.reset();
consistently("the value is cached while the version is not changed", () -> {
try (FDBRecordContext context = fdb.openContext()) {
context.setTimer(timer);
assertThat("the resolved value is still the same", globalScope.resolve(context.getTimer(), key).join(), is(value));
}
return timer.getCount(FDBStoreTimer.Events.DIRECTORY_READ);
}, is(0), 200, 10);
}
use of com.apple.foundationdb.record.provider.foundationdb.FDBStoreTimer in project fdb-record-layer by FoundationDB.
the class LocatableResolverTest method testCachingPerDbPerResolver.
@Test
public void testCachingPerDbPerResolver() {
KeySpace keySpace = new KeySpace(new KeySpaceDirectory("resolver1", KeyType.STRING, "resolver1"), new KeySpaceDirectory("resolver2", KeyType.STRING, "resolver2"));
LocatableResolver resolver1;
LocatableResolver resolver2;
FDBStoreTimer timer = new FDBStoreTimer();
try (FDBRecordContext context = database.openContext()) {
resolver1 = resolverFactory.create(keySpace.path("resolver1").toResolvedPath(context));
resolver2 = resolverFactory.create(keySpace.path("resolver2").toResolvedPath(context));
context.setTimer(timer);
for (int i = 0; i < 10; i++) {
resolver1.getVersion(context.getTimer()).join();
}
assertThat("We only read the value once", timer.getCount(FDBStoreTimer.DetailEvents.RESOLVER_STATE_READ), is(1));
timer = new FDBStoreTimer();
assertThat("count is reset", timer.getCount(FDBStoreTimer.DetailEvents.RESOLVER_STATE_READ), is(0));
context.setTimer(timer);
resolver2.getVersion(context.getTimer()).join();
assertThat("We have to read the value for the new resolver", timer.getCount(FDBStoreTimer.DetailEvents.RESOLVER_STATE_READ), is(1));
LocatableResolver newResolver1 = resolverFactory.create(keySpace.path("resolver1").toResolvedPath(context));
timer = new FDBStoreTimer();
assertThat("count is reset", timer.getCount(FDBStoreTimer.DetailEvents.RESOLVER_STATE_READ), is(0));
context.setTimer(timer);
for (int i = 0; i < 10; i++) {
newResolver1.getVersion(context.getTimer()).join();
}
assertThat("we still hit the cache", timer.getCount(FDBStoreTimer.DetailEvents.RESOLVER_STATE_READ), is(0));
}
}
use of com.apple.foundationdb.record.provider.foundationdb.FDBStoreTimer in project fdb-record-layer by FoundationDB.
the class LocatableResolverTest method testWriteLockCaching.
@Test
public void testWriteLockCaching() {
FDBStoreTimer timer = new FDBStoreTimer();
try (FDBRecordContext context = database.openContext()) {
context.setTimer(timer);
globalScope.resolve(context.getTimer(), "something").join();
int initialCount = timer.getCount(FDBStoreTimer.DetailEvents.RESOLVER_STATE_READ);
assertThat("first read must check the lock in the database", initialCount, greaterThanOrEqualTo(1));
timer.reset();
int oldCount = timer.getCount(FDBStoreTimer.DetailEvents.RESOLVER_STATE_READ);
for (int i = 0; i < 10; i++) {
globalScope.resolve(context.getTimer(), "something-" + i).join();
// depending on the nature of the write safety check we may need to read the key multiple times
// so assert that we do at least one read on each resolve
int currentCount = timer.getCount(FDBStoreTimer.DetailEvents.RESOLVER_STATE_READ);
assertThat("subsequent writes must also check the key", currentCount, is(greaterThan(oldCount)));
oldCount = currentCount;
}
timer.reset();
for (int i = 0; i < 10; i++) {
globalScope.resolve(context.getTimer(), "something-" + i).join();
}
assertThat("reads do not need to check the key", timer.getCount(FDBStoreTimer.DetailEvents.RESOLVER_STATE_READ), is(0));
}
FDBDatabaseFactory.instance().clear();
FDBDatabase newDatabase = FDBDatabaseFactory.instance().getDatabase();
FDBStoreTimer timer2 = new FDBStoreTimer();
try (FDBRecordContext context = newDatabase.openContext()) {
context.setTimer(timer2);
globalScope.resolve(context.getTimer(), "something").join();
assertThat("state is loaded from the new database", timer2.getCount(FDBStoreTimer.DetailEvents.RESOLVER_STATE_READ), is(1));
}
}
use of com.apple.foundationdb.record.provider.foundationdb.FDBStoreTimer in project fdb-record-layer by FoundationDB.
the class FDBRecordStoreStateCacheTest method storeDeletionAcrossContexts.
/**
* After a store is deleted, validate that future transactions need to reload it from cache.
*/
@ParameterizedTest(name = "storeDeletionAcrossContexts (test context = {0})")
@MethodSource("testContextSource")
public void storeDeletionAcrossContexts(@Nonnull StateCacheTestContext testContext) throws Exception {
FDBRecordStoreStateCache storeStateCache = fdb.getStoreStateCache();
try {
fdb.setStoreStateCache(testContext.getCache(fdb));
FDBRecordStore.Builder storeBuilder;
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context);
assertTrue(recordStore.setStateCacheability(true));
storeBuilder = recordStore.asBuilder();
commit(context);
}
// Delete by calling deleteStore.
try (FDBRecordContext context = testContext.getCachedContext(fdb, storeBuilder, FDBRecordStoreBase.StoreExistenceCheck.ERROR_IF_NOT_EXISTS)) {
openSimpleRecordStore(context);
assertEquals(1, context.getTimer().getCount(FDBStoreTimer.Counts.STORE_STATE_CACHE_HIT));
FDBRecordStore.deleteStore(context, recordStore.getSubspace());
commit(context);
}
// After deleting it, when opening the same store again, it shouldn't be cached.
try (FDBRecordContext context = fdb.openContext(null, new FDBStoreTimer())) {
FDBRecordStore store = storeBuilder.setContext(context).create();
assertEquals(1, context.getTimer().getCount(FDBStoreTimer.Counts.STORE_STATE_CACHE_MISS));
assertTrue(store.setStateCacheability(true));
commit(context);
}
// Delete by calling path.deleteAllData
try (FDBRecordContext context = testContext.getCachedContext(fdb, storeBuilder, FDBRecordStoreBase.StoreExistenceCheck.ERROR_IF_NOT_EXISTS)) {
openSimpleRecordStore(context);
assertEquals(1, context.getTimer().getCount(FDBStoreTimer.Counts.STORE_STATE_CACHE_HIT));
path.deleteAllData(context);
commit(context);
}
try (FDBRecordContext context = fdb.openContext(null, new FDBStoreTimer())) {
FDBRecordStore store = storeBuilder.setContext(context).create();
store.setStateCacheabilityAsync(true).get();
assertEquals(1, context.getTimer().getCount(FDBStoreTimer.Counts.STORE_STATE_CACHE_MISS));
commit(context);
}
// Deleting all records should not disable the index state.
final String disabledIndex = "MySimpleRecord$str_value_indexed";
try (FDBRecordContext context = testContext.getCachedContext(fdb, storeBuilder, FDBRecordStoreBase.StoreExistenceCheck.ERROR_IF_NOT_EXISTS)) {
openSimpleRecordStore(context);
recordStore.markIndexDisabled(disabledIndex).get();
commit(context);
}
try (FDBRecordContext context = testContext.getCachedContext(fdb, storeBuilder, FDBRecordStoreBase.StoreExistenceCheck.ERROR_IF_NOT_EXISTS)) {
openSimpleRecordStore(context);
assertTrue(recordStore.isIndexDisabled(disabledIndex));
recordStore.deleteAllRecords();
commit(context);
}
try (FDBRecordContext context = testContext.getCachedContext(fdb, storeBuilder, FDBRecordStoreBase.StoreExistenceCheck.ERROR_IF_NOT_EXISTS)) {
openSimpleRecordStore(context);
assertTrue(recordStore.isIndexDisabled(disabledIndex));
commit(context);
}
} finally {
fdb.setStoreStateCache(storeStateCache);
}
}
Aggregations