Search in sources :

Example 11 with RecordMetaData

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

the class FDBRecordStore method checkRebuildIndexes.

private CompletableFuture<Void> checkRebuildIndexes(@Nullable UserVersionChecker userVersionChecker, @Nonnull RecordMetaDataProto.DataStoreInfo.Builder info, int oldFormatVersion, @Nonnull RecordMetaData metaData, int oldMetaDataVersion, boolean rebuildRecordCounts, List<CompletableFuture<Void>> work) {
    final boolean newStore = oldFormatVersion == 0;
    final Map<Index, List<RecordType>> indexes = metaData.getIndexesToBuildSince(oldMetaDataVersion);
    if (!indexes.isEmpty()) {
        // If all the new indexes are only for a record type whose primary key has a type prefix, then we can scan less.
        RecordType singleRecordTypeWithPrefixKey = singleRecordTypeWithPrefixKey(indexes);
        final AtomicLong recordCountRef = new AtomicLong(-1);
        final Supplier<CompletableFuture<Long>> lazyRecordCount = getAndRememberFutureLong(recordCountRef, () -> getRecordCountForRebuildIndexes(newStore, rebuildRecordCounts, indexes, singleRecordTypeWithPrefixKey));
        AtomicLong recordsSizeRef = new AtomicLong(-1);
        final Supplier<CompletableFuture<Long>> lazyRecordsSize = getAndRememberFutureLong(recordsSizeRef, () -> getRecordSizeForRebuildIndexes(singleRecordTypeWithPrefixKey));
        if (singleRecordTypeWithPrefixKey == null && formatVersion >= SAVE_UNSPLIT_WITH_SUFFIX_FORMAT_VERSION && omitUnsplitRecordSuffix) {
            // Check to see if the unsplit format can be upgraded on an empty store.
            // Only works if singleRecordTypeWithPrefixKey is null as otherwise, the recordCount will not contain
            // all records
            work.add(lazyRecordCount.get().thenAccept(recordCount -> {
                if (recordCount == 0) {
                    if (newStore ? LOGGER.isDebugEnabled() : LOGGER.isInfoEnabled()) {
                        KeyValueLogMessage msg = KeyValueLogMessage.build("upgrading unsplit format on empty store", LogMessageKeys.NEW_FORMAT_VERSION, formatVersion, subspaceProvider.logKey(), subspaceProvider.toString(context));
                        if (newStore) {
                            LOGGER.debug(msg.toString());
                        } else {
                            LOGGER.info(msg.toString());
                        }
                    }
                    omitUnsplitRecordSuffix = formatVersion < SAVE_UNSPLIT_WITH_SUFFIX_FORMAT_VERSION;
                    info.clearOmitUnsplitRecordSuffix();
                    // We used snapshot to determine emptiness, and are now acting on it.
                    addRecordsReadConflict();
                }
            }));
        }
        Map<Index, CompletableFuture<IndexState>> newStates = getStatesForRebuildIndexes(userVersionChecker, indexes, lazyRecordCount, lazyRecordsSize, newStore, oldMetaDataVersion, oldFormatVersion);
        return rebuildIndexes(indexes, newStates, work, newStore ? RebuildIndexReason.NEW_STORE : RebuildIndexReason.FEW_RECORDS, oldMetaDataVersion).thenRun(() -> {
            // Log after checking all index states
            maybeLogIndexesNeedingRebuilding(newStates, recordCountRef, recordsSizeRef, rebuildRecordCounts, newStore);
            context.increment(FDBStoreTimer.Counts.INDEXES_NEED_REBUILDING, newStates.entrySet().size());
        });
    } else {
        return work.isEmpty() ? AsyncUtil.DONE : AsyncUtil.whenAll(work);
    }
}
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) AtomicLong(java.util.concurrent.atomic.AtomicLong) CompletableFuture(java.util.concurrent.CompletableFuture) SyntheticRecordType(com.apple.foundationdb.record.metadata.SyntheticRecordType) RecordType(com.apple.foundationdb.record.metadata.RecordType) FormerIndex(com.apple.foundationdb.record.metadata.FormerIndex) Index(com.apple.foundationdb.record.metadata.Index) ArrayList(java.util.ArrayList) List(java.util.List) LinkedList(java.util.LinkedList) KeyValueLogMessage(com.apple.foundationdb.record.logging.KeyValueLogMessage)

