Convert checkRangeRead to IteratorBase
This commit is contained in:
282
ConflictSet.cpp
282
ConflictSet.cpp
@@ -1891,6 +1891,8 @@ template <class T> struct Iterator;
|
|||||||
// an entry associated with a node or a leaf.
|
// an entry associated with a node or a leaf.
|
||||||
struct IteratorBase {
|
struct IteratorBase {
|
||||||
|
|
||||||
|
IteratorBase() = default;
|
||||||
|
|
||||||
explicit IteratorBase(Node *node)
|
explicit IteratorBase(Node *node)
|
||||||
: node(node), type(node ? node->getType() : Type_Node0) {}
|
: node(node), type(node ? node->getType() : Type_Node0) {}
|
||||||
|
|
||||||
@@ -1928,6 +1930,8 @@ struct IteratorBase {
|
|||||||
IteratorBase nextLogical();
|
IteratorBase nextLogical();
|
||||||
IteratorBase nextPhysical();
|
IteratorBase nextPhysical();
|
||||||
InternalVersionT getMaxVersion();
|
InternalVersionT getMaxVersion();
|
||||||
|
IteratorBase parent() { return IteratorBase{node->parent}; }
|
||||||
|
uint8_t parentsIndex() { return node->parentsIndex; }
|
||||||
InternalVersionT exchangeMaxVersion(InternalVersionT);
|
InternalVersionT exchangeMaxVersion(InternalVersionT);
|
||||||
InternalVersionT setMaxVersion();
|
InternalVersionT setMaxVersion();
|
||||||
TrivialSpan partialKey();
|
TrivialSpan partialKey();
|
||||||
@@ -1936,7 +1940,11 @@ struct IteratorBase {
|
|||||||
struct ChildAndMaxVersion;
|
struct ChildAndMaxVersion;
|
||||||
ChildAndMaxVersion getChildAndMaxVersion(int index);
|
ChildAndMaxVersion getChildAndMaxVersion(int index);
|
||||||
IteratorBase getChildGeq(int index);
|
IteratorBase getChildGeq(int index);
|
||||||
|
IteratorBase getChild(int index);
|
||||||
IteratorBase nextSibling();
|
IteratorBase nextSibling();
|
||||||
|
TrivialSpan getSearchPath(Arena &arena);
|
||||||
|
|
||||||
|
Node *escapeHatch() { return node; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Node *node;
|
Node *node;
|
||||||
@@ -1963,9 +1971,14 @@ template <class T> struct Iterator : IteratorBase {
|
|||||||
IteratorBase getChildGeq(int index) {
|
IteratorBase getChildGeq(int index) {
|
||||||
return IteratorBase{::getChildGeq(static_cast<T *>(node), index)};
|
return IteratorBase{::getChildGeq(static_cast<T *>(node), index)};
|
||||||
}
|
}
|
||||||
|
IteratorBase getChild(int index) {
|
||||||
|
return IteratorBase{::getChild(static_cast<T *>(node), index)};
|
||||||
|
}
|
||||||
TrivialSpan partialKey() {
|
TrivialSpan partialKey() {
|
||||||
return {static_cast<T *>(node)->partialKey(), node->partialKeyLen};
|
return {static_cast<T *>(node)->partialKey(), node->partialKeyLen};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
T *escapeHatch() { return static_cast<T *>(node); }
|
||||||
};
|
};
|
||||||
|
|
||||||
TrivialSpan IteratorBase::partialKey() {
|
TrivialSpan IteratorBase::partialKey() {
|
||||||
@@ -2037,6 +2050,23 @@ IteratorBase IteratorBase::getChildGeq(int index) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IteratorBase IteratorBase::getChild(int index) {
|
||||||
|
switch (type) {
|
||||||
|
case Type_Node0:
|
||||||
|
return as<Node0>().getChild(index);
|
||||||
|
case Type_Node3:
|
||||||
|
return as<Node3>().getChild(index);
|
||||||
|
case Type_Node16:
|
||||||
|
return as<Node16>().getChild(index);
|
||||||
|
case Type_Node48:
|
||||||
|
return as<Node48>().getChild(index);
|
||||||
|
case Type_Node256:
|
||||||
|
return as<Node256>().getChild(index);
|
||||||
|
default: // GCOVR_EXCL_LINE
|
||||||
|
__builtin_unreachable(); // GCOVR_EXCL_LINE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
InternalVersionT IteratorBase::getMaxVersion() { return ::maxVersion(node); }
|
InternalVersionT IteratorBase::getMaxVersion() { return ::maxVersion(node); }
|
||||||
|
|
||||||
bool IteratorBase::checkRangeVersionOfFirstGeq(InternalVersionT readVersion) {
|
bool IteratorBase::checkRangeVersionOfFirstGeq(InternalVersionT readVersion) {
|
||||||
@@ -2049,6 +2079,26 @@ IteratorBase IteratorBase::nextSibling() {
|
|||||||
return IteratorBase{::nextSibling(node)};
|
return IteratorBase{::nextSibling(node)};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TrivialSpan IteratorBase::getSearchPath(Arena &arena) {
|
||||||
|
Node *n = node;
|
||||||
|
assert(n != nullptr);
|
||||||
|
auto result = vector<uint8_t>(arena);
|
||||||
|
for (;;) {
|
||||||
|
for (int i = n->partialKeyLen - 1; i >= 0; --i) {
|
||||||
|
result.push_back(n->partialKey()[i]);
|
||||||
|
}
|
||||||
|
result.push_back(n->parentsIndex);
|
||||||
|
n = n->parent;
|
||||||
|
if (n->parent == nullptr) {
|
||||||
|
// Implicit byte from rootParent
|
||||||
|
result.pop_back();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::reverse(result.begin(), result.end());
|
||||||
|
return {result.begin(), result.size()};
|
||||||
|
}
|
||||||
|
|
||||||
// Precondition: self is not the root. May invalidate nodes along the search
|
// Precondition: self is not the root. May invalidate nodes along the search
|
||||||
// path to self. May invalidate children of self->parent. Returns a pointer to
|
// path to self. May invalidate children of self->parent. Returns a pointer to
|
||||||
// the node after self. Precondition: `self->entryPresent`
|
// the node after self. Precondition: `self->entryPresent`
|
||||||
@@ -2792,58 +2842,58 @@ TrivialSpan getSearchPath(Arena &arena, Node *n) {
|
|||||||
// Precondition: transitively, no child of n has a search path that's a longer
|
// Precondition: transitively, no child of n has a search path that's a longer
|
||||||
// prefix of key than n
|
// prefix of key than n
|
||||||
template <class NodeT>
|
template <class NodeT>
|
||||||
bool checkRangeStartsWith(NodeT *nTyped, TrivialSpan key, int begin, int end,
|
bool checkRangeStartsWith(Iterator<NodeT> nTyped, TrivialSpan key, int begin,
|
||||||
InternalVersionT readVersion,
|
int end, InternalVersionT readVersion,
|
||||||
ReadContext *readContext) {
|
ReadContext *readContext) {
|
||||||
Node *n;
|
IteratorBase n;
|
||||||
#if DEBUG_VERBOSE && !defined(NDEBUG)
|
#if DEBUG_VERBOSE && !defined(NDEBUG)
|
||||||
fprintf(stderr, "%s(%02x,%02x)*\n", printable(key).c_str(), begin, end);
|
fprintf(stderr, "%s(%02x,%02x)*\n", printable(key).c_str(), begin, end);
|
||||||
#endif
|
#endif
|
||||||
auto remaining = key;
|
auto remaining = key;
|
||||||
if (remaining.size() == 0) {
|
if (remaining.size() == 0) {
|
||||||
return checkMaxBetweenExclusive(nTyped, begin, end, readVersion,
|
return checkMaxBetweenExclusive(nTyped.escapeHatch(), begin, end,
|
||||||
readContext);
|
readVersion, readContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto cAndV = getChildAndMaxVersion(nTyped, remaining[0]);
|
auto cAndV = nTyped.getChildAndMaxVersion(remaining[0]);
|
||||||
Node *child = cAndV.child;
|
IteratorBase child = cAndV.child;
|
||||||
if (child == nullptr) {
|
if (!child.valid()) {
|
||||||
auto c = getChildGeq(nTyped, remaining[0]);
|
auto c = nTyped.getChildGeq(remaining[0]);
|
||||||
if (c != nullptr) {
|
if (c.valid()) {
|
||||||
n = c;
|
return c.checkRangeVersionOfFirstGeq(readVersion);
|
||||||
return checkRangeVersionOfFirstGeq(n, readVersion);
|
|
||||||
} else {
|
} else {
|
||||||
n = nextSibling(nTyped);
|
n = nTyped.nextSibling();
|
||||||
if (n == nullptr) {
|
if (!n.valid()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return checkRangeVersionOfFirstGeq(n, readVersion);
|
return n.checkRangeVersionOfFirstGeq(readVersion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
n = child;
|
n = child;
|
||||||
remaining = remaining.subspan(1, remaining.size() - 1);
|
remaining = remaining.subspan(1, remaining.size() - 1);
|
||||||
|
|
||||||
assert(n->partialKeyLen > 0);
|
auto partialKey = n.partialKey();
|
||||||
|
assert(partialKey.size() > 0);
|
||||||
{
|
{
|
||||||
int commonLen = std::min<int>(n->partialKeyLen, remaining.size());
|
int commonLen = std::min<int>(partialKey.size(), remaining.size());
|
||||||
int i = longestCommonPrefix(n->partialKey(), remaining.data(), commonLen);
|
int i = longestCommonPrefix(partialKey.data(), remaining.data(), commonLen);
|
||||||
if (i < commonLen) {
|
if (i < commonLen) {
|
||||||
auto c = n->partialKey()[i] <=> remaining[i];
|
auto c = partialKey[i] <=> remaining[i];
|
||||||
if (c > 0) {
|
if (c > 0) {
|
||||||
return checkRangeVersionOfFirstGeq(n, readVersion);
|
return n.checkRangeVersionOfFirstGeq(readVersion);
|
||||||
} else {
|
} else {
|
||||||
n = nextSibling(n);
|
n = n.nextSibling();
|
||||||
if (n == nullptr) {
|
if (!n.valid()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return checkRangeVersionOfFirstGeq(n, readVersion);
|
return n.checkRangeVersionOfFirstGeq(readVersion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(n->partialKeyLen > remaining.size());
|
assert(partialKey.size() > remaining.size());
|
||||||
if (begin < n->partialKey()[remaining.size()] &&
|
if (begin < partialKey[remaining.size()] &&
|
||||||
n->partialKey()[remaining.size()] < end) {
|
partialKey[remaining.size()] < end) {
|
||||||
if (n->entryPresent && n->entry.rangeVersion > readVersion) {
|
if (n.entryPresent() && n.getEntry().rangeVersion > readVersion) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return cAndV.maxVersion <= readVersion;
|
return cAndV.maxVersion <= readVersion;
|
||||||
@@ -2854,6 +2904,30 @@ bool checkRangeStartsWith(NodeT *nTyped, TrivialSpan key, int begin, int end,
|
|||||||
__builtin_unreachable(); // GCOVR_EXCL_LINE
|
__builtin_unreachable(); // GCOVR_EXCL_LINE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool checkRangeStartsWith(IteratorBase n, TrivialSpan key, int begin, int end,
|
||||||
|
InternalVersionT readVersion,
|
||||||
|
ReadContext *readContext) {
|
||||||
|
switch (n.getType()) {
|
||||||
|
case Type_Node0:
|
||||||
|
return checkRangeStartsWith(n.as<Node0>(), key, begin, end, readVersion,
|
||||||
|
readContext);
|
||||||
|
case Type_Node3:
|
||||||
|
return checkRangeStartsWith(n.as<Node3>(), key, begin, end, readVersion,
|
||||||
|
readContext);
|
||||||
|
case Type_Node16:
|
||||||
|
return checkRangeStartsWith(n.as<Node16>(), key, begin, end, readVersion,
|
||||||
|
readContext);
|
||||||
|
case Type_Node48:
|
||||||
|
return checkRangeStartsWith(n.as<Node48>(), key, begin, end, readVersion,
|
||||||
|
readContext);
|
||||||
|
case Type_Node256:
|
||||||
|
return checkRangeStartsWith(n.as<Node256>(), key, begin, end, readVersion,
|
||||||
|
readContext);
|
||||||
|
default: // GCOVR_EXCL_LINE
|
||||||
|
__builtin_unreachable(); // GCOVR_EXCL_LINE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
// Explicitly instantiate with target avx512f attribute so the compiler can
|
// Explicitly instantiate with target avx512f attribute so the compiler can
|
||||||
// inline compare16_32bit_avx512, and generally use avx512f within more
|
// inline compare16_32bit_avx512, and generally use avx512f within more
|
||||||
@@ -3723,7 +3797,8 @@ PRESERVE_NONE void done_common_prefix_iter(Job *job, Context *context) {
|
|||||||
// If this were not true we would have returned above
|
// If this were not true we would have returned above
|
||||||
assert(job->begin.size() > 0);
|
assert(job->begin.size() > 0);
|
||||||
|
|
||||||
if (!checkRangeStartsWith(n, job->begin.subspan(0, job->lcp),
|
if (!checkRangeStartsWith(IteratorBase{n}.as<NodeT>(),
|
||||||
|
job->begin.subspan(0, job->lcp),
|
||||||
job->begin[job->lcp], job->end[job->lcp],
|
job->begin[job->lcp], job->end[job->lcp],
|
||||||
job->readVersion, &context->readContext)) {
|
job->readVersion, &context->readContext)) {
|
||||||
job->setResult(false);
|
job->setResult(false);
|
||||||
@@ -4689,7 +4764,7 @@ bool checkPrefixRead(IteratorBase n, const TrivialSpan key,
|
|||||||
|
|
||||||
// Return true if the max version among all keys that start with key[:prefixLen]
|
// Return true if the max version among all keys that start with key[:prefixLen]
|
||||||
// that are >= key is <= readVersion
|
// that are >= key is <= readVersion
|
||||||
bool checkRangeLeftSide(Node *n, TrivialSpan key, int prefixLen,
|
bool checkRangeLeftSide(IteratorBase n, TrivialSpan key, int prefixLen,
|
||||||
InternalVersionT readVersion,
|
InternalVersionT readVersion,
|
||||||
ReadContext *readContext) {
|
ReadContext *readContext) {
|
||||||
auto remaining = key;
|
auto remaining = key;
|
||||||
@@ -4697,33 +4772,32 @@ bool checkRangeLeftSide(Node *n, TrivialSpan key, int prefixLen,
|
|||||||
for (;; ++readContext->range_read_iterations_accum) {
|
for (;; ++readContext->range_read_iterations_accum) {
|
||||||
if (remaining.size() == 0) {
|
if (remaining.size() == 0) {
|
||||||
assert(searchPathLen >= prefixLen);
|
assert(searchPathLen >= prefixLen);
|
||||||
return maxVersion(n) <= readVersion;
|
return n.getMaxVersion() <= readVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (searchPathLen >= prefixLen) {
|
if (searchPathLen >= prefixLen) {
|
||||||
if (!checkMaxBetweenExclusive(n, remaining[0], 256, readVersion,
|
if (!checkMaxBetweenExclusive(n.escapeHatch(), remaining[0], 256,
|
||||||
readContext)) {
|
readVersion, readContext)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto [c, maxV] = getChildAndMaxVersion(n, remaining[0]);
|
auto [c, maxV] = n.getChildAndMaxVersion(remaining[0]);
|
||||||
Node *child = c;
|
IteratorBase child = c;
|
||||||
if (child == nullptr) {
|
if (!child.valid()) {
|
||||||
auto c = getChildGeq(n, remaining[0]);
|
auto c = n.getChildGeq(remaining[0]);
|
||||||
if (c != nullptr) {
|
if (c.valid()) {
|
||||||
if (searchPathLen < prefixLen) {
|
if (searchPathLen < prefixLen) {
|
||||||
n = c;
|
return c.checkRangeVersionOfFirstGeq(readVersion);
|
||||||
return checkRangeVersionOfFirstGeq(n, readVersion);
|
|
||||||
}
|
}
|
||||||
n = c;
|
n = c;
|
||||||
return maxVersion(n) <= readVersion;
|
return n.getMaxVersion() <= readVersion;
|
||||||
} else {
|
} else {
|
||||||
n = nextSibling(n);
|
n = n.nextSibling();
|
||||||
if (n == nullptr) {
|
if (!n.valid()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return checkRangeVersionOfFirstGeq(n, readVersion);
|
return n.checkRangeVersionOfFirstGeq(readVersion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4731,34 +4805,36 @@ bool checkRangeLeftSide(Node *n, TrivialSpan key, int prefixLen,
|
|||||||
remaining = remaining.subspan(1, remaining.size() - 1);
|
remaining = remaining.subspan(1, remaining.size() - 1);
|
||||||
++searchPathLen;
|
++searchPathLen;
|
||||||
|
|
||||||
if (n->partialKeyLen > 0) {
|
auto partialKey = n.partialKey();
|
||||||
int commonLen = std::min<int>(n->partialKeyLen, remaining.size());
|
if (partialKey.size() > 0) {
|
||||||
int i = longestCommonPrefix(n->partialKey(), remaining.data(), commonLen);
|
int commonLen = std::min<int>(partialKey.size(), remaining.size());
|
||||||
|
int i =
|
||||||
|
longestCommonPrefix(partialKey.data(), remaining.data(), commonLen);
|
||||||
searchPathLen += i;
|
searchPathLen += i;
|
||||||
if (i < commonLen) {
|
if (i < commonLen) {
|
||||||
auto c = n->partialKey()[i] <=> remaining[i];
|
auto c = partialKey[i] <=> remaining[i];
|
||||||
if (c > 0) {
|
if (c > 0) {
|
||||||
if (searchPathLen < prefixLen) {
|
if (searchPathLen < prefixLen) {
|
||||||
return checkRangeVersionOfFirstGeq(n, readVersion);
|
return n.checkRangeVersionOfFirstGeq(readVersion);
|
||||||
}
|
}
|
||||||
if (n->entryPresent && n->entry.rangeVersion > readVersion) {
|
if (n.entryPresent() && n.getEntry().rangeVersion > readVersion) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return maxV <= readVersion;
|
return maxV <= readVersion;
|
||||||
} else {
|
} else {
|
||||||
n = nextSibling(n);
|
n = n.nextSibling();
|
||||||
if (n == nullptr) {
|
if (!n.valid()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return checkRangeVersionOfFirstGeq(n, readVersion);
|
return n.checkRangeVersionOfFirstGeq(readVersion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (commonLen == n->partialKeyLen) {
|
if (commonLen == partialKey.size()) {
|
||||||
// partial key matches
|
// partial key matches
|
||||||
remaining = remaining.subspan(commonLen, remaining.size() - commonLen);
|
remaining = remaining.subspan(commonLen, remaining.size() - commonLen);
|
||||||
} else if (n->partialKeyLen > remaining.size()) {
|
} else if (partialKey.size() > remaining.size()) {
|
||||||
assert(searchPathLen >= prefixLen);
|
assert(searchPathLen >= prefixLen);
|
||||||
if (n->entryPresent && n->entry.rangeVersion > readVersion) {
|
if (n.entryPresent() && n.getEntry().rangeVersion > readVersion) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return maxV <= readVersion;
|
return maxV <= readVersion;
|
||||||
@@ -4772,7 +4848,7 @@ bool checkRangeLeftSide(Node *n, TrivialSpan key, int prefixLen,
|
|||||||
|
|
||||||
// Return true if the max version among all keys that start with key[:prefixLen]
|
// Return true if the max version among all keys that start with key[:prefixLen]
|
||||||
// that are < key is <= readVersion
|
// that are < key is <= readVersion
|
||||||
bool checkRangeRightSide(Node *n, TrivialSpan key, int prefixLen,
|
bool checkRangeRightSide(IteratorBase n, TrivialSpan key, int prefixLen,
|
||||||
InternalVersionT readVersion,
|
InternalVersionT readVersion,
|
||||||
ReadContext *readContext) {
|
ReadContext *readContext) {
|
||||||
auto remaining = key;
|
auto remaining = key;
|
||||||
@@ -4781,31 +4857,30 @@ bool checkRangeRightSide(Node *n, TrivialSpan key, int prefixLen,
|
|||||||
for (;; ++readContext->range_read_iterations_accum) {
|
for (;; ++readContext->range_read_iterations_accum) {
|
||||||
assert(searchPathLen <= key.size());
|
assert(searchPathLen <= key.size());
|
||||||
if (remaining.size() == 0) {
|
if (remaining.size() == 0) {
|
||||||
return checkRangeVersionOfFirstGeq(n, readVersion);
|
return n.checkRangeVersionOfFirstGeq(readVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (searchPathLen >= prefixLen) {
|
if (searchPathLen >= prefixLen) {
|
||||||
if (n->entryPresent && n->entry.pointVersion > readVersion) {
|
if (n.entryPresent() && n.getEntry().pointVersion > readVersion) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!checkMaxBetweenExclusive(n, -1, remaining[0], readVersion,
|
if (!checkMaxBetweenExclusive(n.escapeHatch(), -1, remaining[0],
|
||||||
readContext)) {
|
readVersion, readContext)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (searchPathLen > prefixLen && n->entryPresent &&
|
if (searchPathLen > prefixLen && n.entryPresent() &&
|
||||||
n->entry.rangeVersion > readVersion) {
|
n.getEntry().rangeVersion > readVersion) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Node *child = getChild(n, remaining[0]);
|
IteratorBase child = n.getChild(remaining[0]);
|
||||||
if (child == nullptr) {
|
if (!child.valid()) {
|
||||||
auto c = getChildGeq(n, remaining[0]);
|
auto c = n.getChildGeq(remaining[0]);
|
||||||
if (c != nullptr) {
|
if (c.valid()) {
|
||||||
n = c;
|
return c.checkRangeVersionOfFirstGeq(readVersion);
|
||||||
return checkRangeVersionOfFirstGeq(n, readVersion);
|
|
||||||
} else {
|
} else {
|
||||||
goto backtrack;
|
goto backtrack;
|
||||||
}
|
}
|
||||||
@@ -4815,87 +4890,91 @@ bool checkRangeRightSide(Node *n, TrivialSpan key, int prefixLen,
|
|||||||
remaining = remaining.subspan(1, remaining.size() - 1);
|
remaining = remaining.subspan(1, remaining.size() - 1);
|
||||||
++searchPathLen;
|
++searchPathLen;
|
||||||
|
|
||||||
if (n->partialKeyLen > 0) {
|
auto partialKey = n.partialKey();
|
||||||
int commonLen = std::min<int>(n->partialKeyLen, remaining.size());
|
if (partialKey.size() > 0) {
|
||||||
int i = longestCommonPrefix(n->partialKey(), remaining.data(), commonLen);
|
int commonLen = std::min<int>(partialKey.size(), remaining.size());
|
||||||
|
int i =
|
||||||
|
longestCommonPrefix(partialKey.data(), remaining.data(), commonLen);
|
||||||
searchPathLen += i;
|
searchPathLen += i;
|
||||||
if (i < commonLen) {
|
if (i < commonLen) {
|
||||||
++searchPathLen;
|
++searchPathLen;
|
||||||
auto c = n->partialKey()[i] <=> remaining[i];
|
auto c = partialKey[i] <=> remaining[i];
|
||||||
if (c > 0) {
|
if (c > 0) {
|
||||||
return checkRangeVersionOfFirstGeq(n, readVersion);
|
return n.checkRangeVersionOfFirstGeq(readVersion);
|
||||||
} else {
|
} else {
|
||||||
if (searchPathLen > prefixLen && n->entryPresent &&
|
if (searchPathLen > prefixLen && n.entryPresent() &&
|
||||||
n->entry.rangeVersion > readVersion) {
|
n.getEntry().rangeVersion > readVersion) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
goto backtrack;
|
goto backtrack;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (commonLen == n->partialKeyLen) {
|
if (commonLen == partialKey.size()) {
|
||||||
// partial key matches
|
// partial key matches
|
||||||
remaining = remaining.subspan(commonLen, remaining.size() - commonLen);
|
remaining = remaining.subspan(commonLen, remaining.size() - commonLen);
|
||||||
} else if (n->partialKeyLen > remaining.size()) {
|
} else if (partialKey.size() > remaining.size()) {
|
||||||
return checkRangeVersionOfFirstGeq(n, readVersion);
|
return n.checkRangeVersionOfFirstGeq(readVersion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
backtrack:
|
backtrack:
|
||||||
for (;;) {
|
for (;;) {
|
||||||
// searchPathLen > prefixLen implies n is not the root
|
// searchPathLen > prefixLen implies n is not the root
|
||||||
if (searchPathLen > prefixLen && maxVersion(n) > readVersion) {
|
if (searchPathLen > prefixLen && n.getMaxVersion() > readVersion) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (n->parent == nullptr) {
|
if (!n.parent().valid()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
auto next = getChildGeq(n->parent, n->parentsIndex + 1);
|
auto next = n.parent().getChildGeq(n.parentsIndex() + 1);
|
||||||
if (next == nullptr) {
|
if (!next.valid()) {
|
||||||
searchPathLen -= 1 + n->partialKeyLen;
|
searchPathLen -= 1 + n.partialKey().size();
|
||||||
n = n->parent;
|
n = n.parent();
|
||||||
} else {
|
} else {
|
||||||
n = next;
|
n = next;
|
||||||
return checkRangeVersionOfFirstGeq(n, readVersion);
|
return n.checkRangeVersionOfFirstGeq(readVersion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool checkRangeRead(Node *n, TrivialSpan begin, TrivialSpan end,
|
bool checkRangeRead(IteratorBase n, TrivialSpan begin, TrivialSpan end,
|
||||||
InternalVersionT readVersion, ReadContext *readContext) {
|
InternalVersionT readVersion, ReadContext *readContext) {
|
||||||
int lcp = longestCommonPrefix(begin.data(), end.data(),
|
int lcp = longestCommonPrefix(begin.data(), end.data(),
|
||||||
std::min(begin.size(), end.size()));
|
std::min(begin.size(), end.size()));
|
||||||
if (lcp == begin.size() && end.size() == begin.size() + 1 &&
|
if (lcp == begin.size() && end.size() == begin.size() + 1 &&
|
||||||
end.back() == 0) {
|
end.back() == 0) {
|
||||||
return checkPointRead(IteratorBase{n}, begin, readVersion, readContext);
|
return checkPointRead(n, begin, readVersion, readContext);
|
||||||
}
|
}
|
||||||
if (lcp == begin.size() - 1 && end.size() == begin.size() &&
|
if (lcp == begin.size() - 1 && end.size() == begin.size() &&
|
||||||
begin.back() + 1 == end.back()) {
|
begin.back() + 1 == end.back()) {
|
||||||
return checkPrefixRead(IteratorBase{n}, begin, readVersion, readContext);
|
return checkPrefixRead(n, begin, readVersion, readContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
++readContext->range_read_accum;
|
++readContext->range_read_accum;
|
||||||
|
|
||||||
auto remaining = begin.subspan(0, lcp);
|
auto remaining = begin.subspan(0, lcp);
|
||||||
|
#ifndef NDEBUG
|
||||||
Arena arena;
|
Arena arena;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Advance down common prefix, but stay on a physical path in the tree
|
// Advance down common prefix, but stay on a physical path in the tree
|
||||||
for (;; ++readContext->range_read_iterations_accum) {
|
for (;; ++readContext->range_read_iterations_accum) {
|
||||||
assert(getSearchPath(arena, n) <=>
|
assert(n.getSearchPath(arena) <=>
|
||||||
begin.subspan(0, lcp - remaining.size()) ==
|
begin.subspan(0, lcp - remaining.size()) ==
|
||||||
0);
|
0);
|
||||||
if (remaining.size() == 0) {
|
if (remaining.size() == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
auto [c, v] = getChildAndMaxVersion(n, remaining[0]);
|
auto [c, v] = n.getChildAndMaxVersion(remaining[0]);
|
||||||
Node *child = c;
|
IteratorBase child = c;
|
||||||
if (child == nullptr) {
|
if (!child.valid()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (child->partialKeyLen > 0) {
|
auto partialKey = child.partialKey();
|
||||||
int cl = std::min<int>(child->partialKeyLen, remaining.size() - 1);
|
if (partialKey.size() > 0) {
|
||||||
int i =
|
int cl = std::min<int>(partialKey.size(), remaining.size() - 1);
|
||||||
longestCommonPrefix(child->partialKey(), remaining.data() + 1, cl);
|
int i = longestCommonPrefix(partialKey.data(), remaining.data() + 1, cl);
|
||||||
if (i != child->partialKeyLen) {
|
if (i != partialKey.size()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4904,11 +4983,10 @@ bool checkRangeRead(Node *n, TrivialSpan begin, TrivialSpan end,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
n = child;
|
n = child;
|
||||||
remaining =
|
remaining = remaining.subspan(1 + partialKey.size(),
|
||||||
remaining.subspan(1 + child->partialKeyLen,
|
remaining.size() - (1 + partialKey.size()));
|
||||||
remaining.size() - (1 + child->partialKeyLen));
|
|
||||||
}
|
}
|
||||||
assert(getSearchPath(arena, n) <=> begin.subspan(0, lcp - remaining.size()) ==
|
assert(n.getSearchPath(arena) <=> begin.subspan(0, lcp - remaining.size()) ==
|
||||||
0);
|
0);
|
||||||
|
|
||||||
const int consumed = lcp - remaining.size();
|
const int consumed = lcp - remaining.size();
|
||||||
@@ -4946,7 +5024,7 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
|
|||||||
InternalVersionT(reads[i].readVersion),
|
InternalVersionT(reads[i].readVersion),
|
||||||
&context.readContext);
|
&context.readContext);
|
||||||
} else {
|
} else {
|
||||||
ok = checkRangeRead(rootParent->children[0],
|
ok = checkRangeRead(IteratorBase{rootParent->children[0]},
|
||||||
TrivialSpan(reads[i].begin.p, reads[i].begin.len),
|
TrivialSpan(reads[i].begin.p, reads[i].begin.len),
|
||||||
TrivialSpan(reads[i].end.p, reads[i].end.len),
|
TrivialSpan(reads[i].end.p, reads[i].end.len),
|
||||||
InternalVersionT(reads[i].readVersion),
|
InternalVersionT(reads[i].readVersion),
|
||||||
|
Reference in New Issue
Block a user