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) { void addWrites(const WriteRange *writes, int count, int64_t writeVersion) {
assert(writeVersion >= newestVersionFullPrecision); assert(writeVersion >= newestVersionFullPrecision);
// TODO allow this condition if (writeVersion > newestVersionFullPrecision + kNominalVersionWindow) {
assert(writeVersion < newestVersionFullPrecision + kNominalVersionWindow); destroyTree(root);
init(writeVersion - kNominalVersionWindow);
}
newestVersionFullPrecision = writeVersion; newestVersionFullPrecision = writeVersion;
setOldestVersion( setOldestVersion(
@@ -2985,14 +2987,18 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
keyUpdates = gcScanStep(keyUpdates); keyUpdates = gcScanStep(keyUpdates);
} }
explicit Impl(int64_t oldestVersion) int64_t getBytes() const { return totalBytes; }
: oldestVersion(oldestVersion), oldestVersionFullPrecision(oldestVersion),
oldestExtantVersion(oldestVersion), void init(int64_t oldestVersion) {
oldestVersionAtGcBegin(oldestVersion), this->oldestVersion = InternalVersionT(oldestVersion);
newestVersionFullPrecision(oldestVersion) { oldestVersionFullPrecision = oldestExtantVersion = oldestVersionAtGcBegin =
#if DEBUG_VERBOSE newestVersionFullPrecision = oldestVersion;
fprintf(stderr, "radix_tree: create\n");
#endif allocators = {};
removalKeyArena = Arena{};
removalKey = {};
keyUpdates = 10;
// Insert "" // Insert ""
root = allocators.node0.allocate(0); root = allocators.node0.allocate(0);
@@ -3009,26 +3015,22 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
root->entry.rangeVersion = this->oldestVersion; root->entry.rangeVersion = this->oldestVersion;
InternalVersionT::zero = this->oldestVersion; InternalVersionT::zero = this->oldestVersion;
// Intentionally not resetting totalBytes
} }
~Impl() {
#if DEBUG_VERBOSE explicit Impl(int64_t oldestVersion) { init(oldestVersion); }
fprintf(stderr, "radix_tree: destroy\n"); ~Impl() { destroyTree(root); }
#endif
destroyTree(root);
}
NodeAllocators allocators; NodeAllocators allocators;
Arena removalKeyArena; Arena removalKeyArena;
std::span<const uint8_t> removalKey; std::span<const uint8_t> removalKey;
int64_t keyUpdates = 10; int64_t keyUpdates;
Node *root; Node *root;
InternalVersionT rootMaxVersion; InternalVersionT rootMaxVersion;
InternalVersionT oldestVersion; 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 oldestVersionFullPrecision;
int64_t oldestExtantVersion; int64_t oldestExtantVersion;
int64_t oldestVersionAtGcBegin; int64_t oldestVersionAtGcBegin;
@@ -3163,7 +3165,7 @@ void internal_destroy(ConflictSet::Impl *impl) {
safe_free(impl, sizeof(ConflictSet::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 ==================== // ==================== END IMPLEMENTATION ====================

View File

@@ -598,6 +598,7 @@ template <class ConflictSetImpl> struct TestDriver {
// Call until it returns true, for "done". Check internal invariants etc // Call until it returns true, for "done". Check internal invariants etc
// between calls to next. // between calls to next.
bool next() { bool next() {
assert(cs.getBytes() >= 0);
if (!arbitrary.hasEntropy()) { if (!arbitrary.hasEntropy()) {
return true; return true;
} }
@@ -605,7 +606,9 @@ template <class ConflictSetImpl> struct TestDriver {
{ {
int numPointWrites = arbitrary.bounded(100); int numPointWrites = arbitrary.bounded(100);
int numRangeWrites = 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 = auto *writes =
new (arena) ConflictSet::WriteRange[numPointWrites + numRangeWrites]; new (arena) ConflictSet::WriteRange[numPointWrites + numRangeWrites];
auto keys = set<std::string_view>(arena); 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")) 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(): def test_decrease_capacity():
# make a Node48, then a Node256 # make a Node48, then a Node256
for count in (17, 49): for count in (17, 49):