Add gcScanStep
Also remove oldestVersion arg in write call tree
This commit is contained in:
@@ -2646,9 +2646,9 @@ void destroyTree(Node *root) {
|
||||
}
|
||||
}
|
||||
|
||||
void addPointWrite(Node *&root, InternalVersionT oldestVersion,
|
||||
std::span<const uint8_t> key, InternalVersionT writeVersion,
|
||||
NodeAllocators *allocators, ConflictSet::Impl *impl) {
|
||||
void addPointWrite(Node *&root, std::span<const uint8_t> key,
|
||||
InternalVersionT writeVersion, NodeAllocators *allocators,
|
||||
ConflictSet::Impl *impl) {
|
||||
auto *n = insert<true>(&root, key, writeVersion, allocators, impl);
|
||||
if (!n->entryPresent) {
|
||||
auto *p = nextLogical(n);
|
||||
@@ -2659,24 +2659,22 @@ void addPointWrite(Node *&root, InternalVersionT oldestVersion,
|
||||
n->entry.pointVersion = writeVersion;
|
||||
setMaxVersion(n, impl, writeVersion);
|
||||
n->entry.rangeVersion =
|
||||
p != nullptr ? p->entry.rangeVersion : oldestVersion;
|
||||
p != nullptr ? p->entry.rangeVersion : InternalVersionT::zero;
|
||||
} else {
|
||||
assert(writeVersion >= n->entry.pointVersion);
|
||||
n->entry.pointVersion = writeVersion;
|
||||
}
|
||||
}
|
||||
|
||||
void addWriteRange(Node *&root, InternalVersionT oldestVersion,
|
||||
std::span<const uint8_t> begin, std::span<const uint8_t> end,
|
||||
InternalVersionT writeVersion, NodeAllocators *allocators,
|
||||
ConflictSet::Impl *impl) {
|
||||
void addWriteRange(Node *&root, std::span<const uint8_t> begin,
|
||||
std::span<const uint8_t> end, InternalVersionT writeVersion,
|
||||
NodeAllocators *allocators, ConflictSet::Impl *impl) {
|
||||
|
||||
int lcp = longestCommonPrefix(begin.data(), end.data(),
|
||||
std::min(begin.size(), end.size()));
|
||||
if (lcp == int(begin.size()) && end.size() == begin.size() + 1 &&
|
||||
end.back() == 0) {
|
||||
return addPointWrite(root, oldestVersion, begin, writeVersion, allocators,
|
||||
impl);
|
||||
return addPointWrite(root, begin, writeVersion, allocators, impl);
|
||||
}
|
||||
const bool beginIsPrefix = lcp == int(begin.size());
|
||||
auto remaining = begin.subspan(0, lcp);
|
||||
@@ -2724,7 +2722,7 @@ void addWriteRange(Node *&root, InternalVersionT oldestVersion,
|
||||
if (insertedBegin) {
|
||||
auto *p = nextLogical(beginNode);
|
||||
beginNode->entry.rangeVersion =
|
||||
p != nullptr ? p->entry.rangeVersion : oldestVersion;
|
||||
p != nullptr ? p->entry.rangeVersion : InternalVersionT::zero;
|
||||
beginNode->entry.pointVersion = writeVersion;
|
||||
assert(maxVersion(beginNode, impl) <= writeVersion);
|
||||
setMaxVersion(beginNode, impl, writeVersion);
|
||||
@@ -2743,7 +2741,7 @@ void addWriteRange(Node *&root, InternalVersionT oldestVersion,
|
||||
if (insertedEnd) {
|
||||
auto *p = nextLogical(endNode);
|
||||
endNode->entry.pointVersion =
|
||||
p != nullptr ? p->entry.rangeVersion : oldestVersion;
|
||||
p != nullptr ? p->entry.rangeVersion : InternalVersionT::zero;
|
||||
auto m = maxVersion(endNode, impl);
|
||||
setMaxVersion(endNode, impl,
|
||||
std::max<InternalVersionT>(m, endNode->entry.pointVersion));
|
||||
@@ -2862,30 +2860,18 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
|
||||
auto end = std::span<const uint8_t>(w.end.p, w.end.len);
|
||||
if (w.end.len > 0) {
|
||||
keyUpdates += 3;
|
||||
addWriteRange(root, oldestVersion, begin, end,
|
||||
InternalVersionT(writeVersion), &allocators, this);
|
||||
addWriteRange(root, begin, end, InternalVersionT(writeVersion),
|
||||
&allocators, this);
|
||||
} else {
|
||||
keyUpdates += 2;
|
||||
addPointWrite(root, oldestVersion, begin,
|
||||
InternalVersionT(writeVersion), &allocators, this);
|
||||
addPointWrite(root, begin, InternalVersionT(writeVersion), &allocators,
|
||||
this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setOldestVersion(int64_t o) {
|
||||
InternalVersionT oldestVersion{o};
|
||||
assert(o >= oldestVersionFullPrecision);
|
||||
this->oldestVersionFullPrecision = o;
|
||||
this->oldestVersion = oldestVersion;
|
||||
InternalVersionT::zero = oldestVersion;
|
||||
#ifdef NDEBUG
|
||||
// This is here for performance reasons, since we want to amortize the cost
|
||||
// of storing the search path as a string. In tests, we want to exercise the
|
||||
// rest of the code often.
|
||||
if (keyUpdates < 100) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
// Spends up to `fuel` gc'ing, and returns its unused fuel
|
||||
int64_t gcScanStep(int64_t fuel) {
|
||||
Node *n = firstGeq(root, removalKey).n;
|
||||
// There's no way to erase removalKey without introducing a key after it
|
||||
assert(n != nullptr);
|
||||
@@ -2893,7 +2879,7 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
|
||||
if (n == root) {
|
||||
n = nextPhysical(n);
|
||||
}
|
||||
for (; keyUpdates > 0 && n != nullptr; --keyUpdates) {
|
||||
for (; fuel > 0 && n != nullptr; --fuel) {
|
||||
if (n->entryPresent && std::max(n->entry.pointVersion,
|
||||
n->entry.rangeVersion) <= oldestVersion) {
|
||||
// Any transaction n would have prevented from committing is
|
||||
@@ -2915,6 +2901,24 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
|
||||
removalKeyArena = Arena();
|
||||
removalKey = getSearchPath(removalKeyArena, n);
|
||||
}
|
||||
return fuel;
|
||||
}
|
||||
|
||||
void setOldestVersion(int64_t o) {
|
||||
InternalVersionT oldestVersion{o};
|
||||
assert(o >= oldestVersionFullPrecision);
|
||||
this->oldestVersionFullPrecision = o;
|
||||
this->oldestVersion = oldestVersion;
|
||||
InternalVersionT::zero = oldestVersion;
|
||||
#ifdef NDEBUG
|
||||
// This is here for performance reasons, since we want to amortize the cost
|
||||
// of storing the search path as a string. In tests, we want to exercise the
|
||||
// rest of the code often.
|
||||
if (keyUpdates < 100) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
keyUpdates = gcScanStep(keyUpdates);
|
||||
}
|
||||
|
||||
explicit Impl(int64_t oldestVersion)
|
||||
|
Reference in New Issue
Block a user