Share common prefix search in addWriteRange
This commit is contained in:
@@ -1396,46 +1396,87 @@ void destroyTree(Node *root) {
|
||||
void addWriteRange(Node *&root, int64_t oldestVersion,
|
||||
const ConflictSet::WriteRange &w) {
|
||||
|
||||
auto *begin = insert(&root, std::span<const uint8_t>(w.begin.p, w.begin.len),
|
||||
w.writeVersion, true);
|
||||
auto begin = std::span<const uint8_t>(w.begin.p, w.begin.len);
|
||||
auto end = std::span<const uint8_t>(w.end.p, w.end.len);
|
||||
|
||||
const bool insertedBegin = !std::exchange(begin->entryPresent, true);
|
||||
int lcp = longestCommonPrefix(begin.data(), end.data(),
|
||||
std::min(begin.size(), end.size()));
|
||||
auto remaining = begin.subspan(0, lcp);
|
||||
|
||||
auto *n = root;
|
||||
|
||||
for (;;) {
|
||||
if (int(remaining.size()) < n->partialKeyLen + 1) {
|
||||
break;
|
||||
}
|
||||
int i = 0;
|
||||
for (; i < n->partialKeyLen; ++i) {
|
||||
if (remaining[i] != n->partialKey[i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i != n->partialKeyLen) {
|
||||
break;
|
||||
}
|
||||
|
||||
int c = getChildGeq(n, remaining[n->partialKeyLen]);
|
||||
if (c != remaining[n->partialKeyLen]) {
|
||||
break;
|
||||
}
|
||||
|
||||
n = getChildExists(n, c);
|
||||
remaining = remaining.subspan(n->partialKeyLen + 1,
|
||||
remaining.size() - (n->partialKeyLen + 1));
|
||||
}
|
||||
|
||||
Node **useAsRoot = n->parent == nullptr
|
||||
? &root
|
||||
: &getChildExists(n->parent, n->parentsIndex);
|
||||
|
||||
int consumed = lcp - remaining.size();
|
||||
|
||||
consumed = 0;
|
||||
useAsRoot = &root;
|
||||
|
||||
begin = begin.subspan(consumed, begin.size() - consumed);
|
||||
end = end.subspan(consumed, end.size() - consumed);
|
||||
|
||||
auto *beginNode = insert(useAsRoot, begin, w.writeVersion, true);
|
||||
|
||||
const bool insertedBegin = !std::exchange(beginNode->entryPresent, true);
|
||||
|
||||
if (insertedBegin) {
|
||||
auto *p = nextLogical(begin);
|
||||
begin->entry.rangeVersion =
|
||||
auto *p = nextLogical(beginNode);
|
||||
beginNode->entry.rangeVersion =
|
||||
p != nullptr ? p->entry.rangeVersion : oldestVersion;
|
||||
begin->entry.pointVersion = w.writeVersion;
|
||||
begin->maxVersion = w.writeVersion;
|
||||
beginNode->entry.pointVersion = w.writeVersion;
|
||||
beginNode->maxVersion = w.writeVersion;
|
||||
}
|
||||
begin->maxVersion = std::max(begin->maxVersion, w.writeVersion);
|
||||
begin->entry.pointVersion =
|
||||
std::max(begin->entry.pointVersion, w.writeVersion);
|
||||
beginNode->maxVersion = std::max(beginNode->maxVersion, w.writeVersion);
|
||||
beginNode->entry.pointVersion =
|
||||
std::max(beginNode->entry.pointVersion, w.writeVersion);
|
||||
|
||||
auto *end = insert(&root, std::span<const uint8_t>(w.end.p, w.end.len),
|
||||
w.writeVersion, false);
|
||||
auto *endNode = insert(useAsRoot, end, w.writeVersion, false);
|
||||
|
||||
const bool insertedEnd = !std::exchange(end->entryPresent, true);
|
||||
const bool insertedEnd = !std::exchange(endNode->entryPresent, true);
|
||||
|
||||
if (insertedEnd) {
|
||||
auto *p = nextLogical(end);
|
||||
end->entry.pointVersion =
|
||||
auto *p = nextLogical(endNode);
|
||||
endNode->entry.pointVersion =
|
||||
p != nullptr ? p->entry.rangeVersion : oldestVersion;
|
||||
end->maxVersion = std::max(end->maxVersion, end->entry.pointVersion);
|
||||
endNode->maxVersion =
|
||||
std::max(endNode->maxVersion, endNode->entry.pointVersion);
|
||||
}
|
||||
end->entry.rangeVersion = w.writeVersion;
|
||||
endNode->entry.rangeVersion = w.writeVersion;
|
||||
|
||||
if (insertedEnd) {
|
||||
// begin may have been invalidated
|
||||
auto iter =
|
||||
firstGeq(root, std::span<const uint8_t>(w.begin.p, w.begin.len));
|
||||
assert(iter.cmp == 0);
|
||||
begin = iter.n;
|
||||
// beginNode may have been invalidated
|
||||
beginNode = insert(useAsRoot, begin, w.writeVersion, true);
|
||||
}
|
||||
|
||||
for (begin = nextLogical(begin); begin != end;) {
|
||||
auto *old = begin;
|
||||
begin = nextLogical(begin);
|
||||
for (beginNode = nextLogical(beginNode); beginNode != endNode;) {
|
||||
auto *old = beginNode;
|
||||
beginNode = nextLogical(beginNode);
|
||||
old->entryPresent = false;
|
||||
if (old->numChildren == 0 && old->parent != nullptr) {
|
||||
eraseChild(old->parent, old->parentsIndex);
|
||||
|
Reference in New Issue
Block a user