From eef3c9e8d0040fb1dbfd4cb919cf6d8c903dc3eb Mon Sep 17 00:00:00 2001 From: Andrew Noyes Date: Tue, 13 Feb 2024 15:37:14 -0800 Subject: [PATCH] Track lcp as loop invariant --- ConflictSet.cpp | 52 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 11 deletions(-) diff --git a/ConflictSet.cpp b/ConflictSet.cpp index f2ea7fe..452cbd6 100644 --- a/ConflictSet.cpp +++ b/ConflictSet.cpp @@ -931,6 +931,35 @@ bytes: return i; } +__attribute__((always_inline)) inline void +ascend(int &depth, int &lcp, Node *oldNode, Vector &searchPath) { + depth -= 1 + oldNode->partialKeyLen; + searchPath.resize(depth); + lcp = std::min(lcp, depth); +} + +__attribute__((always_inline)) inline void +descend(int &depth, int &lcp, Node *newNode, std::span end, + Vector &searchPath) { + if (depth == lcp) { + if (lcp < int(end.size()) && newNode->parentsIndex == end[lcp]) { + ++lcp; + for (int i = 0; i < newNode->partialKeyLen && lcp < int(end.size()); + ++i) { + if (newNode->partialKey[i] == end[lcp]) { + ++lcp; + } else { + break; + } + } + } + } + depth += 1 + newNode->partialKeyLen; + searchPath.push_back(newNode->parentsIndex); + searchPath.insert(searchPath.end(), newNode->partialKey, + newNode->partialKey + newNode->partialKeyLen); +} + bool checkRangeRead(Node *n, const std::span begin, const std::span end, int64_t readVersion, Arena &arena) { @@ -980,10 +1009,15 @@ bool checkRangeRead(Node *n, const std::span begin, return false; } + int depth = searchPath.size(); + lcp = longestCommonPrefix(searchPath.data(), end.data(), + std::min(searchPath.size(), end.size())); + bool first = true; for (auto *iter = left.n; iter != nullptr; first = false) { int cl = std::min(searchPath.size(), end.size()); - int lcp = longestCommonPrefix(searchPath.data(), end.data(), cl); + assert(depth == int(searchPath.size())); + assert(lcp == longestCommonPrefix(searchPath.data(), end.data(), cl)); // if (searchPath >= end) break; if ((cl == lcp ? searchPath.size() <=> end.size() @@ -1005,7 +1039,7 @@ bool checkRangeRead(Node *n, const std::span begin, fprintf(stderr, "Max version of keys starting with %s: %" PRId64 "\n", printable(searchPath).c_str(), iter->maxVersion); #endif - if (lcp == int(searchPath.size())) { + if (lcp == depth) { // end starts with searchPath, so end < range if (iter->maxVersion <= readVersion) { return true; @@ -1015,17 +1049,15 @@ bool checkRangeRead(Node *n, const std::span begin, auto nextChild = getChildGeq(iter, index + 1); if (nextChild >= 0) { auto *result = getChildExists(iter, nextChild); - searchPath.push_back(nextChild); - searchPath.insert(searchPath.end(), result->partialKey, - result->partialKey + result->partialKeyLen); iter = result; + descend(depth, lcp, iter, end, searchPath); break; } if (iter->parent == nullptr) { iter = nullptr; break; } - searchPath.resize(int(searchPath.size()) - 1 - iter->partialKeyLen); + ascend(depth, lcp, iter, searchPath); index = iter->parentsIndex; iter = iter->parent; } @@ -1043,15 +1075,13 @@ bool checkRangeRead(Node *n, const std::span begin, } auto next = getChildGeq(iter->parent, iter->parentsIndex + 1); if (next < 0) { - searchPath.resize(int(searchPath.size()) - (1 + iter->partialKeyLen)); + ascend(depth, lcp, iter, searchPath); iter = iter->parent; } else { - searchPath.resize(int(searchPath.size()) - (1 + iter->partialKeyLen)); + ascend(depth, lcp, iter, searchPath); auto *result = getChildExists(iter->parent, next); - searchPath.push_back(next); - searchPath.insert(searchPath.end(), result->partialKey, - result->partialKey + result->partialKeyLen); iter = result; + descend(depth, lcp, iter, end, searchPath); break; } }