Search in sources :

Example 21 with Index

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

the class IndexingByRecords method buildRangeOnly.

@Nonnull
private CompletableFuture<Tuple> buildRangeOnly(@Nonnull FDBRecordStore store, @Nonnull TupleRange range, boolean respectLimit, @Nullable AtomicLong recordsScanned) {
    validateSameMetadataOrThrow(store);
    Index index = common.getIndex();
    int limit = getLimit();
    final IndexMaintainer maintainer = store.getIndexMaintainer(index);
    final boolean isIdempotent = maintainer.isIdempotent();
    final ExecuteProperties.Builder executeProperties = ExecuteProperties.newBuilder().setIsolationLevel(isIdempotent ? IsolationLevel.SNAPSHOT : IsolationLevel.SERIALIZABLE);
    if (respectLimit) {
        // +1 allows continuation item
        executeProperties.setReturnedRowLimit(limit + 1);
    }
    final ScanProperties scanProperties = new ScanProperties(executeProperties.build());
    final RecordCursor<FDBStoredRecord<Message>> cursor = store.scanRecords(range, null, scanProperties);
    final AtomicBoolean hasMore = new AtomicBoolean(true);
    // Note: This runs all of the updates serially in order to avoid invoking a race condition
    // in the rank code that was causing incorrect results. If everything were thread safe,
    // a larger pipeline size would be possible.
    final AtomicReference<RecordCursorResult<FDBStoredRecord<Message>>> lastResult = new AtomicReference<>(RecordCursorResult.exhausted());
    return iterateRangeOnly(store, cursor, this::getRecordIfTypeMatch, lastResult, hasMore, recordsScanned, isIdempotent).thenApply(vignore -> hasMore.get() ? lastResult.get().get().getPrimaryKey() : range.getHigh());
}
Also used : KeyValueLogMessage(com.apple.foundationdb.record.logging.KeyValueLogMessage) Message(com.google.protobuf.Message) Index(com.apple.foundationdb.record.metadata.Index) RecordCursorResult(com.apple.foundationdb.record.RecordCursorResult) AtomicReference(java.util.concurrent.atomic.AtomicReference) ExecuteProperties(com.apple.foundationdb.record.ExecuteProperties) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) ScanProperties(com.apple.foundationdb.record.ScanProperties) Nonnull(javax.annotation.Nonnull)

Example 22 with Index

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

the class IndexingBase method setScrubberTypeOrThrow.

@Nonnull
private CompletableFuture<Void> setScrubberTypeOrThrow(FDBRecordStore store) {
    // HERE: The index must be readable, checked by the caller
    // if scrubber had already run and still have missing ranges, do nothing
    // else: clear ranges and overwrite type-stamp
    Transaction tr = store.getContext().ensureActive();
    IndexBuildProto.IndexBuildIndexingStamp indexingTypeStamp = getIndexingTypeStamp(store);
    validateOrThrowEx(indexingTypeStamp.getMethod().equals(IndexBuildProto.IndexBuildIndexingStamp.Method.SCRUB_REPAIR), "Not a scrubber type-stamp");
    // Note: the scrubbers do not support multi target (yet)
    final Index index = common.getIndex();
    final Subspace indexesRangeSubspace = indexScrubIndexRangeSubspace(store, index);
    final Subspace recordsRangeSubspace = indexScrubRecordsRangeSubspace(store, index);
    RangeSet indexRangeSet = new RangeSet(indexesRangeSubspace);
    RangeSet recordsRangeSet = new RangeSet(recordsRangeSubspace);
    AsyncIterator<Range> indexRanges = indexRangeSet.missingRanges(tr).iterator();
    AsyncIterator<Range> recordsRanges = recordsRangeSet.missingRanges(tr).iterator();
    return indexRanges.onHasNext().thenCompose(hasNextIndex -> {
        if (Boolean.FALSE.equals(hasNextIndex)) {
            // erase the 'ranges' data to allow a fresh index re-scrubbing.
            if (LOGGER.isInfoEnabled()) {
                LOGGER.info(KeyValueLogMessage.build("Reset scrubber's index range").addKeysAndValues(common.indexLogMessageKeyValues()).toString());
            }
            tr.clear(indexesRangeSubspace.range());
        }
        return recordsRanges.onHasNext().thenAccept(hasNextRecord -> {
            if (Boolean.FALSE.equals(hasNextRecord)) {
                // erase the 'ranges' data to allow a fresh records re-scrubbing.
                if (LOGGER.isInfoEnabled()) {
                    LOGGER.info(KeyValueLogMessage.build("Reset scrubber's records range").addKeysAndValues(common.indexLogMessageKeyValues()).toString());
                }
                tr.clear(recordsRangeSubspace.range());
            }
        });
    });
}
Also used : Transaction(com.apple.foundationdb.Transaction) IndexBuildProto(com.apple.foundationdb.record.IndexBuildProto) Subspace(com.apple.foundationdb.subspace.Subspace) RangeSet(com.apple.foundationdb.async.RangeSet) Index(com.apple.foundationdb.record.metadata.Index) Range(com.apple.foundationdb.Range) Nonnull(javax.annotation.Nonnull)

