Search in sources :

Example 6 with IndexState

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

the class FDBRecordStoreIndexTest method noMaintenanceFilteredIndexOnCheckVersion.

@Test
public void noMaintenanceFilteredIndexOnCheckVersion() throws Exception {
    try (FDBRecordContext context = openContext()) {
        openAnyRecordStore(TestRecordsIndexFilteringProto.getDescriptor(), context);
        TestRecordsIndexFilteringProto.MyBasicRecord recordA = TestRecordsIndexFilteringProto.MyBasicRecord.newBuilder().setRecNo(1001).setNumValue2(101).build();
        recordStore.saveRecord(recordA);
        context.commit();
        Collection<StoreTimer.Event> events = context.getTimer().getEvents();
        assertFalse(events.contains(FDBStoreTimer.Events.SAVE_INDEX_ENTRY));
        assertFalse(events.contains(FDBStoreTimer.Events.SKIP_INDEX_RECORD));
    }
    // add index
    RecordMetaDataHook hook = metaDataBuilder -> {
        metaDataBuilder.setVersion(metaDataBuilder.getVersion() + 1);
        metaDataBuilder.addIndex("MyBasicRecord", "value2$filtered", field("num_value_2"));
    };
    try (FDBRecordContext context = openContext()) {
        RecordMetaDataBuilder metaData = RecordMetaData.newBuilder().setRecords(TestRecordsIndexFilteringProto.getDescriptor());
        if (hook != null) {
            hook.apply(metaData);
        }
        IndexMaintenanceFilter noneFilter = (i, r) -> IndexMaintenanceFilter.IndexValues.NONE;
        FDBRecordStore fdbRecordStore = FDBRecordStore.newBuilder().setContext(context).setMetaDataProvider(metaData).setKeySpacePath(path).setIndexMaintenanceFilter(noneFilter).uncheckedOpen();
        context.getTimer().reset();
        FDBRecordStoreBase.UserVersionChecker userVersionChecker = new FDBRecordStoreBase.UserVersionChecker() {

            @Override
            public CompletableFuture<Integer> checkUserVersion(int oldUserVersion, int oldMetaDataVersion, RecordMetaDataProvider metaData) {
                return CompletableFuture.completedFuture(Integer.valueOf(1));
            }

            @Override
            public IndexState needRebuildIndex(Index index, long recordCount, boolean indexOnNewRecordTypes) {
                return IndexState.READABLE;
            }
        };
        fdbRecordStore.checkVersion(userVersionChecker, FDBRecordStoreBase.StoreExistenceCheck.NONE).get();
        Collection<StoreTimer.Event> events = context.getTimer().getEvents();
        assertFalse(events.contains(FDBStoreTimer.Events.SAVE_INDEX_ENTRY));
        assertTrue(events.contains(FDBStoreTimer.Events.SKIP_INDEX_RECORD));
    }
}
Also used : BeforeEach(org.junit.jupiter.api.BeforeEach) Arrays(java.util.Arrays) LogMessageKeys(com.apple.foundationdb.record.logging.LogMessageKeys) MetaDataException(com.apple.foundationdb.record.metadata.MetaDataException) IndexScanType(com.apple.foundationdb.record.IndexScanType) Pair(org.apache.commons.lang3.tuple.Pair) FDBError(com.apple.foundationdb.FDBError) RecordCoreException(com.apple.foundationdb.record.RecordCoreException) RecordIndexUniquenessViolation(com.apple.foundationdb.record.RecordIndexUniquenessViolation) Expressions.concat(com.apple.foundationdb.record.metadata.Key.Expressions.concat) GroupingKeyExpression(com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression) Tag(org.junit.jupiter.api.Tag) Query(com.apple.foundationdb.record.query.expressions.Query) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) IndexOptions(com.apple.foundationdb.record.metadata.IndexOptions) Set(java.util.Set) FanType(com.apple.foundationdb.record.metadata.expressions.KeyExpression.FanType) TupleRange(com.apple.foundationdb.record.TupleRange) Matchers.instanceOf(org.hamcrest.Matchers.instanceOf) RecordMetaDataProvider(com.apple.foundationdb.record.RecordMetaDataProvider) RecordStoreState(com.apple.foundationdb.record.RecordStoreState) TupleHelpers(com.apple.foundationdb.tuple.TupleHelpers) Assertions.assertTrue(org.junit.jupiter.api.Assertions.assertTrue) InvalidIndexEntry(com.apple.foundationdb.record.provider.foundationdb.indexes.InvalidIndexEntry) AutoContinuingCursor(com.apple.foundationdb.record.cursors.AutoContinuingCursor) Matchers.is(org.hamcrest.Matchers.is) Assertions.assertThrows(org.junit.jupiter.api.Assertions.assertThrows) Assertions.fail(org.junit.jupiter.api.Assertions.fail) FunctionNames(com.apple.foundationdb.record.FunctionNames) RecordMetaData(com.apple.foundationdb.record.RecordMetaData) Assertions.assertNotNull(org.junit.jupiter.api.Assertions.assertNotNull) IndexAggregateFunction(com.apple.foundationdb.record.metadata.IndexAggregateFunction) Assertions.assertNull(org.junit.jupiter.api.Assertions.assertNull) AsyncUtil(com.apple.foundationdb.async.AsyncUtil) ArrayList(java.util.ArrayList) Strings(com.google.common.base.Strings) CloseableAsyncIterator(com.apple.foundationdb.async.CloseableAsyncIterator) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) Assertions.assertEquals(org.junit.jupiter.api.Assertions.assertEquals) FDBRecordStoreBase.indexEntryKey(com.apple.foundationdb.record.provider.foundationdb.FDBRecordStoreBase.indexEntryKey) Nullable(javax.annotation.Nullable) Matchers.greaterThanOrEqualTo(org.hamcrest.Matchers.greaterThanOrEqualTo) IsolationLevel(com.apple.foundationdb.record.IsolationLevel) Tags(com.apple.test.Tags) TestRecords1EvolvedProto(com.apple.foundationdb.record.TestRecords1EvolvedProto) ExecutionException(java.util.concurrent.ExecutionException) Assertions.assertArrayEquals(org.junit.jupiter.api.Assertions.assertArrayEquals) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) Index(com.apple.foundationdb.record.metadata.Index) FDBException(com.apple.foundationdb.FDBException) ThenKeyExpression(com.apple.foundationdb.record.metadata.expressions.ThenKeyExpression) IndexEntry(com.apple.foundationdb.record.IndexEntry) StoreTimer(com.apple.foundationdb.record.provider.common.StoreTimer) LoggerFactory(org.slf4j.LoggerFactory) Assertions.assertNotEquals(org.junit.jupiter.api.Assertions.assertNotEquals) Random(java.util.Random) Tuple(com.apple.foundationdb.tuple.Tuple) Range(com.apple.foundationdb.Range) Assertions.assertFalse(org.junit.jupiter.api.Assertions.assertFalse) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Expressions.concatenateFields(com.apple.foundationdb.record.metadata.Key.Expressions.concatenateFields) ImmutableSet(com.google.common.collect.ImmutableSet) TestRecords1Proto(com.apple.foundationdb.record.TestRecords1Proto) ImmutableMap(com.google.common.collect.ImmutableMap) Matchers.lessThanOrEqualTo(org.hamcrest.Matchers.lessThanOrEqualTo) Collection(java.util.Collection) CompletionException(java.util.concurrent.CompletionException) IndexQueryabilityFilter(com.apple.foundationdb.record.query.IndexQueryabilityFilter) TypeSafeMatcher(org.hamcrest.TypeSafeMatcher) Collectors(java.util.stream.Collectors) Test(org.junit.jupiter.api.Test) List(java.util.List) EvaluationContext(com.apple.foundationdb.record.EvaluationContext) Matchers.equalTo(org.hamcrest.Matchers.equalTo) IndexTypes(com.apple.foundationdb.record.metadata.IndexTypes) Optional(java.util.Optional) TestNoIndexesProto(com.apple.foundationdb.record.TestNoIndexesProto) LazyCursor(com.apple.foundationdb.record.cursors.LazyCursor) EnumSource(org.junit.jupiter.params.provider.EnumSource) CompletableFuture(java.util.concurrent.CompletableFuture) Iterators(com.google.common.collect.Iterators) Key(com.apple.foundationdb.record.metadata.Key) FieldKeyExpression(com.apple.foundationdb.record.metadata.expressions.FieldKeyExpression) HashSet(java.util.HashSet) ExecuteProperties(com.apple.foundationdb.record.ExecuteProperties) ScanProperties(com.apple.foundationdb.record.ScanProperties) RecordCursorIterator(com.apple.foundationdb.record.RecordCursorIterator) BooleanSource(com.apple.test.BooleanSource) Nonnull(javax.annotation.Nonnull) Expressions.field(com.apple.foundationdb.record.metadata.Key.Expressions.field) EmptyKeyExpression(com.apple.foundationdb.record.metadata.expressions.EmptyKeyExpression) Matchers.hasEntry(org.hamcrest.Matchers.hasEntry) Description(org.hamcrest.Description) Matchers.oneOf(org.hamcrest.Matchers.oneOf) Logger(org.slf4j.Logger) RecordMetaDataBuilder(com.apple.foundationdb.record.RecordMetaDataBuilder) RecordTypeBuilder(com.apple.foundationdb.record.metadata.RecordTypeBuilder) IndexState(com.apple.foundationdb.record.IndexState) TestRecordsIndexFilteringProto(com.apple.foundationdb.record.TestRecordsIndexFilteringProto) Message(com.google.protobuf.Message) Collections(java.util.Collections) RecordMetaDataProvider(com.apple.foundationdb.record.RecordMetaDataProvider) Index(com.apple.foundationdb.record.metadata.Index) TestRecordsIndexFilteringProto(com.apple.foundationdb.record.TestRecordsIndexFilteringProto) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) RecordMetaDataBuilder(com.apple.foundationdb.record.RecordMetaDataBuilder) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) Test(org.junit.jupiter.api.Test)

