Search in sources :

Example 21 with Hash

use of org.projectnessie.versioned.Hash in project nessie by projectnessie.

the class AbstractDatabaseAdapter method checkForModifiedKeysBetweenExpectedAndCurrentCommit.

/**
 * If the current HEAD of the target branch for a commit/transplant/merge is not equal to the
 * expected/reference HEAD, verify that there is no conflict, like keys in the operations of the
 * commit(s) contained in keys of the commits 'expectedHead (excluding) .. currentHead
 * (including)'.
 */
protected void checkForModifiedKeysBetweenExpectedAndCurrentCommit(OP_CONTEXT ctx, CommitAttempt commitAttempt, Hash branchHead, List<String> mismatches) throws ReferenceNotFoundException {
    if (commitAttempt.getExpectedHead().isPresent()) {
        Hash expectedHead = commitAttempt.getExpectedHead().get();
        if (!expectedHead.equals(branchHead)) {
            Set<Key> operationKeys = new HashSet<>();
            operationKeys.addAll(commitAttempt.getDeletes());
            operationKeys.addAll(commitAttempt.getUnchanged());
            commitAttempt.getPuts().stream().map(KeyWithBytes::getKey).forEach(operationKeys::add);
            boolean sinceSeen = checkConflictingKeysForCommit(ctx, branchHead, expectedHead, operationKeys, mismatches::add);
            // branch.
            if (!sinceSeen && !expectedHead.equals(NO_ANCESTOR)) {
                throw hashNotFound(commitAttempt.getCommitToBranch(), expectedHead);
            }
        }
    }
}
Also used : Hash(org.projectnessie.versioned.Hash) DatabaseAdapterUtil.randomHash(org.projectnessie.versioned.persist.adapter.spi.DatabaseAdapterUtil.randomHash) DatabaseAdapterUtil.hashKey(org.projectnessie.versioned.persist.adapter.spi.DatabaseAdapterUtil.hashKey) Key(org.projectnessie.versioned.Key) HashSet(java.util.HashSet)

Example 22 with Hash

use of org.projectnessie.versioned.Hash in project nessie by projectnessie.

the class AbstractDatabaseAdapter method findCommonAncestor.

protected <R> R findCommonAncestor(OP_CONTEXT ctx, Hash from, CommonAncestorState state, BiFunction<Integer, Hash, R> result) {
    Iterator<Hash> fromLog = Spliterators.iterator(readCommitLogHashes(ctx, from));
    List<Hash> fromCommitHashes = new ArrayList<>();
    while (true) {
        boolean anyFetched = false;
        for (int i = 0; i < config.getParentsPerCommit(); i++) {
            if (state.fetchNext()) {
                anyFetched = true;
            }
            if (fromLog.hasNext()) {
                fromCommitHashes.add(fromLog.next());
                anyFetched = true;
            }
        }
        if (!anyFetched) {
            return null;
        }
        for (int diffOnFrom = 0; diffOnFrom < fromCommitHashes.size(); diffOnFrom++) {
            Hash f = fromCommitHashes.get(diffOnFrom);
            if (state.contains(f)) {
                return result.apply(diffOnFrom, f);
            }
        }
    }
}
Also used : ArrayList(java.util.ArrayList) Hash(org.projectnessie.versioned.Hash) DatabaseAdapterUtil.randomHash(org.projectnessie.versioned.persist.adapter.spi.DatabaseAdapterUtil.randomHash)

Example 23 with Hash

use of org.projectnessie.versioned.Hash in project nessie by projectnessie.

the class AbstractDatabaseAdapter method buildIndividualCommit.

/**
 * Builds a {@link CommitLogEntry} using the given values. This function also includes a {@link
 * KeyList}, if triggered by the values of {@code currentKeyListDistance} and {@link
 * DatabaseAdapterConfig#getKeyListDistance()}, so read operations may happen.
 */
