WIP just need to identify nodes on begin -> end path
This commit is contained in:
104
ConflictSet.cpp
104
ConflictSet.cpp
@@ -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;
|
||||
|
Reference in New Issue
Block a user