summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRoman Smrž <roman.smrz@seznam.cz>2022-08-08 22:25:46 +0200
committerRoman Smrž <roman.smrz@seznam.cz>2022-08-08 22:50:27 +0200
commit7aa7649e980ff4b335b41eaea34a9a11820c3e2d (patch)
tree0da4b7c4bf0e80e58d75dcac83b052a22a829985 /src
parent5cfdbc49647b6be943d01e4ab141b705e9e5c86d (diff)
Generation number of stored objects with caching
Diffstat (limited to 'src')
-rw-r--r--src/main.cpp47
-rw-r--r--src/storage.cpp69
-rw-r--r--src/storage.h3
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