diff --git a/ConflictSet.cpp b/ConflictSet.cpp index dc31cc8..986b222 100644 --- a/ConflictSet.cpp +++ b/ConflictSet.cpp @@ -3149,6 +3149,7 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl { tls.impl = this; int64_t check_byte_accum = 0; for (int i = 0; i < count; ++i) { + assert(reads[i].readVersion <= newestVersionFullPrecision); const auto &r = reads[i]; check_byte_accum += r.begin.len + r.end.len; auto begin = std::span(r.begin.p, r.begin.len); @@ -3299,6 +3300,7 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl { } void setOldestVersion(int64_t o) { + assert(o <= newestVersionFullPrecision); if (o <= oldestVersionFullPrecision) { return; } @@ -3758,13 +3760,13 @@ std::string getSearchPath(Node *n) { fprintf(file, " k_%p [label=\"m=%" PRId64 " p=%" PRId64 " r=%" PRId64 "\n%s\", pos=\"%d,%d!\"];\n", - (void *)n, maxVersion(n).toInt64(), + (void *)n, n->parent == nullptr ? -1 : maxVersion(n).toInt64(), n->entry.pointVersion.toInt64(), n->entry.rangeVersion.toInt64(), getPartialKeyPrintable(n).c_str(), x, y); } else { fprintf(file, " k_%p [label=\"m=%" PRId64 "\n%s\", pos=\"%d,%d!\"];\n", - (void *)n, maxVersion(n).toInt64(), + (void *)n, n->parent == nullptr ? -1 : maxVersion(n).toInt64(), getPartialKeyPrintable(n).c_str(), x, y); } x += kSeparation; diff --git a/include/ConflictSet.h b/include/ConflictSet.h index 6df3b73..a100e01 100644 --- a/include/ConflictSet.h +++ b/include/ConflictSet.h @@ -54,8 +54,9 @@ 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), and begin must be < 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` */ + /** `readVersion` older than the oldestVersion or the version of the + * latest call to `addWrites` minus two billion will result in `TooOld`. + * Must be <= the version of the latest call to `addWrites` */ int64_t readVersion; }; @@ -72,11 +73,13 @@ struct __attribute__((__visibility__("default"))) ConflictSet { /** Reads intersecting writes where readVersion < `writeVersion` will result * in `Conflict` (or `TooOld`, eventually). `writeVersion` must be greater - * than or equal to all previous write versions. */ + * than or equal to all previous write versions. Call `addWrites` with `count` + * zero to only advance the version. */ void addWrites(const WriteRange *writes, int count, int64_t writeVersion); - /** Reads where readVersion < oldestVersion will result in `TooOld`. Must be - * greater than or equal to all previous oldest versions. */ + /** Reads where readVersion < `oldestVersion` will result in `TooOld`. Must be + * greater than or equal to all previous oldest versions. Must be <= the + * version of the latest call to `addWrites` */ void setOldestVersion(int64_t oldestVersion); /** Reads where readVersion < oldestVersion will result in `TooOld`. There are @@ -170,8 +173,9 @@ typedef struct { /** `end` having length 0 denotes that this range is the single key {begin}. * Otherwise this denotes the range [begin, end), and begin must be < 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` */ + /** `readVersion` older than the oldestVersion or the version of the + * latest call to `addWrites` minus two billion will result in `TooOld`. + * Must be <= the version of the latest call to `addWrites` */ int64_t readVersion; } ConflictSet_ReadRange; @@ -188,15 +192,17 @@ void ConflictSet_check(const ConflictSet *cs, const ConflictSet_ReadRange *reads, ConflictSet_Result *results, int count); -/** Reads intersecting writes where readVersion < `writeVersion` will result in - * `Conflict` (or `TooOld`, eventually). `writeVersion` must be greater than or - * equal to all previous write versions. */ +/** Reads intersecting writes where readVersion < `writeVersion` will result + * in `Conflict` (or `TooOld`, eventually). `writeVersion` must be greater + * than or equal to all previous write versions. Call `addWrites` with `count` + * zero to only advance the version. */ void ConflictSet_addWrites(ConflictSet *cs, const ConflictSet_WriteRange *writes, int count, int64_t writeVersion); -/** Reads where readVersion < oldestVersion will result in `TooOld`. Must be - * greater than or equal to all previous oldest versions. */ +/** Reads where readVersion < `oldestVersion` will result in `TooOld`. Must be + * greater than or equal to all previous oldest versions. Must be <= the + * version of the latest call to `addWrites` */ void ConflictSet_setOldestVersion(ConflictSet *cs, int64_t oldestVersion); /** Reads where readVersion < oldestVersion will result in `TooOld`. There are