Naive range reads implementation and test

This commit is contained in:
2024-02-05 13:59:10 -08:00
parent e3e0e7ba44
commit 57ec97f2ee
2 changed files with 83 additions and 22 deletions

View File

@@ -815,8 +815,6 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
result[i] = TooOld;
continue;
}
// TODO support non-point reads
assert(r.end.len == 0);
auto [l, c] =
lastLeq(root, std::span<const uint8_t>(r.begin.p, r.begin.len));
#if DEBUG_VERBOSE && !defined(NDEBUG)
@@ -830,6 +828,28 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
r.readVersion
? Conflict
: Commit;
if (result[i] == Commit && r.end.len > 0) {
auto [e, c] =
lastLeq(root, std::span<const uint8_t>(r.end.p, r.end.len));
#if DEBUG_VERBOSE && !defined(NDEBUG)
Arena arena;
fprintf(stderr, "LastLeq for `%s' got `%s'\n", printable(r.end).c_str(),
printable(getSearchPath(arena, e)).c_str());
#endif
if (l == e) {
continue;
}
if (c != 0) {
e = nextLogical(e);
}
for (auto iter = nextLogical(l); iter != e; iter = nextLogical(iter)) {
if (iter->entry.pointVersion > r.readVersion ||
iter->entry.rangeVersion > r.readVersion) {
result[i] = Conflict;
break;
}
}
}
}
}
void addWrites(const WriteRange *writes, int count) {

View File

@@ -441,7 +441,7 @@ inline std::string printable(const Key &key) {
namespace {
template <class ConflictSetImpl> struct TestDriver {
// TODO call setOldestVersion, and check range writes/reads
// TODO call setOldestVersion
Arbitrary arbitrary;
explicit TestDriver(const uint8_t *data, size_t size)
: arbitrary({data, size}) {}
@@ -536,11 +536,13 @@ template <class ConflictSetImpl> struct TestDriver {
refImpl.addWrites(writes, numPointWrites + numRangeWrites);
}
{
int numReads = arbitrary.bounded(10);
int numPointReads = arbitrary.bounded(100);
int numRangeReads = arbitrary.bounded(100);
int64_t v = std::max<int64_t>(writeVersion - arbitrary.bounded(10), 0);
auto *reads = new (arena) ConflictSet::ReadRange[numReads];
auto *reads =
new (arena) ConflictSet::ReadRange[numPointReads + numRangeReads];
auto keys = set<std::string_view>(arena);
while (int(keys.size()) < numReads) {
while (int(keys.size()) < numPointReads + numRangeReads * 2) {
if (!arbitrary.hasEntropy()) {
return true;
}
@@ -549,29 +551,68 @@ template <class ConflictSetImpl> struct TestDriver {
arbitrary.randomBytes(begin, keyLen);
keys.insert(std::string_view((const char *)begin, keyLen));
}
auto iter = keys.begin();
for (int i = 0; i < numReads; ++i) {
reads[i].begin.p = (const uint8_t *)iter->data();
reads[i].begin.len = iter->size();
++iter;
reads[i].end.len = 0;
int i = 0;
for (int pointsRemaining = numPointReads, rangesRemaining = numRangeReads;
pointsRemaining > 0 || rangesRemaining > 0; ++i) {
bool pointRead = pointsRemaining > 0 && rangesRemaining > 0
? bool(arbitrary.bounded(2))
: pointsRemaining > 0;
if (pointRead) {
assert(pointsRemaining > 0);
reads[i].begin.p = (const uint8_t *)iter->data();
reads[i].begin.len = iter->size();
reads[i].end.len = 0;
++iter;
--pointsRemaining;
} else {
assert(rangesRemaining > 0);
reads[i].begin.p = (const uint8_t *)iter->data();
reads[i].begin.len = iter->size();
++iter;
reads[i].end.p = (const uint8_t *)iter->data();
reads[i].end.len = iter->size();
++iter;
--rangesRemaining;
}
reads[i].readVersion = v;
#if DEBUG_VERBOSE && !defined(NDEBUG)
fprintf(stderr, "Read: {%s} at %d\n", printable(reads[i].begin).c_str(),
int(reads[i].readVersion));
if (reads[i].end.len == 0) {
fprintf(stderr, "Read: {%s} @ %d\n",
printable(reads[i].begin).c_str(), int(reads[i].readVersion));
} else {
fprintf(stderr, "Read: [%s, %s) @ %d\n",
printable(reads[i].begin).c_str(),
printable(reads[i].end).c_str(), int(reads[i].readVersion));
}
#endif
}
assert(iter == keys.end());
auto *results1 = new (arena) ConflictSet::Result[numReads];
auto *results2 = new (arena) ConflictSet::Result[numReads];
cs.check(reads, results1, numReads);
refImpl.check(reads, results2, numReads);
for (int i = 0; i < numReads; ++i) {
assert(i == numPointReads + numRangeReads);
auto *results1 =
new (arena) ConflictSet::Result[numPointReads + numRangeReads];
auto *results2 =
new (arena) ConflictSet::Result[numPointReads + numRangeReads];
cs.check(reads, results1, numPointReads + numRangeReads);
refImpl.check(reads, results2, numPointReads + numRangeReads);
for (int i = 0; i < numPointReads + numRangeReads; ++i) {
if (results1[i] != results2[i]) {
fprintf(stderr,
"Expected %s, got %s for read of %s at version %" PRId64 "\n",
resultToStr(results2[i]), resultToStr(results1[i]),
printable(reads[i].begin).c_str(), reads[i].readVersion);
if (reads[i].end.len == 0) {
fprintf(stderr,
"Expected %s, got %s for read of {%s} at version %" PRId64
"\n",
resultToStr(results2[i]), resultToStr(results1[i]),
printable(reads[i].begin).c_str(), reads[i].readVersion);
} else {
fprintf(
stderr,
"Expected %s, got %s for read of [%s, %s) at version %" PRId64
"\n",
resultToStr(results2[i]), resultToStr(results1[i]),
printable(reads[i].begin).c_str(),
printable(reads[i].end).c_str(), reads[i].readVersion);
}
ok = false;
return true;
}