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,
|
void addWriteRange(Node *&root, int64_t oldestVersion,
|
||||||
const ConflictSet::WriteRange &w) {
|
const ConflictSet::WriteRange &w) {
|
||||||
|
|
||||||
auto *begin = insert(&root, std::span<const uint8_t>(w.begin.p, w.begin.len),
|
auto begin = std::span<const uint8_t>(w.begin.p, w.begin.len);
|
||||||
w.writeVersion, true);
|
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) {
|
if (insertedBegin) {
|
||||||
auto *p = nextLogical(begin);
|
auto *p = nextLogical(beginNode);
|
||||||
begin->entry.rangeVersion =
|
beginNode->entry.rangeVersion =
|
||||||
p != nullptr ? p->entry.rangeVersion : oldestVersion;
|
p != nullptr ? p->entry.rangeVersion : oldestVersion;
|
||||||
begin->entry.pointVersion = w.writeVersion;
|
beginNode->entry.pointVersion = w.writeVersion;
|
||||||
begin->maxVersion = w.writeVersion;
|
beginNode->maxVersion = w.writeVersion;
|
||||||
}
|
}
|
||||||
begin->maxVersion = std::max(begin->maxVersion, w.writeVersion);
|
beginNode->maxVersion = std::max(beginNode->maxVersion, w.writeVersion);
|
||||||
begin->entry.pointVersion =
|
beginNode->entry.pointVersion =
|
||||||
std::max(begin->entry.pointVersion, w.writeVersion);
|
std::max(beginNode->entry.pointVersion, w.writeVersion);
|
||||||
|
|
||||||
auto *end = insert(&root, std::span<const uint8_t>(w.end.p, w.end.len),
|
auto *endNode = insert(useAsRoot, end, w.writeVersion, false);
|
||||||
w.writeVersion, false);
|
|
||||||
|
|
||||||
const bool insertedEnd = !std::exchange(end->entryPresent, true);
|
const bool insertedEnd = !std::exchange(endNode->entryPresent, true);
|
||||||
|
|
||||||
if (insertedEnd) {
|
if (insertedEnd) {
|
||||||
auto *p = nextLogical(end);
|
auto *p = nextLogical(endNode);
|
||||||
end->entry.pointVersion =
|
endNode->entry.pointVersion =
|
||||||
p != nullptr ? p->entry.rangeVersion : oldestVersion;
|
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) {
|
if (insertedEnd) {
|
||||||
// begin may have been invalidated
|
// beginNode may have been invalidated
|
||||||
auto iter =
|
beginNode = insert(useAsRoot, begin, w.writeVersion, true);
|
||||||
firstGeq(root, std::span<const uint8_t>(w.begin.p, w.begin.len));
|
|
||||||
assert(iter.cmp == 0);
|
|
||||||
begin = iter.n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (begin = nextLogical(begin); begin != end;) {
|
for (beginNode = nextLogical(beginNode); beginNode != endNode;) {
|
||||||
auto *old = begin;
|
auto *old = beginNode;
|
||||||
begin = nextLogical(begin);
|
beginNode = nextLogical(beginNode);
|
||||||
old->entryPresent = false;
|
old->entryPresent = false;
|
||||||
if (old->numChildren == 0 && old->parent != nullptr) {
|
if (old->numChildren == 0 && old->parent != nullptr) {
|
||||||
eraseChild(old->parent, old->parentsIndex);
|
eraseChild(old->parent, old->parentsIndex);
|
||||||
|
Reference in New Issue
Block a user