diff options
author | Roman Smrž <roman.smrz@seznam.cz> | 2022-08-08 22:25:46 +0200 |
---|---|---|
committer | Roman Smrž <roman.smrz@seznam.cz> | 2022-08-08 22:50:27 +0200 |
commit | 7aa7649e980ff4b335b41eaea34a9a11820c3e2d (patch) | |
tree | 0da4b7c4bf0e80e58d75dcac83b052a22a829985 /src | |
parent | 5cfdbc49647b6be943d01e4ab141b705e9e5c86d (diff) |
Generation number of stored objects with caching
Diffstat (limited to 'src')
-rw-r--r-- | src/main.cpp | 47 | ||||
-rw-r--r-- | src/storage.cpp | 69 | ||||
-rw-r--r-- | src/storage.h | 3 |
3 files changed, 119 insertions, 0 deletions
diff --git a/src/main.cpp b/src/main.cpp index cb9002e..a3facea 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,6 +4,8 @@ #include <erebos/storage.h> #include <erebos/sync.h> +#include "storage.h" + #include <arpa/inet.h> #include <netinet/in.h> #include <sys/socket.h> @@ -37,6 +39,7 @@ using std::promise; using std::scoped_lock; using std::string; using std::thread; +using std::to_string; using std::unique_ptr; using std::vector; @@ -104,6 +107,48 @@ struct Command function<void(const vector<string> &)> action; }; +void store(const vector<string> & args) +{ + auto type = args.at(0); + + vector<uint8_t> inner, data; + + char * line = nullptr; + size_t size = 0; + + while (getline(&line, &size, stdin) > 0 && strlen(line) > 1) + copy(line, line + strlen(line), std::back_inserter(inner)); + + free(line); + + auto inserter = std::back_inserter(data); + copy(type.begin(), type.end(), inserter); + inserter = ' '; + + auto slen = to_string(inner.size()); + copy(slen.begin(), slen.end(), inserter); + inserter = '\n'; + + copy(inner.begin(), inner.end(), inserter); + + auto digest = st.priv().storeBytes(data); + + ostringstream ss; + ss << "store-done " << string(digest); + printLine(ss.str()); +} + +void storedGeneration(const vector<string> & args) +{ + auto ref = st.ref(Digest(args.at(0))); + if (!ref) + throw invalid_argument("ref " + args.at(0) + " not found"); + + ostringstream ss; + ss << "stored-generation " << string(ref->digest()) << " " << string(ref->generation()); + printLine(ss.str()); +} + void createIdentity(const vector<string> & args) { optional<Identity> identity; @@ -292,6 +337,8 @@ void attachReject(const vector<string> & params) } vector<Command> commands = { + { "store", store }, + { "stored-generation", storedGeneration }, { "create-identity", createIdentity }, { "start-server", startServer }, { "stop-server", stopServer }, diff --git a/src/storage.cpp b/src/storage.cpp index 05b100a..5784309 100644 --- a/src/storage.cpp +++ b/src/storage.cpp @@ -979,6 +979,56 @@ const Storage & Ref::storage() const return *static_cast<const Storage*>(p->storage.get()); } +vector<Ref> Ref::previous() const +{ + auto rec = (**this).asRecord(); + if (!rec) + return {}; + + vector<Ref> res; + + auto sdata = rec->item("SDATA").asRef(); + if (sdata) { + auto drec = sdata.value()->asRecord(); + if (!drec) + return {}; + + for (const Record::Item & i : drec->items("SPREV")) + if (auto x = i.asRef()) + res.push_back(*x); + return res; + } + + for (const Record::Item & i : rec->items("PREV")) + if (auto x = i.asRef()) + res.push_back(*x); + return res; +} + +Generation Ref::generation() const +{ + scoped_lock lock(p->storage->p->generationCacheLock); + return generationLocked(); +} + +Generation Ref::generationLocked() const +{ + auto it = p->storage->p->generationCache.find(p->digest); + if (it != p->storage->p->generationCache.end()) + return it->second; + + auto prev = previous(); + vector<Generation> pgen; + pgen.reserve(prev.size()); + for (const auto & r : prev) + pgen.push_back(r.generationLocked()); + + auto gen = Generation::next(pgen); + + p->storage->p->generationCache.emplace(p->digest, gen); + return gen; +} + template<class S> RecordT<S>::Item::operator bool() const @@ -1366,6 +1416,25 @@ optional<Blob> ObjectT<S>::asBlob() const template class erebos::ObjectT<Storage>; template class erebos::ObjectT<PartialStorage>; + +Generation::Generation(): Generation(0) {} +Generation::Generation(size_t g): gen(g) {} + +Generation Generation::next(const vector<Generation> & prev) +{ + Generation ret; + for (const auto g : prev) + if (ret.gen <= g.gen) + ret.gen = g.gen + 1; + return ret; +} + +Generation::operator string() const +{ + return to_string(gen); +} + + vector<Stored<Object>> erebos::collectStoredObjects(const Stored<Object> & from) { unordered_set<Digest> seen; diff --git a/src/storage.h b/src/storage.h index 0f7c3bf..ef335b8 100644 --- a/src/storage.h +++ b/src/storage.h @@ -164,6 +164,9 @@ struct PartialStorage::Priv optional<Digest> copy(const typename S::Ref &, vector<Digest> *) const; template<class S> optional<Digest> copy(const ObjectT<S> &, vector<Digest> *) const; + + mutable mutex generationCacheLock {}; + mutable unordered_map<Digest, Generation> generationCache {}; }; struct PartialRef::Priv |