Interface change! Return TooOld after 2e9 versions

Event if setOldestVersion wasn't called
This commit is contained in:
2024-06-30 15:25:44 -07:00
parent 8e3eacb54f
commit a68ad5dd17
4 changed files with 34 additions and 4 deletions

View File

@@ -2765,7 +2765,9 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
auto begin = std::span<const uint8_t>(r.begin.p, r.begin.len);
auto end = std::span<const uint8_t>(r.end.p, r.end.len);
result[i] =
InternalVersionT(reads[i].readVersion) < oldestVersion ? TooOld
InternalVersionT(reads[i].readVersion) < oldestVersion ||
reads[i].readVersion < newestVersionFullPrecision - 2e9
? TooOld
: (end.size() > 0
? checkRangeRead(root, begin, end,
InternalVersionT(reads[i].readVersion), this)
@@ -2777,6 +2779,8 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
}
void addWrites(const WriteRange *writes, int count, int64_t writeVersion) {
assert(writeVersion >= newestVersionFullPrecision);
newestVersionFullPrecision = writeVersion;
#if INTERNAL_VERSION_32_BIT
InternalVersionT::zero = oldestVersion;
#endif
@@ -2798,6 +2802,8 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
void setOldestVersion(int64_t o) {
InternalVersionT oldestVersion{o};
assert(o >= oldestVersionFullPrecision);
this->oldestVersionFullPrecision = o;
this->oldestVersion = oldestVersion;
#if INTERNAL_VERSION_32_BIT
InternalVersionT::zero = oldestVersion;
@@ -2841,7 +2847,9 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
}
}
explicit Impl(int64_t oldestVersion) : oldestVersion(oldestVersion) {
explicit Impl(int64_t oldestVersion)
: oldestVersion(oldestVersion), oldestVersionFullPrecision(oldestVersion),
newestVersionFullPrecision(oldestVersion) {
#if DEBUG_VERBOSE
fprintf(stderr, "radix_tree: create\n");
#endif
@@ -2876,6 +2884,11 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
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 2e9 window.
int64_t oldestVersionFullPrecision;
int64_t newestVersionFullPrecision;
int64_t totalBytes = 0;
};

View File

@@ -577,7 +577,8 @@ struct SkipListConflictSet {};
struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
Impl(int64_t oldestVersion)
: oldestVersion(oldestVersion), skipList(oldestVersion) {}
: oldestVersion(oldestVersion), newestVersion(oldestVersion),
skipList(oldestVersion) {}
void check(const ConflictSet::ReadRange *reads, ConflictSet::Result *results,
int count) const {
Arena arena;
@@ -592,7 +593,8 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
}
skipList.detectConflicts(ranges, count, results);
for (int i = 0; i < count; ++i) {
if (reads[i].readVersion < oldestVersion) {
if (reads[i].readVersion < oldestVersion ||
reads[i].readVersion < newestVersion - 2e9) {
results[i] = TooOld;
}
}
@@ -600,6 +602,8 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
void addWrites(const ConflictSet::WriteRange *writes, int count,
int64_t writeVersion) {
assert(writeVersion >= newestVersion);
newestVersion = writeVersion;
Arena arena;
const int stringCount = count * 2;
@@ -630,6 +634,7 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
}
void setOldestVersion(int64_t oldestVersion) {
assert(oldestVersion >= this->oldestVersion);
this->oldestVersion = oldestVersion;
SkipList::Finger finger;
int temp;
@@ -648,6 +653,7 @@ private:
Arena removalArena;
std::span<const uint8_t> removalKey;
int64_t oldestVersion;
int64_t newestVersion;
SkipList skipList;
};

View File

@@ -54,6 +54,8 @@ struct __attribute__((__visibility__("default"))) ConflictSet {
/** `end` having length 0 denotes that this range is the single key {begin}.
* Otherwise this denotes the range [begin, end) */
Key end;
/** `readVersion` older than the the oldestVersion or the version of the
* latest call to `addWrites` minus two billion will result in `TooOld` */
int64_t readVersion;
};
@@ -141,6 +143,8 @@ typedef struct {
/** `end` having length 0 denotes that this range is the single key {begin}.
* Otherwise this denotes the range [begin, end) */
ConflictSet_Key end;
/** `readVersion` older than the the oldestVersion or the version of the
* latest call to `addWrites` minus two billion will result in `TooOld` */
int64_t readVersion;
} ConflictSet_ReadRange;

View File

@@ -77,6 +77,13 @@ def test_internal_version_zero():
cs.check(read(0xFFFFFFF1, b"\x00", b"\xff"))
def test_two_billion_versions():
with DebugConflictSet() as cs:
cs.addWrites(int(2e9) + 1)
cs.check(read(0, b"\x00", b"\xff"))
cs.check(read(1, b"\x00", b"\xff"))
def test_decrease_capacity():
# make a Node48, then a Node256
for count in (17, 49):