105
ConflictSet.cpp
105
ConflictSet.cpp
@@ -552,6 +552,12 @@ int getChildGeq(Node *self, int child) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
void setChildrenParents(Node4 *n) {
|
||||
for (int i = 0; i < n->numChildren; ++i) {
|
||||
n->children[i].child->parent = n;
|
||||
}
|
||||
}
|
||||
|
||||
void setChildrenParents(Node16 *n) {
|
||||
for (int i = 0; i < n->numChildren; ++i) {
|
||||
n->children[i].child->parent = n;
|
||||
@@ -706,8 +712,95 @@ Node *&getOrCreateChild(Node *&self, uint8_t index,
|
||||
}
|
||||
}
|
||||
|
||||
// TODO fuse into erase child so we don't need to repeat branches on type
|
||||
void maybeDownsize(Node *self, Node *&root, NodeAllocators *allocators) {
|
||||
switch (self->type) {
|
||||
case Type::Node0:
|
||||
__builtin_unreachable(); // GCOVR_EXCL_LINE
|
||||
case Type::Node4:
|
||||
if (self->numChildren < kMinChildrenNode4) {
|
||||
// Merge partial key with child
|
||||
}
|
||||
break;
|
||||
case Type::Node16:
|
||||
if (self->numChildren < kMinChildrenNode16) {
|
||||
auto *self16 = (Node16 *)self;
|
||||
auto *newSelf = allocators->node4.allocate(self->partialKeyLen);
|
||||
memcpy((char *)newSelf + kNodeCopyBegin, (char *)self + kNodeCopyBegin,
|
||||
kNodeCopySize);
|
||||
memcpy(newSelf->partialKey(), self16->partialKey(), self->partialKeyLen);
|
||||
// TODO replace with memcpy?
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
newSelf->index[i] = self16->index[i];
|
||||
newSelf->children[i] = self16->children[i];
|
||||
}
|
||||
allocators->node16.release(self16);
|
||||
setChildrenParents(newSelf);
|
||||
if (newSelf->parent == nullptr) {
|
||||
root = newSelf;
|
||||
} else {
|
||||
getChildExists(newSelf->parent, newSelf->parentsIndex) = newSelf;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Type::Node48:
|
||||
if (self->numChildren < kMinChildrenNode48) {
|
||||
auto *self48 = (Node48 *)self;
|
||||
auto *newSelf = allocators->node16.allocate(self->partialKeyLen);
|
||||
memcpy((char *)newSelf + kNodeCopyBegin, (char *)self + kNodeCopyBegin,
|
||||
kNodeCopySize);
|
||||
memcpy(newSelf->partialKey(), self48->partialKey(), self->partialKeyLen);
|
||||
|
||||
int i = 0;
|
||||
self48->bitSet.forEachInRange(
|
||||
[&](int c) {
|
||||
newSelf->index[i] = c;
|
||||
newSelf->children[i] = self48->children[self48->index[c]];
|
||||
++i;
|
||||
},
|
||||
0, 256);
|
||||
|
||||
allocators->node48.release(self48);
|
||||
setChildrenParents(newSelf);
|
||||
if (newSelf->parent == nullptr) {
|
||||
root = newSelf;
|
||||
} else {
|
||||
getChildExists(newSelf->parent, newSelf->parentsIndex) = newSelf;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Type::Node256:
|
||||
if (self->numChildren < kMinChildrenNode256) {
|
||||
auto *self256 = (Node256 *)self;
|
||||
auto *newSelf = allocators->node48.allocate(self->partialKeyLen);
|
||||
memcpy((char *)newSelf + kNodeCopyBegin, (char *)self + kNodeCopyBegin,
|
||||
kNodeCopySize);
|
||||
memcpy(newSelf->partialKey(), self256->partialKey(), self->partialKeyLen);
|
||||
|
||||
newSelf->bitSet = self256->bitSet;
|
||||
newSelf->bitSet.forEachInRange(
|
||||
[&](int c) {
|
||||
newSelf->index[c] = newSelf->nextFree;
|
||||
newSelf->children[newSelf->nextFree] = self256->children[c];
|
||||
++newSelf->nextFree;
|
||||
},
|
||||
0, 256);
|
||||
|
||||
allocators->node256.release(self256);
|
||||
setChildrenParents(newSelf);
|
||||
if (newSelf->parent == nullptr) {
|
||||
root = newSelf;
|
||||
} else {
|
||||
getChildExists(newSelf->parent, newSelf->parentsIndex) = newSelf;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Precondition - an entry for index must exist in the node
|
||||
void eraseChild(Node *self, uint8_t index, NodeAllocators *allocators) {
|
||||
void eraseChild(Node *self, uint8_t index, NodeAllocators *allocators,
|
||||
Node *&root) {
|
||||
auto *child = getChildExists(self, index);
|
||||
switch (child->type) {
|
||||
case Type::Node0:
|
||||
@@ -733,7 +826,7 @@ void eraseChild(Node *self, uint8_t index, NodeAllocators *allocators) {
|
||||
memmove(self16->index + nodeIndex, self16->index + nodeIndex + 1,
|
||||
sizeof(self16->index[0]) * (self->numChildren - (nodeIndex + 1)));
|
||||
memmove(self16->children + nodeIndex, self16->children + nodeIndex + 1,
|
||||
sizeof(self16->children[0]) * // NOLINT
|
||||
sizeof(self16->children[0]) *
|
||||
(self->numChildren - (nodeIndex + 1)));
|
||||
} else if (self->type == Type::Node48) {
|
||||
auto *self48 = static_cast<Node48 *>(self);
|
||||
@@ -757,7 +850,9 @@ void eraseChild(Node *self, uint8_t index, NodeAllocators *allocators) {
|
||||
--self->numChildren;
|
||||
if (self->numChildren == 0 && !self->entryPresent &&
|
||||
self->parent != nullptr) {
|
||||
eraseChild(self->parent, self->parentsIndex, allocators);
|
||||
eraseChild(self->parent, self->parentsIndex, allocators, root);
|
||||
} else {
|
||||
maybeDownsize(self, root, allocators);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1773,7 +1868,7 @@ void addWriteRange(Node *&root, int64_t oldestVersion,
|
||||
beginNode = nextLogical(beginNode);
|
||||
old->entryPresent = false;
|
||||
if (old->numChildren == 0 && old->parent != nullptr) {
|
||||
eraseChild(old->parent, old->parentsIndex, allocators);
|
||||
eraseChild(old->parent, old->parentsIndex, allocators, root);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1904,7 +1999,7 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
|
||||
assert(n->entry.rangeVersion <= oldestVersion);
|
||||
prev->entryPresent = false;
|
||||
if (prev->numChildren == 0 && prev->parent != nullptr) {
|
||||
eraseChild(prev->parent, prev->parentsIndex, &allocators);
|
||||
eraseChild(prev->parent, prev->parentsIndex, &allocators, root);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user