Specialize partial key split for newly created Node3
This commit is contained in:
@@ -902,6 +902,8 @@ Node *&getChildExists(Node *self, uint8_t index) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
InternalVersionT maxVersion(Node *n, ConflictSet::Impl *);
|
InternalVersionT maxVersion(Node *n, ConflictSet::Impl *);
|
||||||
|
InternalVersionT exchangeMaxVersion(Node *n, InternalVersionT newMax,
|
||||||
|
ConflictSet::Impl *);
|
||||||
|
|
||||||
void setMaxVersion(Node *n, ConflictSet::Impl *, InternalVersionT maxVersion);
|
void setMaxVersion(Node *n, ConflictSet::Impl *, InternalVersionT maxVersion);
|
||||||
|
|
||||||
@@ -2898,26 +2900,28 @@ checkMaxBetweenExclusiveImpl<true>(Node *n, int begin, int end,
|
|||||||
longestCommonPrefix((*self)->partialKey(), key.data(), commonLen);
|
longestCommonPrefix((*self)->partialKey(), key.data(), commonLen);
|
||||||
if (partialKeyIndex < (*self)->partialKeyLen) {
|
if (partialKeyIndex < (*self)->partialKeyLen) {
|
||||||
auto *old = *self;
|
auto *old = *self;
|
||||||
InternalVersionT oldMaxVersion = maxVersion(old, impl);
|
InternalVersionT oldMaxVersion =
|
||||||
|
exchangeMaxVersion(old, writeVersion, impl);
|
||||||
|
|
||||||
// *self will have one child
|
// *self will have one child (old)
|
||||||
*self = tls->allocate<Node3>(partialKeyIndex);
|
auto *newSelf = tls->allocate<Node3>(partialKeyIndex);
|
||||||
|
|
||||||
memcpy((char *)*self + kNodeCopyBegin, (char *)old + kNodeCopyBegin,
|
newSelf->parent = old->parent;
|
||||||
kNodeCopySize);
|
newSelf->parentsIndex = old->parentsIndex;
|
||||||
(*self)->partialKeyLen = partialKeyIndex;
|
newSelf->partialKeyLen = partialKeyIndex;
|
||||||
|
newSelf->entryPresent = false;
|
||||||
|
newSelf->numChildren = 1;
|
||||||
|
|
||||||
// Not necessary to call removeKey here, since this node is "synthetic"
|
memcpy(newSelf->partialKey(), old->partialKey(),
|
||||||
(*self)->entryPresent = false;
|
newSelf->partialKeyLen);
|
||||||
|
|
||||||
(*self)->numChildren = 0;
|
uint8_t oldDistinguishingByte = old->partialKey()[partialKeyIndex];
|
||||||
memcpy((*self)->partialKey(), old->partialKey(),
|
old->parent = newSelf;
|
||||||
(*self)->partialKeyLen);
|
old->parentsIndex = oldDistinguishingByte;
|
||||||
|
newSelf->index[0] = oldDistinguishingByte;
|
||||||
getOrCreateChild(*self, old->partialKey()[partialKeyIndex], tls) = old;
|
newSelf->children[0] = old;
|
||||||
old->parent = *self;
|
newSelf->childMaxVersion[0] = oldMaxVersion;
|
||||||
old->parentsIndex = old->partialKey()[partialKeyIndex];
|
*self = newSelf;
|
||||||
setMaxVersion(old, impl, oldMaxVersion);
|
|
||||||
|
|
||||||
memmove(old->partialKey(), old->partialKey() + partialKeyIndex + 1,
|
memmove(old->partialKey(), old->partialKey() + partialKeyIndex + 1,
|
||||||
old->partialKeyLen - (partialKeyIndex + 1));
|
old->partialKeyLen - (partialKeyIndex + 1));
|
||||||
@@ -3548,6 +3552,41 @@ InternalVersionT maxVersion(Node *n, ConflictSet::Impl *impl) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
InternalVersionT exchangeMaxVersion(Node *n, InternalVersionT newMax,
|
||||||
|
ConflictSet::Impl *impl) {
|
||||||
|
int index = n->parentsIndex;
|
||||||
|
n = n->parent;
|
||||||
|
if (n == nullptr) {
|
||||||
|
return std::exchange(impl->rootMaxVersion, newMax);
|
||||||
|
}
|
||||||
|
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) {
|
void setMaxVersion(Node *n, ConflictSet::Impl *impl, InternalVersionT newMax) {
|
||||||
int index = n->parentsIndex;
|
int index = n->parentsIndex;
|
||||||
n = n->parent;
|
n = n->parent;
|
||||||
|
Reference in New Issue
Block a user