summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/erebos/storage.h4
-rw-r--r--src/network/protocol.cpp2
-rw-r--r--src/storage.cpp29
3 files changed, 30 insertions, 5 deletions
diff --git a/include/erebos/storage.h b/include/erebos/storage.h
index 3feb22b..48bedd7 100644
--- a/include/erebos/storage.h
+++ b/include/erebos/storage.h
@@ -174,6 +174,7 @@ public:
PartialRef & operator=(PartialRef &&) = default;
static PartialRef create(const PartialStorage &, const Digest &);
+ static PartialRef zcreate(const PartialStorage &);
const Digest & digest() const;
@@ -234,6 +235,7 @@ private:
ptr(ptr) {}
public:
+ RecordT(): RecordT(std::vector<Item> {}) {}
RecordT(const std::vector<Item> &);
RecordT(std::vector<Item> &&);
std::vector<uint8_t> encode() const;
@@ -420,6 +422,8 @@ public:
std::vector<uint8_t> encode() const;
static ObjectT<S> load(const typename S::Ref &);
+ operator bool() const;
+
std::optional<RecordT<S>> asRecord() const;
std::optional<Blob> asBlob() const;
diff --git a/src/network/protocol.cpp b/src/network/protocol.cpp
index 8e0de61..02c3dae 100644
--- a/src/network/protocol.cpp
+++ b/src/network/protocol.cpp
@@ -134,7 +134,7 @@ NetworkProtocol::Connection NetworkProtocol::connect(sockaddr_in6 addr)
connections.push_back(conn.get());
vector<Header::Item> header {
- Header::Initiation { Digest(array<uint8_t, Digest::size> {}) },
+ Header::Initiation { Digest::of(Object(Record())) },
Header::AnnounceSelf { self->ref()->digest() },
Header::Version { defaultVersion },
};
diff --git a/src/storage.cpp b/src/storage.cpp
index 366fe71..19f35a9 100644
--- a/src/storage.cpp
+++ b/src/storage.cpp
@@ -746,7 +746,11 @@ optional<PartialObject> PartialStorage::loadObject(const Digest & digest) const
}
PartialRef PartialStorage::storeObject(const PartialObject & obj) const
-{ return ref(p->storeBytes(obj.encode())); }
+{
+ if (not obj)
+ return PartialRef::zcreate(*this);
+ return ref(p->storeBytes(obj.encode()));
+}
PartialRef PartialStorage::storeObject(const PartialRecord & val) const
{ return storeObject(PartialObject(val)); }
@@ -775,6 +779,8 @@ Ref Storage::storeObject(const Blob & val) const
template<class S>
optional<Digest> Storage::Priv::copy(const typename S::Ref & pref, vector<Digest> * missing) const
{
+ if (pref.digest().isZero())
+ return pref.digest();
if (backend->contains(pref.digest()))
return pref.digest();
if (pref)
@@ -787,6 +793,9 @@ optional<Digest> Storage::Priv::copy(const typename S::Ref & pref, vector<Digest
template<class S>
optional<Digest> Storage::Priv::copy(const ObjectT<S> & pobj, vector<Digest> * missing) const
{
+ if (not pobj)
+ return Digest(array<uint8_t, Digest::size> {});
+
bool fail = false;
if (auto rec = pobj.asRecord())
for (const auto & r : rec->items().asRef())
@@ -948,6 +957,11 @@ PartialRef PartialRef::create(const PartialStorage & st, const Digest & digest)
return PartialRef(shared_ptr<Priv>(p));
}
+PartialRef PartialRef::zcreate(const PartialStorage & st)
+{
+ return create(st, Digest(array<uint8_t, Digest::size> {}));
+}
+
const Digest & PartialRef::digest() const
{
return p->digest;
@@ -1421,9 +1435,6 @@ vector<uint8_t> RecordT<S>::encodeInner() const
vector<uint8_t> res;
auto inserter = std::back_inserter(res);
for (const auto & item : *ptr) {
- copy(item.name.begin(), item.name.end(), inserter);
- inserter = ':';
-
string type;
string value;
@@ -1451,6 +1462,8 @@ vector<uint8_t> RecordT<S>::encodeInner() const
value = string(*x);
} else if (auto x = item.asRef()) {
type = "r";
+ if (x->digest().isZero())
+ continue;
value = string(x->digest());
} else if (auto x = item.asUnknown()) {
type = x->type;
@@ -1459,6 +1472,8 @@ vector<uint8_t> RecordT<S>::encodeInner() const
throw runtime_error("unhandeled record item type");
}
+ copy(item.name.begin(), item.name.end(), inserter);
+ inserter = ':';
copy(type.begin(), type.end(), inserter);
inserter = ' ';
@@ -1599,6 +1614,12 @@ ObjectT<S> ObjectT<S>::load(const typename S::Ref & ref)
}
template<class S>
+ObjectT<S>::operator bool() const
+{
+ return not holds_alternative<monostate>(content);
+}
+
+template<class S>
optional<RecordT<S>> ObjectT<S>::asRecord() const
{
if (holds_alternative<RecordT<S>>(content))