Check min number of children invariant

CC #9
This commit is contained in:
2024-03-11 16:03:56 -07:00
parent b3b91ef860
commit 52db15d8bd

View File

@@ -718,10 +718,23 @@ void maybeDownsize(Node *self, Node *&root, NodeAllocators *allocators,
switch (self->type) { switch (self->type) {
case Type::Node0: case Type::Node0:
__builtin_unreachable(); // GCOVR_EXCL_LINE __builtin_unreachable(); // GCOVR_EXCL_LINE
case Type::Node4: case Type::Node4: {
if (self->numChildren < 2) { auto *self4 = (Node4 *)self;
if (self->numChildren == 0) {
auto *newSelf = allocators->node0.allocate(self->partialKeyLen);
memcpy((char *)newSelf + kNodeCopyBegin, (char *)self + kNodeCopyBegin,
kNodeCopySize);
memcpy(newSelf->partialKey(), self4->partialKey(), self->partialKeyLen);
if (self->parent == nullptr) {
root = newSelf;
} else {
getChildExists(self->parent, self->parentsIndex) = newSelf;
}
allocators->node4.release(self4);
} else if (self->numChildren == 1) {
if (!self->entryPresent) { if (!self->entryPresent) {
auto *self4 = (Node4 *)self;
auto *child = self4->children[0].child; auto *child = self4->children[0].child;
int minCapacity = self4->partialKeyLen + 1 + child->partialKeyLen; int minCapacity = self4->partialKeyLen + 1 + child->partialKeyLen;
@@ -763,7 +776,7 @@ void maybeDownsize(Node *self, Node *&root, NodeAllocators *allocators,
allocators->node4.release(self4); allocators->node4.release(self4);
} }
} }
break; } break;
case Type::Node16: case Type::Node16:
if (self->numChildren < kMinChildrenNode16) { if (self->numChildren < kMinChildrenNode16) {
auto *self16 = (Node16 *)self; auto *self16 = (Node16 *)self;
@@ -2365,6 +2378,39 @@ Iterator firstGeq(Node *n, std::string_view key) {
return total; return total;
} }
[[maybe_unused]] void checkMinChildCount(Node *node, bool &success) {
int minNumChildren;
switch (node->type) {
case Type::Node0:
minNumChildren = 0;
break;
case Type::Node4:
minNumChildren = kMinChildrenNode4;
break;
case Type::Node16:
minNumChildren = kMinChildrenNode16;
break;
case Type::Node48:
minNumChildren = kMinChildrenNode48;
break;
case Type::Node256:
minNumChildren = kMinChildrenNode256;
break;
}
if (node->numChildren < minNumChildren) {
Arena arena;
fprintf(stderr,
"%s has %d children, which is less than the minimum required %d\n",
getSearchPathPrintable(node).c_str(), node->numChildren,
minNumChildren);
success = false;
}
for (int i = getChildGeq(node, 0); i >= 0; i = getChildGeq(node, i + 1)) {
auto *child = getChildExists(node, i);
checkMinChildCount(child, success);
}
}
bool checkCorrectness(Node *node, int64_t oldestVersion, bool checkCorrectness(Node *node, int64_t oldestVersion,
ConflictSet::Impl *impl) { ConflictSet::Impl *impl) {
bool success = true; bool success = true;
@@ -2372,6 +2418,7 @@ bool checkCorrectness(Node *node, int64_t oldestVersion,
checkParentPointers(node, success); checkParentPointers(node, success);
checkMaxVersion(node, node, oldestVersion, success, impl); checkMaxVersion(node, node, oldestVersion, success, impl);
checkEntriesExist(node, success); checkEntriesExist(node, success);
checkMinChildCount(node, success);
return success; return success;
} }