Example 12 with RecordMetaData

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

the class IndexingBase method validateSameMetadataOrThrow.

protected void validateSameMetadataOrThrow(FDBRecordStore store) {
    final RecordMetaData metaData = store.getRecordMetaData();
    final RecordMetaDataProvider recordMetaDataProvider = common.getRecordStoreBuilder().getMetaDataProvider();
    if (recordMetaDataProvider == null || !metaData.equals(recordMetaDataProvider.getRecordMetaData())) {
        throw new MetaDataException("Store does not have the same metadata");
    }
}
Also used : RecordMetaData(com.apple.foundationdb.record.RecordMetaData) RecordMetaDataProvider(com.apple.foundationdb.record.RecordMetaDataProvider) MetaDataException(com.apple.foundationdb.record.metadata.MetaDataException)

Example 13 with RecordMetaData

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

the class FDBMetaDataStore method saveAndSetCurrent.

/**
 * Build meta-data to use from Protobuf and save.
 * @param metaDataProto the Protobuf form of the meta-data to save
 * @return a future that completes when the save is done
 */
@Nonnull
public CompletableFuture<Void> saveAndSetCurrent(@Nonnull RecordMetaDataProto.MetaData metaDataProto) {
    RecordMetaData validatedMetaData = buildMetaData(metaDataProto, true);
    // Load even if not maintaining history so as to get compatibility upgrade before (over-)writing.
    CompletableFuture<Void> future = loadCurrentSerialized().thenApply(oldSerialized -> {
        if (oldSerialized != null) {
            RecordMetaDataProto.MetaData oldProto = parseMetaDataProto(oldSerialized);
            int oldVersion = oldProto.getVersion();
            if (metaDataProto.getVersion() <= oldVersion) {
                LOGGER.warn(KeyValueLogMessage.of("Meta-data version did not increase", subspaceProvider.logKey(), subspaceProvider.toString(context), LogMessageKeys.OLD, oldVersion, LogMessageKeys.NEW, metaDataProto.getVersion()));
                throw new MetaDataException("meta-data version must increase");
            }
            // Build the meta-data, but don't use the local file descriptor as this should validate the original descriptors
            // against each other.
            RecordMetaData oldMetaData = buildMetaData(oldProto, true, false);
            RecordMetaData newMetaData = buildMetaData(metaDataProto, true, false);
            evolutionValidator.validate(oldMetaData, newMetaData);
            if (maintainHistory) {
                SplitHelper.saveWithSplit(context, getSubspace(), HISTORY_KEY_PREFIX.add(oldVersion), oldSerialized, null);
            }
        }
        return null;
    });
    future = future.thenApply(vignore -> {
        recordMetaData = validatedMetaData;
        byte[] serialized = metaDataProto.toByteArray();
        SplitHelper.saveWithSplit(context, getSubspace(), CURRENT_KEY, serialized, null);
        if (cache != null) {
            cache.setCurrentVersion(context, recordMetaData.getVersion());
            addPendingCacheUpdate(recordMetaData);
            addPendingCacheUpdate(serialized);
        }
        return null;
    });
    return instrument(FDBStoreTimer.Events.SAVE_META_DATA, future);
}
Also used : MetaDataEvolutionValidator(com.apple.foundationdb.record.metadata.MetaDataEvolutionValidator) RecordMetaData(com.apple.foundationdb.record.RecordMetaData) SpotBugsSuppressWarnings(com.apple.foundationdb.annotation.SpotBugsSuppressWarnings) LogMessageKeys(com.apple.foundationdb.record.logging.LogMessageKeys) Descriptors(com.google.protobuf.Descriptors) LoggerFactory(org.slf4j.LoggerFactory) CompletableFuture(java.util.concurrent.CompletableFuture) AsyncUtil(com.apple.foundationdb.async.AsyncUtil) MetaDataException(com.apple.foundationdb.record.metadata.MetaDataException) Subspace(com.apple.foundationdb.subspace.Subspace) ArrayList(java.util.ArrayList) Tuple(com.apple.foundationdb.tuple.Tuple) KeyValueLogMessage(com.apple.foundationdb.record.logging.KeyValueLogMessage) RecordCoreException(com.apple.foundationdb.record.RecordCoreException) RecordMetaDataProto(com.apple.foundationdb.record.RecordMetaDataProto) RecordMetaDataOptionsProto(com.apple.foundationdb.record.RecordMetaDataOptionsProto) Nonnull(javax.annotation.Nonnull) Nullable(javax.annotation.Nullable) InvalidProtocolBufferException(com.google.protobuf.InvalidProtocolBufferException) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) Logger(org.slf4j.Logger) RecordMetaDataBuilder(com.apple.foundationdb.record.RecordMetaDataBuilder) RecordTypeBuilder(com.apple.foundationdb.record.metadata.RecordTypeBuilder) Consumer(java.util.function.Consumer) KeySpacePath(com.apple.foundationdb.record.provider.foundationdb.keyspace.KeySpacePath) List(java.util.List) RecordMetaDataProvider(com.apple.foundationdb.record.RecordMetaDataProvider) Index(com.apple.foundationdb.record.metadata.Index) ExtensionRegistry(com.google.protobuf.ExtensionRegistry) TupleHelpers(com.apple.foundationdb.tuple.TupleHelpers) API(com.apple.foundationdb.annotation.API) VisibleForTesting(com.google.common.annotations.VisibleForTesting) RecordMetaData(com.apple.foundationdb.record.RecordMetaData) RecordMetaDataProto(com.apple.foundationdb.record.RecordMetaDataProto) MetaDataException(com.apple.foundationdb.record.metadata.MetaDataException) Nonnull(javax.annotation.Nonnull)