Example 7 with IndexState

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

the class OnlineIndexerBuildIndexTest method singleRebuild.

void singleRebuild(@Nonnull List<TestRecords1Proto.MySimpleRecord> records, @Nullable List<TestRecords1Proto.MySimpleRecord> recordsWhileBuilding, int agents, boolean overlap, boolean splitLongRecords, @Nonnull Index index, @Nonnull Runnable beforeBuild, @Nonnull Runnable afterBuild, @Nonnull Runnable afterReadable) {
    LOGGER.info(KeyValueLogMessage.of("beginning rebuild test", TestLogMessageKeys.RECORDS, records.size(), LogMessageKeys.RECORDS_WHILE_BUILDING, recordsWhileBuilding == null ? 0 : recordsWhileBuilding.size(), TestLogMessageKeys.AGENTS, agents, TestLogMessageKeys.OVERLAP, overlap, TestLogMessageKeys.SPLIT_LONG_RECORDS, splitLongRecords, TestLogMessageKeys.INDEX, index));
    final FDBStoreTimer timer = new FDBStoreTimer();
    final FDBRecordStoreTestBase.RecordMetaDataHook onlySplitHook = metaDataBuilder -> {
        if (splitLongRecords) {
            metaDataBuilder.setSplitLongRecords(true);
            metaDataBuilder.removeIndex("MySimpleRecord$str_value_indexed");
        }
    };
    final FDBRecordStoreTestBase.RecordMetaDataHook hook = metaDataBuilder -> {
        onlySplitHook.apply(metaDataBuilder);
        metaDataBuilder.addIndex("MySimpleRecord", index);
    };
    LOGGER.info(KeyValueLogMessage.of("inserting elements prior to test", TestLogMessageKeys.RECORDS, records.size()));
    openSimpleMetaData(onlySplitHook);
    try (FDBRecordContext context = openContext()) {
        for (TestRecords1Proto.MySimpleRecord record : records) {
            // Check presence first to avoid overwriting version information of previously added records.
            Tuple primaryKey = Tuple.from(record.getRecNo());
            if (recordStore.loadRecord(primaryKey) == null) {
                recordStore.saveRecord(record);
            }
        }
        context.commit();
    }
    LOGGER.info(KeyValueLogMessage.of("running before build for test"));
    beforeBuild.run();
    openSimpleMetaData(hook);
    LOGGER.info(KeyValueLogMessage.of("adding index", TestLogMessageKeys.INDEX, index));
    openSimpleMetaData(hook);
    final boolean isAlwaysReadable;
    try (FDBRecordContext context = openContext()) {
        // care of by OnlineIndexer.
        if (!safeBuild) {
            LOGGER.info(KeyValueLogMessage.of("marking write-only", TestLogMessageKeys.INDEX, index));
            recordStore.clearAndMarkIndexWriteOnly(index).join();
        }
        isAlwaysReadable = safeBuild && recordStore.isIndexReadable(index);
        context.commit();
    }
    LOGGER.info(KeyValueLogMessage.of("creating online index builder", TestLogMessageKeys.INDEX, index, TestLogMessageKeys.RECORD_TYPES, metaData.recordTypesForIndex(index), LogMessageKeys.SUBSPACE, ByteArrayUtil2.loggable(subspace.pack()), LogMessageKeys.LIMIT, 20, TestLogMessageKeys.RECORDS_PER_SECOND, OnlineIndexer.DEFAULT_RECORDS_PER_SECOND * 100));
    final OnlineIndexer.Builder builder = OnlineIndexer.newBuilder().setDatabase(fdb).setMetaData(metaData).setIndex(index).setSubspace(subspace).setConfigLoader(old -> {
        OnlineIndexer.Config.Builder conf = OnlineIndexer.Config.newBuilder().setMaxLimit(20).setMaxRetries(Integer.MAX_VALUE).setRecordsPerSecond(OnlineIndexer.DEFAULT_RECORDS_PER_SECOND * 100);
        if (ThreadLocalRandom.current().nextBoolean()) {
            // randomly enable the progress logging to ensure that it doesn't throw exceptions,
            // or otherwise disrupt the build.
            LOGGER.info("Setting progress log interval");
            conf.setProgressLogIntervalMillis(0);
        }
        return conf.build();
    }).setTimer(timer);
    if (ThreadLocalRandom.current().nextBoolean()) {
        LOGGER.info("Setting priority to DEFAULT");
        builder.setPriority(FDBTransactionPriority.DEFAULT);
    }
    if (fdb.isTrackLastSeenVersion()) {
        LOGGER.info("Setting weak read semantics");
        builder.setWeakReadSemantics(new FDBDatabase.WeakReadSemantics(0L, Long.MAX_VALUE, true));
    }
    if (!safeBuild) {
        builder.setIndexingPolicy(OnlineIndexer.IndexingPolicy.newBuilder().setIfDisabled(OnlineIndexer.IndexingPolicy.DesiredAction.ERROR).setIfMismatchPrevious(OnlineIndexer.IndexingPolicy.DesiredAction.ERROR));
        builder.setUseSynchronizedSession(false);
    }
    try (OnlineIndexer indexBuilder = builder.build()) {
        CompletableFuture<Void> buildFuture;
        LOGGER.info(KeyValueLogMessage.of("building index", TestLogMessageKeys.INDEX, index, TestLogMessageKeys.AGENT, agents, LogMessageKeys.RECORDS_WHILE_BUILDING, recordsWhileBuilding == null ? 0 : recordsWhileBuilding.size(), TestLogMessageKeys.OVERLAP, overlap));
        if (agents == 1) {
            buildFuture = indexBuilder.buildIndexAsync(false);
        } else {
            if (overlap) {
                CompletableFuture<?>[] futures = new CompletableFuture<?>[agents];
                for (int i = 0; i < agents; i++) {
                    final int agent = i;
                    futures[i] = safeBuild ? indexBuilder.buildIndexAsync(false).exceptionally(exception -> {
                        // because the other one is already working on building the index.
                        if (exception.getCause() instanceof SynchronizedSessionLockedException) {
                            LOGGER.info(KeyValueLogMessage.of("Detected another worker processing this index", TestLogMessageKeys.INDEX, index, TestLogMessageKeys.AGENT, agent), exception);
                            return null;
                        } else {
                            throw new CompletionException(exception);
                        }
                    }) : indexBuilder.buildIndexAsync(false);
                }
                buildFuture = CompletableFuture.allOf(futures);
            } else {
                // Safe builds do not support building ranges yet.
                assumeFalse(safeBuild);
                buildFuture = indexBuilder.buildEndpoints().thenCompose(tupleRange -> {
                    if (tupleRange != null) {
                        long start = tupleRange.getLow().getLong(0);
                        long end = tupleRange.getHigh().getLong(0);
                        CompletableFuture<?>[] futures = new CompletableFuture<?>[agents];
                        for (int i = 0; i < agents; i++) {
                            long itrStart = start + (end - start) / agents * i;
                            long itrEnd = (i == agents - 1) ? end : start + (end - start) / agents * (i + 1);
                            LOGGER.info(KeyValueLogMessage.of("building range", TestLogMessageKeys.INDEX, index, TestLogMessageKeys.AGENT, i, TestLogMessageKeys.BEGIN, itrStart, TestLogMessageKeys.END, itrEnd));
                            futures[i] = indexBuilder.buildRange(Key.Evaluated.scalar(itrStart), Key.Evaluated.scalar(itrEnd));
                        }
                        return CompletableFuture.allOf(futures);
                    } else {
                        return AsyncUtil.DONE;
                    }
                });
            }
        }
        if (safeBuild) {
            buildFuture = MoreAsyncUtil.composeWhenComplete(buildFuture, (result, ex) -> indexBuilder.checkAnyOngoingOnlineIndexBuildsAsync().thenAccept(Assertions::assertFalse), fdb::mapAsyncToSyncException);
        }
        if (recordsWhileBuilding != null && recordsWhileBuilding.size() > 0) {
            int i = 0;
            while (i < recordsWhileBuilding.size()) {
                List<TestRecords1Proto.MySimpleRecord> thisBatch = recordsWhileBuilding.subList(i, Math.min(i + 30, recordsWhileBuilding.size()));
                fdb.run(context -> {
                    FDBRecordStore store = recordStore.asBuilder().setContext(context).build();
                    thisBatch.forEach(store::saveRecord);
                    return null;
                });
                i += 30;
            }
        }
        buildFuture.join();
        // if a record is added to a range that has already been built, it will not be counted, otherwise,
        // it will.
        long additionalScans = 0;
        if (recordsWhileBuilding != null && recordsWhileBuilding.size() > 0) {
            additionalScans += (long) recordsWhileBuilding.size();
        }
        try (FDBRecordContext context = openContext()) {
            IndexBuildState indexBuildState = context.asyncToSync(FDBStoreTimer.Waits.WAIT_GET_INDEX_BUILD_STATE, IndexBuildState.loadIndexBuildStateAsync(recordStore, index));
            IndexState indexState = indexBuildState.getIndexState();
            if (isAlwaysReadable) {
                assertEquals(IndexState.READABLE, indexState);
            } else {
                assertEquals(IndexState.WRITE_ONLY, indexState);
                assertEquals(indexBuilder.getTotalRecordsScanned(), indexBuildState.getRecordsScanned());
                // Count index is not defined so we cannot determine the records in total from it.
                assertNull(indexBuildState.getRecordsInTotal());
            }
        }
        assertThat(indexBuilder.getTotalRecordsScanned(), allOf(greaterThanOrEqualTo((long) records.size()), lessThanOrEqualTo((long) records.size() + additionalScans)));
    }
    KeyValueLogMessage msg = KeyValueLogMessage.build("building index - completed", TestLogMessageKeys.INDEX, index);
    msg.addKeysAndValues(timer.getKeysAndValues());
    LOGGER.info(msg.toString());
    LOGGER.info(KeyValueLogMessage.of("running post build checks", TestLogMessageKeys.INDEX, index));
    // uses the index in quereis since the index is readable.
    if (!isAlwaysReadable) {
        afterBuild.run();
    }
    LOGGER.info(KeyValueLogMessage.of("verifying range set emptiness", TestLogMessageKeys.INDEX, index));
    try (FDBRecordContext context = openContext()) {
        RangeSet rangeSet = new RangeSet(recordStore.indexRangeSubspace(metaData.getIndex(index.getName())));
        System.out.println("Range set for " + records.size() + " records:\n" + rangeSet.rep(context.ensureActive()).join());
        if (!isAlwaysReadable) {
            assertEquals(Collections.emptyList(), rangeSet.missingRanges(context.ensureActive()).asList().join());
        }
        context.commit();
    }
    LOGGER.info(KeyValueLogMessage.of("marking index readable", TestLogMessageKeys.INDEX, index));
    try (FDBRecordContext context = openContext()) {
        boolean updated = recordStore.markIndexReadable(index).join();
        if (isAlwaysReadable) {
            assertFalse(updated);
        } else {
            assertTrue(updated);
        }
        context.commit();
    }
    afterReadable.run();
    LOGGER.info(KeyValueLogMessage.of("ending rebuild test", TestLogMessageKeys.RECORDS, records.size(), LogMessageKeys.RECORDS_WHILE_BUILDING, recordsWhileBuilding == null ? 0 : recordsWhileBuilding.size(), TestLogMessageKeys.AGENTS, agents, TestLogMessageKeys.OVERLAP, overlap, TestLogMessageKeys.SPLIT_LONG_RECORDS, splitLongRecords, TestLogMessageKeys.INDEX, index));
}
Also used : LogMessageKeys(com.apple.foundationdb.record.logging.LogMessageKeys) LoggerFactory(org.slf4j.LoggerFactory) Assertions.assertNull(org.junit.jupiter.api.Assertions.assertNull) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) AsyncUtil(com.apple.foundationdb.async.AsyncUtil) RecordQuery(com.apple.foundationdb.record.query.RecordQuery) RangeSet(com.apple.foundationdb.async.RangeSet) RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) Function(java.util.function.Function) ArrayList(java.util.ArrayList) Key(com.apple.foundationdb.record.metadata.Key) Tuple(com.apple.foundationdb.tuple.Tuple) KeyValueLogMessage(com.apple.foundationdb.record.logging.KeyValueLogMessage) SynchronizedSessionLockedException(com.apple.foundationdb.synchronizedsession.SynchronizedSessionLockedException) Assertions.assertFalse(org.junit.jupiter.api.Assertions.assertFalse) TestLogMessageKeys(com.apple.foundationdb.record.logging.TestLogMessageKeys) Assumptions.assumeFalse(org.junit.jupiter.api.Assumptions.assumeFalse) Map(java.util.Map) ThreadLocalRandom(java.util.concurrent.ThreadLocalRandom) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) Assertions.assertEquals(org.junit.jupiter.api.Assertions.assertEquals) Nonnull(javax.annotation.Nonnull) Nullable(javax.annotation.Nullable) ByteArrayUtil2(com.apple.foundationdb.tuple.ByteArrayUtil2) MoreAsyncUtil(com.apple.foundationdb.async.MoreAsyncUtil) Matchers.greaterThanOrEqualTo(org.hamcrest.Matchers.greaterThanOrEqualTo) Logger(org.slf4j.Logger) TestRecords1Proto(com.apple.foundationdb.record.TestRecords1Proto) Matchers.allOf(org.hamcrest.Matchers.allOf) Matchers.lessThanOrEqualTo(org.hamcrest.Matchers.lessThanOrEqualTo) IndexState(com.apple.foundationdb.record.IndexState) CompletionException(java.util.concurrent.CompletionException) List(java.util.List) Index(com.apple.foundationdb.record.metadata.Index) Assertions.assertTrue(org.junit.jupiter.api.Assertions.assertTrue) Message(com.google.protobuf.Message) Assertions(org.junit.jupiter.api.Assertions) Comparator(java.util.Comparator) Collections(java.util.Collections) IndexState(com.apple.foundationdb.record.IndexState) CompletableFuture(java.util.concurrent.CompletableFuture) SynchronizedSessionLockedException(com.apple.foundationdb.synchronizedsession.SynchronizedSessionLockedException) TestRecords1Proto(com.apple.foundationdb.record.TestRecords1Proto) RangeSet(com.apple.foundationdb.async.RangeSet) Assertions(org.junit.jupiter.api.Assertions) KeyValueLogMessage(com.apple.foundationdb.record.logging.KeyValueLogMessage) CompletionException(java.util.concurrent.CompletionException) Tuple(com.apple.foundationdb.tuple.Tuple)

