Add childMaxVersion

This commit is contained in:
2024-02-23 17:02:46 -08:00
parent d43a8a5907
commit 921005edb3

View File

@@ -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<Node16 *>(self);
return self16->children[getNodeIndex(self16, index)];
return self16->children[getNodeIndex(self16, index)].child;
} else if (self->type == Type::Node48) {
auto *self48 = static_cast<Node48 *>(self);
assert(self48->bitSet.test(index));
return self48->children[self48->index[index]];
return self48->children[self48->index[index]].child;
} else {
auto *self256 = static_cast<Node256 *>(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<Node16 *>(self);
return self16->children[getNodeIndex(self16, index)].childMaxVersion;
} else if (self->type == Type::Node48) {
auto *self48 = static_cast<Node48 *>(self);
assert(self48->bitSet.test(index));
return self48->children[self48->index[index]].childMaxVersion;
} else {
auto *self256 = static_cast<Node256 *>(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<Node16 *>(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<Node48 *>(self);
assert(self48->bitSet.test(index));
self48->children[self48->index[index]].childMaxVersion =
self48->children[self48->index[index]].child->maxVersion;
} else {
auto *self256 = static_cast<Node256 *>(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<Node16 *>(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<Node48 *>(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<Node256 *>(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<Node16 *>(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<Node48 *>(self);
int secondIndex = self48->index[index];
if (secondIndex >= 0) {
return self48->children[secondIndex];
return self48->children[secondIndex].child;
}
} else {
auto *self256 = static_cast<Node256 *>(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<Node256 *>(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<Node256 *>(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<Node16 *>(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 <bool kBegin>
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 <bool kBegin>
if constexpr (kBegin) {
(*self)->maxVersion = std::max((*self)->maxVersion, writeVersion);
setParentsChildMaxVersion(*self);
}
if (key.size() == 0) {
@@ -1461,6 +1515,7 @@ template <bool kBegin>
if constexpr (!kBegin) {
(*self)->maxVersion = std::max((*self)->maxVersion, writeVersion);
setParentsChildMaxVersion(*self);
}
auto &child = getOrCreateChild(*self, key.front(), allocators);
@@ -1470,6 +1525,7 @@ template <bool kBegin>
child->parentsIndex = key.front();
child->maxVersion =
kBegin ? writeVersion : std::numeric_limits<int64_t>::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);