use of org.projectnessie.versioned.ReferenceConflictException in project nessie by projectnessie.
the class TxDatabaseAdapter method assign.
@Override
public void assign(NamedRef assignee, Optional<Hash> expectedHead, Hash assignTo) throws ReferenceNotFoundException, ReferenceConflictException {
try {
opLoop("assignRef", assignee, true, (conn, assigneeHead) -> {
assigneeHead = fetchNamedRefHead(conn, assignee);
verifyExpectedHash(assigneeHead, assignee, expectedHead);
if (!NO_ANCESTOR.equals(assignTo) && fetchFromCommitLog(conn, assignTo) == null) {
throw referenceNotFound(assignTo);
}
Hash resultHash = tryMoveNamedReference(conn, assignee, assigneeHead, assignTo);
commitRefLog(conn, commitTimeInMicros(), assignTo, assignee, RefLogEntry.Operation.ASSIGN_REFERENCE, Collections.singletonList(assigneeHead));
return resultHash;
}, () -> assignConflictMessage("Conflict", assignee, expectedHead, assignTo), () -> assignConflictMessage("Retry-Failure", assignee, expectedHead, assignTo));
} catch (ReferenceNotFoundException | ReferenceConflictException | RuntimeException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
use of org.projectnessie.versioned.ReferenceConflictException in project nessie by projectnessie.
the class NonTransactionalDatabaseAdapter method commit.
@Override
public Hash commit(CommitAttempt commitAttempt) throws ReferenceConflictException, ReferenceNotFoundException {
try {
return casOpLoop("commit", commitAttempt.getCommitToBranch(), CasOpVariant.COMMIT, (ctx, pointer, x, newKeyLists) -> {
Hash branchHead = branchHead(pointer, commitAttempt.getCommitToBranch());
long timeInMicros = commitTimeInMicros();
CommitLogEntry newBranchCommit = commitAttempt(ctx, timeInMicros, branchHead, commitAttempt, newKeyLists);
GlobalStateLogEntry newGlobalHead = writeGlobalCommit(ctx, timeInMicros, pointer, commitAttempt.getGlobal().entrySet().stream().map(e -> ContentIdAndBytes.of(e.getKey(), e.getValue())).collect(Collectors.toList()));
RefLogEntry newRefLog = writeRefLogEntry(ctx, pointer, commitAttempt.getCommitToBranch().getName(), RefLogEntry.RefType.Branch, newBranchCommit.getHash(), RefLogEntry.Operation.COMMIT, timeInMicros, Collections.emptyList());
return updateGlobalStatePointer(commitAttempt.getCommitToBranch(), pointer, newBranchCommit.getHash(), newGlobalHead, newRefLog);
}, () -> commitConflictMessage("Retry-Failure", commitAttempt.getCommitToBranch(), commitAttempt.getExpectedHead()));
} catch (ReferenceNotFoundException | ReferenceConflictException | RuntimeException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
use of org.projectnessie.versioned.ReferenceConflictException in project nessie by projectnessie.
the class NonTransactionalDatabaseAdapter method delete.
@Override
public void delete(NamedRef reference, Optional<Hash> expectedHead) throws ReferenceNotFoundException, ReferenceConflictException {
try {
casOpLoop("deleteRef", reference, CasOpVariant.DELETE_REF, (ctx, pointer, branchCommits, newKeyLists) -> {
Hash branchHead = branchHead(pointer, reference);
verifyExpectedHash(branchHead, reference, expectedHead);
GlobalStateLogEntry newGlobalHead = noopGlobalLogEntry(ctx, pointer);
RefLogEntry.RefType refType = reference instanceof TagName ? RefLogEntry.RefType.Tag : RefLogEntry.RefType.Branch;
RefLogEntry newRefLog = writeRefLogEntry(ctx, pointer, reference.getName(), refType, branchHead, RefLogEntry.Operation.DELETE_REFERENCE, commitTimeInMicros(), Collections.emptyList());
return updateGlobalStatePointer(reference, pointer, null, newGlobalHead, newRefLog);
}, () -> deleteConflictMessage("Retry-Failure", reference, expectedHead));
} catch (ReferenceNotFoundException | ReferenceConflictException | RuntimeException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
use of org.projectnessie.versioned.ReferenceConflictException in project nessie by projectnessie.
the class NonTransactionalDatabaseAdapter method initializeRepo.
@Override
public void initializeRepo(String defaultBranchName) {
NonTransactionalOperationContext ctx = NON_TRANSACTIONAL_OPERATION_CONTEXT;
if (fetchGlobalPointer(ctx) == null) {
GlobalStateLogEntry globalHead;
RefLogEntry newRefLog;
try {
long timeInMicros = commitTimeInMicros();
GlobalStatePointer dummyPointer = GlobalStatePointer.newBuilder().setGlobalId(NO_ANCESTOR.asBytes()).addGlobalParentsInclHead(NO_ANCESTOR.asBytes()).setRefLogId(NO_ANCESTOR.asBytes()).addRefLogParentsInclHead(NO_ANCESTOR.asBytes()).build();
globalHead = writeGlobalCommit(ctx, timeInMicros, dummyPointer, Collections.emptyList());
newRefLog = writeRefLogEntry(ctx, dummyPointer, defaultBranchName, RefLogEntry.RefType.Branch, NO_ANCESTOR, RefLogEntry.Operation.CREATE_REFERENCE, commitTimeInMicros(), Collections.emptyList());
} catch (ReferenceConflictException e) {
throw new RuntimeException(e);
}
unsafeWriteGlobalPointer(ctx, GlobalStatePointer.newBuilder().setGlobalId(globalHead.getId()).addNamedReferences(NamedReference.newBuilder().setName(defaultBranchName).setRef(RefPointer.newBuilder().setType(Type.Branch).setHash(NO_ANCESTOR.asBytes()))).setRefLogId(newRefLog.getRefLogId()).addRefLogParentsInclHead(newRefLog.getRefLogId()).addRefLogParentsInclHead(NO_ANCESTOR.asBytes()).addGlobalParentsInclHead(globalHead.getId()).addGlobalParentsInclHead(NO_ANCESTOR.asBytes()).build());
}
}
use of org.projectnessie.versioned.ReferenceConflictException in project nessie by projectnessie.
the class AbstractDatabaseAdapter method mergeAttempt.
/**
* Logic implementation of a merge-attempt.
*
* @param ctx technical operation context
* @param from merge-from commit
* @param toBranch merge-into reference with expected hash of HEAD
* @param expectedHead if present, {@code toBranch}'s current HEAD must be equal to this value
* @param toHead current HEAD of {@code toBranch}
* @param branchCommits consumer for the individual commits to merge
* @param newKeyLists consumer for optimistically written {@link KeyListEntity}s
* @param rewriteMetadata function to rewrite the commit-metadata for copied commits
* @return hash of the last commit-log-entry written to {@code toBranch}
*/
protected Hash mergeAttempt(OP_CONTEXT ctx, long timeInMicros, Hash from, BranchName toBranch, Optional<Hash> expectedHead, Hash toHead, Consumer<Hash> branchCommits, Consumer<Hash> newKeyLists, Function<ByteString, ByteString> rewriteMetadata) throws ReferenceNotFoundException, ReferenceConflictException {
validateHashExists(ctx, from);
// 1. ensure 'expectedHash' is a parent of HEAD-of-'toBranch'
hashOnRef(ctx, toBranch, expectedHead, toHead);
// 2. find nearest common-ancestor between 'from' + 'fromHash'
Hash commonAncestor = findCommonAncestor(ctx, from, toBranch, toHead);
// 3. Collect commit-log-entries
List<CommitLogEntry> toEntriesReverseChronological = takeUntilExcludeLast(readCommitLogStream(ctx, toHead), e -> e.getHash().equals(commonAncestor)).collect(Collectors.toList());
Collections.reverse(toEntriesReverseChronological);
List<CommitLogEntry> commitsToMergeChronological = takeUntilExcludeLast(readCommitLogStream(ctx, from), e -> e.getHash().equals(commonAncestor)).collect(Collectors.toList());
if (commitsToMergeChronological.isEmpty()) {
// Nothing to merge, shortcut
throw new IllegalArgumentException(String.format("No hashes to merge from '%s' onto '%s' @ '%s'.", from.asString(), toBranch.getName(), toHead));
}
// 4. Collect modified keys.
Set<Key> keysTouchedOnTarget = collectModifiedKeys(toEntriesReverseChronological);
// 5. check for key-collisions
checkForKeyCollisions(ctx, toHead, keysTouchedOnTarget, commitsToMergeChronological);
// (no need to verify the global states during a transplant)
// 6. re-apply commits in 'sequenceToTransplant' onto 'targetBranch'
toHead = copyCommits(ctx, timeInMicros, toHead, commitsToMergeChronological, newKeyLists, rewriteMetadata);
// 7. Write commits
commitsToMergeChronological.stream().map(CommitLogEntry::getHash).forEach(branchCommits);
writeMultipleCommits(ctx, commitsToMergeChronological);
return toHead;
}
Aggregations