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:
2024-08-15 17:15:37 -07:00
parent e480f66846
commit b808b97940

View File

@@ -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;