Example 8 with IndexState

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

the class FDBRecordStore method vacuumReadableIndexesBuildData.

public void vacuumReadableIndexesBuildData() {
    Transaction tr = ensureContextActive();
    // also adds state to read conflicts
    Map<Index, IndexState> indexStates = getAllIndexStates();
    for (Map.Entry<Index, IndexState> entry : indexStates.entrySet()) {
        if (entry.getValue().equals(IndexState.READABLE)) {
            clearReadableIndexBuildData(tr, entry.getKey());
        }
    }
}
Also used : Transaction(com.apple.foundationdb.Transaction) ReadTransaction(com.apple.foundationdb.ReadTransaction) FormerIndex(com.apple.foundationdb.record.metadata.FormerIndex) Index(com.apple.foundationdb.record.metadata.Index) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) IndexState(com.apple.foundationdb.record.IndexState)

Example 9 with IndexState

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

the class FDBRecordStore method rebuildIndexes.

@Nonnull
protected CompletableFuture<Void> rebuildIndexes(@Nonnull Map<Index, List<RecordType>> indexes, @Nonnull Map<Index, CompletableFuture<IndexState>> newStates, @Nonnull List<CompletableFuture<Void>> work, @Nonnull RebuildIndexReason reason, @Nullable Integer oldMetaDataVersion) {
    Iterator<Map.Entry<Index, List<RecordType>>> indexIter = indexes.entrySet().iterator();
    return AsyncUtil.whileTrue(() -> {
        Iterator<CompletableFuture<Void>> workIter = work.iterator();
        while (workIter.hasNext()) {
            CompletableFuture<Void> workItem = workIter.next();
            if (workItem.isDone()) {
                // Just for error handling.
                context.asyncToSync(FDBStoreTimer.Waits.WAIT_ERROR_CHECK, workItem);
                workIter.remove();
            }
        }
        while (work.size() < MAX_PARALLEL_INDEX_REBUILD) {
            if (indexIter.hasNext()) {
                Map.Entry<Index, List<RecordType>> indexItem = indexIter.next();
                Index index = indexItem.getKey();
                List<RecordType> recordTypes = indexItem.getValue();
                final CompletableFuture<Void> rebuildOrMarkIndexSafely = MoreAsyncUtil.handleOnException(() -> newStates.getOrDefault(index, READY_READABLE).thenCompose(indexState -> rebuildOrMarkIndex(index, indexState, recordTypes, reason, oldMetaDataVersion)), exception -> {
                    // If there is any issue, simply mark the index as disabled without blocking checkVersion
                    logExceptionAsWarn(KeyValueLogMessage.build("unable to build index", LogMessageKeys.INDEX_NAME, index.getName()), exception);
                    return markIndexDisabled(index).thenApply(b -> null);
                });
                work.add(rebuildOrMarkIndexSafely);
            } else {
                break;
            }
        }
        if (work.isEmpty()) {
            return AsyncUtil.READY_FALSE;
        }
        return AsyncUtil.whenAny(work).thenApply(v -> true);
    }, getExecutor());
}
Also used : LogMessageKeys(com.apple.foundationdb.record.logging.LogMessageKeys) UnaryOperator(java.util.function.UnaryOperator) MetaDataException(com.apple.foundationdb.record.metadata.MetaDataException) RecordSerializer(com.apple.foundationdb.record.provider.common.RecordSerializer) Subspace(com.apple.foundationdb.subspace.Subspace) MutationType(com.apple.foundationdb.MutationType) RecordCoreException(com.apple.foundationdb.record.RecordCoreException) Map(java.util.Map) RecordIndexUniquenessViolation(com.apple.foundationdb.record.RecordIndexUniquenessViolation) QueryToKeyMatcher(com.apple.foundationdb.record.query.QueryToKeyMatcher) InvalidProtocolBufferException(com.google.protobuf.InvalidProtocolBufferException) Query(com.apple.foundationdb.record.query.expressions.Query) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) Set(java.util.Set) TupleRange(com.apple.foundationdb.record.TupleRange) KeySpacePath(com.apple.foundationdb.record.provider.foundationdb.keyspace.KeySpacePath) ByteOrder(java.nio.ByteOrder) SyntheticRecordType(com.apple.foundationdb.record.metadata.SyntheticRecordType) RecordMetaDataProvider(com.apple.foundationdb.record.RecordMetaDataProvider) RecordStoreState(com.apple.foundationdb.record.RecordStoreState) TupleHelpers(com.apple.foundationdb.tuple.TupleHelpers) API(com.apple.foundationdb.annotation.API) FunctionNames(com.apple.foundationdb.record.FunctionNames) RecordMetaData(com.apple.foundationdb.record.RecordMetaData) IndexAggregateFunction(com.apple.foundationdb.record.metadata.IndexAggregateFunction) AsyncUtil(com.apple.foundationdb.async.AsyncUtil) RecordQuery(com.apple.foundationdb.record.query.RecordQuery) RangeSet(com.apple.foundationdb.async.RangeSet) RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) Supplier(java.util.function.Supplier) FormerIndex(com.apple.foundationdb.record.metadata.FormerIndex) ArrayList(java.util.ArrayList) ByteScanLimiter(com.apple.foundationdb.record.ByteScanLimiter) ParameterRelationshipGraph(com.apple.foundationdb.record.query.ParameterRelationshipGraph) LoggableException(com.apple.foundationdb.util.LoggableException) CloseableAsyncIterator(com.apple.foundationdb.async.CloseableAsyncIterator) IndexRecordFunction(com.apple.foundationdb.record.metadata.IndexRecordFunction) Nullable(javax.annotation.Nullable) ByteArrayUtil2(com.apple.foundationdb.tuple.ByteArrayUtil2) IsolationLevel(com.apple.foundationdb.record.IsolationLevel) CursorLimitManager(com.apple.foundationdb.record.cursors.CursorLimitManager) ExecuteState(com.apple.foundationdb.record.ExecuteState) AtomicLong(java.util.concurrent.atomic.AtomicLong) RecordType(com.apple.foundationdb.record.metadata.RecordType) Index(com.apple.foundationdb.record.metadata.Index) DynamicMessageRecordSerializer(com.apple.foundationdb.record.provider.common.DynamicMessageRecordSerializer) SyntheticRecordPlanner(com.apple.foundationdb.record.query.plan.synthetic.SyntheticRecordPlanner) IndexEntry(com.apple.foundationdb.record.IndexEntry) LoggerFactory(org.slf4j.LoggerFactory) RecordCoreStorageException(com.apple.foundationdb.record.RecordCoreStorageException) ByteBuffer(java.nio.ByteBuffer) RecordQueryPlanner(com.apple.foundationdb.record.query.plan.RecordQueryPlanner) Transaction(com.apple.foundationdb.Transaction) Tuple(com.apple.foundationdb.tuple.Tuple) Range(com.apple.foundationdb.Range) KeyValueLogMessage(com.apple.foundationdb.record.logging.KeyValueLogMessage) PipelineOperation(com.apple.foundationdb.record.PipelineOperation) RecordMetaDataProto(com.apple.foundationdb.record.RecordMetaDataProto) ByteArrayUtil(com.apple.foundationdb.tuple.ByteArrayUtil) KeyValue(com.apple.foundationdb.KeyValue) ImmutableMap(com.google.common.collect.ImmutableMap) Predicate(java.util.function.Predicate) Collection(java.util.Collection) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) IndexQueryabilityFilter(com.apple.foundationdb.record.query.IndexQueryabilityFilter) AndComponent(com.apple.foundationdb.record.query.expressions.AndComponent) RecordCoreArgumentException(com.apple.foundationdb.record.RecordCoreArgumentException) Collectors(java.util.stream.Collectors) ByteString(com.google.protobuf.ByteString) List(java.util.List) EvaluationContext(com.apple.foundationdb.record.EvaluationContext) AggregateFunctionNotSupportedException(com.apple.foundationdb.record.AggregateFunctionNotSupportedException) RecordTypeKeyComparison(com.apple.foundationdb.record.query.expressions.RecordTypeKeyComparison) IndexTypes(com.apple.foundationdb.record.metadata.IndexTypes) Optional(java.util.Optional) MutableRecordStoreState(com.apple.foundationdb.record.MutableRecordStoreState) RecordTypeOrBuilder(com.apple.foundationdb.record.metadata.RecordTypeOrBuilder) SyntheticRecordFromStoredRecordPlan(com.apple.foundationdb.record.query.plan.synthetic.SyntheticRecordFromStoredRecordPlan) SpotBugsSuppressWarnings(com.apple.foundationdb.annotation.SpotBugsSuppressWarnings) Descriptors(com.google.protobuf.Descriptors) AsyncIterator(com.apple.foundationdb.async.AsyncIterator) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) AtomicReference(java.util.concurrent.atomic.AtomicReference) Function(java.util.function.Function) CursorStreamingMode(com.apple.foundationdb.record.CursorStreamingMode) Key(com.apple.foundationdb.record.metadata.Key) ExecuteProperties(com.apple.foundationdb.record.ExecuteProperties) EndpointType(com.apple.foundationdb.record.EndpointType) ScanProperties(com.apple.foundationdb.record.ScanProperties) Suppliers(com.google.common.base.Suppliers) LinkedList(java.util.LinkedList) Nonnull(javax.annotation.Nonnull) EmptyKeyExpression(com.apple.foundationdb.record.metadata.expressions.EmptyKeyExpression) MoreAsyncUtil(com.apple.foundationdb.async.MoreAsyncUtil) Logger(org.slf4j.Logger) Iterator(java.util.Iterator) IndexState(com.apple.foundationdb.record.IndexState) StoreRecordFunction(com.apple.foundationdb.record.metadata.StoreRecordFunction) ReadTransaction(com.apple.foundationdb.ReadTransaction) AsyncIterable(com.apple.foundationdb.async.AsyncIterable) FDBRecordStoreStateCache(com.apple.foundationdb.record.provider.foundationdb.storestate.FDBRecordStoreStateCache) Message(com.google.protobuf.Message) RecordCursor(com.apple.foundationdb.record.RecordCursor) QueryComponent(com.apple.foundationdb.record.query.expressions.QueryComponent) VisibleForTesting(com.google.common.annotations.VisibleForTesting) Collections(java.util.Collections) FormerIndex(com.apple.foundationdb.record.metadata.FormerIndex) Index(com.apple.foundationdb.record.metadata.Index) IndexEntry(com.apple.foundationdb.record.IndexEntry) CompletableFuture(java.util.concurrent.CompletableFuture) SyntheticRecordType(com.apple.foundationdb.record.metadata.SyntheticRecordType) RecordType(com.apple.foundationdb.record.metadata.RecordType) ArrayList(java.util.ArrayList) List(java.util.List) LinkedList(java.util.LinkedList) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) Nonnull(javax.annotation.Nonnull)

