WIP just need to identify nodes on begin -> end path

This commit is contained in:
2024-02-09 12:45:34 -08:00
parent 8e918acc05
commit 403608c794
2 changed files with 76 additions and 35 deletions

View File

@@ -485,6 +485,21 @@ Node *nextPhysical(Node *node) {
}
}
Node *nextPhysicalSkipSubtree(Node *node) {
int index = -1;
for (;;) {
index = node->parentsIndex;
node = node->parent;
if (node == nullptr) {
return nullptr;
}
auto nextChild = getChildGeq(node, index + 1);
if (nextChild >= 0) {
return getChildExists(node, nextChild);
}
}
}
Node *nextLogical(Node *node) {
for (node = nextPhysical(node); node != nullptr && !node->entryPresent;
node = nextPhysical(node))
@@ -711,33 +726,6 @@ bool checkRangeRead(Node *n, const std::span<const uint8_t> begin,
}
}
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;
}
}
}
// TODO make it sublinear
if (!leftDone) {
while (!left.step())
;
@@ -746,6 +734,43 @@ bool checkRangeRead(Node *n, const std::span<const uint8_t> begin,
while (!right.step())
;
}
Arena arena;
auto leftPath = vector<Node *>(arena);
auto rightPath = vector<Node *>(arena);
for (auto *iter = left.n; iter != nullptr; iter = iter->parent) {
leftPath.push_back(iter);
}
for (auto *iter = right.n; iter != nullptr; iter = iter->parent) {
rightPath.push_back(iter);
}
std::reverse(leftPath.begin(), leftPath.end());
std::reverse(rightPath.begin(), rightPath.end());
Node *lca = n;
int longestCommonPrefixSize = 0;
for (int i = 0, end = std::min<int>(leftPath.size(), rightPath.size());
i < end; ++i, ++longestCommonPrefixSize) {
if (leftPath[i] != rightPath[i]) {
break;
}
lca = leftPath[i];
}
auto border = vector<Node *>(arena);
for (int i = longestCommonPrefixSize; i < int(leftPath.size()); ++i) {
border.push_back(leftPath[i]);
}
for (int i = longestCommonPrefixSize; i < int(rightPath.size()); ++i) {
border.push_back(rightPath[i]);
}
#if DEBUG_VERBOSE && !defined(NDEBUG)
fprintf(stderr, "firstGeq for `%s' got `%s'\n", printable(begin).c_str(),
getSearchPath(left.n).c_str());
fprintf(stderr, "firstGeq for `%s' got `%s'\n", printable(end).c_str(),
getSearchPath(right.n).c_str());
fprintf(stderr, "lca `%s'\n", getSearchPath(lca).c_str());
#endif
if (left.n != nullptr && left.cmp != 0 &&
left.n->entry.rangeVersion > readVersion) {
return false;
@@ -754,16 +779,25 @@ bool checkRangeRead(Node *n, const std::span<const uint8_t> begin,
return true;
}
assert(left.n != nullptr);
auto boundaryVersion = left.n->entry.pointVersion;
// Already checked left rangeVersion
if (boundaryVersion > readVersion) {
if (left.n->entry.pointVersion > readVersion) {
return false;
}
for (auto *iter = nextLogical(left.n); iter != right.n;
iter = nextLogical(iter)) {
if (std::max(iter->entry.pointVersion, iter->entry.rangeVersion) >
readVersion) {
return false;
// TODO make it sublinear
for (auto *iter = nextPhysical(left.n); iter != right.n;) {
assert(iter != lca);
if (std::find(border.begin(), border.end(), iter) == border.end()) {
if (iter->maxVersion > readVersion) {
return false;
}
iter = nextPhysicalSkipSubtree(iter);
} else {
if (iter->entryPresent &&
std::max(iter->entry.pointVersion, iter->entry.rangeVersion) >
readVersion) {
return false;
}
iter = nextPhysical(iter);
}
}
return true;