Compare commits
2 Commits
09cf807747
...
29c05187fb
Author | SHA1 | Date | |
---|---|---|---|
29c05187fb | |||
d89028dd2f |
103
ConflictSet.cpp
103
ConflictSet.cpp
@@ -1849,43 +1849,6 @@ int longestCommonPrefix(const uint8_t *ap, const uint8_t *bp, int cl) {
|
||||
return i;
|
||||
}
|
||||
|
||||
// Performs a physical search for remaining
|
||||
struct SearchStepWise {
|
||||
Node *n;
|
||||
InternalVersionT maxV;
|
||||
std::span<const uint8_t> remaining;
|
||||
|
||||
SearchStepWise() {}
|
||||
SearchStepWise(Node *n, std::span<const uint8_t> remaining)
|
||||
: n(n), remaining(remaining) {
|
||||
assert(n->partialKeyLen == 0);
|
||||
}
|
||||
|
||||
bool step() {
|
||||
if (remaining.size() == 0) {
|
||||
return true;
|
||||
}
|
||||
auto [child, v] = getChildAndMaxVersion(n, remaining[0]);
|
||||
maxV = v;
|
||||
if (child == nullptr) {
|
||||
return true;
|
||||
}
|
||||
if (child->partialKeyLen > 0) {
|
||||
int cl = std::min<int>(child->partialKeyLen, remaining.size() - 1);
|
||||
int i =
|
||||
longestCommonPrefix(child->partialKey(), remaining.data() + 1, cl);
|
||||
if (i != child->partialKeyLen) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
n = child;
|
||||
remaining =
|
||||
remaining.subspan(1 + child->partialKeyLen,
|
||||
remaining.size() - (1 + child->partialKeyLen));
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// Logically this is the same as performing firstGeq and then checking against
|
||||
// point or range version according to cmp, but this version short circuits as
|
||||
// soon as it can prove that there's no conflict.
|
||||
@@ -2820,30 +2783,78 @@ bool checkRangeRead(Node *n, std::span<const uint8_t> begin,
|
||||
|
||||
++tls->range_read_accum;
|
||||
|
||||
SearchStepWise search{n, begin.subspan(0, lcp)};
|
||||
auto remaining = begin.subspan(0, lcp);
|
||||
Arena arena;
|
||||
// If the common prefix isn't a prefix of any physical entry in the tree, we
|
||||
// can go to "downLeftSpine"
|
||||
for (;; ++tls->range_read_iterations_accum) {
|
||||
assert(getSearchPath(arena, search.n) <=>
|
||||
begin.subspan(0, lcp - search.remaining.size()) ==
|
||||
assert(getSearchPath(arena, n) <=>
|
||||
begin.subspan(0, lcp - remaining.size()) ==
|
||||
0);
|
||||
if (search.step()) {
|
||||
if (remaining.size() == 0) {
|
||||
break;
|
||||
}
|
||||
if (search.maxV <= readVersion) {
|
||||
auto [child, v] = getChildAndMaxVersion(n, remaining[0]);
|
||||
if (child == nullptr) {
|
||||
auto c = getChildGeq(n, remaining[0]);
|
||||
if (c != nullptr) {
|
||||
n = c;
|
||||
goto downLeftSpine;
|
||||
} else {
|
||||
n = nextSibling(n);
|
||||
if (n == nullptr) {
|
||||
return true;
|
||||
}
|
||||
goto downLeftSpine;
|
||||
}
|
||||
}
|
||||
|
||||
if (child->partialKeyLen > 0) {
|
||||
int cl = std::min<int>(child->partialKeyLen, remaining.size() - 1);
|
||||
int i =
|
||||
longestCommonPrefix(child->partialKey(), remaining.data() + 1, cl);
|
||||
if (i < cl) {
|
||||
auto c = child->partialKey()[i] <=> remaining[1 + i];
|
||||
if (c > 0) {
|
||||
n = child;
|
||||
goto downLeftSpine;
|
||||
} else {
|
||||
n = nextSibling(child);
|
||||
if (n == nullptr) {
|
||||
return true;
|
||||
}
|
||||
goto downLeftSpine;
|
||||
}
|
||||
}
|
||||
// If the partial key is longer than the common prefix (remaining), we
|
||||
// still need to keep searching
|
||||
if (i != child->partialKeyLen) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (v <= readVersion) {
|
||||
++tls->range_read_short_circuit_accum;
|
||||
return true;
|
||||
}
|
||||
n = child;
|
||||
remaining =
|
||||
remaining.subspan(1 + child->partialKeyLen,
|
||||
remaining.size() - (1 + child->partialKeyLen));
|
||||
}
|
||||
assert(getSearchPath(arena, search.n) <=>
|
||||
begin.subspan(0, lcp - search.remaining.size()) ==
|
||||
assert(getSearchPath(arena, n) <=> begin.subspan(0, lcp - remaining.size()) ==
|
||||
0);
|
||||
if (0) {
|
||||
downLeftSpine:
|
||||
for (; !n->entryPresent; n = getFirstChildExists(n)) {
|
||||
}
|
||||
return n->entry.rangeVersion <= readVersion;
|
||||
}
|
||||
|
||||
const int consumed = lcp - search.remaining.size();
|
||||
const int consumed = lcp - remaining.size();
|
||||
assume(consumed >= 0);
|
||||
|
||||
begin = begin.subspan(consumed, int(begin.size()) - consumed);
|
||||
end = end.subspan(consumed, int(end.size()) - consumed);
|
||||
n = search.n;
|
||||
lcp -= consumed;
|
||||
|
||||
if (lcp == int(begin.size())) {
|
||||
|
Reference in New Issue
Block a user