use of com.apple.foundationdb.record.provider.foundationdb.FDBRecordStore in project fdb-record-layer by FoundationDB.
the class SyntheticRecordPlannerTest method rankJoinIndex.
@Test
public void rankJoinIndex() throws Exception {
final JoinedRecordTypeBuilder joined = metaDataBuilder.addJoinedRecordType("JoinedForRank");
joined.addConstituent("simple", "MySimpleRecord");
joined.addConstituent("other", "MyOtherRecord");
joined.addJoin("simple", "other_rec_no", "other", "rec_no");
final GroupingKeyExpression group = field("simple").nest("num_value_2").groupBy(field("other").nest("num_value"));
metaDataBuilder.addIndex(joined, new Index("simple.num_value_2_by_other.num_value", group, IndexTypes.RANK));
try (FDBRecordContext context = openContext()) {
final FDBRecordStore recordStore = recordStoreBuilder.setContext(context).create();
for (int i = 0; i < 4; i++) {
for (int j = 0; j < i; j++) {
TestRecordsJoinIndexProto.MySimpleRecord.Builder simple = TestRecordsJoinIndexProto.MySimpleRecord.newBuilder();
simple.setRecNo(100 * i + j).setOtherRecNo(1000 + i);
simple.setNumValue2(i + j);
recordStore.saveRecord(simple.build());
}
TestRecordsJoinIndexProto.MyOtherRecord.Builder other = TestRecordsJoinIndexProto.MyOtherRecord.newBuilder();
other.setRecNo(1000 + i);
other.setNumValue(i % 2);
recordStore.saveRecord(other.build());
}
context.commit();
}
try (FDBRecordContext context = openContext()) {
final FDBRecordStore recordStore = recordStoreBuilder.setContext(context).open();
Index index = recordStore.getRecordMetaData().getIndex("simple.num_value_2_by_other.num_value");
RecordCursor<IndexEntry> cursor = recordStore.scanIndex(index, IndexScanType.BY_RANK, TupleRange.allOf(Tuple.from(0, 1)), null, ScanProperties.FORWARD_SCAN);
Tuple pkey = cursor.first().get().map(IndexEntry::getPrimaryKey).orElse(null);
assertFalse(cursor.getNext().hasNext());
// 201, 1002 and 200, 1003 both have score 3, but in different groups.
assertEquals(Tuple.from(-1, Tuple.from(201), Tuple.from(1002)), pkey);
FDBSyntheticRecord record = recordStore.loadSyntheticRecord(pkey).join();
IndexRecordFunction<Long> rankFunction = ((IndexRecordFunction<Long>) Query.rank(group).getFunction()).cloneWithIndex(index.getName());
assertEquals(1, recordStore.evaluateRecordFunction(rankFunction, record).join().longValue());
}
}
use of com.apple.foundationdb.record.provider.foundationdb.FDBRecordStore in project fdb-record-layer by FoundationDB.
the class VersionIndexTest method deleteRecordInTwoStores.
@ParameterizedTest(name = "deleteRecordInTwoStores [formatVersion = {0}, splitLongRecords = {1}]")
@MethodSource("formatVersionArguments")
@SuppressWarnings("try")
public void deleteRecordInTwoStores(int testFormatVersion, boolean testSplitLongRecords) {
formatVersion = testFormatVersion;
splitLongRecords = testSplitLongRecords;
final MySimpleRecord record1 = MySimpleRecord.newBuilder().setRecNo(1066L).setNumValue2(42).build();
final MySimpleRecord record2 = MySimpleRecord.newBuilder().setRecNo(1066L).setNumValue2(1729).build();
try (FDBRecordContext context = openContext(simpleVersionHook)) {
final FDBRecordStore recordStore2 = recordStore.asBuilder().setSubspace(subspace2).create();
// Store the records with a fake complete pseudo version to avoid potential problems
// tested in saveSameRecordInTwoStores
final FDBRecordVersion pseudoVersion = FDBRecordVersion.firstInDBVersion(context.getReadVersion());
recordStore.saveRecord(record1, FDBRecordVersion.complete(pseudoVersion.getGlobalVersion(), 1));
recordStore2.saveRecord(record2, FDBRecordVersion.complete(pseudoVersion.getGlobalVersion(), 2));
context.commit();
}
final FDBRecordVersion version1;
try (FDBRecordContext context = openContext(simpleVersionHook)) {
final FDBRecordStore recordStore2 = recordStore.asBuilder().setSubspace(subspace2).open();
// Change the version in one record store
FDBStoredRecord<?> storedRecord1 = recordStore.saveRecord(record1);
assertNotNull(storedRecord1.getVersion());
assertFalse(storedRecord1.getVersion().isComplete());
// Delete the record in the other record store
assertTrue(recordStore2.deleteRecord(Tuple.from(record2.getRecNo())));
context.commit();
assertNotNull(context.getVersionStamp());
version1 = storedRecord1.getVersion().withCommittedVersion(context.getVersionStamp());
}
try (FDBRecordContext context = openContext(simpleVersionHook)) {
final FDBRecordStore recordStore2 = recordStore.asBuilder().setSubspace(subspace2).open();
FDBStoredRecord<?> storedRecord1 = recordStore.loadRecord(Tuple.from(record1.getRecNo()));
assertNotNull(storedRecord1);
assertEquals(version1, storedRecord1.getVersion());
assertNull(recordStore2.loadRecord(Tuple.from(record2.getRecNo())));
}
}
use of com.apple.foundationdb.record.provider.foundationdb.FDBRecordStore in project fdb-record-layer by FoundationDB.
the class VersionIndexTest method updateRecordInTwoStores.
@ParameterizedTest(name = "updateRecordInTwoStores [formatVersion = {0}, splitLongRecords = {1}]")
@MethodSource("formatVersionArguments")
@SuppressWarnings("try")
public void updateRecordInTwoStores(int testFormatVersion, boolean testSplitLongRecords) {
formatVersion = testFormatVersion;
splitLongRecords = testSplitLongRecords;
final MySimpleRecord record1 = MySimpleRecord.newBuilder().setRecNo(1066L).setNumValue2(42).build();
final MySimpleRecord record2 = MySimpleRecord.newBuilder().setRecNo(1066L).setNumValue2(1729).build();
try (FDBRecordContext context = openContext(simpleVersionHook)) {
final FDBRecordStore recordStore2 = recordStore.asBuilder().setSubspace(subspace2).create();
// Store the records with a fake complete pseudo version to avoid potential problems
// tested in saveSameRecordInTwoStores
final FDBRecordVersion pseudoVersion = FDBRecordVersion.firstInDBVersion(context.getReadVersion());
recordStore.saveRecord(record1, FDBRecordVersion.complete(pseudoVersion.getGlobalVersion(), 1));
recordStore2.saveRecord(record2, FDBRecordVersion.complete(pseudoVersion.getGlobalVersion(), 2));
context.commit();
}
final FDBRecordVersion version1;
final FDBRecordVersion version2;
try (FDBRecordContext context = openContext(simpleVersionHook)) {
final FDBRecordStore recordStore2 = recordStore.asBuilder().setSubspace(subspace2).open();
// Update each record (just by saving with a new version)
FDBStoredRecord<?> storedRecord1 = recordStore.saveRecord(record1);
assertNotNull(storedRecord1.getVersion());
assertFalse(storedRecord1.getVersion().isComplete());
FDBStoredRecord<?> storedRecord2 = recordStore2.saveRecord(record2);
assertNotNull(storedRecord2.getVersion());
assertFalse(storedRecord2.getVersion().isComplete());
assertThat(storedRecord2.getVersion(), greaterThan(storedRecord1.getVersion()));
context.commit();
assertNotNull(context.getVersionStamp());
version1 = storedRecord1.getVersion().withCommittedVersion(context.getVersionStamp());
version2 = storedRecord2.getVersion().withCommittedVersion(context.getVersionStamp());
}
try (FDBRecordContext context = openContext(simpleVersionHook)) {
final FDBRecordStore recordStore2 = recordStore.asBuilder().setSubspace(subspace2).open();
FDBStoredRecord<?> storedRecord1 = recordStore.loadRecord(Tuple.from(record1.getRecNo()));
assertNotNull(storedRecord1);
assertEquals(version1, storedRecord1.getVersion());
FDBStoredRecord<?> storedRecord2 = recordStore2.loadRecord(Tuple.from(record2.getRecNo()));
assertNotNull(storedRecord2);
assertEquals(version2, storedRecord2.getVersion());
}
}
use of com.apple.foundationdb.record.provider.foundationdb.FDBRecordStore in project fdb-record-layer by FoundationDB.
the class VersionIndexTest method saveSameRecordTwoStores.
/**
* Store two records with the same primary key in two record stores. Each one should get its own version.
* This validates that the local version cache is per-record-store.
*/
@ParameterizedTest(name = "saveSameRecordTwoStores [formatVersion = {0}, splitLongRecords = {1}]")
@MethodSource("formatVersionArguments")
@SuppressWarnings("try")
public void saveSameRecordTwoStores(int testFormatVersion, boolean testSplitLongRecords) {
formatVersion = testFormatVersion;
splitLongRecords = testSplitLongRecords;
final MySimpleRecord record1 = MySimpleRecord.newBuilder().setRecNo(1066).setNumValue2(42).build();
final MySimpleRecord record2 = MySimpleRecord.newBuilder().setRecNo(1066).setNumValue2(1729).build();
final FDBRecordVersion version1;
final FDBRecordVersion version2;
try (FDBRecordContext context = openContext(simpleVersionHook)) {
final FDBRecordStore recordStore2 = recordStore.asBuilder().setSubspace(subspace2).create();
FDBStoredRecord<?> storedRecord1 = recordStore.saveRecord(record1);
assertNotNull(storedRecord1.getVersion());
assertFalse(storedRecord1.getVersion().isComplete());
assertNull(recordStore2.loadRecord(Tuple.from(record1.getRecNo())));
FDBStoredRecord<?> storedRecord2 = recordStore2.saveRecord(record2);
assertNotNull(storedRecord2.getVersion());
assertFalse(storedRecord2.getVersion().isComplete());
assertThat(storedRecord2.getVersion(), greaterThan(storedRecord1.getVersion()));
context.commit();
assertNotNull(context.getVersionStamp());
version1 = storedRecord1.getVersion().withCommittedVersion(context.getVersionStamp());
version2 = storedRecord2.getVersion().withCommittedVersion(context.getVersionStamp());
}
// Validate that the right versions are associated with the right records
try (FDBRecordContext context = openContext(simpleVersionHook)) {
final FDBRecordStore recordStore2 = recordStore.asBuilder().setSubspace(subspace2).open();
FDBStoredRecord<?> storedRecord1 = recordStore.loadRecord(Tuple.from(record1.getRecNo()));
assertNotNull(storedRecord1);
assertEquals(version1, storedRecord1.getVersion());
assertEquals(record1, storedRecord1.getRecord());
FDBStoredRecord<?> storedRecord2 = recordStore2.loadRecord(Tuple.from(record2.getRecNo()));
assertNotNull(storedRecord2);
assertEquals(version2, storedRecord2.getVersion());
assertEquals(record2, storedRecord2.getRecord());
}
}
use of com.apple.foundationdb.record.provider.foundationdb.FDBRecordStore in project fdb-record-layer by FoundationDB.
the class FDBRecordStoreStateCacheTest method cacheByReadVersion.
/**
* Validate that caching by read version works.
*/
@Test
public void cacheByReadVersion() throws Exception {
FDBRecordStoreStateCache origStoreStateCache = fdb.getStoreStateCache();
try {
fdb.setStoreStateCache(readVersionCacheFactory.getCache(fdb));
long readVersion;
int metaDataVersion;
// Open a record store but do not commit to make sure that the updated value is not cached
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context);
assertEquals(1, context.getTimer().getCount(FDBStoreTimer.Counts.STORE_STATE_CACHE_MISS));
assertTrue(context.hasDirtyStoreState());
readVersion = context.getReadVersion();
metaDataVersion = recordStore.getRecordMetaData().getVersion();
// do not commit
}
// Open a record store and validate that the cached state is updated
try (FDBRecordContext context = openContext()) {
context.getTimer().reset();
context.setReadVersion(readVersion);
openSimpleRecordStore(context);
// For this specific case, we hit the cache, but then we need to validate that the store is empty
// in order to match its null store header.
assertEquals(0, context.getTimer().getCount(FDBStoreTimer.Counts.STORE_STATE_CACHE_MISS));
assertTrue(context.hasDirtyStoreState());
assertEquals(metaDataVersion, recordStore.getRecordMetaData().getVersion());
// commit so a stable value is put into the database
commit(context);
}
try (FDBRecordContext context = openContext()) {
context.getTimer().reset();
openSimpleRecordStore(context);
assertEquals(1, context.getTimer().getCount(FDBStoreTimer.Counts.STORE_STATE_CACHE_MISS));
assertFalse(context.hasDirtyStoreState());
assertEquals(metaDataVersion, recordStore.getRecordMetaData().getVersion());
readVersion = context.getReadVersion();
// does not matter whether we commit or not
}
try (FDBRecordContext context = openContext()) {
context.setReadVersion(readVersion);
openSimpleRecordStore(context);
assertFalse(context.hasDirtyStoreState());
assertEquals(1, context.getTimer().getCount(FDBStoreTimer.Counts.STORE_STATE_CACHE_HIT));
assertEquals(metaDataVersion, recordStore.getRecordMetaData().getVersion());
}
// Make a change to the stored info
try (FDBRecordContext context = openContext()) {
context.getTimer().reset();
context.setReadVersion(readVersion);
openSimpleRecordStore(context);
assertFalse(context.hasDirtyStoreState());
assertEquals(1, context.getTimer().getCount(FDBStoreTimer.Counts.STORE_STATE_CACHE_HIT));
recordStore.markIndexWriteOnly("MySimpleRecord$str_value_indexed").get();
assertTrue(context.hasDirtyStoreState());
assertFalse(recordStore.isIndexReadable("MySimpleRecord$str_value_indexed"));
FDBRecordStore initialRecordStore = recordStore;
// Reopen the store with the same context and ensure the index is still not readable
openSimpleRecordStore(context);
assertEquals(1, context.getTimer().getCount(FDBStoreTimer.Counts.STORE_STATE_CACHE_MISS));
assertNotSame(initialRecordStore, recordStore);
assertNotSame(initialRecordStore.getRecordStoreState(), recordStore.getRecordStoreState());
assertFalse(recordStore.isIndexReadable("MySimpleRecord$str_value_indexed"));
commit(context);
}
// Validate that that change is not present in the cache
try (FDBRecordContext context = openContext()) {
context.getTimer().reset();
context.setReadVersion(readVersion);
openSimpleRecordStore(context);
assertEquals(1, context.getTimer().getCount(FDBStoreTimer.Counts.STORE_STATE_CACHE_HIT));
assertTrue(recordStore.isIndexReadable("MySimpleRecord$str_value_indexed"));
// Add a random write-conflict range to ensure conflicts are actually checked
context.ensureActive().addWriteConflictKey(recordStore.recordsSubspace().pack(UUID.randomUUID()));
// Should not be able to commit due to conflict on str_value_indexed key in record store store
assertThrows(FDBExceptions.FDBStoreTransactionConflictException.class, context::commit);
}
// Get a fresh read version
try (FDBRecordContext context = openContext()) {
context.getTimer().reset();
openSimpleRecordStore(context);
assertEquals(1, context.getTimer().getCount(FDBStoreTimer.Counts.STORE_STATE_CACHE_MISS));
long newReadVersion = context.getReadVersion();
assertThat(newReadVersion, greaterThan(readVersion));
readVersion = newReadVersion;
assertFalse(recordStore.isIndexReadable("MySimpleRecord$str_value_indexed"));
}
try (FDBRecordContext context = openContext()) {
context.getTimer().reset();
context.setReadVersion(readVersion);
openSimpleRecordStore(context);
assertEquals(1, context.getTimer().getCount(FDBStoreTimer.Counts.STORE_STATE_CACHE_HIT));
assertFalse(recordStore.isIndexReadable("MySimpleRecord$str_value_indexed"));
}
} finally {
fdb.setStoreStateCache(origStoreStateCache);
}
}
Aggregations