WIP checkLeftOfPyramid seems to be correct

This commit is contained in:
2024-02-14 17:01:00 -08:00
parent 838d08c70b
commit 98dccf5c23
2 changed files with 56 additions and 52 deletions

View File

@@ -736,14 +736,21 @@ int64_t maxRightOf(Node *n, int begin) {
return result;
}
// Return the maximum version among all keys starting with the search path of
// `n` + a child > `begin`
int64_t maxRightOfExclusive(Node *n, int begin) {
int64_t result = std::numeric_limits<int64_t>::lowest();
int index = begin;
for (;;) {
begin = getChildGeq(n, begin + 1);
if (begin < 0) {
index = getChildGeq(n, index + 1);
if (index < 0) {
break;
}
result = std::max(result, getChildExists(n, begin)->maxVersion);
auto *child = getChildExists(n, index);
if (index > begin + 1 && child->entryPresent) {
result = std::max(result, child->entry.rangeVersion);
}
result = std::max(result, child->maxVersion);
}
#if DEBUG_VERBOSE && !defined(NDEBUG)
fprintf(stderr, "At `%s', max version right of %02x is %" PRId64 "\n",
@@ -789,7 +796,8 @@ int64_t maxBetweenExclusive(Node *n, int begin, int end) {
return result;
}
// Returns true if the version of all keys >= key in n is <= readVersion
// Returns true if the version of all keys >= key in the subtree rooted at n is
// <= readVersion
bool checkLeftOfPyramid(Node *n, const std::span<const uint8_t> key,
int64_t readVersion) {
auto remaining = key;
@@ -799,30 +807,36 @@ bool checkLeftOfPyramid(Node *n, const std::span<const uint8_t> key,
return true;
}
if (remaining.size() == 0) {
if (n->entryPresent) {
return n->entry.pointVersion <= readVersion;
return n->maxVersion <= readVersion;
}
auto v = maxRightOfExclusive(n, remaining[0]);
if (v > readVersion) {
return false;
};
{
int c = getChildGeq(n, int(remaining[0]) + 1);
if (c >= 0) {
auto *child = getChildExists(n, c);
if (child->entryPresent && child->entry.rangeVersion > readVersion) {
return false;
}
}
int c = getChildGeq(n, 0);
assert(c >= 0);
n = getChildExists(n, c);
goto downLeftSpine;
}
int c = getChildGeq(n, remaining[0]);
if (c == remaining[0]) {
auto v = maxRightOfExclusive(n, c);
if (v > readVersion) {
return false;
}
n = getChildExists(n, c);
remaining = remaining.subspan(1, remaining.size() - 1);
} else {
if (c >= 0) {
n = getChildExists(n, c);
goto downLeftSpine;
if (n->entryPresent && n->entry.rangeVersion > readVersion) {
return false;
}
return n->maxVersion <= readVersion;
} else {
n = nextSibling(n);
goto downLeftSpine;
return true;
}
}
@@ -833,35 +847,26 @@ bool checkLeftOfPyramid(Node *n, const std::span<const uint8_t> key,
if (c == 0) {
continue;
}
if (c > 0) {
goto downLeftSpine;
if (c < 0) {
return true;
} else {
n = nextSibling(n);
goto downLeftSpine;
if (n->entryPresent && n->entry.rangeVersion > readVersion) {
return false;
}
return n->maxVersion <= readVersion;
}
}
if (commonLen == n->partialKeyLen) {
// partial key matches
remaining = remaining.subspan(commonLen, remaining.size() - commonLen);
} else if (n->partialKeyLen > int(remaining.size())) {
// n is the first physical node greater than remaining, and there's no
// eq node
goto downLeftSpine;
if (n->entryPresent && n->entry.rangeVersion > readVersion) {
return false;
}
return n->maxVersion <= readVersion;
}
}
}
downLeftSpine:
if (n == nullptr) {
return true;
}
for (;;) {
if (n->entryPresent) {
return n->entry.rangeVersion <= readVersion;
}
int c = getChildGeq(n, 0);
assert(c >= 0);
n = getChildExists(n, c);
}
}
// Returns true if the version of all keys < key in n is <= readVersion
@@ -1356,20 +1361,19 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
reads[i].readVersion))
? Commit
: Conflict;
// auto k = std::span<const uint8_t>(reads[i].begin.p,
// reads[i].begin.len); if (k.size() > 0) {
// bool expected =
// checkRangeRead(root, {}, k, reads[i].readVersion, arena);
// bool actual = checkRightOfPyramid(root, k,
// reads[i].readVersion); if (expected != actual) {
// #if DEBUG_VERBOSE && !defined(NDEBUG)
// fprintf(stderr, "Expected %d, got %d for [,%s)\n",
// int(expected),
// int(actual), printable(k).c_str());
// #endif
// result[i] = TooOld;
// }
// }
auto k = std::span<const uint8_t>(reads[i].begin.p, reads[i].begin.len);
if (k.size() > 0) {
bool expected = checkRangeRead(root, k, std::vector<uint8_t>(33, 0xff),
reads[i].readVersion, arena);
bool actual = checkLeftOfPyramid(root, k, reads[i].readVersion);
if (expected != actual) {
#if DEBUG_VERBOSE && !defined(NDEBUG)
fprintf(stderr, "Expected %d, got %d for [%s,)\n", int(expected),
int(actual), printable(k).c_str());
#endif
result[i] = TooOld;
}
}
}
}