From 921005edb313432d81a6d8e80be2ef7b0ebea4d6 Mon Sep 17 00:00:00 2001 From: Andrew Noyes Date: Fri, 23 Feb 2024 17:02:46 -0800 Subject: [PATCH] Add childMaxVersion --- ConflictSet.cpp | 132 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 101 insertions(+), 31 deletions(-) diff --git a/ConflictSet.cpp b/ConflictSet.cpp index 0f56d70..8edd983 100644 --- a/ConflictSet.cpp +++ b/ConflictSet.cpp @@ -174,24 +174,29 @@ struct Node { Type type = Type::Invalid; }; +struct Child { + int64_t childMaxVersion; + Node *child; +}; + struct Node4 : Node { // Sorted uint8_t index[16]; // 16 so that we can use the same simd index search // implementation for Node4 as Node16 - Node *children[4]; + Child children[4]; Node4() { this->type = Type::Node4; } }; struct Node16 : Node { // Sorted uint8_t index[16]; - Node *children[16]; + Child children[16]; Node16() { this->type = Type::Node16; } }; struct Node48 : Node { BitSet bitSet; - Node *children[48]; + Child children[48]; int8_t nextFree = 0; int8_t index[256]; Node48() { @@ -202,8 +207,13 @@ struct Node48 : Node { struct Node256 : Node { BitSet bitSet; - Node *children[256] = {}; - Node256() { this->type = Type::Node256; } + Child children[256]; + Node256() { + this->type = Type::Node256; + for (int i = 0; i < 256; ++i) { + children[i].child = nullptr; + } + } }; struct NodeAllocators { @@ -275,36 +285,75 @@ int getNodeIndex(Node16 *self, uint8_t index) { Node *&getChildExists(Node *self, uint8_t index) { if (self->type <= Type::Node16) { auto *self16 = static_cast(self); - return self16->children[getNodeIndex(self16, index)]; + return self16->children[getNodeIndex(self16, index)].child; } else if (self->type == Type::Node48) { auto *self48 = static_cast(self); assert(self48->bitSet.test(index)); - return self48->children[self48->index[index]]; + return self48->children[self48->index[index]].child; } else { auto *self256 = static_cast(self); - return self256->children[index]; + return self256->children[index].child; } __builtin_unreachable(); // GCOVR_EXCL_LINE } +// Precondition - an entry for index must exist in the node +int64_t getChildMaxVersion(Node *self, uint8_t index) { + if (self->type <= Type::Node16) { + auto *self16 = static_cast(self); + return self16->children[getNodeIndex(self16, index)].childMaxVersion; + } else if (self->type == Type::Node48) { + auto *self48 = static_cast(self); + assert(self48->bitSet.test(index)); + return self48->children[self48->index[index]].childMaxVersion; + } else { + auto *self256 = static_cast(self); + return self256->children[index].childMaxVersion; + } + __builtin_unreachable(); // GCOVR_EXCL_LINE +} + +// Precondition - an entry for index must exist in the node +void setParentsChildMaxVersion(Node *self) { + int index = self->parentsIndex; + self = self->parent; + if (self == nullptr) { + return; + } + if (self->type <= Type::Node16) { + auto *self16 = static_cast(self); + int i = getNodeIndex(self16, index); + self16->children[i].childMaxVersion = self16->children[i].child->maxVersion; + } else if (self->type == Type::Node48) { + auto *self48 = static_cast(self); + assert(self48->bitSet.test(index)); + self48->children[self48->index[index]].childMaxVersion = + self48->children[self48->index[index]].child->maxVersion; + } else { + auto *self256 = static_cast(self); + self256->children[index].childMaxVersion = + self256->children[index].child->maxVersion; + } +} + Node *getChild(Node *self, uint8_t index) { if (self->type <= Type::Node16) { auto *self16 = static_cast(self); int i = getNodeIndex(self16, index); if (i >= 0) { - return self16->children[i]; + return self16->children[i].child; } return nullptr; } else if (self->type == Type::Node48) { auto *self48 = static_cast(self); int secondIndex = self48->index[index]; if (secondIndex >= 0) { - return self48->children[secondIndex]; + return self48->children[secondIndex].child; } return nullptr; } else { auto *self256 = static_cast(self); - return self256->children[index]; + return self256->children[index].child; } } @@ -376,7 +425,7 @@ int getChildGeq(Node *self, int child) { void setChildrenParents(Node16 *n) { for (int i = 0; i < n->numChildren; ++i) { - n->children[i]->parent = n; + n->children[i].child->parent = n; } } @@ -384,13 +433,13 @@ void setChildrenParents(Node48 *n) { if (n->numChildren < kSparseScanThreshold) { for (int i = n->bitSet.firstSetGeq(0); i >= 0; i = n->bitSet.firstSetGeq(i + 1)) { - n->children[n->index[i]]->parent = n; + n->children[n->index[i]].child->parent = n; } } else { for (int i = 0; i < 256; ++i) { int c = n->index[i]; if (c != -1) { - n->children[c]->parent = n; + n->children[c].child->parent = n; } } } @@ -400,11 +449,11 @@ void setChildrenParents(Node256 *n) { if (n->numChildren < kSparseScanThreshold) { for (int i = n->bitSet.firstSetGeq(0); i >= 0; i = n->bitSet.firstSetGeq(i + 1)) { - n->children[i]->parent = n; + n->children[i].child->parent = n; } } else { for (int i = 0; i < 256; ++i) { - auto *child = n->children[i]; + auto *child = n->children[i].child; if (child != nullptr) { child->parent = n; } @@ -422,17 +471,17 @@ Node *&getOrCreateChild(Node *&self, uint8_t index, auto *self16 = static_cast(self); int i = getNodeIndex(self16, index); if (i >= 0) { - return self16->children[i]; + return self16->children[i].child; } } else if (self->type == Type::Node48) { auto *self48 = static_cast(self); int secondIndex = self48->index[index]; if (secondIndex >= 0) { - return self48->children[secondIndex]; + return self48->children[secondIndex].child; } } else { auto *self256 = static_cast(self); - if (auto &result = self256->children[index]; result != nullptr) { + if (auto &result = self256->children[index].child; result != nullptr) { return result; } } @@ -482,12 +531,12 @@ Node *&getOrCreateChild(Node *&self, uint8_t index, memmove(self16->index + i + 1, self16->index + i, self->numChildren - (i + 1)); memmove(self16->children + i + 1, self16->children + i, - (self->numChildren - (i + 1)) * sizeof(void *)); + (self->numChildren - (i + 1)) * sizeof(Child)); break; } } self16->index[i] = index; - auto &result = self16->children[i]; + auto &result = self16->children[i].child; result = nullptr; return result; } else if (self->type == Type::Node48) { @@ -516,7 +565,7 @@ Node *&getOrCreateChild(Node *&self, uint8_t index, assert(self48->nextFree < 48); int nextFree = self48->nextFree++; self48->index[index] = nextFree; - auto &result = self48->children[nextFree]; + auto &result = self48->children[nextFree].child; result = nullptr; return result; } else { @@ -524,7 +573,7 @@ Node *&getOrCreateChild(Node *&self, uint8_t index, auto *self256 = static_cast(self); ++self->numChildren; self256->bitSet.set(index); - return self256->children[index]; + return self256->children[index].child; } } @@ -566,13 +615,14 @@ void eraseChild(Node *self, uint8_t index, NodeAllocators *allocators) { if (toRemoveChildrenIndex != lastChildrenIndex) { self48->children[toRemoveChildrenIndex] = self48->children[lastChildrenIndex]; - self48->index[self48->children[toRemoveChildrenIndex]->parentsIndex] = + self48 + ->index[self48->children[toRemoveChildrenIndex].child->parentsIndex] = toRemoveChildrenIndex; } } else { auto *self256 = static_cast(self); self256->bitSet.reset(index); - self256->children[index] = nullptr; + self256->children[index].child = nullptr; } --self->numChildren; if (self->numChildren == 0 && !self->entryPresent && @@ -919,7 +969,7 @@ int64_t maxBetweenExclusive(Node *n, int begin, int end) { auto *self = static_cast(n); for (int i = 0; i < self->numChildren && self->index[i] < end; ++i) { if (begin < self->index[i]) { - result = std::max(result, self->children[i]->maxVersion); + result = std::max(result, self->children[i].childMaxVersion); } } break; @@ -930,13 +980,15 @@ int64_t maxBetweenExclusive(Node *n, int begin, int end) { for (int i = self->bitSet.firstSetGeq(begin + 1); i < end && i >= 0; i = self->bitSet.firstSetGeq(i + 1)) { if (self->index[i] != -1) { - result = std::max(result, self->children[self->index[i]]->maxVersion); + result = + std::max(result, self->children[self->index[i]].childMaxVersion); } } } else { for (int i = begin + 1; i < end; ++i) { if (self->index[i] != -1) { - result = std::max(result, self->children[self->index[i]]->maxVersion); + result = + std::max(result, self->children[self->index[i]].childMaxVersion); } } } @@ -947,12 +999,12 @@ int64_t maxBetweenExclusive(Node *n, int begin, int end) { if (self->numChildren < kSparseScanThreshold) { for (int i = self->bitSet.firstSetGeq(begin + 1); i < end && i >= 0; i = self->bitSet.firstSetGeq(i + 1)) { - result = std::max(result, self->children[i]->maxVersion); + result = std::max(result, self->children[i].childMaxVersion); } } else { for (int i = begin + 1; i < end; ++i) { - if (self->children[i] != nullptr) { - result = std::max(result, self->children[i]->maxVersion); + if (self->children[i].child != nullptr) { + result = std::max(result, self->children[i].childMaxVersion); } } } @@ -1433,6 +1485,7 @@ template old; old->parent = *self; old->parentsIndex = old->partialKey[partialKeyIndex]; + setParentsChildMaxVersion(old); memmove(old->partialKey, old->partialKey + partialKeyIndex + 1, old->partialKeyLen - (partialKeyIndex + 1)); @@ -1453,6 +1506,7 @@ template if constexpr (kBegin) { (*self)->maxVersion = std::max((*self)->maxVersion, writeVersion); + setParentsChildMaxVersion(*self); } if (key.size() == 0) { @@ -1461,6 +1515,7 @@ template if constexpr (!kBegin) { (*self)->maxVersion = std::max((*self)->maxVersion, writeVersion); + setParentsChildMaxVersion(*self); } auto &child = getOrCreateChild(*self, key.front(), allocators); @@ -1470,6 +1525,7 @@ template child->parentsIndex = key.front(); child->maxVersion = kBegin ? writeVersion : std::numeric_limits::lowest(); + setParentsChildMaxVersion(child); } self = &child; @@ -1504,6 +1560,7 @@ void addPointWrite(Node *&root, int64_t oldestVersion, n->entryPresent = true; n->entry.pointVersion = writeVersion; n->maxVersion = writeVersion; + setParentsChildMaxVersion(n); n->entry.rangeVersion = p != nullptr ? p->entry.rangeVersion : oldestVersion; } else { @@ -1541,6 +1598,7 @@ void addWriteRange(Node *&root, int64_t oldestVersion, } n->maxVersion = std::max(n->maxVersion, writeVersion); + setParentsChildMaxVersion(n); remaining = remaining.subspan(n->partialKeyLen + 1, remaining.size() - (n->partialKeyLen + 1)); @@ -1568,6 +1626,7 @@ void addWriteRange(Node *&root, int64_t oldestVersion, beginNode->maxVersion = writeVersion; } beginNode->maxVersion = std::max(beginNode->maxVersion, writeVersion); + setParentsChildMaxVersion(beginNode); beginNode->entry.pointVersion = std::max(beginNode->entry.pointVersion, writeVersion); @@ -1581,6 +1640,7 @@ void addWriteRange(Node *&root, int64_t oldestVersion, p != nullptr ? p->entry.rangeVersion : oldestVersion; endNode->maxVersion = std::max(endNode->maxVersion, endNode->entry.pointVersion); + setParentsChildMaxVersion(endNode); } endNode->entry.rangeVersion = writeVersion; @@ -2005,6 +2065,16 @@ void checkParentPointers(Node *node, bool &success) { expected = std::max(expected, borrowed.n->entry.rangeVersion); } } + if (node->parent != nullptr && + getChildMaxVersion(node->parent, node->parentsIndex) != + node->maxVersion) { + fprintf(stderr, + "%s has max version %" PRId64 + " . But parent has child max version %" PRId64 "\n", + getSearchPathPrintable(node).c_str(), node->maxVersion, + getChildMaxVersion(node->parent, node->parentsIndex)); + success = false; + } if (node->maxVersion > oldestVersion && node->maxVersion != expected) { fprintf(stderr, "%s has max version %" PRId64 " . Expected %" PRId64 "\n", getSearchPathPrintable(node).c_str(), node->maxVersion, expected);