Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

An workaround for conflict resolve failure #1087

Open
wants to merge 2 commits into
base: release/hydrogen
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions LiteCore/RevTrees/RevTree.cc
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,28 @@ void RevTree::resetConflictSequence(const Rev* winningRev) {
return false;
}

bool RevTree::ensureConflictStateConsistent() {
if (hasConflict()) {
sort();
bool recovered = false;
// _revs[0] is current rev after sort
for (auto rev = _revs.begin() + 1; rev != _revs.end(); rev++) {
auto f = (*rev)->flags;
// a undeleted, non-closed, unconflict leaf rev
if ((f & Rev::kLeaf) &&
!(f & Rev::kClosed) &&
!(f & Rev::kDeleted) &&
!(f & Rev::kIsConflict)) {
(*rev)->addFlag(Rev::kIsConflict);
recovered = true;
}
}
_changed |= recovered;
return recovered;
}
return false;
}

void RevTree::saved(sequence_t newSequence) {
for (Rev *rev : _revs) {
rev->clearFlag(Rev::kNew);
Expand Down
9 changes: 9 additions & 0 deletions LiteCore/RevTrees/RevTree.hh
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,15 @@ namespace litecore {
bool hasConflict() const;
bool hasNewRevisions() const;

/// For unknown reason, sometimes the rev tree would come into an inconsistent state,
/// in which some conflicted leaf revs are not tagged conflict.
/// The method is a workaround for the problem. It tag those unclosed, non-current
/// leaves as conflict, solving the problem regardless of its real cause.
///
/// Return true if it was recovered from inconsistent state
/// Return false otherwise
bool ensureConflictStateConsistent();

/// Given an array of revision IDs in consecutive descending-generation order,
/// finds the first one that exists in this tree. Returns:
/// * {rev, index} if a common ancestor was found;
Expand Down
3 changes: 3 additions & 0 deletions LiteCore/RevTrees/VersionedDocument.cc
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,9 @@ namespace litecore {
}

VersionedDocument::SaveResult VersionedDocument::save(Transaction& transaction) {
if (_usuallyFalse(ensureConflictStateConsistent())) {
Warn("Document '%.*s' recovered from inconsistent state", SPLAT(docID()));
}
if (!_changed)
return kNoNewSequence;
updateMeta();
Expand Down
2 changes: 2 additions & 0 deletions LiteCore/RevTrees/VersionedDocument.hh
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
#include "RevTree.hh"
#include "Record.hh"
#include "Doc.hh"
#include "Logging.hh"
#include "StringUtil.hh"
#include <memory>
#include <vector>

Expand Down