Naive range reads implementation and test
This commit is contained in:
@@ -815,8 +815,6 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
|
|||||||
result[i] = TooOld;
|
result[i] = TooOld;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// TODO support non-point reads
|
|
||||||
assert(r.end.len == 0);
|
|
||||||
auto [l, c] =
|
auto [l, c] =
|
||||||
lastLeq(root, std::span<const uint8_t>(r.begin.p, r.begin.len));
|
lastLeq(root, std::span<const uint8_t>(r.begin.p, r.begin.len));
|
||||||
#if DEBUG_VERBOSE && !defined(NDEBUG)
|
#if DEBUG_VERBOSE && !defined(NDEBUG)
|
||||||
@@ -830,6 +828,28 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
|
|||||||
r.readVersion
|
r.readVersion
|
||||||
? Conflict
|
? Conflict
|
||||||
: Commit;
|
: 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) {
|
void addWrites(const WriteRange *writes, int count) {
|
||||||
|
81
Internal.h
81
Internal.h
@@ -441,7 +441,7 @@ inline std::string printable(const Key &key) {
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
template <class ConflictSetImpl> struct TestDriver {
|
template <class ConflictSetImpl> struct TestDriver {
|
||||||
// TODO call setOldestVersion, and check range writes/reads
|
// TODO call setOldestVersion
|
||||||
Arbitrary arbitrary;
|
Arbitrary arbitrary;
|
||||||
explicit TestDriver(const uint8_t *data, size_t size)
|
explicit TestDriver(const uint8_t *data, size_t size)
|
||||||
: arbitrary({data, size}) {}
|
: arbitrary({data, size}) {}
|
||||||
@@ -536,11 +536,13 @@ template <class ConflictSetImpl> struct TestDriver {
|
|||||||
refImpl.addWrites(writes, numPointWrites + numRangeWrites);
|
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);
|
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);
|
auto keys = set<std::string_view>(arena);
|
||||||
while (int(keys.size()) < numReads) {
|
while (int(keys.size()) < numPointReads + numRangeReads * 2) {
|
||||||
if (!arbitrary.hasEntropy()) {
|
if (!arbitrary.hasEntropy()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -549,29 +551,68 @@ template <class ConflictSetImpl> struct TestDriver {
|
|||||||
arbitrary.randomBytes(begin, keyLen);
|
arbitrary.randomBytes(begin, keyLen);
|
||||||
keys.insert(std::string_view((const char *)begin, keyLen));
|
keys.insert(std::string_view((const char *)begin, keyLen));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto iter = keys.begin();
|
auto iter = keys.begin();
|
||||||
for (int i = 0; i < numReads; ++i) {
|
int i = 0;
|
||||||
reads[i].begin.p = (const uint8_t *)iter->data();
|
for (int pointsRemaining = numPointReads, rangesRemaining = numRangeReads;
|
||||||
reads[i].begin.len = iter->size();
|
pointsRemaining > 0 || rangesRemaining > 0; ++i) {
|
||||||
++iter;
|
bool pointRead = pointsRemaining > 0 && rangesRemaining > 0
|
||||||
reads[i].end.len = 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;
|
reads[i].readVersion = v;
|
||||||
#if DEBUG_VERBOSE && !defined(NDEBUG)
|
#if DEBUG_VERBOSE && !defined(NDEBUG)
|
||||||
fprintf(stderr, "Read: {%s} at %d\n", printable(reads[i].begin).c_str(),
|
if (reads[i].end.len == 0) {
|
||||||
int(reads[i].readVersion));
|
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
|
#endif
|
||||||
}
|
}
|
||||||
assert(iter == keys.end());
|
assert(iter == keys.end());
|
||||||
auto *results1 = new (arena) ConflictSet::Result[numReads];
|
assert(i == numPointReads + numRangeReads);
|
||||||
auto *results2 = new (arena) ConflictSet::Result[numReads];
|
auto *results1 =
|
||||||
cs.check(reads, results1, numReads);
|
new (arena) ConflictSet::Result[numPointReads + numRangeReads];
|
||||||
refImpl.check(reads, results2, numReads);
|
auto *results2 =
|
||||||
for (int i = 0; i < numReads; ++i) {
|
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]) {
|
if (results1[i] != results2[i]) {
|
||||||
fprintf(stderr,
|
if (reads[i].end.len == 0) {
|
||||||
"Expected %s, got %s for read of %s at version %" PRId64 "\n",
|
fprintf(stderr,
|
||||||
resultToStr(results2[i]), resultToStr(results1[i]),
|
"Expected %s, got %s for read of {%s} at version %" PRId64
|
||||||
printable(reads[i].begin).c_str(), reads[i].readVersion);
|
"\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;
|
ok = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user