diff --git a/ConflictSet.cpp b/ConflictSet.cpp index e4ed8d9..38a66e1 100644 --- a/ConflictSet.cpp +++ b/ConflictSet.cpp @@ -2785,6 +2785,8 @@ bool checkRangeRead(Node *n, std::span begin, auto remaining = begin.subspan(0, lcp); Arena arena; + // If the common prefix isn't a prefix of any physical entry in the tree, we + // can go to "downLeftSpine" for (;; ++tls->range_read_iterations_accum) { assert(getSearchPath(arena, n) <=> begin.subspan(0, lcp - remaining.size()) == @@ -2794,12 +2796,38 @@ bool checkRangeRead(Node *n, std::span begin, } auto [child, v] = getChildAndMaxVersion(n, remaining[0]); if (child == nullptr) { - break; + auto c = getChildGeq(n, remaining[0]); + if (c != nullptr) { + n = c; + goto downLeftSpine; + } else { + n = nextSibling(n); + if (n == nullptr) { + return true; + } + goto downLeftSpine; + } } + if (child->partialKeyLen > 0) { int cl = std::min(child->partialKeyLen, remaining.size() - 1); int i = longestCommonPrefix(child->partialKey(), remaining.data() + 1, cl); + if (i < cl) { + auto c = child->partialKey()[i] <=> remaining[1 + i]; + if (c > 0) { + n = child; + goto downLeftSpine; + } else { + n = nextSibling(child); + if (n == nullptr) { + return true; + } + goto downLeftSpine; + } + } + // If the partial key is longer than the common prefix (remaining), we + // still need to keep searching if (i != child->partialKeyLen) { break; } @@ -2815,6 +2843,12 @@ bool checkRangeRead(Node *n, std::span begin, } assert(getSearchPath(arena, n) <=> begin.subspan(0, lcp - remaining.size()) == 0); + if (0) { + downLeftSpine: + for (; !n->entryPresent; n = getFirstChildExists(n)) { + } + return n->entry.rangeVersion <= readVersion; + } const int consumed = lcp - remaining.size(); assume(consumed >= 0);