Search in sources :

Example 46 with IndexEntry

use of com.apple.foundationdb.record.IndexEntry in project fdb-record-layer by FoundationDB.

the class FDBRecordStoreReplaceIndexTest method markExistingAsReplacement.

@Test
public void markExistingAsReplacement() {
    final String recordTypeName = "MyOtherRecord";
    final Index origIndex = new Index("MyOtherRecord$(num_value_2, num_value_3_indexed)", "num_value_2", "num_value_3_indexed");
    final Index newIndex = new Index("MyOtherRecord$(num_value_3_indexed, num_value_2)", "num_value_3_indexed", "num_value_2");
    final RecordMetaDataHook addBothIndexes = composeHooks(addIndexHook(recordTypeName, origIndex), addIndexHook(recordTypeName, newIndex));
    try (FDBRecordContext context = openContext()) {
        openSimpleRecordStore(context, addBothIndexes);
        assertTrue(recordStore.isIndexReadable(origIndex), "Old index should be readable at start");
        assertTrue(recordStore.isIndexReadable(newIndex), "New index should be readable at start");
        recordStore.saveRecord(TestRecords1Proto.MyOtherRecord.newBuilder().setRecNo(1415L).setNumValue2(42).setNumValue3Indexed(3).build());
        final List<IndexEntry> oldIndexEntries = scanIndex(origIndex);
        assertThat(oldIndexEntries, hasSize(1));
        assertEquals(Tuple.from(1415L), oldIndexEntries.get(0).getPrimaryKey());
        assertEquals(Tuple.from(42L, 3L, 1415L), oldIndexEntries.get(0).getKey());
        commit(context);
    }
    try (FDBRecordContext context = openContext()) {
        openSimpleRecordStore(context, composeHooks(addIndexAndReplacements(recordTypeName, origIndex, newIndex), bumpMetaDataVersionHook()));
        assertTrue(recordStore.isIndexDisabled(origIndex.getName()));
        commit(context);
    }
    try (FDBRecordContext context = openContext()) {
        openSimpleRecordStore(context, composeHooks(addBothIndexes, bumpMetaDataVersionHook(), bumpMetaDataVersionHook()));
        assertTrue(uncheckedMarkIndexReadable(origIndex));
        assertThat(scanIndex(origIndex), empty());
    }
}
Also used : IndexEntry(com.apple.foundationdb.record.IndexEntry) Index(com.apple.foundationdb.record.metadata.Index) Matchers.containsString(org.hamcrest.Matchers.containsString) Test(org.junit.jupiter.api.Test)

Example 47 with IndexEntry

use of com.apple.foundationdb.record.IndexEntry in project fdb-record-layer by FoundationDB.

the class FDBRecordStoreReplaceIndexTest method buildTwoReplacements.

@Test
public void buildTwoReplacements() {
    final String recordTypeName = "MySimpleRecord";
    final Index origIndex = new Index("MySimpleRecord$(str_value_indexed, num_value_2)", "str_value_indexed", "num_value_2");
    final Index newIndex1 = new Index("MySimpleRecord$(str_value_indexed, num_value_2, num_value_3_indexed)", "str_value_indexed", "num_value_2", "num_value_3_indexed");
    final Index newIndex2 = new Index("MySimpleRecord$(str_value_indexed, num_value_2, num_value_unique)", "str_value_indexed", "num_value_2", "num_value_unique");
    final RecordMetaDataHook addAllIndexesHook = composeHooks(addIndexHook(recordTypeName, origIndex), addIndexHook(recordTypeName, newIndex1), addIndexHook(recordTypeName, newIndex2));
    try (FDBRecordContext context = openContext()) {
        openSimpleRecordStore(context, addAllIndexesHook);
        assertTrue(disableIndex(newIndex1));
        assertTrue(disableIndex(newIndex2));
        recordStore.saveRecord(TestRecords1Proto.MySimpleRecord.newBuilder().setRecNo(800L).setStrValueIndexed("a_value").setNumValue2(962).setNumValue3Indexed(1806).build());
        commit(context);
    }
    // Mark the index as replaced by the two new indexes and expect the index to be gone once both new indexes are built
    RecordMetaDataHook withReplacementsHook = composeHooks(addIndexAndReplacements(recordTypeName, origIndex, newIndex1, newIndex2), bumpMetaDataVersionHook());
    final List<IndexEntry> origEntries;
    try (FDBRecordContext context = openContext()) {
        openSimpleRecordStore(context, withReplacementsHook);
        assertTrue(recordStore.isIndexReadable(origIndex));
        origEntries = scanIndex(origIndex);
        assertThat(origEntries, hasSize(1));
        assertEquals(Tuple.from(800L), origEntries.get(0).getPrimaryKey());
        assertEquals(Tuple.from("a_value", 962L, 800L), origEntries.get(0).getKey());
        buildIndex(newIndex1);
        commit(context);
    }
    try (FDBRecordContext context = openContext()) {
        openSimpleRecordStore(context, withReplacementsHook);
        assertTrue(recordStore.isIndexReadable(origIndex));
        assertEquals(origEntries, scanIndex(origIndex));
        disableIndex(newIndex1);
        buildIndex(newIndex2);
        commit(context);
    }
    try (FDBRecordContext context = openContext()) {
        openSimpleRecordStore(context, withReplacementsHook);
        assertTrue(recordStore.isIndexReadable(origIndex));
        assertEquals(origEntries, scanIndex(origIndex));
        buildIndex(newIndex1);
        commit(context);
    }
    try (FDBRecordContext context = openContext()) {
        openSimpleRecordStore(context, withReplacementsHook);
        assertTrue(recordStore.isIndexDisabled(origIndex));
        commit(context);
    }
    try (FDBRecordContext context = openContext()) {
        openSimpleRecordStore(context, composeHooks(addAllIndexesHook, bumpMetaDataVersionHook(), bumpMetaDataVersionHook()));
        assertTrue(uncheckedMarkIndexReadable(origIndex));
        assertThat(scanIndex(origIndex), empty());
    }
}
Also used : IndexEntry(com.apple.foundationdb.record.IndexEntry) Index(com.apple.foundationdb.record.metadata.Index) Matchers.containsString(org.hamcrest.Matchers.containsString) Test(org.junit.jupiter.api.Test)