Example 23 with Index

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

the class RecordMetaData method toProto.

/**
 * Serializes the record meta-data to a <code>MetaData</code> proto message. This operates like
 * {@link #toProto()} except that any dependency in the excluded list is not included in the
 * serialized proto message. If the list is set to {@code null}, then all dependencies will be serialized
 * to the proto message including those that are execluded by default.
 *
 * @param excludedDependencies a list of dependencies not to include in the serialized proto
 * @return the serialized <code>MetaData</code> proto message
 * @throws KeyExpression.SerializationException on any serialization failures
 * @throws MetaDataException if this {@code RecordMetaData} was initialized with a
 *      {@linkplain RecordMetaDataBuilder#setLocalFileDescriptor(Descriptors.FileDescriptor) local file descriptor}
 * @see #toProto()
 */
@Nonnull
@SuppressWarnings("deprecation")
public RecordMetaDataProto.MetaData toProto(@Nullable Descriptors.FileDescriptor[] excludedDependencies) throws KeyExpression.SerializationException {
    if (usesLocalRecordsDescriptor) {
        throw new MetaDataException("cannot serialize meta-data with a local records descriptor to proto");
    }
    RecordMetaDataProto.MetaData.Builder builder = RecordMetaDataProto.MetaData.newBuilder();
    // Set the root records.
    builder.setRecords(recordsDescriptor.toProto());
    // Convert the exclusion list to a map
    Map<String, Descriptors.FileDescriptor> excludeMap = null;
    if (excludedDependencies != null) {
        excludeMap = new HashMap<>(excludedDependencies.length);
        for (Descriptors.FileDescriptor dependency : excludedDependencies) {
            excludeMap.put(dependency.getName(), dependency);
        }
    }
    // Add in the rest of dependencies.
    Map<String, Descriptors.FileDescriptor> allDependencies = new TreeMap<>();
    getDependencies(recordsDescriptor, allDependencies, excludeMap);
    for (Descriptors.FileDescriptor dependency : allDependencies.values()) {
        builder.addDependencies(dependency.toProto());
    }
    // Create builders for each index so that we can then add associated record types (etc.).
    Map<String, RecordMetaDataProto.Index.Builder> indexBuilders = new TreeMap<>();
    for (Map.Entry<String, Index> entry : indexes.entrySet()) {
        indexBuilders.put(entry.getKey(), entry.getValue().toProto().toBuilder());
    }
    for (RecordType recordType : getRecordTypes().values()) {
        // Add this record type to each appropriate index.
        for (Index index : recordType.getIndexes()) {
            indexBuilders.get(index.getName()).addRecordType(recordType.getName());
        }
        for (Index index : recordType.getMultiTypeIndexes()) {
            indexBuilders.get(index.getName()).addRecordType(recordType.getName());
        }
        RecordMetaDataProto.RecordType.Builder typeBuilder = builder.addRecordTypesBuilder().setName(recordType.getName()).setPrimaryKey(recordType.getPrimaryKey().toKeyExpression());
        if (recordType.getSinceVersion() != null) {
            typeBuilder.setSinceVersion(recordType.getSinceVersion());
        }
        if (recordType.hasExplicitRecordTypeKey()) {
            typeBuilder.setExplicitKey(LiteralKeyExpression.toProtoValue(recordType.getExplicitRecordTypeKey()));
        }
    }
    indexBuilders.values().forEach(builder::addIndexes);
    // Add in the former indexes.
    for (FormerIndex formerIndex : getFormerIndexes()) {
        builder.addFormerIndexes(formerIndex.toProto());
    }
    // Add in the final options.
    builder.setSplitLongRecords(splitLongRecords);
    builder.setStoreRecordVersions(storeRecordVersions);
    builder.setVersion(version);
    if (usesSubspaceKeyCounter()) {
        builder.setSubspaceKeyCounter(subspaceKeyCounter);
        builder.setUsesSubspaceKeyCounter(true);
    }
    if (recordCountKey != null) {
        builder.setRecordCountKey(recordCountKey.toKeyExpression());
    }
    for (SyntheticRecordType<?> syntheticRecordType : syntheticRecordTypes.values()) {
        if (syntheticRecordType instanceof JoinedRecordType) {
            builder.addJoinedRecordTypes(((JoinedRecordType) syntheticRecordType).toProto());
        }
    }
    return builder.build();
}
Also used : JoinedRecordType(com.apple.foundationdb.record.metadata.JoinedRecordType) FormerIndex(com.apple.foundationdb.record.metadata.FormerIndex) Index(com.apple.foundationdb.record.metadata.Index) TreeMap(java.util.TreeMap) MetaDataException(com.apple.foundationdb.record.metadata.MetaDataException) FormerIndex(com.apple.foundationdb.record.metadata.FormerIndex) JoinedRecordType(com.apple.foundationdb.record.metadata.JoinedRecordType) RecordType(com.apple.foundationdb.record.metadata.RecordType) SyntheticRecordType(com.apple.foundationdb.record.metadata.SyntheticRecordType) Descriptors(com.google.protobuf.Descriptors) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) TreeMap(java.util.TreeMap) Map(java.util.Map) Nonnull(javax.annotation.Nonnull)