Example 14 with RecordMetaData

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

the class JoinedRecordTypeBuilder method build.

@Nonnull
@Override
public JoinedRecordType build(@Nonnull RecordMetaData metaData, @Nonnull Descriptors.FileDescriptor fileDescriptor) {
    final List<JoinedRecordType.JoinConstituent> builtConstituents = getConstituents().stream().map(constituent -> constituent.build(metaData)).collect(Collectors.toList());
    final Descriptors.Descriptor descriptor = fileDescriptor.findMessageTypeByName(name);
    final KeyExpression primaryKey = buildPrimaryKey();
    final Map<String, JoinedRecordType.JoinConstituent> constituentsByName = builtConstituents.stream().collect(Collectors.toMap(JoinedRecordType.Constituent::getName, Function.identity()));
    final List<JoinedRecordType.Join> builtJoins = joins.stream().map(join -> join.build(constituentsByName)).collect(Collectors.toList());
    return new JoinedRecordType(metaData, descriptor, primaryKey, recordTypeKey, indexes, multiTypeIndexes, builtConstituents, builtJoins);
}
Also used : RecordMetaData(com.apple.foundationdb.record.RecordMetaData) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) LiteralKeyExpression(com.apple.foundationdb.record.metadata.expressions.LiteralKeyExpression) RecordMetaDataBuilder(com.apple.foundationdb.record.RecordMetaDataBuilder) Descriptors(com.google.protobuf.Descriptors) RecordCoreArgumentException(com.apple.foundationdb.record.RecordCoreArgumentException) Function(java.util.function.Function) Collectors(java.util.stream.Collectors) ArrayList(java.util.ArrayList) List(java.util.List) RecordMetaDataProto(com.apple.foundationdb.record.RecordMetaDataProto) Map(java.util.Map) API(com.apple.foundationdb.annotation.API) Nonnull(javax.annotation.Nonnull) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) LiteralKeyExpression(com.apple.foundationdb.record.metadata.expressions.LiteralKeyExpression) Descriptors(com.google.protobuf.Descriptors) Nonnull(javax.annotation.Nonnull)

