Allow write version to jump by more than 2e9

This commit is contained in:
2024-07-03 09:07:09 -07:00
parent e59fee39c7
commit 3e6be6bd83
3 changed files with 35 additions and 22 deletions

View File

@@ -2892,8 +2892,10 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
void addWrites(const WriteRange *writes, int count, int64_t writeVersion) {
assert(writeVersion >= newestVersionFullPrecision);
// TODO allow this condition
assert(writeVersion < newestVersionFullPrecision + kNominalVersionWindow);
if (writeVersion > newestVersionFullPrecision + kNominalVersionWindow) {
destroyTree(root);
init(writeVersion - kNominalVersionWindow);
}
newestVersionFullPrecision = writeVersion;
setOldestVersion(
@@ -2985,14 +2987,18 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
keyUpdates = gcScanStep(keyUpdates);
}
explicit Impl(int64_t oldestVersion)
: oldestVersion(oldestVersion), oldestVersionFullPrecision(oldestVersion),
oldestExtantVersion(oldestVersion),
oldestVersionAtGcBegin(oldestVersion),
newestVersionFullPrecision(oldestVersion) {
#if DEBUG_VERBOSE
fprintf(stderr, "radix_tree: create\n");
#endif
int64_t getBytes() const { return totalBytes; }
void init(int64_t oldestVersion) {
this->oldestVersion = InternalVersionT(oldestVersion);
oldestVersionFullPrecision = oldestExtantVersion = oldestVersionAtGcBegin =
newestVersionFullPrecision = oldestVersion;
allocators = {};
removalKeyArena = Arena{};
removalKey = {};
keyUpdates = 10;
// Insert ""
root = allocators.node0.allocate(0);
@@ -3009,26 +3015,22 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
root->entry.rangeVersion = this->oldestVersion;
InternalVersionT::zero = this->oldestVersion;
// Intentionally not resetting totalBytes
}
~Impl() {
#if DEBUG_VERBOSE
fprintf(stderr, "radix_tree: destroy\n");
#endif
destroyTree(root);
}
explicit Impl(int64_t oldestVersion) { init(oldestVersion); }
~Impl() { destroyTree(root); }
NodeAllocators allocators;
Arena removalKeyArena;
std::span<const uint8_t> removalKey;
int64_t keyUpdates = 10;
int64_t keyUpdates;
Node *root;
InternalVersionT rootMaxVersion;
InternalVersionT oldestVersion;
// TODO this doesn't fully mitigate the 32-bit precision issue, since we still
// need to make sure we clean up versions in the tree before they fall out of
// the `kMaxCorrectVersionWindow` window.
int64_t oldestVersionFullPrecision;
int64_t oldestExtantVersion;
int64_t oldestVersionAtGcBegin;
@@ -3163,7 +3165,7 @@ void internal_destroy(ConflictSet::Impl *impl) {
safe_free(impl, sizeof(ConflictSet::Impl));
}
int64_t internal_getBytes(ConflictSet::Impl *impl) { return impl->totalBytes; }
int64_t internal_getBytes(ConflictSet::Impl *impl) { return impl->getBytes(); }
// ==================== END IMPLEMENTATION ====================

View File

@@ -598,6 +598,7 @@ template <class ConflictSetImpl> struct TestDriver {
// Call until it returns true, for "done". Check internal invariants etc
// between calls to next.
bool next() {
assert(cs.getBytes() >= 0);
if (!arbitrary.hasEntropy()) {
return true;
}
@@ -605,7 +606,9 @@ template <class ConflictSetImpl> struct TestDriver {
{
int numPointWrites = arbitrary.bounded(100);
int numRangeWrites = arbitrary.bounded(100);
int64_t v = (writeVersion += arbitrary.bounded(2e9));
int64_t v =
(writeVersion += arbitrary.bounded(10) == 0 ? arbitrary.bounded(10)
: arbitrary.next());
auto *writes =
new (arena) ConflictSet::WriteRange[numPointWrites + numRangeWrites];
auto keys = set<std::string_view>(arena);

View File

@@ -84,6 +84,14 @@ def test_two_billion_versions():
cs.check(read(1, b"\x00", b"\xff"))
def test_positive_bytes():
with DebugConflictSet() as cs:
cs.addWrites(1, write(b"hello"))
assert cs.getBytes() > 0
cs.addWrites(1 + 2**32)
assert cs.getBytes() > 0
def test_decrease_capacity():
# make a Node48, then a Node256
for count in (17, 49):