Example 24 with Index

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

the class RecordMetaDataBuilder method removeIndex.

public void removeIndex(@Nonnull String name) {
    Index index = indexes.remove(name);
    if (index == null) {
        throw new MetaDataException("No index named " + name + " defined");
    }
    for (RecordTypeBuilder recordType : recordTypes.values()) {
        recordType.getIndexes().remove(index);
        recordType.getMultiTypeIndexes().remove(index);
    }
    universalIndexes.remove(name);
    formerIndexes.add(new FormerIndex(index.getSubspaceKey(), index.getAddedVersion(), ++version, name));
}
Also used : FormerIndex(com.apple.foundationdb.record.metadata.FormerIndex) FormerIndex(com.apple.foundationdb.record.metadata.FormerIndex) Index(com.apple.foundationdb.record.metadata.Index) SyntheticRecordTypeBuilder(com.apple.foundationdb.record.metadata.SyntheticRecordTypeBuilder) RecordTypeBuilder(com.apple.foundationdb.record.metadata.RecordTypeBuilder) JoinedRecordTypeBuilder(com.apple.foundationdb.record.metadata.JoinedRecordTypeBuilder) MetaDataException(com.apple.foundationdb.record.metadata.MetaDataException)

Example 25 with Index

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

the class RecordMetaDataBuilder method loadProtoExceptRecords.

