From 7d403431e354c4a24d7dfdbef3a39ab7297ae7b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roman=20Smr=C5=BE?= Date: Mon, 6 Jan 2020 21:22:07 +0100 Subject: Deep copy of object to different storage --- include/erebos/storage.h | 7 ++++- src/storage.cpp | 71 ++++++++++++++++++++++++++++++++++++++++++------ src/storage.h | 5 ++++ 3 files changed, 74 insertions(+), 9 deletions(-) diff --git a/include/erebos/storage.h b/include/erebos/storage.h index 51fa3a4..d855460 100644 --- a/include/erebos/storage.h +++ b/include/erebos/storage.h @@ -74,6 +74,11 @@ public: Ref storeObject(const Record &) const; Ref storeObject(const Blob &) const; + std::variant> copy(const PartialRef &) const; + std::variant> copy(const PartialObject &) const; + Ref copy(const Ref &) const; + Ref copy(const Object &) const; + template Stored store(const T &) const; void storeKey(Ref pubref, const std::vector &) const; @@ -89,7 +94,7 @@ public: static constexpr size_t size = 32; Digest(const Digest &) = default; - Digest & operator=(const Digest &) = delete; + Digest & operator=(const Digest &) = default; explicit Digest(std::array value): value(value) {} explicit Digest(const std::string &); diff --git a/src/storage.cpp b/src/storage.cpp index 2b4e027..608f82b 100644 --- a/src/storage.cpp +++ b/src/storage.cpp @@ -347,9 +347,40 @@ optional Storage::loadObject(const Digest & digest) const } Ref Storage::storeObject(const Object & object) const +{ return copy(object); } + +Ref Storage::storeObject(const Record & val) const +{ return storeObject(Object(val)); } + +Ref Storage::storeObject(const Blob & val) const +{ return storeObject(Object(val)); } + +template +optional Storage::Priv::copy(const typename S::Ref & pref, vector * missing) const +{ + if (backend->contains(pref.digest())) + return pref.digest(); + if (pref) + return copy(*pref, missing); + if (missing) + missing->push_back(pref.digest()); + return nullopt; +} + +template +optional Storage::Priv::copy(const ObjectT & pobj, vector * missing) const { - // TODO: ensure storage transitively - auto content = object.encode(); + bool fail = false; + if (auto rec = pobj.asRecord()) + for (const auto & item : rec->items()) + if (auto r = item.asRef()) + if (!copy(*r, missing)) + fail = true; + + if (fail) + return nullopt; + + auto content = pobj.encode(); array arr; int ret = blake2b(arr.data(), content.data(), nullptr, @@ -358,15 +389,39 @@ Ref Storage::storeObject(const Object & object) const throw runtime_error("failed to compute digest"); Digest digest(arr); - p->backend->storeBytes(digest, content); - return Ref::create(*this, digest).value(); + backend->storeBytes(digest, content); + return digest; } -Ref Storage::storeObject(const Record & val) const -{ return storeObject(Object(val)); } +variant> Storage::copy(const PartialRef & pref) const +{ + vector missing; + if (auto digest = p->copy(pref, &missing)) + return Ref::create(*this, *digest).value(); + return missing; +} -Ref Storage::storeObject(const Blob & val) const -{ return storeObject(Object(val)); } +variant> Storage::copy(const PartialObject & pobj) const +{ + vector missing; + if (auto digest = p->copy(pobj, &missing)) + return Ref::create(*this, *digest).value(); + return missing; +} + +Ref Storage::copy(const Ref & ref) const +{ + if (auto digest = p->copy(ref, nullptr)) + return Ref::create(*this, *digest).value(); + throw runtime_error("corrupted storage"); +} + +Ref Storage::copy(const Object & obj) const +{ + if (auto digest = p->copy(obj, nullptr)) + return Ref::create(*this, *digest).value(); + throw runtime_error("corrupted storage"); +} void Storage::storeKey(Ref pubref, const vector & key) const { diff --git a/src/storage.h b/src/storage.h index cdb8984..9e22a4a 100644 --- a/src/storage.h +++ b/src/storage.h @@ -103,6 +103,11 @@ struct Storage::Priv shared_ptr backend; optional> loadBytes(const Digest & digest) const; + + template + optional copy(const typename S::Ref &, vector *) const; + template + optional copy(const ObjectT &, vector *) const; }; struct Ref::Priv -- cgit v1.2.3