From 8ac21c24e49bc3702c55d1c796f969f1d1f6128b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roman=20Smr=C5=BE?= Date: Sun, 7 Jun 2020 22:23:40 +0200 Subject: Storage: typed heads --- include/erebos/storage.h | 103 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 100 insertions(+), 3 deletions(-) (limited to 'include/erebos') diff --git a/include/erebos/storage.h b/include/erebos/storage.h index 09dc481..57304e1 100644 --- a/include/erebos/storage.h +++ b/include/erebos/storage.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -31,6 +32,7 @@ typedef ObjectT PartialObject; class Blob; template class Stored; +template class Head; class PartialStorage { @@ -87,11 +89,24 @@ public: template Stored store(const T &) const; + template std::optional> head(UUID id) const; + template std::vector> heads() const; + template Head storeHead(const T &) const; + template Head storeHead(const Stored &) const; + void storeKey(Ref pubref, const std::vector &) const; std::optional> loadKey(Ref pubref) const; protected: + template friend class Head; + Storage(const std::shared_ptr p): PartialStorage(p) {} + + std::optional headRef(UUID type, UUID id) const; + std::vector> headRefs(UUID type) const; + static UUID storeHead(UUID type, const Ref & ref); + static bool replaceHead(UUID type, UUID id, const Ref & old, const Ref & ref); + static std::optional updateHead(UUID type, UUID id, const Ref & old, const std::function &); }; class Digest @@ -316,12 +331,14 @@ class Stored { Stored(Ref ref, std::future && val): mref(ref), mval(std::move(val)) {} friend class Storage; + friend class Head; public: Stored(const Stored &) = default; Stored(Stored &&) = default; Stored & operator=(const Stored &) = default; Stored & operator=(Stored &&) = default; + Stored(const Ref &); static Stored load(const Ref &); Ref store(const Storage &) const; @@ -359,12 +376,18 @@ Stored Storage::store(const T & val) const })); } +template +Stored::Stored(const Ref & ref): + mref(ref), + mval(std::async(std::launch::deferred, [ref] { + return T::load(ref); + })) +{} + template Stored Stored::load(const Ref & ref) { - return Stored(ref, std::async(std::launch::deferred, [ref] { - return T::load(ref); - })); + return Stored(ref); } template @@ -436,6 +459,80 @@ void filterAncestors(std::vector> & xs) } } +template +class Head +{ + Head(UUID id, Ref ref, std::future && val): + mid(id), mstored(ref, std::move(val)) {} + friend class Storage; +public: + Head(UUID id, Ref ref): mid(id), mstored(ref) {} + + const T & operator*() const { return *mstored; } + const T * operator->() const { return &(*mstored); } + + std::vector> previous() const; + bool precedes(const Stored &) const; + + UUID id() const { return mid; } + const Stored & stored() const { return mstored; } + const Ref & ref() const { return mstored.ref(); } + + std::optional> update(const std::function(const Stored &)> &) const; + +private: + UUID mid; + Stored mstored; +}; + +template +std::optional> Storage::head(UUID id) const +{ + if (auto ref = headRef(T::headTypeId, id)) + return Head(id, *ref); + return std::nullopt; +} + +template +std::vector> Storage::heads() const +{ + std::vector> res; + for (const auto & x : headRefs(T::headTypeId)) + res.emplace_back(std::get(x), std::get(x)); + return res; +} + +template +Head Storage::storeHead(const T & val) const +{ + auto ref = val.store(*this); + auto id = storeHead(T::headTypeId, ref); + return Head(id, ref, std::async(std::launch::deferred, [val] { + return val; + })); +} + +template +Head Storage::storeHead(const Stored & val) const +{ + auto id = storeHead(T::headTypeId, val.ref()); + return Head(id, val.ref(), val.mval); +} + +template +std::optional> Head::update(const std::function(const Stored &)> & f) const +{ + auto res = Storage::updateHead(T::headTypeId, mid, ref(), [&f, this](const Ref & r) { + return f(r == ref() ? stored() : Stored::load(r)).ref(); + }); + + if (!res) + return std::nullopt; + if (*res == ref()) + return *this; + return Head(mid, *res); +} + } namespace std -- cgit v1.2.3