@SuppressWarnings("deprecation")
private void loadProtoExceptRecords(@Nonnull RecordMetaDataProto.MetaData metaDataProto) {
    for (RecordMetaDataProto.Index indexProto : metaDataProto.getIndexesList()) {
        List<RecordTypeBuilder> recordTypeBuilders = new ArrayList<>(indexProto.getRecordTypeCount());
        for (String recordTypeName : indexProto.getRecordTypeList()) {
            recordTypeBuilders.add(getRecordType(recordTypeName));
        }
        try {
            addMultiTypeIndex(recordTypeBuilders, new Index(indexProto));
        } catch (KeyExpression.DeserializationException e) {
            throw new MetaDataProtoDeserializationException(e);
        }
    }
    for (RecordMetaDataProto.RecordType typeProto : metaDataProto.getRecordTypesList()) {
        RecordTypeBuilder typeBuilder = getRecordType(typeProto.getName());
        if (typeProto.hasPrimaryKey()) {
            try {
                typeBuilder.setPrimaryKey(KeyExpression.fromProto(typeProto.getPrimaryKey()));
            } catch (KeyExpression.DeserializationException e) {
                throw new MetaDataProtoDeserializationException(e);
            }
        }
        if (typeProto.hasSinceVersion()) {
            typeBuilder.setSinceVersion(typeProto.getSinceVersion());
        }
        if (typeProto.hasExplicitKey()) {
            typeBuilder.setRecordTypeKey(LiteralKeyExpression.fromProtoValue(typeProto.getExplicitKey()));
        }
    }
    if (metaDataProto.hasSplitLongRecords()) {
        splitLongRecords = metaDataProto.getSplitLongRecords();
    }
    if (metaDataProto.hasStoreRecordVersions()) {
        storeRecordVersions = metaDataProto.getStoreRecordVersions();
    }
    for (RecordMetaDataProto.FormerIndex formerIndex : metaDataProto.getFormerIndexesList()) {
        formerIndexes.add(new FormerIndex(formerIndex));
    }
    if (metaDataProto.hasRecordCountKey()) {
        try {
            recordCountKey = KeyExpression.fromProto(metaDataProto.getRecordCountKey());
        } catch (KeyExpression.DeserializationException e) {
            throw new MetaDataProtoDeserializationException(e);
        }
    }
    if (metaDataProto.hasVersion()) {
        version = metaDataProto.getVersion();
    }
    for (RecordMetaDataProto.JoinedRecordType joinedProto : metaDataProto.getJoinedRecordTypesList()) {
        JoinedRecordTypeBuilder typeBuilder = new JoinedRecordTypeBuilder(joinedProto, this);
        syntheticRecordTypes.put(typeBuilder.getName(), typeBuilder);
    }
}
Also used : ArrayList(java.util.ArrayList) LiteralKeyExpression(com.apple.foundationdb.record.metadata.expressions.LiteralKeyExpression) FieldKeyExpression(com.apple.foundationdb.record.metadata.expressions.FieldKeyExpression) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) FormerIndex(com.apple.foundationdb.record.metadata.FormerIndex) Index(com.apple.foundationdb.record.metadata.Index) SyntheticRecordTypeBuilder(com.apple.foundationdb.record.metadata.SyntheticRecordTypeBuilder) RecordTypeBuilder(com.apple.foundationdb.record.metadata.RecordTypeBuilder) JoinedRecordTypeBuilder(com.apple.foundationdb.record.metadata.JoinedRecordTypeBuilder) JoinedRecordTypeBuilder(com.apple.foundationdb.record.metadata.JoinedRecordTypeBuilder) FormerIndex(com.apple.foundationdb.record.metadata.FormerIndex)

Aggregations

Index (com.apple.foundationdb.record.metadata.Index)347 Test (org.junit.jupiter.api.Test)262 List (java.util.List)183 IndexTypes (com.apple.foundationdb.record.metadata.IndexTypes)178 Assertions.assertEquals (org.junit.jupiter.api.Assertions.assertEquals)171 Collections (java.util.Collections)168 Message (com.google.protobuf.Message)166 Tags (com.apple.test.Tags)156 Tag (org.junit.jupiter.api.Tag)156 Expressions.field (com.apple.foundationdb.record.metadata.Key.Expressions.field)155 Query (com.apple.foundationdb.record.query.expressions.Query)151 MatcherAssert.assertThat (org.hamcrest.MatcherAssert.assertThat)150 Nonnull (javax.annotation.Nonnull)147 Key (com.apple.foundationdb.record.metadata.Key)143 Tuple (com.apple.foundationdb.tuple.Tuple)142 Arrays (java.util.Arrays)139 RecordCoreException (com.apple.foundationdb.record.RecordCoreException)138 RecordQuery (com.apple.foundationdb.record.query.RecordQuery)138 ArrayList (java.util.ArrayList)135 Assertions.assertTrue (org.junit.jupiter.api.Assertions.assertTrue)134