diff --git a/ConflictSet.cpp b/ConflictSet.cpp index 3680250..ab9996d 100644 --- a/ConflictSet.cpp +++ b/ConflictSet.cpp @@ -2594,110 +2594,97 @@ downLeftSpine: // Return true if the max version among all keys that start with key[:prefixLen] // that are < key is <= readVersion -struct CheckRangeRightSide { +bool checkRangeRightSide(Node *n, std::span key, int prefixLen, + InternalVersionT readVersion, ReadContext *tls) { + auto remaining = key; + int searchPathLen = 0; - bool step(Node *n, std::span key, int prefixLen, - InternalVersionT readVersion, ReadContext *tls) { - bool ok; - auto remaining = key; - int searchPathLen = 0; + for (;; ++tls->range_read_iterations_accum) { + assert(searchPathLen <= int(key.size())); + if (remaining.size() == 0) { + goto downLeftSpine; + } - for (;; ++tls->range_read_iterations_accum) { - assert(searchPathLen <= int(key.size())); - if (remaining.size() == 0) { + if (searchPathLen >= prefixLen) { + if (n->entryPresent && n->entry.pointVersion > readVersion) { + return false; + } + + if (!checkMaxBetweenExclusive(n, -1, remaining[0], readVersion, tls)) { + return false; + } + } + + if (searchPathLen > prefixLen && n->entryPresent && + n->entry.rangeVersion > readVersion) { + return false; + } + + auto *child = getChild(n, remaining[0]); + if (child == nullptr) { + auto c = getChildGeq(n, remaining[0]); + if (c != nullptr) { + n = c; goto downLeftSpine; + } else { + goto backtrack; } + } - if (searchPathLen >= prefixLen) { - if (n->entryPresent && n->entry.pointVersion > readVersion) { - ok = false; - return ok; - } + n = child; + remaining = remaining.subspan(1, remaining.size() - 1); + ++searchPathLen; - if (!checkMaxBetweenExclusive(n, -1, remaining[0], readVersion, tls)) { - ok = false; - return ok; - } - } - - if (searchPathLen > prefixLen && n->entryPresent && - n->entry.rangeVersion > readVersion) { - ok = false; - return ok; - } - - auto *child = getChild(n, remaining[0]); - if (child == nullptr) { - auto c = getChildGeq(n, remaining[0]); - if (c != nullptr) { - n = c; + if (n->partialKeyLen > 0) { + int commonLen = std::min(n->partialKeyLen, remaining.size()); + int i = longestCommonPrefix(n->partialKey(), remaining.data(), commonLen); + searchPathLen += i; + if (i < commonLen) { + ++searchPathLen; + auto c = n->partialKey()[i] <=> remaining[i]; + if (c > 0) { goto downLeftSpine; } else { + if (searchPathLen > prefixLen && n->entryPresent && + n->entry.rangeVersion > readVersion) { + return false; + } goto backtrack; } } - - n = child; - remaining = remaining.subspan(1, remaining.size() - 1); - ++searchPathLen; - - if (n->partialKeyLen > 0) { - int commonLen = std::min(n->partialKeyLen, remaining.size()); - int i = - longestCommonPrefix(n->partialKey(), remaining.data(), commonLen); - searchPathLen += i; - if (i < commonLen) { - ++searchPathLen; - auto c = n->partialKey()[i] <=> remaining[i]; - if (c > 0) { - goto downLeftSpine; - } else { - if (searchPathLen > prefixLen && n->entryPresent && - n->entry.rangeVersion > readVersion) { - ok = false; - return ok; - } - goto backtrack; - } - } - if (commonLen == n->partialKeyLen) { - // partial key matches - remaining = - remaining.subspan(commonLen, remaining.size() - commonLen); - } else if (n->partialKeyLen > int(remaining.size())) { - goto downLeftSpine; - } - } - } - backtrack: - for (;;) { - // searchPathLen > prefixLen implies n is not the root - if (searchPathLen > prefixLen && maxVersion(n) > readVersion) { - ok = false; - return ok; - } - if (n->parent == nullptr) { - ok = true; - return ok; - } - auto next = getChildGeq(n->parent, n->parentsIndex + 1); - if (next == nullptr) { - searchPathLen -= 1 + n->partialKeyLen; - n = n->parent; - } else { - searchPathLen -= n->partialKeyLen; - n = next; - searchPathLen += n->partialKeyLen; + if (commonLen == n->partialKeyLen) { + // partial key matches + remaining = remaining.subspan(commonLen, remaining.size() - commonLen); + } else if (n->partialKeyLen > int(remaining.size())) { goto downLeftSpine; } } - downLeftSpine: - for (; !n->entryPresent; n = getFirstChildExists(n)) { - } - ok = n->entry.rangeVersion <= readVersion; - return ok; } -}; +backtrack: + for (;;) { + // searchPathLen > prefixLen implies n is not the root + if (searchPathLen > prefixLen && maxVersion(n) > readVersion) { + return false; + } + if (n->parent == nullptr) { + return true; + } + auto next = getChildGeq(n->parent, n->parentsIndex + 1); + if (next == nullptr) { + searchPathLen -= 1 + n->partialKeyLen; + n = n->parent; + } else { + searchPathLen -= n->partialKeyLen; + n = next; + searchPathLen += n->partialKeyLen; + goto downLeftSpine; + } + } +downLeftSpine: + for (; !n->entryPresent; n = getFirstChildExists(n)) { + } + return n->entry.rangeVersion <= readVersion; +} } // namespace bool checkRangeRead(Node *n, std::span begin, @@ -2760,21 +2747,17 @@ bool checkRangeRead(Node *n, std::span begin, lcp -= consumed; if (lcp == int(begin.size())) { - CheckRangeRightSide checkRangeRightSide{}; - return checkRangeRightSide.step(n, end, lcp, readVersion, tls); - } - - if (!checkRangeStartsWith(n, begin.subspan(0, lcp), begin[lcp], end[lcp], - readVersion, tls)) { - return false; + return checkRangeRightSide(n, end, lcp, readVersion, tls); } // This makes it safe to check maxVersion within CheckRangeLeftSide. If this // were false, then we would have returned above since lcp == begin.size(). assert(!(n->parent == nullptr && begin.size() == 0)); - CheckRangeRightSide checkRangeRightSide{}; - return checkRangeLeftSide(n, begin, lcp + 1, readVersion, tls) && - checkRangeRightSide.step(n, end, lcp + 1, readVersion, tls); + + return checkRangeStartsWith(n, begin.subspan(0, lcp), begin[lcp], end[lcp], + readVersion, tls) && + checkRangeLeftSide(n, begin, lcp + 1, readVersion, tls) && + checkRangeRightSide(n, end, lcp + 1, readVersion, tls); } #ifdef __x86_64__