diff --git a/Facade.h b/Facade.h index b42d0f6..459b53a 100644 --- a/Facade.h +++ b/Facade.h @@ -35,6 +35,14 @@ struct Facade { return result; } + // Make sure versionedIter[1] param1 is >= `end` + if (versionedIter[1] != facade->versioned.end(version)) { + auto m = *versionedIter[1]; + if (String(m.param1, m.param1Len) < end) { + ++versionedIter[1]; + } + } + static const uint8_t zero_[] = {0}; static const String zero{zero_, 1}; @@ -43,11 +51,10 @@ struct Facade { weaselab::VersionedMap::Iterator endIter = versionedIter[0]; String readUntil = end; - // Make *iter intersect [begin, end) - --iter; - - for (;; --iter) { + do { + --iter; auto m = *iter; + const auto mBegin = String(m.param1, m.param1Len); const auto mEnd = m.type == weaselab::VersionedMap::Set || m.param2Len == 0 ? String(m.param1, m.param1Len) + zero @@ -58,31 +65,31 @@ struct Facade { } switch (m.type) { case weaselab::VersionedMap::Set: { - result.emplace_back(String(m.param1, m.param1Len), - String(m.param2, m.param2Len)); + result.emplace_back(mBegin, String(m.param2, m.param2Len)); --limit; if (limit == 0) { return result; } - readUntil = String(m.param1, m.param1Len); + readUntil = mBegin; } break; case weaselab::VersionedMap::Clear: - readUntil = String(m.param1, m.param1Len); + readUntil = mBegin; break; } - if (iter == endIter) { - break; - } - } + } while (iter != endIter); + facade->unversionedRead(begin, readUntil, limit, true, result); return result; } else { - weaselab::VersionedMap::Iterator iter = versionedIter[0]; - weaselab::VersionedMap::Iterator endIter = versionedIter[1]; String readFrom = begin; - for (; iter != endIter; ++iter) { + + for (auto iter = versionedIter[0]; iter != versionedIter[1]; ++iter) { auto m = *iter; const auto mBegin = String(m.param1, m.param1Len); + const auto mEnd = + m.type == weaselab::VersionedMap::Set || m.param2Len == 0 + ? String(m.param1, m.param1Len) + zero + : String(m.param2, m.param2Len); facade->unversionedRead(readFrom, mBegin, limit, false, result); if (limit == 0) { return result; @@ -94,13 +101,14 @@ struct Facade { if (limit == 0) { return result; } - readFrom = mBegin + zero; + readFrom = mEnd; } break; case weaselab::VersionedMap::Clear: - readFrom = String(m.param2, m.param2Len); + readFrom = mEnd; break; } } + facade->unversionedRead(readFrom, end, limit, false, result); return result; } diff --git a/VersionedMap.cpp b/VersionedMap.cpp index 867824b..69a6a32 100644 --- a/VersionedMap.cpp +++ b/VersionedMap.cpp @@ -1169,13 +1169,6 @@ void VersionedMap::Impl::firstGeq(const Key *key, const int64_t *version, } else { iterator[i].impl->mutationIndex = 0; } - - // TODO Interposable call - auto m = *iterator[i]; - if (Key{m.param1, m.param1Len} < key[i]) { - // TODO Interposable call - ++iterator[i]; - } } } diff --git a/include/VersionedMap.h b/include/VersionedMap.h index 751b530..d5ff61e 100644 --- a/include/VersionedMap.h +++ b/include/VersionedMap.h @@ -150,9 +150,12 @@ struct __attribute__((__visibility__("default"))) VersionedMap { Impl *impl = nullptr; }; - /** Perform `count` "first greater than or equal to" queries, comparing to - * mutations' `param1`. `version[i]` must be >= `getOldestVersion()` and <= - * `getVersion()`. + /** 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()`. * * Thread-safe as long as a version is not concurrently invalidated by * `setOldestVersion`. There's a performance benefit if you pass iterator[i]