use of com.apple.foundationdb.record.provider.foundationdb.FDBRecordStore 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);
}
}
use of com.apple.foundationdb.record.provider.foundationdb.FDBRecordStore in project fdb-record-layer by FoundationDB.
the class FDBRecordStoreStateCacheTest method setCacheableAtWrongFormatVersion.
@Test
public void setCacheableAtWrongFormatVersion() throws Exception {
FDBRecordStoreStateCache currentCache = fdb.getStoreStateCache();
try {
fdb.setStoreStateCache(metaDataVersionStampCacheFactory.getCache(fdb));
// Initialize the store at the format version prior to the cacheable state version
FDBRecordStore.Builder storeBuilder = FDBRecordStore.newBuilder().setKeySpacePath(path).setMetaDataProvider(RecordMetaData.build(TestRecords1Proto.getDescriptor())).setFormatVersion(FDBRecordStore.CACHEABLE_STATE_FORMAT_VERSION - 1);
try (FDBRecordContext context = openContext()) {
storeBuilder.copyBuilder().setContext(context).create();
commit(context);
}
try (FDBRecordContext context = openContext()) {
FDBRecordStore recordStore = storeBuilder.copyBuilder().setContext(context).open();
assertEquals(FDBRecordStore.CACHEABLE_STATE_FORMAT_VERSION - 1, recordStore.getFormatVersion());
RecordCoreException e = assertThrows(RecordCoreException.class, () -> recordStore.setStateCacheability(true));
assertThat(e.getMessage(), containsString("cannot mark record store state cacheable at format version"));
commit(context);
}
// Update the format version
try (FDBRecordContext context = openContext()) {
storeBuilder.copyBuilder().setContext(context).setFormatVersion(FDBRecordStore.CACHEABLE_STATE_FORMAT_VERSION).open();
commit(context);
}
try (FDBRecordContext context = openContext()) {
// Assert that format version happens because of the upgrade behind the scenes
assertEquals(FDBRecordStore.CACHEABLE_STATE_FORMAT_VERSION - 1, storeBuilder.getFormatVersion());
FDBRecordStore recordStore = storeBuilder.copyBuilder().setContext(context).open();
assertEquals(FDBRecordStore.CACHEABLE_STATE_FORMAT_VERSION, recordStore.getFormatVersion());
assertTrue(recordStore.setStateCacheability(true));
commit(context);
}
} finally {
fdb.setStoreStateCache(currentCache);
}
}
use of com.apple.foundationdb.record.provider.foundationdb.FDBRecordStore in project fdb-record-layer by FoundationDB.
the class FDBRecordStoreStateCacheTest method existenceCheckOnCachedStoreStates.
/**
* Validate that the store existence check is still performed on the cached store info.
*/
@ParameterizedTest(name = "existenceCheckOnCachedStoreStates (test context = {0})")
@MethodSource("testContextSource")
public void existenceCheckOnCachedStoreStates(@Nonnull StateCacheTestContext testContext) throws Exception {
FDBRecordStoreStateCache origStoreStateCache = fdb.getStoreStateCache();
try {
fdb.setStoreStateCache(testContext.getCache(fdb));
// Create a record store
FDBRecordStore.Builder storeBuilder;
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context);
assertEquals(1, context.getTimer().getCount(FDBStoreTimer.Counts.STORE_STATE_CACHE_MISS));
assertTrue(context.hasDirtyStoreState());
// Save a record so that when the store header is deleted, it won't be an empty record store
recordStore.saveRecord(TestRecords1Proto.MySimpleRecord.newBuilder().setRecNo(1066L).build());
storeBuilder = recordStore.asBuilder();
commit(context);
}
byte[] storeInfoKey;
try (FDBRecordContext context = testContext.getCachedContext(fdb, storeBuilder)) {
storeBuilder.setContext(context);
assertThrows(RecordStoreAlreadyExistsException.class, storeBuilder::create);
context.getTimer().reset();
FDBRecordStore store = storeBuilder.open();
assertEquals(1, context.getTimer().getCount(FDBStoreTimer.Counts.STORE_STATE_CACHE_HIT));
// Delete the store header
storeInfoKey = store.getSubspace().pack(FDBRecordStoreKeyspace.STORE_INFO.key());
context.ensureActive().clear(storeInfoKey);
commit(context);
}
// The caches have dirty information from the out-of-band "clear".
testContext.invalidateCache(fdb);
assertThrows(RecordStoreNoInfoAndNotEmptyException.class, () -> testContext.getCachedContext(fdb, storeBuilder));
// Ensure the store info key is still empty
try (FDBRecordContext context = fdb.openContext()) {
assertNull(context.readTransaction(true).get(storeInfoKey).get());
}
} finally {
fdb.setStoreStateCache(origStoreStateCache);
}
}
use of com.apple.foundationdb.record.provider.foundationdb.FDBRecordStore in project fdb-record-layer by FoundationDB.
the class SyntheticRecordPlannerTest method manyToMany.
@Test
public void manyToMany() throws Exception {
final JoinedRecordTypeBuilder joined = metaDataBuilder.addJoinedRecordType("ManyToMany");
joined.addConstituent("simple", "MySimpleRecord");
joined.addConstituent("other", "MyOtherRecord");
joined.addConstituent("joining", "JoiningRecord");
joined.addJoin("joining", "simple_rec_no", "simple", "rec_no");
joined.addJoin("joining", "other_rec_no", "other", "rec_no");
try (FDBRecordContext context = openContext()) {
final FDBRecordStore recordStore = recordStoreBuilder.setContext(context).create();
for (int i = 0; i < 3; i++) {
TestRecordsJoinIndexProto.MySimpleRecord.Builder simple = TestRecordsJoinIndexProto.MySimpleRecord.newBuilder();
simple.setRecNo(i);
recordStore.saveRecord(simple.build());
TestRecordsJoinIndexProto.MyOtherRecord.Builder other = TestRecordsJoinIndexProto.MyOtherRecord.newBuilder();
other.setRecNo(1000 + i);
recordStore.saveRecord(other.build());
}
TestRecordsJoinIndexProto.JoiningRecord.Builder joining = TestRecordsJoinIndexProto.JoiningRecord.newBuilder();
joining.setRecNo(100).setSimpleRecNo(1).setOtherRecNo(1000);
recordStore.saveRecord(joining.build());
joining.setRecNo(101).setSimpleRecNo(2).setOtherRecNo(1000);
recordStore.saveRecord(joining.build());
joining.setRecNo(102).setSimpleRecNo(2).setOtherRecNo(1002);
recordStore.saveRecord(joining.build());
context.commit();
}
try (FDBRecordContext context = openContext()) {
final FDBRecordStore recordStore = recordStoreBuilder.setContext(context).open();
final SyntheticRecordPlanner planner = new SyntheticRecordPlanner(recordStore);
SyntheticRecordPlan plan1 = planner.scanForType(recordStore.getRecordMetaData().getSyntheticRecordType("ManyToMany"));
Multiset<Tuple> expected1 = ImmutableMultiset.of(Tuple.from(-1, Tuple.from(1), Tuple.from(1000), Tuple.from(100)), Tuple.from(-1, Tuple.from(2), Tuple.from(1000), Tuple.from(101)), Tuple.from(-1, Tuple.from(2), Tuple.from(1002), Tuple.from(102)));
Multiset<Tuple> results1 = HashMultiset.create(plan1.execute(recordStore).map(FDBSyntheticRecord::getPrimaryKey).asList().join());
assertEquals(expected1, results1);
}
}
use of com.apple.foundationdb.record.provider.foundationdb.FDBRecordStore in project fdb-record-layer by FoundationDB.
the class SyntheticRecordPlannerTest method manyToOne.
@Test
public void manyToOne() throws Exception {
metaDataBuilder.addIndex("MySimpleRecord", "other_rec_no");
final JoinedRecordTypeBuilder joined = metaDataBuilder.addJoinedRecordType("ManyToOne");
joined.addConstituent("simple", "MySimpleRecord");
joined.addConstituent("other", "MyOtherRecord");
joined.addJoin("simple", "other_rec_no", "other", "rec_no");
try (FDBRecordContext context = openContext()) {
final FDBRecordStore recordStore = recordStoreBuilder.setContext(context).create();
for (int i = 0; i < 3; i++) {
for (int j = 0; j < i; j++) {
TestRecordsJoinIndexProto.MySimpleRecord.Builder simple = TestRecordsJoinIndexProto.MySimpleRecord.newBuilder();
simple.setRecNo(100 * i + j).setOtherRecNo(1000 + i);
recordStore.saveRecord(simple.build());
}
TestRecordsJoinIndexProto.MyOtherRecord.Builder other = TestRecordsJoinIndexProto.MyOtherRecord.newBuilder();
other.setRecNo(1000 + i);
recordStore.saveRecord(other.build());
}
context.commit();
}
try (FDBRecordContext context = openContext()) {
final FDBRecordStore recordStore = recordStoreBuilder.setContext(context).open();
final SyntheticRecordPlanner planner = new SyntheticRecordPlanner(recordStore);
SyntheticRecordPlan plan1 = planner.scanForType(recordStore.getRecordMetaData().getSyntheticRecordType("ManyToOne"));
Multiset<Tuple> expected1 = ImmutableMultiset.of(Tuple.from(-1, Tuple.from(100), Tuple.from(1001)), Tuple.from(-1, Tuple.from(200), Tuple.from(1002)), Tuple.from(-1, Tuple.from(201), Tuple.from(1002)));
Multiset<Tuple> results1 = HashMultiset.create(plan1.execute(recordStore).map(FDBSyntheticRecord::getPrimaryKey).asList().join());
assertEquals(expected1, results1);
FDBStoredRecord<Message> record = recordStore.loadRecord(Tuple.from(1002));
SyntheticRecordFromStoredRecordPlan plan2 = planner.fromStoredType(record.getRecordType(), false);
Multiset<Tuple> expected2 = ImmutableMultiset.of(Tuple.from(-1, Tuple.from(200), Tuple.from(1002)), Tuple.from(-1, Tuple.from(201), Tuple.from(1002)));
Multiset<Tuple> results2 = HashMultiset.create(plan2.execute(recordStore, record).map(FDBSyntheticRecord::getPrimaryKey).asList().join());
assertEquals(expected2, results2);
}
}
Aggregations