protected CommitLogEntry buildIndividualCommit(OP_CONTEXT ctx, long timeInMicros, List<Hash> parentHashes, long commitSeq, ByteString commitMeta, List<KeyWithBytes> puts, List<Key> deletes, int currentKeyListDistance, Consumer<Hash> newKeyLists, @Nonnull Function<Hash, CommitLogEntry> inMemoryCommits) throws ReferenceNotFoundException {
    Hash commitHash = individualCommitHash(parentHashes, commitMeta, puts, deletes);
    int keyListDistance = currentKeyListDistance + 1;
    CommitLogEntry entry = CommitLogEntry.of(timeInMicros, commitHash, commitSeq, parentHashes, commitMeta, puts, deletes, keyListDistance, null, Collections.emptyList());
    if (keyListDistance >= config.getKeyListDistance()) {
        entry = buildKeyList(ctx, entry, newKeyLists, inMemoryCommits);
    }
    return entry;
}
Also used : CommitLogEntry(org.projectnessie.versioned.persist.adapter.CommitLogEntry) ImmutableCommitLogEntry(org.projectnessie.versioned.persist.adapter.ImmutableCommitLogEntry) Hash(org.projectnessie.versioned.Hash) DatabaseAdapterUtil.randomHash(org.projectnessie.versioned.persist.adapter.spi.DatabaseAdapterUtil.randomHash)

Example 24 with Hash

use of org.projectnessie.versioned.Hash in project nessie by projectnessie.

the class AbstractDatabaseAdapter method findCommonAncestor.

/**
 * Finds the common-ancestor of two commit-log-entries. If no common-ancestor is found, throws a
 * {@link ReferenceConflictException} or. Otherwise this method returns the hash of the
 * common-ancestor.
 */
protected Hash findCommonAncestor(OP_CONTEXT ctx, Hash from, NamedRef toBranch, Hash toHead) throws ReferenceConflictException {
    // TODO this implementation requires guardrails:
    // max number of "to"-commits to fetch, max number of "from"-commits to fetch,
    // both impact the cost (CPU, memory, I/O) of a merge operation.
    CommonAncestorState commonAncestorState = new CommonAncestorState(ctx, toHead, false);
    Hash commonAncestorHash = findCommonAncestor(ctx, from, commonAncestorState, (dist, hash) -> hash);
    if (commonAncestorHash == null) {
        throw new ReferenceConflictException(String.format("No common ancestor found for merge of '%s' into branch '%s'", from, toBranch.getName()));
    }
    return commonAncestorHash;
}
Also used : ReferenceConflictException(org.projectnessie.versioned.ReferenceConflictException) Hash(org.projectnessie.versioned.Hash) DatabaseAdapterUtil.randomHash(org.projectnessie.versioned.persist.adapter.spi.DatabaseAdapterUtil.randomHash)

Example 25 with Hash

use of org.projectnessie.versioned.Hash in project nessie by projectnessie.

the class AbstractDatabaseAdapter method namedRefsWithDefaultBranchRelatedInfo.

/**
 * If necessary based on the given {@link GetNamedRefsParams}, updates the returned {@link
 * ReferenceInfo}s with the common-ancestor of the named reference and the default branch and the
 * number of commits behind/ahead compared to the default branch.
 *
 * <p>The common ancestor and/or information of commits behind/ahead is meaningless ({@code null})
 * for the default branch. Both fields are also {@code null} if the named reference points to the
 * {@link #noAncestorHash()} (beginning of time).
 */