Example 15 with RecordMetaData

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

the class OrderingProperty method fromIndexScanOrCoveringIndexScan.

@Nonnull
private static Optional<Ordering> fromIndexScanOrCoveringIndexScan(@Nonnull final PlanContext context, @Nonnull final RecordQueryPlan plan) {
    final RecordQueryIndexPlan recordQueryIndexPlan;
    if (plan instanceof RecordQueryIndexPlan) {
        recordQueryIndexPlan = (RecordQueryIndexPlan) plan;
    } else if (plan instanceof RecordQueryCoveringIndexPlan) {
        final RecordQueryPlanWithIndex planWithIndex = ((RecordQueryCoveringIndexPlan) plan).getIndexPlan();
        if (planWithIndex instanceof RecordQueryIndexPlan) {
            recordQueryIndexPlan = (RecordQueryIndexPlan) planWithIndex;
        } else {
            return Optional.empty();
        }
    } else {
        return Optional.empty();
    }
    final String indexName = recordQueryIndexPlan.getIndexName();
    final RecordMetaData metaData = context.getMetaData();
    final Index index = metaData.getIndex(indexName);
    final Collection<RecordType> recordTypesForIndex = metaData.recordTypesForIndex(index);
    final KeyExpression commonPrimaryKeyForIndex = RecordMetaData.commonPrimaryKey(recordTypesForIndex);
    final KeyExpression keyExpression = ValueIndexExpansionVisitor.fullKey(index, commonPrimaryKeyForIndex);
    final ScanComparisons scanComparisons = recordQueryIndexPlan.getComparisons();
    return fromKeyAndScanComparisons(keyExpression, scanComparisons, plan.isReverse(), index.isUnique());
}
Also used : RecordMetaData(com.apple.foundationdb.record.RecordMetaData) ScanComparisons(com.apple.foundationdb.record.query.plan.ScanComparisons) RecordType(com.apple.foundationdb.record.metadata.RecordType) RecordQueryIndexPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryIndexPlan) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) RecordQueryCoveringIndexPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryCoveringIndexPlan) RecordQueryPlanWithIndex(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlanWithIndex) RecordQueryPlanWithIndex(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlanWithIndex) Index(com.apple.foundationdb.record.metadata.Index) Nonnull(javax.annotation.Nonnull)

Aggregations

RecordMetaData (com.apple.foundationdb.record.RecordMetaData)168 Test (org.junit.jupiter.api.Test)130 RecordMetaDataBuilder (com.apple.foundationdb.record.RecordMetaDataBuilder)81 ParameterizedTest (org.junit.jupiter.params.ParameterizedTest)66 Nonnull (javax.annotation.Nonnull)47 Descriptors (com.google.protobuf.Descriptors)44 RecordMetaDataProto (com.apple.foundationdb.record.RecordMetaDataProto)39 MetaDataException (com.apple.foundationdb.record.metadata.MetaDataException)39 MetaDataProtoTest (com.apple.foundationdb.record.metadata.MetaDataProtoTest)38 Tuple (com.apple.foundationdb.tuple.Tuple)36 List (java.util.List)33 ArrayList (java.util.ArrayList)31 TestRecords1Proto (com.apple.foundationdb.record.TestRecords1Proto)30 Index (com.apple.foundationdb.record.metadata.Index)30 DescriptorProtos (com.google.protobuf.DescriptorProtos)30 Collectors (java.util.stream.Collectors)30 RecordCoreException (com.apple.foundationdb.record.RecordCoreException)27 ByteString (com.google.protobuf.ByteString)27 Assertions.assertNotNull (org.junit.jupiter.api.Assertions.assertNotNull)27 RecordMetaDataOptionsProto (com.apple.foundationdb.record.RecordMetaDataOptionsProto)26