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,
|
void addPointWrite(Node *&root, std::span<const uint8_t> key,
|
||||||
std::span<const uint8_t> key, InternalVersionT writeVersion,
|
InternalVersionT writeVersion, NodeAllocators *allocators,
|
||||||
NodeAllocators *allocators, ConflictSet::Impl *impl) {
|
ConflictSet::Impl *impl) {
|
||||||
auto *n = insert<true>(&root, key, writeVersion, allocators, impl);
|
auto *n = insert<true>(&root, key, writeVersion, allocators, impl);
|
||||||
if (!n->entryPresent) {
|
if (!n->entryPresent) {
|
||||||
auto *p = nextLogical(n);
|
auto *p = nextLogical(n);
|
||||||
@@ -2659,24 +2659,22 @@ void addPointWrite(Node *&root, InternalVersionT oldestVersion,
|
|||||||
n->entry.pointVersion = writeVersion;
|
n->entry.pointVersion = writeVersion;
|
||||||
setMaxVersion(n, impl, writeVersion);
|
setMaxVersion(n, impl, writeVersion);
|
||||||
n->entry.rangeVersion =
|
n->entry.rangeVersion =
|
||||||
p != nullptr ? p->entry.rangeVersion : oldestVersion;
|
p != nullptr ? p->entry.rangeVersion : InternalVersionT::zero;
|
||||||
} else {
|
} else {
|
||||||
assert(writeVersion >= n->entry.pointVersion);
|
assert(writeVersion >= n->entry.pointVersion);
|
||||||
n->entry.pointVersion = writeVersion;
|
n->entry.pointVersion = writeVersion;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void addWriteRange(Node *&root, InternalVersionT oldestVersion,
|
void addWriteRange(Node *&root, std::span<const uint8_t> begin,
|
||||||
std::span<const uint8_t> begin, std::span<const uint8_t> end,
|
std::span<const uint8_t> end, InternalVersionT writeVersion,
|
||||||
InternalVersionT writeVersion, NodeAllocators *allocators,
|
NodeAllocators *allocators, ConflictSet::Impl *impl) {
|
||||||
ConflictSet::Impl *impl) {
|
|
||||||
|
|
||||||
int lcp = longestCommonPrefix(begin.data(), end.data(),
|
int lcp = longestCommonPrefix(begin.data(), end.data(),
|
||||||
std::min(begin.size(), end.size()));
|
std::min(begin.size(), end.size()));
|
||||||
if (lcp == int(begin.size()) && end.size() == begin.size() + 1 &&
|
if (lcp == int(begin.size()) && end.size() == begin.size() + 1 &&
|
||||||
end.back() == 0) {
|
end.back() == 0) {
|
||||||
return addPointWrite(root, oldestVersion, begin, writeVersion, allocators,
|
return addPointWrite(root, begin, writeVersion, allocators, impl);
|
||||||
impl);
|
|
||||||
}
|
}
|
||||||
const bool beginIsPrefix = lcp == int(begin.size());
|
const bool beginIsPrefix = lcp == int(begin.size());
|
||||||
auto remaining = begin.subspan(0, lcp);
|
auto remaining = begin.subspan(0, lcp);
|
||||||
@@ -2724,7 +2722,7 @@ void addWriteRange(Node *&root, InternalVersionT oldestVersion,
|
|||||||
if (insertedBegin) {
|
if (insertedBegin) {
|
||||||
auto *p = nextLogical(beginNode);
|
auto *p = nextLogical(beginNode);
|
||||||
beginNode->entry.rangeVersion =
|
beginNode->entry.rangeVersion =
|
||||||
p != nullptr ? p->entry.rangeVersion : oldestVersion;
|
p != nullptr ? p->entry.rangeVersion : InternalVersionT::zero;
|
||||||
beginNode->entry.pointVersion = writeVersion;
|
beginNode->entry.pointVersion = writeVersion;
|
||||||
assert(maxVersion(beginNode, impl) <= writeVersion);
|
assert(maxVersion(beginNode, impl) <= writeVersion);
|
||||||
setMaxVersion(beginNode, impl, writeVersion);
|
setMaxVersion(beginNode, impl, writeVersion);
|
||||||
@@ -2743,7 +2741,7 @@ void addWriteRange(Node *&root, InternalVersionT oldestVersion,
|
|||||||
if (insertedEnd) {
|
if (insertedEnd) {
|
||||||
auto *p = nextLogical(endNode);
|
auto *p = nextLogical(endNode);
|
||||||
endNode->entry.pointVersion =
|
endNode->entry.pointVersion =
|
||||||
p != nullptr ? p->entry.rangeVersion : oldestVersion;
|
p != nullptr ? p->entry.rangeVersion : InternalVersionT::zero;
|
||||||
auto m = maxVersion(endNode, impl);
|
auto m = maxVersion(endNode, impl);
|
||||||
setMaxVersion(endNode, impl,
|
setMaxVersion(endNode, impl,
|
||||||
std::max<InternalVersionT>(m, endNode->entry.pointVersion));
|
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);
|
auto end = std::span<const uint8_t>(w.end.p, w.end.len);
|
||||||
if (w.end.len > 0) {
|
if (w.end.len > 0) {
|
||||||
keyUpdates += 3;
|
keyUpdates += 3;
|
||||||
addWriteRange(root, oldestVersion, begin, end,
|
addWriteRange(root, begin, end, InternalVersionT(writeVersion),
|
||||||
InternalVersionT(writeVersion), &allocators, this);
|
&allocators, this);
|
||||||
} else {
|
} else {
|
||||||
keyUpdates += 2;
|
keyUpdates += 2;
|
||||||
addPointWrite(root, oldestVersion, begin,
|
addPointWrite(root, begin, InternalVersionT(writeVersion), &allocators,
|
||||||
InternalVersionT(writeVersion), &allocators, this);
|
this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setOldestVersion(int64_t o) {
|
// Spends up to `fuel` gc'ing, and returns its unused fuel
|
||||||
InternalVersionT oldestVersion{o};
|
int64_t gcScanStep(int64_t fuel) {
|
||||||
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
|
|
||||||
Node *n = firstGeq(root, removalKey).n;
|
Node *n = firstGeq(root, removalKey).n;
|
||||||
// There's no way to erase removalKey without introducing a key after it
|
// There's no way to erase removalKey without introducing a key after it
|
||||||
assert(n != nullptr);
|
assert(n != nullptr);
|
||||||
@@ -2893,7 +2879,7 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
|
|||||||
if (n == root) {
|
if (n == root) {
|
||||||
n = nextPhysical(n);
|
n = nextPhysical(n);
|
||||||
}
|
}
|
||||||
for (; keyUpdates > 0 && n != nullptr; --keyUpdates) {
|
for (; fuel > 0 && n != nullptr; --fuel) {
|
||||||
if (n->entryPresent && std::max(n->entry.pointVersion,
|
if (n->entryPresent && std::max(n->entry.pointVersion,
|
||||||
n->entry.rangeVersion) <= oldestVersion) {
|
n->entry.rangeVersion) <= oldestVersion) {
|
||||||
// Any transaction n would have prevented from committing is
|
// Any transaction n would have prevented from committing is
|
||||||
@@ -2915,6 +2901,24 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
|
|||||||
removalKeyArena = Arena();
|
removalKeyArena = Arena();
|
||||||
removalKey = getSearchPath(removalKeyArena, n);
|
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)
|
explicit Impl(int64_t oldestVersion)
|
||||||
|
Reference in New Issue
Block a user