Check indices between left and right after they diverge
This commit is contained in:
@@ -515,6 +515,7 @@ struct FirstGeqStepwise {
|
||||
FirstGeqStepwise(Node *n, std::span<const uint8_t> remaining)
|
||||
: n(n), remaining(remaining), phase(Init) {}
|
||||
|
||||
// Not being done implies that n is not the firstGeq
|
||||
bool step() {
|
||||
switch (phase) {
|
||||
case Search:
|
||||
@@ -573,26 +574,30 @@ struct FirstGeqStepwise {
|
||||
return downLeftSpine();
|
||||
}
|
||||
}
|
||||
if (remaining.size() == 0 && n->entryPresent) {
|
||||
cmp = 0;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case DownLeftSpine:
|
||||
int c = getChildGeq(n, 0);
|
||||
assert(c >= 0);
|
||||
n = getChildExists(n, c);
|
||||
if (n->entryPresent) {
|
||||
cmp = 1;
|
||||
return true;
|
||||
}
|
||||
int c = getChildGeq(n, 0);
|
||||
assert(c >= 0);
|
||||
n = getChildExists(n, c);
|
||||
return false;
|
||||
}
|
||||
__builtin_unreachable(); // GCOVR_EXCL_LINE
|
||||
}
|
||||
|
||||
bool downLeftSpine() {
|
||||
if (n == nullptr) {
|
||||
phase = DownLeftSpine;
|
||||
if (n == nullptr || n->entryPresent) {
|
||||
cmp = 1;
|
||||
return true;
|
||||
}
|
||||
phase = DownLeftSpine;
|
||||
return step();
|
||||
}
|
||||
};
|
||||
@@ -682,27 +687,57 @@ downLeftSpine:
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
std::string getSearchPathPrintable(Node *n);
|
||||
}
|
||||
|
||||
bool checkRangeRead(Node *n, const std::span<const uint8_t> begin,
|
||||
const std::span<const uint8_t> end, int64_t readVersion) {
|
||||
auto left = FirstGeqStepwise{n, begin};
|
||||
auto right = FirstGeqStepwise{n, end};
|
||||
bool leftDone = left.step();
|
||||
bool rightDone = right.step();
|
||||
assert(!leftDone);
|
||||
assert(!rightDone);
|
||||
for (;;) {
|
||||
if (left.phase == FirstGeqStepwise::Search &&
|
||||
right.phase == FirstGeqStepwise::Search &&
|
||||
left.n->maxVersion <= readVersion) {
|
||||
return true;
|
||||
if (!leftDone && !rightDone) {
|
||||
for (;;) {
|
||||
if (left.phase == FirstGeqStepwise::Search &&
|
||||
right.phase == FirstGeqStepwise::Search &&
|
||||
left.n->maxVersion <= readVersion) {
|
||||
return true;
|
||||
}
|
||||
leftDone = left.step();
|
||||
rightDone = right.step();
|
||||
if (leftDone || rightDone) {
|
||||
break;
|
||||
}
|
||||
if (left.n != right.n) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
leftDone = left.step();
|
||||
rightDone = right.step();
|
||||
if (leftDone || rightDone) {
|
||||
break;
|
||||
}
|
||||
if (left.n != right.n) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!leftDone && !rightDone && left.n->parent == right.n->parent) {
|
||||
// Check between left parent index and right parent index
|
||||
int c = getChildGeq(left.n->parent, int(left.n->parentsIndex) + 1);
|
||||
assert(c >= 0);
|
||||
|
||||
for (;;) {
|
||||
if (c < right.n->parentsIndex) {
|
||||
#if DEBUG_VERBOSE && !defined(NDEBUG)
|
||||
fprintf(
|
||||
stderr, "Check [%s, %s)\n",
|
||||
getSearchPathPrintable(getChildExists(left.n->parent, c)).c_str(),
|
||||
getSearchPathPrintable(
|
||||
getChildExists(left.n->parent,
|
||||
getChildGeq(left.n->parent, c + 1)))
|
||||
.c_str());
|
||||
#endif
|
||||
if (getChildExists(left.n->parent, c)->maxVersion > readVersion) {
|
||||
return false;
|
||||
}
|
||||
c = getChildGeq(left.n->parent, c + 1);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -715,11 +750,6 @@ bool checkRangeRead(Node *n, const std::span<const uint8_t> begin,
|
||||
while (!right.step())
|
||||
;
|
||||
}
|
||||
#if DEBUG_VERBOSE && !defined(NDEBUG)
|
||||
fprintf(stderr, "Left firstGeq: %s, right firstGeq: %s\n",
|
||||
getSearchPathPrintable(left.n).c_str(),
|
||||
getSearchPathPrintable(right.n).c_str());
|
||||
#endif
|
||||
if (left.n != nullptr && left.cmp != 0 &&
|
||||
left.n->entry.rangeVersion > readVersion) {
|
||||
return false;
|
||||
@@ -1032,6 +1062,17 @@ std::string getSearchPathPrintable(Node *n) {
|
||||
}
|
||||
}
|
||||
|
||||
std::string getPartialKeyPrintable(Node *n) {
|
||||
Arena arena;
|
||||
if (n == nullptr) {
|
||||
return "<end>";
|
||||
}
|
||||
auto result = std::string((const char *)&n->parentsIndex,
|
||||
n->parent == nullptr ? 0 : 1) +
|
||||
std::string((const char *)n->partialKey, n->partialKeyLen);
|
||||
return printable(result); // NOLINT
|
||||
}
|
||||
|
||||
std::string strinc(std::string_view str, bool &ok) {
|
||||
int index;
|
||||
for (index = str.size() - 1; index >= 0; index--)
|
||||
@@ -1071,7 +1112,7 @@ std::string getSearchPath(Node *n) {
|
||||
|
||||
[[maybe_unused]] void debugPrintDot(FILE *file, Node *node) {
|
||||
|
||||
constexpr int kSeparation = 2;
|
||||
constexpr int kSeparation = 3;
|
||||
|
||||
struct DebugDotPrinter {
|
||||
|
||||
@@ -1084,10 +1125,10 @@ std::string getSearchPath(Node *n) {
|
||||
" k_%p [label=\"m=%" PRId64 " p=%" PRId64 " r=%" PRId64
|
||||
"\n%s\", pos=\"%d,%d!\"];\n",
|
||||
(void *)n, n->maxVersion, n->entry.pointVersion,
|
||||
n->entry.rangeVersion, getSearchPathPrintable(n).c_str(), x, y);
|
||||
n->entry.rangeVersion, getPartialKeyPrintable(n).c_str(), x, y);
|
||||
} else {
|
||||
fprintf(file, " k_%p [label=\"m=%" PRId64 "\n%s\", pos=\"%d,%d!\"];\n",
|
||||
(void *)n, n->maxVersion, getSearchPathPrintable(n).c_str(), x,
|
||||
(void *)n, n->maxVersion, getPartialKeyPrintable(n).c_str(), x,
|
||||
y);
|
||||
}
|
||||
x += kSeparation;
|
||||
|
Reference in New Issue
Block a user