#include "Internal.h" #include #include #include #include #include #include #include #include inline size_t getPageSize() { static size_t kPageSize = sysconf(_SC_PAGESIZE); return kPageSize; } /// Helper for rounding up to page size (or some other alignment) constexpr inline size_t rightAlign(size_t offset, size_t alignment) { return offset % alignment == 0 ? offset : ((offset / alignment) + 1) * alignment; } using StringView = std::basic_string_view; inline StringView operator"" _v(const char *str, size_t size) { return {reinterpret_cast(str), size}; } int main(int argc, const char **argv) { ConflictSet cs{0}; ReferenceImpl ref{0}; for (int i = 1; i < argc; ++i) { int fd = open(argv[i], O_RDONLY); struct stat st; if (fstat(fd, &st) == -1) { int err = errno; fprintf(stderr, "stat error %s - %s\n", argv[i], strerror(err)); fflush(stderr); abort(); } int64_t size = rightAlign(st.st_size, getPageSize()); const uint8_t *begin = (uint8_t *)mmap(0, size, PROT_READ, MAP_PRIVATE, fd, 0); madvise((void *)begin, size, MADV_SEQUENTIAL); auto *const mapOriginal = begin; const auto sizeOriginal = size; StringView b; StringView e; int64_t v = 0; std::vector writeRanges; std::vector readRanges; std::vector results; for (uint8_t *end = (uint8_t *)memchr(begin, '\n', size); end != nullptr;) { StringView line{begin, static_cast(end - begin)}; size -= end - begin + 1; begin = end + 1; end = (uint8_t *)memchr(begin, '\n', size); if (line.starts_with("begin"_v)) { b = line.substr("begin "_v.size(), line.size()); printf("b <- %.*s\n", int(b.size()), b.data()); } else if (line.starts_with("end"_v)) { e = line.substr("end "_v.size(), line.size()); printf("e <- %.*s\n", int(e.size()), e.data()); } else if (line.starts_with("version"_v)) { line = line.substr("version "_v.size(), line.size()); v = 0; for (auto c : line) { v = v * 10 + int(c) - int('0'); } printf("v <- %" PRId64 "\n", v); } else if (line.starts_with("pointread"_v)) { printf("pointread\n"); ConflictSet::ReadRange r; r.begin.p = b.data(); r.begin.len = b.size(); r.end.len = 0; r.readVersion = v; readRanges.push_back(r); } else if (line.starts_with("pointwrite"_v)) { printf("pointwrite\n"); // TODO check sorted ConflictSet::WriteRange w; w.begin.p = b.data(); w.begin.len = b.size(); w.end.len = 0; writeRanges.push_back(w); } else if (line.starts_with("rangeread"_v)) { printf("rangeread\n"); ConflictSet::ReadRange r; r.begin.p = b.data(); r.begin.len = b.size(); r.end.p = e.data(); r.end.len = e.size(); r.readVersion = v; readRanges.push_back(r); } else if (line.starts_with("rangewrite"_v)) { printf("rangewrite\n"); // TODO check sorted ConflictSet::WriteRange w; w.begin.p = b.data(); w.begin.len = b.size(); w.end.p = e.data(); w.end.len = e.size(); writeRanges.push_back(w); } else if (line.starts_with("check"_v)) { printf("check\n"); Arena arena; auto *expected = new (arena) ConflictSet::Result[readRanges.size()]; auto *actual = new (arena) ConflictSet::Result[readRanges.size()]; ref.check(readRanges.data(), expected, readRanges.size()); cs.check(readRanges.data(), actual, readRanges.size()); for (int i = 0; i < int(readRanges.size()); ++i) { if (expected[i] != actual[i]) { fprintf(stderr, "Expected %s, got %s at index %d\n", resultToStr(expected[i]), resultToStr(actual[i]), i); return 1; } } readRanges = {}; } else if (line.starts_with("addwrites"_v)) { printf("addwrites\n"); cs.addWrites(writeRanges.data(), writeRanges.size(), v); ref.addWrites(writeRanges.data(), writeRanges.size(), v); writeRanges = {}; } else if (line.starts_with("setoldest"_v)) { printf("setoldest\n"); cs.setOldestVersion(v); ref.setOldestVersion(v); } else if (line.empty() || line.starts_with(";"_v)) { // skip } else { printf("Unrecognized line: %.*s\n", int(line.size()), line.data()); } } munmap((void *)mapOriginal, sizeOriginal); close(fd); } }