protected Stream<ReferenceInfo<ByteString>> namedRefsWithDefaultBranchRelatedInfo(OP_CONTEXT ctx, GetNamedRefsParams params, Stream<ReferenceInfo<ByteString>> refs, Hash defaultBranchHead) {
    if (defaultBranchHead == null) {
        // No enhancement of common ancestor and/or commits behind/ahead.
        return refs;
    }
    CommonAncestorState commonAncestorState = new CommonAncestorState(ctx, defaultBranchHead, params.getBranchRetrieveOptions().isComputeAheadBehind() || params.getTagRetrieveOptions().isComputeAheadBehind());
    return refs.map(ref -> {
        if (ref.getNamedRef().equals(params.getBaseReference())) {
            return ref;
        }
        RetrieveOptions retrieveOptions = namedRefsRetrieveOptionsForReference(params, ref);
        ReferenceInfo<ByteString> updated = namedRefsRequiresBaseReference(retrieveOptions) ? findCommonAncestor(ctx, ref.getHash(), commonAncestorState, (diffOnFrom, hash) -> {
            ReferenceInfo<ByteString> newRef = ref;
            if (retrieveOptions.isComputeCommonAncestor()) {
                newRef = newRef.withCommonAncestor(hash);
            }
            if (retrieveOptions.isComputeAheadBehind()) {
                int behind = commonAncestorState.indexOf(hash);
                CommitsAheadBehind aheadBehind = CommitsAheadBehind.of(diffOnFrom, behind);
                newRef = newRef.withAheadBehind(aheadBehind);
            }
            return newRef;
        }) : null;
        return updated != null ? updated : ref;
    });
}
Also used : Spliterators(java.util.Spliterators) BiFunction(java.util.function.BiFunction) DatabaseAdapterUtil.referenceNotFound(org.projectnessie.versioned.persist.adapter.spi.DatabaseAdapterUtil.referenceNotFound) KeyListEntity(org.projectnessie.versioned.persist.adapter.KeyListEntity) DatabaseAdapterUtil.takeUntilExcludeLast(org.projectnessie.versioned.persist.adapter.spi.DatabaseAdapterUtil.takeUntilExcludeLast) GetNamedRefsParams(org.projectnessie.versioned.GetNamedRefsParams) DatabaseAdapterMetrics.tryLoopFinished(org.projectnessie.versioned.persist.adapter.spi.DatabaseAdapterMetrics.tryLoopFinished) CommitAttempt(org.projectnessie.versioned.persist.adapter.CommitAttempt) Map(java.util.Map) ContentVariant(org.projectnessie.versioned.persist.adapter.ContentVariant) DatabaseAdapter(org.projectnessie.versioned.persist.adapter.DatabaseAdapter) DatabaseAdapterUtil.hashKey(org.projectnessie.versioned.persist.adapter.spi.DatabaseAdapterUtil.hashKey) NamedRef(org.projectnessie.versioned.NamedRef) Predicate(java.util.function.Predicate) Collection(java.util.Collection) Set(java.util.Set) DatabaseAdapterUtil.takeUntilIncludeLast(org.projectnessie.versioned.persist.adapter.spi.DatabaseAdapterUtil.takeUntilIncludeLast) Instant(java.time.Instant) Collectors(java.util.stream.Collectors) StandardCharsets(java.nio.charset.StandardCharsets) DatabaseAdapterUtil.newHasher(org.projectnessie.versioned.persist.adapter.spi.DatabaseAdapterUtil.newHasher) ByteString(com.google.protobuf.ByteString) Objects(java.util.Objects) BranchName(org.projectnessie.versioned.BranchName) ReferenceConflictException(org.projectnessie.versioned.ReferenceConflictException) List(java.util.List) KeyList(org.projectnessie.versioned.persist.adapter.KeyList) Stream(java.util.stream.Stream) Difference(org.projectnessie.versioned.persist.adapter.Difference) Entry(java.util.Map.Entry) DatabaseAdapterConfig(org.projectnessie.versioned.persist.adapter.DatabaseAdapterConfig) Optional(java.util.Optional) Spliterator(java.util.Spliterator) IntStream(java.util.stream.IntStream) AbstractSpliterator(java.util.Spliterators.AbstractSpliterator) NANOSECONDS(java.util.concurrent.TimeUnit.NANOSECONDS) RefLogNotFoundException(org.projectnessie.versioned.RefLogNotFoundException) TagName(org.projectnessie.versioned.TagName) KeyListEntry(org.projectnessie.versioned.persist.adapter.KeyListEntry) HashMap(java.util.HashMap) Callable(java.util.concurrent.Callable) Function(java.util.function.Function) UnsafeByteOperations(com.google.protobuf.UnsafeByteOperations) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) KeyFilterPredicate(org.projectnessie.versioned.persist.adapter.KeyFilterPredicate) RefLog(org.projectnessie.versioned.persist.adapter.RefLog) CommitLogEntry(org.projectnessie.versioned.persist.adapter.CommitLogEntry) StreamSupport(java.util.stream.StreamSupport) Hasher(com.google.common.hash.Hasher) Nonnull(javax.annotation.Nonnull) ContentVariantSupplier(org.projectnessie.versioned.persist.adapter.ContentVariantSupplier) Iterator(java.util.Iterator) Hash(org.projectnessie.versioned.Hash) Traced.trace(org.projectnessie.versioned.persist.adapter.spi.Traced.trace) ALLOW_ALL(org.projectnessie.versioned.persist.adapter.KeyFilterPredicate.ALLOW_ALL) DatabaseAdapterUtil.hashNotFound(org.projectnessie.versioned.persist.adapter.spi.DatabaseAdapterUtil.hashNotFound) Key(org.projectnessie.versioned.Key) ReferenceNotFoundException(org.projectnessie.versioned.ReferenceNotFoundException) KeyWithBytes(org.projectnessie.versioned.persist.adapter.KeyWithBytes) DatabaseAdapterUtil.randomHash(org.projectnessie.versioned.persist.adapter.spi.DatabaseAdapterUtil.randomHash) RetrieveOptions(org.projectnessie.versioned.GetNamedRefsParams.RetrieveOptions) CommitsAheadBehind(org.projectnessie.versioned.ReferenceInfo.CommitsAheadBehind) TimeUnit(java.util.concurrent.TimeUnit) Consumer(java.util.function.Consumer) ContentAndState(org.projectnessie.versioned.persist.adapter.ContentAndState) ImmutableCommitLogEntry(org.projectnessie.versioned.persist.adapter.ImmutableCommitLogEntry) ReferenceInfo(org.projectnessie.versioned.ReferenceInfo) Preconditions(com.google.common.base.Preconditions) Diff(org.projectnessie.versioned.Diff) ImmutableReferenceInfo(org.projectnessie.versioned.ImmutableReferenceInfo) Collections(java.util.Collections) ContentId(org.projectnessie.versioned.persist.adapter.ContentId) ImmutableKeyList(org.projectnessie.versioned.persist.adapter.ImmutableKeyList) ByteString(com.google.protobuf.ByteString) CommitsAheadBehind(org.projectnessie.versioned.ReferenceInfo.CommitsAheadBehind) RetrieveOptions(org.projectnessie.versioned.GetNamedRefsParams.RetrieveOptions) ReferenceInfo(org.projectnessie.versioned.ReferenceInfo) ImmutableReferenceInfo(org.projectnessie.versioned.ImmutableReferenceInfo)

