#pragma once #include "VersionedMap.h" #include #include #include using String = std::basic_string; struct Facade { explicit Facade(int64_t version) : versioned{version} {} struct View { std::vector> rangeRead(const String &begin, const String &end, int limit, bool reverse) const { std::vector> result; weaselab::VersionedMap::Iterator versionedIter[2]; const weaselab::VersionedMap::Key key[] = { {begin.data(), int(begin.size())}, {end.data(), int(end.size())}}; const int64_t v[] = {version, version}; facade->versioned.firstGeq(key, v, versionedIter, 2); const uint8_t zero[] = {0}; if (reverse) { weaselab::VersionedMap::Iterator iter = versionedIter[1]; weaselab::VersionedMap::Iterator endIter = versionedIter[0]; String readUntil = end; for (; iter != endIter; --iter) { auto m = *iter; auto mEnd = m.type == weaselab::VersionedMap::Set ? String(m.param1, m.param1Len) + String(zero, 1) : String(m.param2, m.param2Len); auto remaining = facade->unversionedRead(mEnd, readUntil, limit, true); result.insert(result.end(), remaining.begin(), remaining.end()); if (limit == 0) { return result; } switch (m.type) { case weaselab::VersionedMap::Set: { result.push_back( {String(m.param1, m.param1Len), String(m.param2, m.param2Len)}); --limit; if (limit == 0) { return result; } readUntil = String(m.param1, m.param1Len); } break; case weaselab::VersionedMap::Clear: readUntil = String(m.param1, m.param1Len); break; } } auto remaining = facade->unversionedRead(begin, readUntil, limit, true); result.insert(result.end(), remaining.begin(), remaining.end()); return result; } else { weaselab::VersionedMap::Iterator iter = versionedIter[0]; weaselab::VersionedMap::Iterator endIter = versionedIter[1]; String readThrough = begin; for (; iter != endIter; ++iter) { auto m = *iter; auto remaining = facade->unversionedRead( readThrough, String(m.param1, m.param1Len), limit, false); result.insert(result.end(), remaining.begin(), remaining.end()); if (limit == 0) { return result; } switch (m.type) { case weaselab::VersionedMap::Set: { result.push_back( {String(m.param1, m.param1Len), String(m.param2, m.param2Len)}); --limit; if (limit == 0) { return result; } uint8_t zero[] = {0}; readThrough = String(m.param1, m.param1Len) + String(zero, 1); } break; case weaselab::VersionedMap::Clear: readThrough = String(m.param2, m.param2Len); break; } } auto remaining = facade->unversionedRead(readThrough, end, limit, false); result.insert(result.end(), remaining.begin(), remaining.end()); return result; } } /** @private */ View(const Facade *facade, int64_t version) : facade{facade}, version{version} {} private: const Facade *facade; int64_t version; }; void addMutations(const weaselab::VersionedMap::Mutation *mutations, int numMutations, int64_t version) { versioned.addMutations(mutations, numMutations, version); } void setOldestVersion(int64_t version) { for (auto iter = versioned.begin(version), end = versioned.end(version); iter != end; ++iter) { auto m = *iter; switch (m.type) { case weaselab::VersionedMap::Set: unversioned[String(m.param1, m.param1Len)] = String(m.param2, m.param2Len); break; case weaselab::VersionedMap::Clear: for (auto unversionedIter = unversioned.lower_bound(String(m.param1, m.param1Len)); unversionedIter != unversioned.end() && unversionedIter->first < String(m.param2, m.param2Len);) { unversionedIter = unversioned.erase(unversionedIter); } break; } } versioned.setOldestVersion(version); } View viewAt(int64_t version) const { return View{this, version}; } int64_t getVersion() const { return versioned.getVersion(); } int64_t getOldestVersion() const { return versioned.getOldestVersion(); } std::vector> unversionedRead(const String &begin, const String &end, int &limit, bool reverse) const { std::vector> result; if (reverse) { if (unversioned.empty()) { return result; } for (auto iter = --unversioned.lower_bound(end); iter->first >= begin && limit > 0; --iter) { result.push_back(*iter); --limit; } } else { for (auto iter = unversioned.lower_bound(begin), iterEnd = unversioned.lower_bound(end); iter != iterEnd && limit > 0; ++iter) { result.push_back(*iter); --limit; } } return result; } std::map unversioned; weaselab::VersionedMap versioned; };