Example 48 with IndexEntry

use of com.apple.foundationdb.record.IndexEntry in project fdb-record-layer by FoundationDB.

the class OnlineIndexScrubberTest method testScrubberSimpleMissing.

@Test
void testScrubberSimpleMissing() throws ExecutionException, InterruptedException {
    final FDBStoreTimer timer = new FDBStoreTimer();
    final long numRecords = 50;
    long res;
    Index tgtIndex = new Index("tgt_index", field("num_value_2"), EmptyKeyExpression.EMPTY, IndexTypes.VALUE, IndexOptions.UNIQUE_OPTIONS);
    FDBRecordStoreTestBase.RecordMetaDataHook hook = myHook(tgtIndex);
    openSimpleMetaData();
    populateData(numRecords);
    openSimpleMetaData(hook);
    buildIndex(tgtIndex);
    try (OnlineIndexScrubber indexScrubber = OnlineIndexScrubber.newBuilder().setDatabase(fdb).setMetaData(metaData).setIndex(tgtIndex).setSubspace(subspace).setScrubbingPolicy(OnlineIndexScrubber.ScrubbingPolicy.newBuilder().setLogWarningsLimit(Integer.MAX_VALUE).setAllowRepair(false).build()).setTimer(timer).build()) {
        res = indexScrubber.scrubMissingIndexEntries();
    }
    assertEquals(numRecords, timer.getCount(FDBStoreTimer.Counts.ONLINE_INDEX_BUILDER_RECORDS_SCANNED));
    assertEquals(0, timer.getCount(FDBStoreTimer.Counts.ONLINE_INDEX_BUILDER_RECORDS_INDEXED));
    assertEquals(0, timer.getCount(FDBStoreTimer.Counts.INDEX_SCRUBBER_MISSING_ENTRIES));
    assertEquals(0, res);
    // manually delete a few index entries
    openSimpleMetaData(hook);
    int missingCount = 0;
    try (FDBRecordContext context = openContext()) {
        List<IndexEntry> indexEntries = recordStore.scanIndex(tgtIndex, IndexScanType.BY_VALUE, TupleRange.ALL, null, ScanProperties.FORWARD_SCAN).asList().get();
        for (int i = 3; i < numRecords; i *= 2) {
            final IndexEntry indexEntry = indexEntries.get(i);
            final Tuple valueKey = indexEntry.getKey();
            final byte[] keyBytes = recordStore.indexSubspace(tgtIndex).pack(valueKey);
            recordStore.getContext().ensureActive().clear(keyBytes);
            missingCount++;
        }
        context.commit();
    }
    // verify the missing entries are found and fixed
    timer.reset();
    try (OnlineIndexScrubber indexScrubber = OnlineIndexScrubber.newBuilder().setDatabase(fdb).setMetaData(metaData).setIndex(tgtIndex).setSubspace(subspace).setScrubbingPolicy(OnlineIndexScrubber.ScrubbingPolicy.newBuilder().build()).setTimer(timer).build()) {
        res = indexScrubber.scrubMissingIndexEntries();
    }
    assertEquals(numRecords, timer.getCount(FDBStoreTimer.Counts.ONLINE_INDEX_BUILDER_RECORDS_SCANNED));
    assertEquals(missingCount, timer.getCount(FDBStoreTimer.Counts.ONLINE_INDEX_BUILDER_RECORDS_INDEXED));
    assertEquals(missingCount, timer.getCount(FDBStoreTimer.Counts.INDEX_SCRUBBER_MISSING_ENTRIES));
    assertEquals(missingCount, res);
    // now verify it's fixed
    timer.reset();
    try (OnlineIndexScrubber indexScrubber = OnlineIndexScrubber.newBuilder().setDatabase(fdb).setMetaData(metaData).setIndex(tgtIndex).setSubspace(subspace).setScrubbingPolicy(OnlineIndexScrubber.ScrubbingPolicy.newBuilder().build()).setTimer(timer).build()) {
        res = indexScrubber.scrubMissingIndexEntries();
    }
    assertEquals(numRecords, timer.getCount(FDBStoreTimer.Counts.ONLINE_INDEX_BUILDER_RECORDS_SCANNED));
    assertEquals(0, timer.getCount(FDBStoreTimer.Counts.ONLINE_INDEX_BUILDER_RECORDS_INDEXED));
    assertEquals(0, timer.getCount(FDBStoreTimer.Counts.INDEX_SCRUBBER_MISSING_ENTRIES));
    assertEquals(0, res);
}
Also used : IndexEntry(com.apple.foundationdb.record.IndexEntry) Index(com.apple.foundationdb.record.metadata.Index) Tuple(com.apple.foundationdb.tuple.Tuple) Test(org.junit.jupiter.api.Test)

