diff --git a/Facade.h b/Facade.h index 175b839..496ddd0 100644 --- a/Facade.h +++ b/Facade.h @@ -30,6 +30,8 @@ struct Facade { facade->versioned.firstGeq(key, v, versionedIter, 2); if (versionedIter[0] == versionedIter[1]) { + // No mutations intersect [begin, end) + facade->unversionedRead(begin, end, limit, reverse, result); return result; } @@ -40,9 +42,10 @@ struct Facade { weaselab::VersionedMap::Iterator iter = versionedIter[1]; weaselab::VersionedMap::Iterator endIter = versionedIter[0]; String readUntil = end; - if (iter == facade->versioned.end(version)) { - --iter; - } + + // Make *iter intersect [begin, end) + --iter; + for (;; --iter) { auto m = *iter; const auto mEnd = diff --git a/FacadeTest.cpp b/FacadeTest.cpp index 8c4a088..e260dbd 100644 --- a/FacadeTest.cpp +++ b/FacadeTest.cpp @@ -47,7 +47,7 @@ int main() { for (int64_t i = 1; i < version; ++i) { printf("--- version %" PRId64 " ---\n", i); printf("merged:\n"); - auto result = f.viewAt(i).rangeRead("a"_s, "z"_s, 100, false); + auto result = f.viewAt(i).rangeRead("a"_s, "e"_s, 100, false); for (const auto &[k, v] : result) { for (auto c : k) { if (isprint(c)) { diff --git a/VersionedMap.cpp b/VersionedMap.cpp index c10df89..0d9054a 100644 --- a/VersionedMap.cpp +++ b/VersionedMap.cpp @@ -390,6 +390,17 @@ auto operator<=>(const VersionedMap::Key &lhs, const Node &rhs) { return lhs.len <=> rhs.entry->keyLen; } +auto operator<=>(const VersionedMap::Key &lhs, const VersionedMap::Key &rhs) { + int cl = std::min(lhs.len, rhs.len); + if (cl > 0) { + int c = memcmp(lhs.p, rhs.p, cl); + if (c != 0) { + return c <=> 0; + } + } + return lhs.len <=> rhs.len; +} + constexpr int orderToInt(std::strong_ordering o) { return o == std::strong_ordering::less ? -1 : o == std::strong_ordering::equal ? 0 @@ -1156,6 +1167,11 @@ void VersionedMap::Impl::firstGeq(const Key *key, const int64_t *version, } else { iterator[i].impl->mutationIndex = 0; } + + auto m = *iterator[i]; + if (Key{m.param1, m.param1Len} < key[i]) { + ++iterator[i]; + } } } diff --git a/include/VersionedMap.h b/include/VersionedMap.h index 1423265..751b530 100644 --- a/include/VersionedMap.h +++ b/include/VersionedMap.h @@ -150,11 +150,9 @@ struct __attribute__((__visibility__("default"))) VersionedMap { Impl *impl = nullptr; }; - /** Perform `count` "first greater than or equal to" queries. If there's a - * mutation intersecting `key[i]` at `version[i]` then `iterator[i]` will - * point to that mutation. Otherwise it points to the first mutation greater - * or `end()` if none exists. `version[i]` must be >= `getOldestVersion()` - * and <= `getVersion()`. + /** Perform `count` "first greater than or equal to" queries, comparing to + * mutations' `param1`. `version[i]` must be >= `getOldestVersion()` and <= + * `getVersion()`. * * Thread-safe as long as a version is not concurrently invalidated by * `setOldestVersion`. There's a performance benefit if you pass iterator[i]