summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoman Smrž <roman.smrz@seznam.cz>2020-01-06 21:22:07 +0100
committerRoman Smrž <roman.smrz@seznam.cz>2020-01-06 21:22:07 +0100
commit7d403431e354c4a24d7dfdbef3a39ab7297ae7b5 (patch)
tree251f40ac82488dc2690ff4dea6affc22085f7b48
parent94f4127f71d0358424bbaba3e849c761903a75a1 (diff)
Deep copy of object to different storage
-rw-r--r--include/erebos/storage.h7
-rw-r--r--src/storage.cpp71
-rw-r--r--src/storage.h5
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<Ref, std::vector<Digest>> copy(const PartialRef &) const;
+ std::variant<Ref, std::vector<Digest>> copy(const PartialObject &) const;
+ Ref copy(const Ref &) const;
+ Ref copy(const Object &) const;
+
template<typename T> Stored<T> store(const T &) const;
void storeKey(Ref pubref, const std::vector<uint8_t> &) 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<uint8_t, size> 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<Object> 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<class S>
+optional<Digest> Storage::Priv::copy(const typename S::Ref & pref, vector<Digest> * missing) const
+{
+ if (backend->contains(pref.digest()))
+ return pref.digest();
+ if (pref)
+ return copy<S>(*pref, missing);
+ if (missing)
+ missing->push_back(pref.digest());
+ return nullopt;
+}
+
+template<class S>
+optional<Digest> Storage::Priv::copy(const ObjectT<S> & pobj, vector<Digest> * 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<S>(*r, missing))
+ fail = true;
+
+ if (fail)
+ return nullopt;
+
+ auto content = pobj.encode();
array<uint8_t, Digest::size> 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<Ref, vector<Digest>> Storage::copy(const PartialRef & pref) const
+{
+ vector<Digest> missing;
+ if (auto digest = p->copy<PartialStorage>(pref, &missing))
+ return Ref::create(*this, *digest).value();
+ return missing;
+}
-Ref Storage::storeObject(const Blob & val) const
-{ return storeObject(Object(val)); }
+variant<Ref, vector<Digest>> Storage::copy(const PartialObject & pobj) const
+{
+ vector<Digest> missing;
+ if (auto digest = p->copy<PartialStorage>(pobj, &missing))
+ return Ref::create(*this, *digest).value();
+ return missing;
+}
+
+Ref Storage::copy(const Ref & ref) const
+{
+ if (auto digest = p->copy<Storage>(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<Storage>(obj, nullptr))
+ return Ref::create(*this, *digest).value();
+ throw runtime_error("corrupted storage");
+}
void Storage::storeKey(Ref pubref, const vector<uint8_t> & 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<StorageBackend> backend;
optional<vector<uint8_t>> loadBytes(const Digest & digest) const;
+
+ template<class S>
+ optional<Digest> copy(const typename S::Ref &, vector<Digest> *) const;
+ template<class S>
+ optional<Digest> copy(const ObjectT<S> &, vector<Digest> *) const;
};
struct Ref::Priv