@@ -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;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user