Example 49 with IndexEntry

use of com.apple.foundationdb.record.IndexEntry in project fdb-record-layer by FoundationDB.

the class FunctionKeyIndexTest method testCountIndex.

@Test
public void testCountIndex() throws Exception {
    Index index = new Index("group_index", new GroupingKeyExpression(function("substr", concat(field("str_value"), value(0), value(3))), 0), IndexTypes.COUNT);
    Records records = Records.create();
    for (int i = 0; i < 10; i++) {
        records.add(i, "ab" + Character.toString((char) ('c' + (i % 3))) + "_" + i);
    }
    saveRecords(records, index);
    try (FDBRecordContext context = openContext()) {
        openRecordStore(context, index);
        List<IndexEntry> keyValues = getIndexKeyValues(recordStore, index, IndexScanType.BY_GROUP);
        assertEquals(Tuple.from("abc"), keyValues.get(0).getKey());
        assertEquals(Tuple.from(4), keyValues.get(0).getValue());
        assertEquals(Tuple.from("abd"), keyValues.get(1).getKey());
        assertEquals(Tuple.from(3), keyValues.get(1).getValue());
        assertEquals(Tuple.from("abe"), keyValues.get(2).getKey());
        assertEquals(Tuple.from(3), keyValues.get(2).getValue());
    }
}
Also used : GroupingKeyExpression(com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression) IndexEntry(com.apple.foundationdb.record.IndexEntry) Index(com.apple.foundationdb.record.metadata.Index) Test(org.junit.jupiter.api.Test) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest)

Example 50 with IndexEntry

use of com.apple.foundationdb.record.IndexEntry in project fdb-record-layer by FoundationDB.

the class TextIndexTest method scanWithZeroScanRecordLimit.

private void scanWithZeroScanRecordLimit(@Nonnull Index index, @Nonnull String token, boolean reverse) throws Exception {
    try (FDBRecordContext context = openContext()) {
        openRecordStore(context);
        ScanProperties scanProperties = ExecuteProperties.newBuilder().setScannedRecordsLimit(0).build().asScanProperties(reverse);
        RecordCursor<IndexEntry> cursor = recordStore.scanIndex(index, BY_TEXT_TOKEN, TupleRange.allOf(Tuple.from(token)), null, scanProperties);
        RecordCursorResult<IndexEntry> result = cursor.getNext();
        if (!result.hasNext()) {
            assertEquals(SOURCE_EXHAUSTED, result.getNoNextReason());
            return;
        }
        result = cursor.getNext();
        assertThat(result.hasNext(), is(false));
        assertEquals(SCAN_LIMIT_REACHED, result.getNoNextReason());
    }
}
Also used : FDBRecordContext(com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext) ScanProperties(com.apple.foundationdb.record.ScanProperties) IndexEntry(com.apple.foundationdb.record.IndexEntry)

Aggregations

IndexEntry (com.apple.foundationdb.record.IndexEntry)74 Tuple (com.apple.foundationdb.tuple.Tuple)41 Nonnull (javax.annotation.Nonnull)37 Index (com.apple.foundationdb.record.metadata.Index)34 Test (org.junit.jupiter.api.Test)34 FDBRecordContext (com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext)32 Message (com.google.protobuf.Message)32 ScanProperties (com.apple.foundationdb.record.ScanProperties)29 ArrayList (java.util.ArrayList)29 RecordCoreException (com.apple.foundationdb.record.RecordCoreException)28 TupleRange (com.apple.foundationdb.record.TupleRange)28 List (java.util.List)28 Nullable (javax.annotation.Nullable)27 IndexScanType (com.apple.foundationdb.record.IndexScanType)24 RecordCursor (com.apple.foundationdb.record.RecordCursor)22 CompletableFuture (java.util.concurrent.CompletableFuture)21 Collectors (java.util.stream.Collectors)21 ExecuteProperties (com.apple.foundationdb.record.ExecuteProperties)20 TupleHelpers (com.apple.foundationdb.tuple.TupleHelpers)20 FDBStoreTimer (com.apple.foundationdb.record.provider.foundationdb.FDBStoreTimer)19