Extract consumePartialKey to its own function
This commit is contained in:
@@ -2883,56 +2883,65 @@ checkMaxBetweenExclusiveImpl<true>(Node *n, int begin, int end,
|
|||||||
InternalVersionT readVersion, ReadContext *);
|
InternalVersionT readVersion, ReadContext *);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Consume the partial key of `self` if it exists, and update `self` and `key`
|
||||||
|
// such that `self` is along the search path of `key`, and has maxVersion
|
||||||
|
// `writeVersion`
|
||||||
|
void consumePartialKey(Node *&self, std::span<const uint8_t> &key,
|
||||||
|
InternalVersionT writeVersion, WriteContext *tls,
|
||||||
|
ConflictSet::Impl *impl) {
|
||||||
|
if (self->partialKeyLen > 0) {
|
||||||
|
// Handle an existing partial key
|
||||||
|
int commonLen = std::min<int>(self->partialKeyLen, key.size());
|
||||||
|
int partialKeyIndex =
|
||||||
|
longestCommonPrefix(self->partialKey(), key.data(), commonLen);
|
||||||
|
if (partialKeyIndex < self->partialKeyLen) {
|
||||||
|
auto *old = self;
|
||||||
|
InternalVersionT oldMaxVersion =
|
||||||
|
exchangeMaxVersion(old, writeVersion, impl);
|
||||||
|
|
||||||
|
// *self will have one child (old)
|
||||||
|
auto *newSelf = tls->allocate<Node3>(partialKeyIndex);
|
||||||
|
|
||||||
|
newSelf->parent = old->parent;
|
||||||
|
newSelf->parentsIndex = old->parentsIndex;
|
||||||
|
newSelf->partialKeyLen = partialKeyIndex;
|
||||||
|
newSelf->entryPresent = false;
|
||||||
|
newSelf->numChildren = 1;
|
||||||
|
|
||||||
|
memcpy(newSelf->partialKey(), old->partialKey(), newSelf->partialKeyLen);
|
||||||
|
|
||||||
|
uint8_t oldDistinguishingByte = old->partialKey()[partialKeyIndex];
|
||||||
|
old->parent = newSelf;
|
||||||
|
old->parentsIndex = oldDistinguishingByte;
|
||||||
|
newSelf->index[0] = oldDistinguishingByte;
|
||||||
|
newSelf->children[0] = old;
|
||||||
|
newSelf->childMaxVersion[0] = oldMaxVersion;
|
||||||
|
self = newSelf;
|
||||||
|
|
||||||
|
memmove(old->partialKey(), old->partialKey() + partialKeyIndex + 1,
|
||||||
|
old->partialKeyLen - (partialKeyIndex + 1));
|
||||||
|
old->partialKeyLen -= partialKeyIndex + 1;
|
||||||
|
|
||||||
|
// We would consider decreasing capacity here, but we can't invalidate
|
||||||
|
// old since it's not on the search path. setOldestVersion will clean it
|
||||||
|
// up.
|
||||||
|
}
|
||||||
|
key = key.subspan(partialKeyIndex, key.size() - partialKeyIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Returns a pointer to the newly inserted node. Caller must set
|
// Returns a pointer to the newly inserted node. Caller must set
|
||||||
// `entryPresent`, and `entry` fields. All nodes along the search path of the
|
// `entryPresent`, and `entry` fields. All nodes along the search path of the
|
||||||
// result will have `maxVersion` set to `writeVersion` as a postcondition. Nodes
|
// result will have `maxVersion` set to `writeVersion` as a postcondition. Nodes
|
||||||
// along the search path may be invalidated.
|
// along the search path may be invalidated.
|
||||||
[[nodiscard]] Node *insert(Node **self, std::span<const uint8_t> key,
|
[[nodiscard]]
|
||||||
InternalVersionT writeVersion, WriteContext *tls,
|
Node *insert(Node **self, std::span<const uint8_t> key,
|
||||||
ConflictSet::Impl *impl) {
|
InternalVersionT writeVersion, WriteContext *tls,
|
||||||
|
ConflictSet::Impl *impl) {
|
||||||
|
|
||||||
for (;; ++tls->accum.insert_iterations) {
|
for (;; ++tls->accum.insert_iterations) {
|
||||||
|
|
||||||
if ((*self)->partialKeyLen > 0) {
|
consumePartialKey(*self, key, writeVersion, tls, impl);
|
||||||
// Handle an existing partial key
|
|
||||||
int commonLen = std::min<int>((*self)->partialKeyLen, key.size());
|
|
||||||
int partialKeyIndex =
|
|
||||||
longestCommonPrefix((*self)->partialKey(), key.data(), commonLen);
|
|
||||||
if (partialKeyIndex < (*self)->partialKeyLen) {
|
|
||||||
auto *old = *self;
|
|
||||||
InternalVersionT oldMaxVersion =
|
|
||||||
exchangeMaxVersion(old, writeVersion, impl);
|
|
||||||
|
|
||||||
// *self will have one child (old)
|
|
||||||
auto *newSelf = tls->allocate<Node3>(partialKeyIndex);
|
|
||||||
|
|
||||||
newSelf->parent = old->parent;
|
|
||||||
newSelf->parentsIndex = old->parentsIndex;
|
|
||||||
newSelf->partialKeyLen = partialKeyIndex;
|
|
||||||
newSelf->entryPresent = false;
|
|
||||||
newSelf->numChildren = 1;
|
|
||||||
|
|
||||||
memcpy(newSelf->partialKey(), old->partialKey(),
|
|
||||||
newSelf->partialKeyLen);
|
|
||||||
|
|
||||||
uint8_t oldDistinguishingByte = old->partialKey()[partialKeyIndex];
|
|
||||||
old->parent = newSelf;
|
|
||||||
old->parentsIndex = oldDistinguishingByte;
|
|
||||||
newSelf->index[0] = oldDistinguishingByte;
|
|
||||||
newSelf->children[0] = old;
|
|
||||||
newSelf->childMaxVersion[0] = oldMaxVersion;
|
|
||||||
*self = newSelf;
|
|
||||||
|
|
||||||
memmove(old->partialKey(), old->partialKey() + partialKeyIndex + 1,
|
|
||||||
old->partialKeyLen - (partialKeyIndex + 1));
|
|
||||||
old->partialKeyLen -= partialKeyIndex + 1;
|
|
||||||
|
|
||||||
// We would consider decreasing capacity here, but we can't invalidate
|
|
||||||
// old since it's not on the search path. setOldestVersion will clean it
|
|
||||||
// up.
|
|
||||||
}
|
|
||||||
key = key.subspan(partialKeyIndex, key.size() - partialKeyIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(maxVersion(*self, impl) <= writeVersion);
|
assert(maxVersion(*self, impl) <= writeVersion);
|
||||||
setMaxVersion(*self, impl, writeVersion);
|
setMaxVersion(*self, impl, writeVersion);
|
||||||
|
Reference in New Issue
Block a user