diff --git a/ConflictSet.cpp b/ConflictSet.cpp index b54593b..13bb91c 100644 --- a/ConflictSet.cpp +++ b/ConflictSet.cpp @@ -1125,6 +1125,53 @@ Node *getFirstChildExists(Node *self) { } } +// Consume any partial key of `self`, and update `self` and +// `key` such that `self` is along the search path of `key` +void consumePartialKey(Node *&self, std::span &key, + InternalVersionT writeVersion, WriteContext *tls) { + if (self->partialKeyLen == 0) { + return; + } + // Handle an existing partial key + int commonLen = std::min(self->partialKeyLen, key.size()); + int partialKeyIndex = + longestCommonPrefix(self->partialKey(), key.data(), commonLen); + if (partialKeyIndex < self->partialKeyLen) { + auto *old = self; + // Since root cannot have a partial key + assert(old->parent != nullptr); + InternalVersionT oldMaxVersion = exchangeMaxVersion(old, writeVersion); + + // *self will have one child (old) + auto *newSelf = tls->allocate(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); +} + // Caller is responsible for assigning a non-null pointer to the returned // reference if null. Updates child's max version to `newMaxVersion` if child // exists but does not have a partial key. @@ -2743,51 +2790,6 @@ checkMaxBetweenExclusiveImpl(Node *n, int begin, int end, InternalVersionT readVersion, ReadContext *); #endif -// Consume the partial key of `self` (which must exist), and update `self` and -// `key` such that `self` is along the search path of `key` -void consumePartialKey(Node *&self, std::span &key, - InternalVersionT writeVersion, WriteContext *tls) { - assert(self->partialKeyLen > 0); - // Handle an existing partial key - int commonLen = std::min(self->partialKeyLen, key.size()); - int partialKeyIndex = - longestCommonPrefix(self->partialKey(), key.data(), commonLen); - if (partialKeyIndex < self->partialKeyLen) { - auto *old = self; - // Since root cannot have a partial key - assert(old->parent != nullptr); - InternalVersionT oldMaxVersion = exchangeMaxVersion(old, writeVersion); - - // *self will have one child (old) - auto *newSelf = tls->allocate(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 the pointer to the newly inserted node in the tree. Caller // must set `entryPresent`, and `entry` fields. All nodes along the search path // of the result will have `maxVersion` set to `writeVersion` as a @@ -2814,11 +2816,9 @@ Node **insert(Node **self, std::span key, self = &child; - if ((*self)->partialKeyLen > 0) { - consumePartialKey(*self, key, writeVersion, tls); - assert(maxVersion(*self, impl) <= writeVersion); - setMaxVersion(*self, impl, writeVersion); - } + consumePartialKey(*self, key, writeVersion, tls); + assert(maxVersion(*self, impl) <= writeVersion); + setMaxVersion(*self, impl, writeVersion); } }