Check indices between left and right after they diverge
This commit is contained in:
@@ -21,8 +21,12 @@ if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
|||||||
"MinSizeRel" "RelWithDebInfo")
|
"MinSizeRel" "RelWithDebInfo")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_compile_options(-fdata-sections -ffunction-sections
|
add_compile_options(-fdata-sections -ffunction-sections)
|
||||||
-Wno-return-stack-address)
|
|
||||||
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||||
|
add_compile_options(-Wno-maybe-uninitialized)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
add_link_options(-Wl,-dead_strip)
|
add_link_options(-Wl,-dead_strip)
|
||||||
else()
|
else()
|
||||||
|
@@ -515,6 +515,7 @@ struct FirstGeqStepwise {
|
|||||||
FirstGeqStepwise(Node *n, std::span<const uint8_t> remaining)
|
FirstGeqStepwise(Node *n, std::span<const uint8_t> remaining)
|
||||||
: n(n), remaining(remaining), phase(Init) {}
|
: n(n), remaining(remaining), phase(Init) {}
|
||||||
|
|
||||||
|
// Not being done implies that n is not the firstGeq
|
||||||
bool step() {
|
bool step() {
|
||||||
switch (phase) {
|
switch (phase) {
|
||||||
case Search:
|
case Search:
|
||||||
@@ -573,26 +574,30 @@ struct FirstGeqStepwise {
|
|||||||
return downLeftSpine();
|
return downLeftSpine();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (remaining.size() == 0 && n->entryPresent) {
|
||||||
|
cmp = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
case DownLeftSpine:
|
case DownLeftSpine:
|
||||||
|
int c = getChildGeq(n, 0);
|
||||||
|
assert(c >= 0);
|
||||||
|
n = getChildExists(n, c);
|
||||||
if (n->entryPresent) {
|
if (n->entryPresent) {
|
||||||
cmp = 1;
|
cmp = 1;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
int c = getChildGeq(n, 0);
|
|
||||||
assert(c >= 0);
|
|
||||||
n = getChildExists(n, c);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
__builtin_unreachable(); // GCOVR_EXCL_LINE
|
__builtin_unreachable(); // GCOVR_EXCL_LINE
|
||||||
}
|
}
|
||||||
|
|
||||||
bool downLeftSpine() {
|
bool downLeftSpine() {
|
||||||
if (n == nullptr) {
|
phase = DownLeftSpine;
|
||||||
|
if (n == nullptr || n->entryPresent) {
|
||||||
cmp = 1;
|
cmp = 1;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
phase = DownLeftSpine;
|
|
||||||
return step();
|
return step();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -682,27 +687,57 @@ downLeftSpine:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
std::string getSearchPathPrintable(Node *n);
|
||||||
|
}
|
||||||
|
|
||||||
bool checkRangeRead(Node *n, const std::span<const uint8_t> begin,
|
bool checkRangeRead(Node *n, const std::span<const uint8_t> begin,
|
||||||
const std::span<const uint8_t> end, int64_t readVersion) {
|
const std::span<const uint8_t> end, int64_t readVersion) {
|
||||||
auto left = FirstGeqStepwise{n, begin};
|
auto left = FirstGeqStepwise{n, begin};
|
||||||
auto right = FirstGeqStepwise{n, end};
|
auto right = FirstGeqStepwise{n, end};
|
||||||
bool leftDone = left.step();
|
bool leftDone = left.step();
|
||||||
bool rightDone = right.step();
|
bool rightDone = right.step();
|
||||||
assert(!leftDone);
|
if (!leftDone && !rightDone) {
|
||||||
assert(!rightDone);
|
for (;;) {
|
||||||
for (;;) {
|
if (left.phase == FirstGeqStepwise::Search &&
|
||||||
if (left.phase == FirstGeqStepwise::Search &&
|
right.phase == FirstGeqStepwise::Search &&
|
||||||
right.phase == FirstGeqStepwise::Search &&
|
left.n->maxVersion <= readVersion) {
|
||||||
left.n->maxVersion <= readVersion) {
|
return true;
|
||||||
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) {
|
if (!leftDone && !rightDone && left.n->parent == right.n->parent) {
|
||||||
break;
|
// Check between left parent index and right parent index
|
||||||
}
|
int c = getChildGeq(left.n->parent, int(left.n->parentsIndex) + 1);
|
||||||
if (left.n != right.n) {
|
assert(c >= 0);
|
||||||
break;
|
|
||||||
|
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())
|
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 &&
|
if (left.n != nullptr && left.cmp != 0 &&
|
||||||
left.n->entry.rangeVersion > readVersion) {
|
left.n->entry.rangeVersion > readVersion) {
|
||||||
return false;
|
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) {
|
std::string strinc(std::string_view str, bool &ok) {
|
||||||
int index;
|
int index;
|
||||||
for (index = str.size() - 1; index >= 0; 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) {
|
[[maybe_unused]] void debugPrintDot(FILE *file, Node *node) {
|
||||||
|
|
||||||
constexpr int kSeparation = 2;
|
constexpr int kSeparation = 3;
|
||||||
|
|
||||||
struct DebugDotPrinter {
|
struct DebugDotPrinter {
|
||||||
|
|
||||||
@@ -1084,10 +1125,10 @@ std::string getSearchPath(Node *n) {
|
|||||||
" k_%p [label=\"m=%" PRId64 " p=%" PRId64 " r=%" PRId64
|
" k_%p [label=\"m=%" PRId64 " p=%" PRId64 " r=%" PRId64
|
||||||
"\n%s\", pos=\"%d,%d!\"];\n",
|
"\n%s\", pos=\"%d,%d!\"];\n",
|
||||||
(void *)n, n->maxVersion, n->entry.pointVersion,
|
(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 {
|
} else {
|
||||||
fprintf(file, " k_%p [label=\"m=%" PRId64 "\n%s\", pos=\"%d,%d!\"];\n",
|
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);
|
y);
|
||||||
}
|
}
|
||||||
x += kSeparation;
|
x += kSeparation;
|
||||||
|
Reference in New Issue
Block a user