Aggregations

Hash (org.projectnessie.versioned.Hash)99 BranchName (org.projectnessie.versioned.BranchName)49 DatabaseAdapterUtil.randomHash (org.projectnessie.versioned.persist.adapter.spi.DatabaseAdapterUtil.randomHash)44 ReferenceConflictException (org.projectnessie.versioned.ReferenceConflictException)36 Test (org.junit.jupiter.api.Test)33 DatabaseAdapterUtil.verifyExpectedHash (org.projectnessie.versioned.persist.adapter.spi.DatabaseAdapterUtil.verifyExpectedHash)30 ByteString (com.google.protobuf.ByteString)28 ReferenceNotFoundException (org.projectnessie.versioned.ReferenceNotFoundException)27 Key (org.projectnessie.versioned.Key)25 CommitLogEntry (org.projectnessie.versioned.persist.adapter.CommitLogEntry)23 ArrayList (java.util.ArrayList)20 RefLogNotFoundException (org.projectnessie.versioned.RefLogNotFoundException)20 Stream (java.util.stream.Stream)19 Collectors (java.util.stream.Collectors)17 TagName (org.projectnessie.versioned.TagName)17 HashMap (java.util.HashMap)16 Optional (java.util.Optional)16 ReferenceAlreadyExistsException (org.projectnessie.versioned.ReferenceAlreadyExistsException)16 ReferenceInfo (org.projectnessie.versioned.ReferenceInfo)16 Collections (java.util.Collections)15