Remove a bunch of impl plumbing
By making it a precondition that nodes aren't the root for certain functions
This commit is contained in:
268
ConflictSet.cpp
268
ConflictSet.cpp
@@ -905,10 +905,115 @@ Node *&getChildExists(Node *self, uint8_t index) {
|
||||
}
|
||||
}
|
||||
|
||||
InternalVersionT maxVersion(Node *n, ConflictSet::Impl *);
|
||||
InternalVersionT exchangeMaxVersion(Node *n, InternalVersionT newMax);
|
||||
// Precondition `n` is not the root
|
||||
InternalVersionT maxVersion(Node *n) {
|
||||
int index = n->parentsIndex;
|
||||
n = n->parent;
|
||||
assert(n != nullptr);
|
||||
switch (n->getType()) {
|
||||
case Type_Node0: // GCOVR_EXCL_LINE
|
||||
__builtin_unreachable(); // GCOVR_EXCL_LINE
|
||||
case Type_Node3: {
|
||||
auto *n3 = static_cast<Node3 *>(n);
|
||||
int i = getNodeIndex(n3, index);
|
||||
return n3->childMaxVersion[i];
|
||||
}
|
||||
case Type_Node16: {
|
||||
auto *n16 = static_cast<Node16 *>(n);
|
||||
int i = getNodeIndex(n16, index);
|
||||
return n16->childMaxVersion[i];
|
||||
}
|
||||
case Type_Node48: {
|
||||
auto *n48 = static_cast<Node48 *>(n);
|
||||
assert(n48->bitSet.test(index));
|
||||
return n48->childMaxVersion[n48->index[index]];
|
||||
}
|
||||
case Type_Node256: {
|
||||
auto *n256 = static_cast<Node256 *>(n);
|
||||
assert(n256->bitSet.test(index));
|
||||
return n256->childMaxVersion[index];
|
||||
}
|
||||
default: // GCOVR_EXCL_LINE
|
||||
__builtin_unreachable(); // GCOVR_EXCL_LINE
|
||||
}
|
||||
}
|
||||
|
||||
void setMaxVersion(Node *n, ConflictSet::Impl *, InternalVersionT maxVersion);
|
||||
// Precondition `n` is not the root
|
||||
InternalVersionT exchangeMaxVersion(Node *n, InternalVersionT newMax) {
|
||||
int index = n->parentsIndex;
|
||||
n = n->parent;
|
||||
assert(n != nullptr);
|
||||
switch (n->getType()) {
|
||||
case Type_Node0: // GCOVR_EXCL_LINE
|
||||
__builtin_unreachable(); // GCOVR_EXCL_LINE
|
||||
case Type_Node3: {
|
||||
auto *n3 = static_cast<Node3 *>(n);
|
||||
int i = getNodeIndex(n3, index);
|
||||
return std::exchange(n3->childMaxVersion[i], newMax);
|
||||
}
|
||||
case Type_Node16: {
|
||||
auto *n16 = static_cast<Node16 *>(n);
|
||||
int i = getNodeIndex(n16, index);
|
||||
return std::exchange(n16->childMaxVersion[i], newMax);
|
||||
}
|
||||
case Type_Node48: {
|
||||
auto *n48 = static_cast<Node48 *>(n);
|
||||
assert(n48->bitSet.test(index));
|
||||
return std::exchange(n48->childMaxVersion[n48->index[index]], newMax);
|
||||
}
|
||||
case Type_Node256: {
|
||||
auto *n256 = static_cast<Node256 *>(n);
|
||||
assert(n256->bitSet.test(index));
|
||||
return std::exchange(n256->childMaxVersion[index], newMax);
|
||||
}
|
||||
default: // GCOVR_EXCL_LINE
|
||||
__builtin_unreachable(); // GCOVR_EXCL_LINE
|
||||
}
|
||||
}
|
||||
|
||||
// Precondition `n` is not the root
|
||||
void setMaxVersion(Node *n, InternalVersionT newMax) {
|
||||
assert(newMax >= InternalVersionT::zero);
|
||||
int index = n->parentsIndex;
|
||||
n = n->parent;
|
||||
assert(n != nullptr);
|
||||
switch (n->getType()) {
|
||||
case Type_Node0: // GCOVR_EXCL_LINE
|
||||
__builtin_unreachable(); // GCOVR_EXCL_LINE
|
||||
case Type_Node3: {
|
||||
auto *n3 = static_cast<Node3 *>(n);
|
||||
int i = getNodeIndex(n3, index);
|
||||
n3->childMaxVersion[i] = newMax;
|
||||
return;
|
||||
}
|
||||
case Type_Node16: {
|
||||
auto *n16 = static_cast<Node16 *>(n);
|
||||
int i = getNodeIndex(n16, index);
|
||||
n16->childMaxVersion[i] = newMax;
|
||||
return;
|
||||
}
|
||||
case Type_Node48: {
|
||||
auto *n48 = static_cast<Node48 *>(n);
|
||||
assert(n48->bitSet.test(index));
|
||||
int i = n48->index[index];
|
||||
n48->childMaxVersion[i] = newMax;
|
||||
n48->maxOfMax[i >> Node48::kMaxOfMaxShift] = std::max<InternalVersionT>(
|
||||
n48->maxOfMax[i >> Node48::kMaxOfMaxShift], newMax);
|
||||
return;
|
||||
}
|
||||
case Type_Node256: {
|
||||
auto *n256 = static_cast<Node256 *>(n);
|
||||
assert(n256->bitSet.test(index));
|
||||
n256->childMaxVersion[index] = newMax;
|
||||
n256->maxOfMax[index >> Node256::kMaxOfMaxShift] =
|
||||
std::max<InternalVersionT>(
|
||||
n256->maxOfMax[index >> Node256::kMaxOfMaxShift], newMax);
|
||||
return;
|
||||
}
|
||||
default: // GCOVR_EXCL_LINE
|
||||
__builtin_unreachable(); // GCOVR_EXCL_LINE
|
||||
}
|
||||
}
|
||||
|
||||
Node *&getInTree(Node *n, ConflictSet::Impl *);
|
||||
|
||||
@@ -1578,7 +1683,7 @@ void mergeWithChild(Node *&self, WriteContext *tls, ConflictSet::Impl *impl,
|
||||
|
||||
// Max versions are stored in the parent, so we need to update it now
|
||||
// that we have a new parent.
|
||||
setMaxVersion(child, impl, std::max(childMaxVersion, tls->zero));
|
||||
setMaxVersion(child, std::max(childMaxVersion, tls->zero));
|
||||
|
||||
self = child;
|
||||
tls->release(self3);
|
||||
@@ -1850,10 +1955,9 @@ bool checkPrefixRead(Node *n, const std::span<const uint8_t> key,
|
||||
fprintf(stderr, "Check prefix read: %s\n", printable(key).c_str());
|
||||
#endif
|
||||
auto remaining = key;
|
||||
auto *impl = tls->impl;
|
||||
for (;; ++tls->prefix_read_iterations_accum) {
|
||||
if (remaining.size() == 0) {
|
||||
return maxVersion(n, impl) <= readVersion;
|
||||
return maxVersion(n) <= readVersion;
|
||||
}
|
||||
|
||||
auto [child, maxV] = getChildAndMaxVersion(n, remaining[0]);
|
||||
@@ -1896,7 +2000,7 @@ bool checkPrefixRead(Node *n, const std::span<const uint8_t> key,
|
||||
// n is the first physical node greater than remaining, and there's no
|
||||
// eq node. All physical nodes that start with prefix are reachable from
|
||||
// n.
|
||||
if (maxVersion(n, impl) > readVersion) {
|
||||
if (maxVersion(n) > readVersion) {
|
||||
return false;
|
||||
}
|
||||
goto downLeftSpine;
|
||||
@@ -2375,7 +2479,6 @@ bool checkRangeStartsWith(Node *n, std::span<const uint8_t> key, int begin,
|
||||
fprintf(stderr, "%s(%02x,%02x)*\n", printable(key).c_str(), begin, end);
|
||||
#endif
|
||||
auto remaining = key;
|
||||
auto *impl = tls->impl;
|
||||
if (remaining.size() == 0) {
|
||||
return checkMaxBetweenExclusive(n, begin, end, readVersion, tls);
|
||||
}
|
||||
@@ -2420,7 +2523,7 @@ bool checkRangeStartsWith(Node *n, std::span<const uint8_t> key, int begin,
|
||||
if (n->entryPresent && n->entry.rangeVersion > readVersion) {
|
||||
return false;
|
||||
}
|
||||
return maxVersion(n, impl) <= readVersion;
|
||||
return maxVersion(n) <= readVersion;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -2460,7 +2563,7 @@ struct CheckRangeLeftSide {
|
||||
bool step() {
|
||||
if (remaining.size() == 0) {
|
||||
assert(searchPathLen >= prefixLen);
|
||||
ok = maxVersion(n, impl) <= readVersion;
|
||||
ok = maxVersion(n) <= readVersion;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2480,7 +2583,7 @@ struct CheckRangeLeftSide {
|
||||
return downLeftSpine();
|
||||
}
|
||||
n = c;
|
||||
ok = maxVersion(n, impl) <= readVersion;
|
||||
ok = maxVersion(n) <= readVersion;
|
||||
return true;
|
||||
} else {
|
||||
n = nextSibling(n);
|
||||
@@ -2510,7 +2613,7 @@ struct CheckRangeLeftSide {
|
||||
ok = false;
|
||||
return true;
|
||||
}
|
||||
ok = maxVersion(n, impl) <= readVersion;
|
||||
ok = maxVersion(n) <= readVersion;
|
||||
return true;
|
||||
} else {
|
||||
n = nextSibling(n);
|
||||
@@ -2530,7 +2633,7 @@ struct CheckRangeLeftSide {
|
||||
ok = false;
|
||||
return true;
|
||||
}
|
||||
ok = maxVersion(n, impl) <= readVersion;
|
||||
ok = maxVersion(n) <= readVersion;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -2651,7 +2754,7 @@ struct CheckRangeRightSide {
|
||||
|
||||
bool backtrack() {
|
||||
for (;;) {
|
||||
if (searchPathLen > prefixLen && maxVersion(n, impl) > readVersion) {
|
||||
if (searchPathLen > prefixLen && maxVersion(n) > readVersion) {
|
||||
ok = false;
|
||||
return true;
|
||||
}
|
||||
@@ -2878,8 +2981,9 @@ void addPointWrite(Node *&root, std::span<const uint8_t> key,
|
||||
}
|
||||
}
|
||||
|
||||
// Precondition: `node->entryPresent`
|
||||
void fixupMaxVersion(Node *node, ConflictSet::Impl *impl, WriteContext *tls) {
|
||||
// Precondition: `node->entryPresent`, and node is not the root
|
||||
void fixupMaxVersion(Node *node, WriteContext *tls) {
|
||||
assert(node->parent);
|
||||
InternalVersionT max;
|
||||
assert(node->entryPresent);
|
||||
max = std::max(node->entry.pointVersion, tls->zero);
|
||||
@@ -2913,7 +3017,7 @@ void fixupMaxVersion(Node *node, ConflictSet::Impl *impl, WriteContext *tls) {
|
||||
default: // GCOVR_EXCL_LINE
|
||||
__builtin_unreachable(); // GCOVR_EXCL_LINE
|
||||
}
|
||||
setMaxVersion(node, impl, max);
|
||||
setMaxVersion(node, max);
|
||||
}
|
||||
|
||||
void addWriteRange(Node *&root, std::span<const uint8_t> begin,
|
||||
@@ -2966,7 +3070,7 @@ void addWriteRange(Node *&root, std::span<const uint8_t> begin,
|
||||
}
|
||||
|
||||
// Inserting end trashed endNode's maxVersion. Fix that
|
||||
fixupMaxVersion(endNode, impl, tls);
|
||||
fixupMaxVersion(endNode, tls);
|
||||
}
|
||||
|
||||
Node *firstGeqPhysical(Node *n, const std::span<const uint8_t> key) {
|
||||
@@ -3134,7 +3238,6 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
|
||||
// Don't erase the root
|
||||
if (n == root) {
|
||||
rezero(n, oldestVersion);
|
||||
rootMaxVersion = std::max(rootMaxVersion, oldestVersion);
|
||||
n = nextPhysical(n);
|
||||
}
|
||||
int64_t set_oldest_iterations_accum = 0;
|
||||
@@ -3225,7 +3328,6 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
|
||||
root = tls.allocate<Node0>(0);
|
||||
root->numChildren = 0;
|
||||
root->parent = nullptr;
|
||||
rootMaxVersion = this->oldestVersion;
|
||||
root->entryPresent = false;
|
||||
root->partialKeyLen = 0;
|
||||
|
||||
@@ -3256,7 +3358,6 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
|
||||
int64_t keyUpdates;
|
||||
|
||||
Node *root;
|
||||
InternalVersionT rootMaxVersion;
|
||||
InternalVersionT oldestVersion;
|
||||
int64_t oldestVersionFullPrecision;
|
||||
int64_t oldestExtantVersion;
|
||||
@@ -3355,119 +3456,6 @@ Metric::Metric(ConflictSet::Impl *impl, const char *name, const char *help,
|
||||
++impl->metricsCount;
|
||||
}
|
||||
|
||||
InternalVersionT maxVersion(Node *n, ConflictSet::Impl *impl) {
|
||||
int index = n->parentsIndex;
|
||||
n = n->parent;
|
||||
if (n == nullptr) {
|
||||
return impl->rootMaxVersion;
|
||||
}
|
||||
switch (n->getType()) {
|
||||
case Type_Node0: // GCOVR_EXCL_LINE
|
||||
__builtin_unreachable(); // GCOVR_EXCL_LINE
|
||||
case Type_Node3: {
|
||||
auto *n3 = static_cast<Node3 *>(n);
|
||||
int i = getNodeIndex(n3, index);
|
||||
return n3->childMaxVersion[i];
|
||||
}
|
||||
case Type_Node16: {
|
||||
auto *n16 = static_cast<Node16 *>(n);
|
||||
int i = getNodeIndex(n16, index);
|
||||
return n16->childMaxVersion[i];
|
||||
}
|
||||
case Type_Node48: {
|
||||
auto *n48 = static_cast<Node48 *>(n);
|
||||
assert(n48->bitSet.test(index));
|
||||
return n48->childMaxVersion[n48->index[index]];
|
||||
}
|
||||
case Type_Node256: {
|
||||
auto *n256 = static_cast<Node256 *>(n);
|
||||
assert(n256->bitSet.test(index));
|
||||
return n256->childMaxVersion[index];
|
||||
}
|
||||
default: // GCOVR_EXCL_LINE
|
||||
__builtin_unreachable(); // GCOVR_EXCL_LINE
|
||||
}
|
||||
}
|
||||
|
||||
// Precondition `n` is not the root
|
||||
InternalVersionT exchangeMaxVersion(Node *n, InternalVersionT newMax) {
|
||||
int index = n->parentsIndex;
|
||||
n = n->parent;
|
||||
assert(n != nullptr);
|
||||
switch (n->getType()) {
|
||||
case Type_Node0: // GCOVR_EXCL_LINE
|
||||
__builtin_unreachable(); // GCOVR_EXCL_LINE
|
||||
case Type_Node3: {
|
||||
auto *n3 = static_cast<Node3 *>(n);
|
||||
int i = getNodeIndex(n3, index);
|
||||
return std::exchange(n3->childMaxVersion[i], newMax);
|
||||
}
|
||||
case Type_Node16: {
|
||||
auto *n16 = static_cast<Node16 *>(n);
|
||||
int i = getNodeIndex(n16, index);
|
||||
return std::exchange(n16->childMaxVersion[i], newMax);
|
||||
}
|
||||
case Type_Node48: {
|
||||
auto *n48 = static_cast<Node48 *>(n);
|
||||
assert(n48->bitSet.test(index));
|
||||
return std::exchange(n48->childMaxVersion[n48->index[index]], newMax);
|
||||
}
|
||||
case Type_Node256: {
|
||||
auto *n256 = static_cast<Node256 *>(n);
|
||||
assert(n256->bitSet.test(index));
|
||||
return std::exchange(n256->childMaxVersion[index], newMax);
|
||||
}
|
||||
default: // GCOVR_EXCL_LINE
|
||||
__builtin_unreachable(); // GCOVR_EXCL_LINE
|
||||
}
|
||||
}
|
||||
|
||||
void setMaxVersion(Node *n, ConflictSet::Impl *impl, InternalVersionT newMax) {
|
||||
assert(newMax >= InternalVersionT::zero);
|
||||
int index = n->parentsIndex;
|
||||
n = n->parent;
|
||||
if (n == nullptr) {
|
||||
impl->rootMaxVersion = newMax;
|
||||
return;
|
||||
}
|
||||
switch (n->getType()) {
|
||||
case Type_Node0: // GCOVR_EXCL_LINE
|
||||
__builtin_unreachable(); // GCOVR_EXCL_LINE
|
||||
case Type_Node3: {
|
||||
auto *n3 = static_cast<Node3 *>(n);
|
||||
int i = getNodeIndex(n3, index);
|
||||
n3->childMaxVersion[i] = newMax;
|
||||
return;
|
||||
}
|
||||
case Type_Node16: {
|
||||
auto *n16 = static_cast<Node16 *>(n);
|
||||
int i = getNodeIndex(n16, index);
|
||||
n16->childMaxVersion[i] = newMax;
|
||||
return;
|
||||
}
|
||||
case Type_Node48: {
|
||||
auto *n48 = static_cast<Node48 *>(n);
|
||||
assert(n48->bitSet.test(index));
|
||||
int i = n48->index[index];
|
||||
n48->childMaxVersion[i] = newMax;
|
||||
n48->maxOfMax[i >> Node48::kMaxOfMaxShift] = std::max<InternalVersionT>(
|
||||
n48->maxOfMax[i >> Node48::kMaxOfMaxShift], newMax);
|
||||
return;
|
||||
}
|
||||
case Type_Node256: {
|
||||
auto *n256 = static_cast<Node256 *>(n);
|
||||
assert(n256->bitSet.test(index));
|
||||
n256->childMaxVersion[index] = newMax;
|
||||
n256->maxOfMax[index >> Node256::kMaxOfMaxShift] =
|
||||
std::max<InternalVersionT>(
|
||||
n256->maxOfMax[index >> Node256::kMaxOfMaxShift], newMax);
|
||||
return;
|
||||
}
|
||||
default: // GCOVR_EXCL_LINE
|
||||
__builtin_unreachable(); // GCOVR_EXCL_LINE
|
||||
}
|
||||
}
|
||||
|
||||
Node *&getInTree(Node *n, ConflictSet::Impl *impl) {
|
||||
return n->parent == nullptr ? impl->root
|
||||
: getChildExists(n->parent, n->parentsIndex);
|
||||
@@ -3749,13 +3737,13 @@ std::string getSearchPath(Node *n) {
|
||||
fprintf(file,
|
||||
" k_%p [label=\"m=%" PRId64 " p=%" PRId64 " r=%" PRId64
|
||||
"\n%s\", pos=\"%d,%d!\"];\n",
|
||||
(void *)n, maxVersion(n, impl).toInt64(),
|
||||
(void *)n, maxVersion(n).toInt64(),
|
||||
n->entry.pointVersion.toInt64(),
|
||||
n->entry.rangeVersion.toInt64(),
|
||||
getPartialKeyPrintable(n).c_str(), x, y);
|
||||
} else {
|
||||
fprintf(file, " k_%p [label=\"m=%" PRId64 "\n%s\", pos=\"%d,%d!\"];\n",
|
||||
(void *)n, maxVersion(n, impl).toInt64(),
|
||||
(void *)n, maxVersion(n).toInt64(),
|
||||
getPartialKeyPrintable(n).c_str(), x, y);
|
||||
}
|
||||
x += kSeparation;
|
||||
@@ -3866,11 +3854,11 @@ checkMaxVersion(Node *root, Node *node, InternalVersionT oldestVersion,
|
||||
expected = std::max(expected, borrowed->entry.rangeVersion);
|
||||
}
|
||||
}
|
||||
if (maxVersion(node, impl) > oldestVersion &&
|
||||
maxVersion(node, impl) != expected) {
|
||||
if (node->parent && maxVersion(node) > oldestVersion &&
|
||||
maxVersion(node) != expected) {
|
||||
fprintf(stderr, "%s has max version %" PRId64 " . Expected %" PRId64 "\n",
|
||||
getSearchPathPrintable(node).c_str(),
|
||||
maxVersion(node, impl).toInt64(), expected.toInt64());
|
||||
getSearchPathPrintable(node).c_str(), maxVersion(node).toInt64(),
|
||||
expected.toInt64());
|
||||
success = false;
|
||||
}
|
||||
return expected;
|
||||
|
Reference in New Issue
Block a user