Example 10 with IndexState

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

the class FDBRecordStore method getStatesForRebuildIndexes.

@Nonnull
protected Map<Index, CompletableFuture<IndexState>> getStatesForRebuildIndexes(@Nullable UserVersionChecker userVersionChecker, @Nonnull Map<Index, List<RecordType>> indexes, @Nonnull Supplier<CompletableFuture<Long>> lazyRecordCount, @Nonnull Supplier<CompletableFuture<Long>> lazyRecordsSize, boolean newStore, int oldMetaDataVersion, int oldFormatVersion) {
    Map<Index, CompletableFuture<IndexState>> newStates = new HashMap<>();
    for (Map.Entry<Index, List<RecordType>> entry : indexes.entrySet()) {
        Index index = entry.getKey();
        List<RecordType> recordTypes = entry.getValue();
        boolean indexOnNewRecordTypes = areAllRecordTypesSince(recordTypes, oldMetaDataVersion);
        CompletableFuture<IndexState> stateFuture = userVersionChecker == null ? lazyRecordCount.get().thenApply(recordCount -> FDBRecordStore.disabledIfTooManyRecordsForRebuild(recordCount, indexOnNewRecordTypes)) : userVersionChecker.needRebuildIndex(index, lazyRecordCount, lazyRecordsSize, indexOnNewRecordTypes);
        if (index.getType().equals(IndexTypes.VERSION) && !newStore && oldFormatVersion < SAVE_VERSION_WITH_RECORD_FORMAT_VERSION && !useOldVersionFormat()) {
            stateFuture = stateFuture.thenApply(state -> {
                if (IndexState.READABLE.equals(state)) {
                    // build and some versions won't be indexed correctly.
                    return IndexState.DISABLED;
                }
                return state;
            });
        }
        newStates.put(index, stateFuture);
    }
    return newStates;
}
Also used : LogMessageKeys(com.apple.foundationdb.record.logging.LogMessageKeys) UnaryOperator(java.util.function.UnaryOperator) MetaDataException(com.apple.foundationdb.record.metadata.MetaDataException) RecordSerializer(com.apple.foundationdb.record.provider.common.RecordSerializer) Subspace(com.apple.foundationdb.subspace.Subspace) MutationType(com.apple.foundationdb.MutationType) RecordCoreException(com.apple.foundationdb.record.RecordCoreException) Map(java.util.Map) RecordIndexUniquenessViolation(com.apple.foundationdb.record.RecordIndexUniquenessViolation) QueryToKeyMatcher(com.apple.foundationdb.record.query.QueryToKeyMatcher) InvalidProtocolBufferException(com.google.protobuf.InvalidProtocolBufferException) Query(com.apple.foundationdb.record.query.expressions.Query) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) Set(java.util.Set) TupleRange(com.apple.foundationdb.record.TupleRange) KeySpacePath(com.apple.foundationdb.record.provider.foundationdb.keyspace.KeySpacePath) ByteOrder(java.nio.ByteOrder) SyntheticRecordType(com.apple.foundationdb.record.metadata.SyntheticRecordType) RecordMetaDataProvider(com.apple.foundationdb.record.RecordMetaDataProvider) RecordStoreState(com.apple.foundationdb.record.RecordStoreState) TupleHelpers(com.apple.foundationdb.tuple.TupleHelpers) API(com.apple.foundationdb.annotation.API) FunctionNames(com.apple.foundationdb.record.FunctionNames) RecordMetaData(com.apple.foundationdb.record.RecordMetaData) IndexAggregateFunction(com.apple.foundationdb.record.metadata.IndexAggregateFunction) AsyncUtil(com.apple.foundationdb.async.AsyncUtil) RecordQuery(com.apple.foundationdb.record.query.RecordQuery) RangeSet(com.apple.foundationdb.async.RangeSet) RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) Supplier(java.util.function.Supplier) FormerIndex(com.apple.foundationdb.record.metadata.FormerIndex) ArrayList(java.util.ArrayList) ByteScanLimiter(com.apple.foundationdb.record.ByteScanLimiter) ParameterRelationshipGraph(com.apple.foundationdb.record.query.ParameterRelationshipGraph) LoggableException(com.apple.foundationdb.util.LoggableException) CloseableAsyncIterator(com.apple.foundationdb.async.CloseableAsyncIterator) IndexRecordFunction(com.apple.foundationdb.record.metadata.IndexRecordFunction) Nullable(javax.annotation.Nullable) ByteArrayUtil2(com.apple.foundationdb.tuple.ByteArrayUtil2) IsolationLevel(com.apple.foundationdb.record.IsolationLevel) CursorLimitManager(com.apple.foundationdb.record.cursors.CursorLimitManager) ExecuteState(com.apple.foundationdb.record.ExecuteState) AtomicLong(java.util.concurrent.atomic.AtomicLong) RecordType(com.apple.foundationdb.record.metadata.RecordType) Index(com.apple.foundationdb.record.metadata.Index) DynamicMessageRecordSerializer(com.apple.foundationdb.record.provider.common.DynamicMessageRecordSerializer) SyntheticRecordPlanner(com.apple.foundationdb.record.query.plan.synthetic.SyntheticRecordPlanner) IndexEntry(com.apple.foundationdb.record.IndexEntry) LoggerFactory(org.slf4j.LoggerFactory) RecordCoreStorageException(com.apple.foundationdb.record.RecordCoreStorageException) ByteBuffer(java.nio.ByteBuffer) RecordQueryPlanner(com.apple.foundationdb.record.query.plan.RecordQueryPlanner) Transaction(com.apple.foundationdb.Transaction) Tuple(com.apple.foundationdb.tuple.Tuple) Range(com.apple.foundationdb.Range) KeyValueLogMessage(com.apple.foundationdb.record.logging.KeyValueLogMessage) PipelineOperation(com.apple.foundationdb.record.PipelineOperation) RecordMetaDataProto(com.apple.foundationdb.record.RecordMetaDataProto) ByteArrayUtil(com.apple.foundationdb.tuple.ByteArrayUtil) KeyValue(com.apple.foundationdb.KeyValue) ImmutableMap(com.google.common.collect.ImmutableMap) Predicate(java.util.function.Predicate) Collection(java.util.Collection) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) IndexQueryabilityFilter(com.apple.foundationdb.record.query.IndexQueryabilityFilter) AndComponent(com.apple.foundationdb.record.query.expressions.AndComponent) RecordCoreArgumentException(com.apple.foundationdb.record.RecordCoreArgumentException) Collectors(java.util.stream.Collectors) ByteString(com.google.protobuf.ByteString) List(java.util.List) EvaluationContext(com.apple.foundationdb.record.EvaluationContext) AggregateFunctionNotSupportedException(com.apple.foundationdb.record.AggregateFunctionNotSupportedException) RecordTypeKeyComparison(com.apple.foundationdb.record.query.expressions.RecordTypeKeyComparison) IndexTypes(com.apple.foundationdb.record.metadata.IndexTypes) Optional(java.util.Optional) MutableRecordStoreState(com.apple.foundationdb.record.MutableRecordStoreState) RecordTypeOrBuilder(com.apple.foundationdb.record.metadata.RecordTypeOrBuilder) SyntheticRecordFromStoredRecordPlan(com.apple.foundationdb.record.query.plan.synthetic.SyntheticRecordFromStoredRecordPlan) SpotBugsSuppressWarnings(com.apple.foundationdb.annotation.SpotBugsSuppressWarnings) Descriptors(com.google.protobuf.Descriptors) AsyncIterator(com.apple.foundationdb.async.AsyncIterator) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) AtomicReference(java.util.concurrent.atomic.AtomicReference) Function(java.util.function.Function) CursorStreamingMode(com.apple.foundationdb.record.CursorStreamingMode) Key(com.apple.foundationdb.record.metadata.Key) ExecuteProperties(com.apple.foundationdb.record.ExecuteProperties) EndpointType(com.apple.foundationdb.record.EndpointType) ScanProperties(com.apple.foundationdb.record.ScanProperties) Suppliers(com.google.common.base.Suppliers) LinkedList(java.util.LinkedList) Nonnull(javax.annotation.Nonnull) EmptyKeyExpression(com.apple.foundationdb.record.metadata.expressions.EmptyKeyExpression) MoreAsyncUtil(com.apple.foundationdb.async.MoreAsyncUtil) Logger(org.slf4j.Logger) Iterator(java.util.Iterator) IndexState(com.apple.foundationdb.record.IndexState) StoreRecordFunction(com.apple.foundationdb.record.metadata.StoreRecordFunction) ReadTransaction(com.apple.foundationdb.ReadTransaction) AsyncIterable(com.apple.foundationdb.async.AsyncIterable) FDBRecordStoreStateCache(com.apple.foundationdb.record.provider.foundationdb.storestate.FDBRecordStoreStateCache) Message(com.google.protobuf.Message) RecordCursor(com.apple.foundationdb.record.RecordCursor) QueryComponent(com.apple.foundationdb.record.query.expressions.QueryComponent) VisibleForTesting(com.google.common.annotations.VisibleForTesting) Collections(java.util.Collections) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) FormerIndex(com.apple.foundationdb.record.metadata.FormerIndex) Index(com.apple.foundationdb.record.metadata.Index) IndexState(com.apple.foundationdb.record.IndexState) CompletableFuture(java.util.concurrent.CompletableFuture) SyntheticRecordType(com.apple.foundationdb.record.metadata.SyntheticRecordType) RecordType(com.apple.foundationdb.record.metadata.RecordType) ArrayList(java.util.ArrayList) List(java.util.List) LinkedList(java.util.LinkedList) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) Nonnull(javax.annotation.Nonnull)

Aggregations

IndexState (com.apple.foundationdb.record.IndexState)11 Nonnull (javax.annotation.Nonnull)10 Index (com.apple.foundationdb.record.metadata.Index)9 AsyncUtil (com.apple.foundationdb.async.AsyncUtil)8 LogMessageKeys (com.apple.foundationdb.record.logging.LogMessageKeys)8 ArrayList (java.util.ArrayList)8 List (java.util.List)8 CompletableFuture (java.util.concurrent.CompletableFuture)8 Nullable (javax.annotation.Nullable)8 Logger (org.slf4j.Logger)8 LoggerFactory (org.slf4j.LoggerFactory)8 MoreAsyncUtil (com.apple.foundationdb.async.MoreAsyncUtil)7 KeyValueLogMessage (com.apple.foundationdb.record.logging.KeyValueLogMessage)7 ImmutableMap (com.google.common.collect.ImmutableMap)7 HashMap (java.util.HashMap)7 Map (java.util.Map)7 Function (java.util.function.Function)7 Range (com.apple.foundationdb.Range)6 Transaction (com.apple.foundationdb.Transaction)6 API (com.apple.foundationdb.annotation.API)6