Search in sources :

Example 16 with FDBRecordStore

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());
    }
}
Also used : IndexRecordFunction(com.apple.foundationdb.record.metadata.IndexRecordFunction) GroupingKeyExpression(com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression) FDBSyntheticRecord(com.apple.foundationdb.record.provider.foundationdb.FDBSyntheticRecord) IndexEntry(com.apple.foundationdb.record.IndexEntry) Index(com.apple.foundationdb.record.metadata.Index) FDBRecordStore(com.apple.foundationdb.record.provider.foundationdb.FDBRecordStore) JoinedRecordTypeBuilder(com.apple.foundationdb.record.metadata.JoinedRecordTypeBuilder) FDBRecordContext(com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext) Tuple(com.apple.foundationdb.tuple.Tuple) Test(org.junit.jupiter.api.Test)

Example 17 with FDBRecordStore

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())));
    }
}
Also used : MySimpleRecord(com.apple.foundationdb.record.TestRecords1Proto.MySimpleRecord) FDBRecordContext(com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext) FDBRecordStore(com.apple.foundationdb.record.provider.foundationdb.FDBRecordStore) FDBRecordVersion(com.apple.foundationdb.record.provider.foundationdb.FDBRecordVersion) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) MethodSource(org.junit.jupiter.params.provider.MethodSource)

Example 18 with FDBRecordStore

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());
    }
}
Also used : MySimpleRecord(com.apple.foundationdb.record.TestRecords1Proto.MySimpleRecord) FDBRecordContext(com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext) FDBRecordStore(com.apple.foundationdb.record.provider.foundationdb.FDBRecordStore) FDBRecordVersion(com.apple.foundationdb.record.provider.foundationdb.FDBRecordVersion) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) MethodSource(org.junit.jupiter.params.provider.MethodSource)

Example 19 with FDBRecordStore

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());
    }
}
Also used : MySimpleRecord(com.apple.foundationdb.record.TestRecords1Proto.MySimpleRecord) FDBRecordContext(com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext) FDBRecordStore(com.apple.foundationdb.record.provider.foundationdb.FDBRecordStore) FDBRecordVersion(com.apple.foundationdb.record.provider.foundationdb.FDBRecordVersion) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) MethodSource(org.junit.jupiter.params.provider.MethodSource)

Example 20 with FDBRecordStore

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);
    }
}
Also used : FDBRecordContext(com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext) FDBRecordStore(com.apple.foundationdb.record.provider.foundationdb.FDBRecordStore) FDBExceptions(com.apple.foundationdb.record.provider.foundationdb.FDBExceptions) Test(org.junit.jupiter.api.Test) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest)

Aggregations

FDBRecordStore (com.apple.foundationdb.record.provider.foundationdb.FDBRecordStore)33 FDBRecordContext (com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext)25 Test (org.junit.jupiter.api.Test)15 JoinedRecordTypeBuilder (com.apple.foundationdb.record.metadata.JoinedRecordTypeBuilder)12 Tuple (com.apple.foundationdb.tuple.Tuple)11 ParameterizedTest (org.junit.jupiter.params.ParameterizedTest)11 Message (com.google.protobuf.Message)8 MethodSource (org.junit.jupiter.params.provider.MethodSource)8 Index (com.apple.foundationdb.record.metadata.Index)7 RecordMetaDataBuilder (com.apple.foundationdb.record.RecordMetaDataBuilder)5 MySimpleRecord (com.apple.foundationdb.record.TestRecords1Proto.MySimpleRecord)4 GroupingKeyExpression (com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression)4 FDBStoreTimer (com.apple.foundationdb.record.provider.foundationdb.FDBStoreTimer)4 IndexEntry (com.apple.foundationdb.record.IndexEntry)3 TupleRange (com.apple.foundationdb.record.TupleRange)3 FDBRecordVersion (com.apple.foundationdb.record.provider.foundationdb.FDBRecordVersion)3 KeySpacePath (com.apple.foundationdb.record.provider.foundationdb.keyspace.KeySpacePath)3 RecordCoreArgumentException (com.apple.foundationdb.record.RecordCoreArgumentException)2 RecordCoreException (com.apple.foundationdb.record.RecordCoreException)2 RecordMetaData (com.apple.foundationdb.record.RecordMetaData)2