diff options
author | Roman Smrž <roman.smrz@seznam.cz> | 2020-07-22 22:13:33 +0200 |
---|---|---|
committer | Roman Smrž <roman.smrz@seznam.cz> | 2020-07-22 22:40:34 +0200 |
commit | 90021e1d335efac1017562c1d5dee43e99580319 (patch) | |
tree | 2a6c70ab6664085f5a86f210ac63cb064c9cb5c8 | |
parent | 8ac21c24e49bc3702c55d1c796f969f1d1f6128b (diff) |
Local and shared state
-rw-r--r-- | include/erebos/identity.h | 10 | ||||
-rw-r--r-- | include/erebos/state.h | 55 | ||||
-rw-r--r-- | src/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/identity.cpp | 11 | ||||
-rw-r--r-- | src/state.cpp | 127 | ||||
-rw-r--r-- | src/state.h | 32 |
6 files changed, 235 insertions, 1 deletions
diff --git a/include/erebos/identity.h b/include/erebos/identity.h index 7ba3f29..66a4afb 100644 --- a/include/erebos/identity.h +++ b/include/erebos/identity.h @@ -7,8 +7,14 @@ namespace erebos { class Identity { public: + Identity(const Identity &) = default; + Identity(Identity &&) = default; + Identity & operator=(const Identity &) = default; + Identity & operator=(Identity &&) = default; + static std::optional<Identity> load(const Ref &); static std::optional<Identity> load(const std::vector<Ref> &); + std::vector<Ref> store(const Storage & st) const; std::optional<std::string> name() const; std::optional<Identity> owner() const; @@ -38,9 +44,11 @@ public: static Builder create(const Storage &); Builder modify() const; + static const UUID sharedTypeId; + private: struct Priv; - const std::shared_ptr<const Priv> p; + std::shared_ptr<const Priv> p; Identity(const Priv * p); Identity(std::shared_ptr<const Priv> && p); }; diff --git a/include/erebos/state.h b/include/erebos/state.h new file mode 100644 index 0000000..543e03c --- /dev/null +++ b/include/erebos/state.h @@ -0,0 +1,55 @@ +#pragma once + +#include <erebos/identity.h> +#include <erebos/uuid.h> + +#include <optional> + +namespace erebos { + +using std::optional; +using std::vector; + +class LocalState +{ +public: + LocalState(); + explicit LocalState(const Ref &); + static LocalState load(const Ref & ref) { return LocalState(ref); } + Ref store(const Storage &) const; + + static const UUID headTypeId; + + const optional<Identity> & identity() const; + LocalState identity(const Identity &) const; + + template<class T> optional<T> shared() const; + template<class T> LocalState shared(const vector<Stored<T>> &) const; + template<class T> LocalState shared(const Stored<T> & x) const { return shared({ x }); }; + template<class T> LocalState shared(const Storage & st, const T & x) + { return updateShared(T::sharedTypeId, x.store(st)); } + +private: + vector<Ref> lookupShared(UUID) const; + LocalState updateShared(UUID, const vector<Ref> &) const; + + struct Priv; + std::shared_ptr<Priv> p; +}; + +template<class T> +optional<T> LocalState::shared() const +{ + return T::load(lookupShared(T::sharedTypeId)); +} + +template<class T> +LocalState LocalState::shared(const vector<Stored<T>> & v) const +{ + vector<Ref> refs; + for (const auto x : v) + refs.push_back(x.ref()); + return updateShared(T::sharedTypeId, refs); +} + +} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 64c14b5..b97293c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -9,6 +9,7 @@ add_library(erebos network pubkey service + state storage time uuid diff --git a/src/identity.cpp b/src/identity.cpp index 2396b9f..7364a8b 100644 --- a/src/identity.cpp +++ b/src/identity.cpp @@ -11,6 +11,8 @@ using std::nullopt; using std::runtime_error; using std::set; +const UUID Identity::sharedTypeId { "0c6c1fe0-f2d7-4891-926b-c332449f7871" }; + Identity::Identity(const Priv * p): p(p) {} Identity::Identity(shared_ptr<const Priv> && p): p(std::move(p)) {} @@ -32,6 +34,15 @@ optional<Identity> Identity::load(const vector<Ref> & refs) return nullopt; } +vector<Ref> Identity::store(const Storage & st) const +{ + vector<Ref> res; + res.reserve(p->data.size()); + for (const auto & x : p->data) + res.push_back(x.store(st)); + return res; +} + optional<string> Identity::name() const { return p->name.get(); diff --git a/src/state.cpp b/src/state.cpp new file mode 100644 index 0000000..8790dfc --- /dev/null +++ b/src/state.cpp @@ -0,0 +1,127 @@ +#include "state.h" + +#include "identity.h" + +using namespace erebos; + +using std::make_shared; + +const UUID LocalState::headTypeId { "1d7491a9-7bcb-4eaa-8f13-c8c4c4087e4e" }; + +LocalState::LocalState(): + p(make_shared<Priv>()) +{} + +LocalState::LocalState(const Ref & ref): + LocalState() +{ + auto rec = ref->asRecord(); + if (!rec) + return; + + if (auto x = rec->item("id").asRef()) + p->identity = Identity::load(*x); + + for (auto i : rec->items("shared")) + if (const auto & x = i.as<SharedState>()) + p->shared.push_back(*x); +} + +Ref LocalState::store(const Storage & st) const +{ + vector<Record::Item> items; + + if (p->identity) + items.emplace_back("id", *p->identity->ref()); + for (const auto & x : p->shared) + items.emplace_back("shared", x); + + return st.storeObject(Record(std::move(items))); +} + +const optional<Identity> & LocalState::identity() const +{ + return p->identity; +} + +LocalState LocalState::identity(const Identity & id) const +{ + LocalState ret; + ret.p->identity = id; + ret.p->shared = p->shared; + return ret; +} + +vector<Ref> LocalState::lookupShared(UUID type) const +{ + vector<Stored<SharedState>> found; + vector<Stored<SharedState>> process = p->shared; + + while (!process.empty()) { + auto cur = std::move(process.back()); + process.pop_back(); + + if (cur->type == type) { + found.push_back(std::move(cur)); + continue; + } + + for (const auto & x : cur->prev) + process.push_back(x); + } + + filterAncestors(found); + vector<Ref> res; + for (const auto & s : found) + for (const auto & v : s->value) + res.push_back(v); + return res; +} + +LocalState LocalState::updateShared(UUID type, const vector<Ref> & xs) const +{ + const Storage * st; + if (xs.size() > 0) + st = &xs[0].storage(); + else if (p->shared.size() > 0) + st = &p->shared[0].ref().storage(); + else + return *this; + + LocalState ret; + ret.p->identity = p->identity; + ret.p->shared.push_back(SharedState(p->shared, type, xs).store(*st)); + return ret; +} + + +SharedState::SharedState(const Ref & ref) +{ + auto rec = ref->asRecord(); + if (!rec) + return; + + for (auto i : rec->items("PREV")) + if (const auto & x = i.as<SharedState>()) + prev.push_back(*x); + + if (auto x = rec->item("type").asUUID()) + type = *x; + + for (auto i : rec->items("value")) + if (const auto & x = i.asRef()) + value.push_back(*x); +} + +Ref SharedState::store(const Storage & st) const +{ + vector<Record::Item> items; + + for (const auto & x : prev) + items.emplace_back("PREV", x); + items.emplace_back("type", type); + for (const auto & x : value) + items.emplace_back("value", x); + + return st.storeObject(Record(std::move(items))); +} diff --git a/src/state.h b/src/state.h new file mode 100644 index 0000000..d2c89fc --- /dev/null +++ b/src/state.h @@ -0,0 +1,32 @@ +#pragma once + +#include <erebos/state.h> + +#include "pubkey.h" + +using std::optional; +using std::vector; + +namespace erebos { + +struct LocalState::Priv +{ + optional<Identity> identity; + vector<Stored<struct SharedState>> shared; +}; + +struct SharedState +{ + explicit SharedState(vector<Stored<SharedState>> prev, + UUID type, vector<Ref> value): + prev(prev), type(type), value(value) {} + explicit SharedState(const Ref &); + static SharedState load(const Ref & ref) { return SharedState(ref); } + Ref store(const Storage &) const; + + vector<Stored<SharedState>> prev; + UUID type; + vector<Ref> value; +}; + +} |