Share common prefix search in addWriteRange

This commit is contained in:
2024-02-16 17:50:21 -08:00
parent c20d0c5581
commit 69a1b9099d

View File

@@ -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);