Search in sources :

Example 21 with FDBRecordStore

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

Example 22 with FDBRecordStore

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

Example 23 with FDBRecordStore

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

Example 24 with FDBRecordStore

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);
    }
}
Also used : 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 25 with FDBRecordStore

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);
    }
}
Also used : Message(com.google.protobuf.Message) 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)

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