Update save/load hooks in LCP
Reviewers: mtomic Reviewed By: mtomic Subscribers: pullbot Differential Revision: https://phabricator.memgraph.io/D1517
This commit is contained in:
parent
4fd5b1ebc4
commit
09bc9cb164
@ -50,13 +50,6 @@ cpp<#
|
||||
(property "storage::Property")
|
||||
(property-name "std::string")
|
||||
(value "PropertyValue" :initval "PropertyValue::Null"
|
||||
:save-fun #>cpp utils::SaveTypedValue(ar, value); cpp<#
|
||||
:load-fun
|
||||
#>cpp
|
||||
query::TypedValue tv;
|
||||
utils::LoadTypedValue(ar, tv);
|
||||
value = tv;
|
||||
cpp<#
|
||||
:capnp-type "Dis.TypedValue"
|
||||
:capnp-save
|
||||
(lambda (builder member)
|
||||
|
@ -57,54 +57,14 @@ cpp<#
|
||||
((global-address "storage::Address<mvcc::VersionList<TElement>>"
|
||||
:capnp-type "Storage.Address")
|
||||
(old-element-input "TElement *"
|
||||
:save-fun
|
||||
"if (old_element_input) {
|
||||
ar << true;
|
||||
SaveElement(ar, *old_element_input, worker_id);
|
||||
} else {
|
||||
ar << false;
|
||||
}"
|
||||
:load-fun ""
|
||||
:capnp-type '((null "Void") (vertex "Dis.Vertex") (edge "Dis.Edge"))
|
||||
:capnp-save #'save-element :capnp-load #'load-element)
|
||||
(old-element-output "std::unique_ptr<TElement>"
|
||||
:save-fun ""
|
||||
:load-fun
|
||||
"bool has_old;
|
||||
ar >> has_old;
|
||||
if (has_old) {
|
||||
if constexpr (std::is_same<TElement, Vertex>::value) {
|
||||
old_element_output = std::move(LoadVertex(ar));
|
||||
} else {
|
||||
old_element_output = std::move(LoadEdge(ar));
|
||||
}
|
||||
}"
|
||||
:capnp-save :dont-save)
|
||||
(old-element-output "std::unique_ptr<TElement>" :capnp-save :dont-save)
|
||||
(new-element-input "TElement *"
|
||||
:save-fun
|
||||
"if (new_element_input) {
|
||||
ar << true;
|
||||
SaveElement(ar, *new_element_input, worker_id);
|
||||
} else {
|
||||
ar << false;
|
||||
}"
|
||||
:load-fun ""
|
||||
:capnp-type '((null "Void") (vertex "Dis.Vertex") (edge "Dis.Edge"))
|
||||
:capnp-save #'save-element :capnp-load #'load-element)
|
||||
(new-element-output "std::unique_ptr<TElement>"
|
||||
:save-fun ""
|
||||
:load-fun
|
||||
"bool has_new;
|
||||
ar >> has_new;
|
||||
if (has_new) {
|
||||
if constexpr (std::is_same<TElement, Vertex>::value) {
|
||||
new_element_output = std::move(LoadVertex(ar));
|
||||
} else {
|
||||
new_element_output = std::move(LoadEdge(ar));
|
||||
}
|
||||
}"
|
||||
:capnp-save :dont-save)
|
||||
(worker-id :int16_t :save-fun "" :load-fun "" :capnp-save :dont-save))
|
||||
(new-element-output "std::unique_ptr<TElement>" :capnp-save :dont-save)
|
||||
(worker-id :int16_t :capnp-save :dont-save))
|
||||
(:public
|
||||
#>cpp
|
||||
SerializedGraphElement(storage::Address<mvcc::VersionList<TElement>> global_address,
|
||||
@ -146,7 +106,7 @@ cpp<#
|
||||
'(in out both)))
|
||||
;; TODO(mtomic): Why isn't edge-types serialized?
|
||||
(edge-types "std::vector<storage::EdgeType>"
|
||||
:save-fun "" :load-fun "" :capnp-save :dont-save)
|
||||
:capnp-save :dont-save)
|
||||
(graph-view "query::GraphView"
|
||||
:capnp-type "Query.GraphView" :capnp-init nil
|
||||
:capnp-save (lcp:capnp-save-enum "::query::capnp::GraphView"
|
||||
@ -244,7 +204,7 @@ cpp<#
|
||||
cpp<#))
|
||||
(:response
|
||||
((subcursor-id :int64_t ;; TODO(mtomic): Unused?
|
||||
:save-fun "" :load-fun "" :capnp-save :dont-save)
|
||||
:capnp-save :dont-save)
|
||||
(edges "std::vector<SerializedEdge>" :capnp-type "List(SerializedGraphElement)"
|
||||
:capnp-save (lcp:capnp-save-vector "capnp::SerializedGraphElement" "SerializedEdge")
|
||||
:capnp-load (lcp:capnp-load-vector "capnp::SerializedGraphElement" "SerializedEdge"))
|
||||
|
@ -29,7 +29,6 @@ cpp<#
|
||||
(:request ((member "TxGidPair")))
|
||||
(:response
|
||||
((vertex-input "const Vertex *"
|
||||
:save-fun "SaveVertex(ar, *vertex_input, worker_id);" :load-fun ""
|
||||
:capnp-type "Dist.Vertex"
|
||||
:capnp-save
|
||||
(lambda (builder member)
|
||||
@ -42,16 +41,14 @@ cpp<#
|
||||
#>cpp
|
||||
vertex_output = LoadVertex(${reader});
|
||||
cpp<#))
|
||||
(worker-id :int64_t :save-fun "" :load-fun "" :capnp-save :dont-save)
|
||||
(worker-id :int64_t :capnp-save :dont-save)
|
||||
(vertex-output "std::unique_ptr<Vertex>" :initarg nil
|
||||
:save-fun "" :load-fun "vertex_output = LoadVertex(ar);"
|
||||
:capnp-save :dont-save))))
|
||||
|
||||
(lcp:define-rpc edge
|
||||
(:request ((member "TxGidPair")))
|
||||
(:response
|
||||
((edge-input "const Edge *"
|
||||
:save-fun "SaveEdge(ar, *edge_input, worker_id);" :load-fun ""
|
||||
:capnp-type "Dist.Edge"
|
||||
:capnp-save
|
||||
(lambda (builder member)
|
||||
@ -64,9 +61,8 @@ cpp<#
|
||||
#>cpp
|
||||
edge_output = LoadEdge(${reader});
|
||||
cpp<#))
|
||||
(worker-id :int64_t :save-fun "" :load-fun "" :capnp-save :dont-save)
|
||||
(worker-id :int64_t :capnp-save :dont-save)
|
||||
(edge-output "std::unique_ptr<Edge>" :initarg nil
|
||||
:save-fun "" :load-fun "edge_output = LoadEdge(ar);"
|
||||
:capnp-save :dont-save))))
|
||||
|
||||
(lcp:define-rpc vertex-count
|
||||
|
@ -46,10 +46,7 @@ cpp<#
|
||||
:capnp-type "Utils.SharedPtr(Plan.LogicalOperator)"
|
||||
:capnp-save #'save-plan :capnp-load #'load-plan)
|
||||
(symbol-table "query::SymbolTable" :capnp-type "Sem.SymbolTable")
|
||||
(storage "query::AstStorage" :initarg nil
|
||||
:save-fun ""
|
||||
:load-fun "storage = std::move(ar.template get_helper<query::AstStorage>(query::AstStorage::kHelperId));"
|
||||
:capnp-save :dont-save)))
|
||||
(storage "query::AstStorage" :initarg nil :capnp-save :dont-save)))
|
||||
(:response ()))
|
||||
|
||||
(lcp:define-rpc remove-plan
|
||||
|
@ -179,125 +179,6 @@ to the appropriate value. Not used on side that generates the response.")
|
||||
PullResData &operator=(const PullResData &) = delete;
|
||||
PullResData(PullResData &&) = default;
|
||||
PullResData &operator=(PullResData &&) = default;
|
||||
|
||||
|
||||
/// Saves a typed value that is a vertex/edge/path.
|
||||
template <class TArchive>
|
||||
void SaveGraphElement(TArchive &ar, const query::TypedValue &value) const {
|
||||
// Helper template function for storing a vertex or an edge.
|
||||
auto save_element = [&ar, this](auto element_accessor) {
|
||||
ar << element_accessor.GlobalAddress().raw();
|
||||
|
||||
// If both old and new are null, we need to reconstruct.
|
||||
if (!(element_accessor.GetOld() || element_accessor.GetNew())) {
|
||||
bool result = element_accessor.Reconstruct();
|
||||
CHECK(result) << "Attempting to serialize an element not visible to "
|
||||
"current transaction.";
|
||||
}
|
||||
auto *old_rec = element_accessor.GetOld();
|
||||
if (send_old && old_rec) {
|
||||
ar << true;
|
||||
distributed::SaveElement(ar, *old_rec, worker_id);
|
||||
} else {
|
||||
ar << false;
|
||||
}
|
||||
if (send_new) {
|
||||
// Must call SwitchNew as that will trigger a potentially necesary
|
||||
// Reconstruct.
|
||||
element_accessor.SwitchNew();
|
||||
auto *new_rec = element_accessor.GetNew();
|
||||
if (new_rec) {
|
||||
ar << true;
|
||||
distributed::SaveElement(ar, *new_rec, worker_id);
|
||||
} else {
|
||||
ar << false;
|
||||
}
|
||||
} else {
|
||||
ar << false;
|
||||
}
|
||||
};
|
||||
switch (value.type()) {
|
||||
case query::TypedValue::Type::Vertex:
|
||||
save_element(value.ValueVertex());
|
||||
break;
|
||||
case query::TypedValue::Type::Edge:
|
||||
save_element(value.ValueEdge());
|
||||
break;
|
||||
case query::TypedValue::Type::Path: {
|
||||
auto &path = value.ValuePath();
|
||||
ar << path.size();
|
||||
save_element(path.vertices()[0]);
|
||||
for (size_t i = 0; i < path.size(); ++i) {
|
||||
save_element(path.edges()[i]);
|
||||
save_element(path.vertices()[i + 1]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOG(FATAL) << "Unsupported graph element type: " << value.type();
|
||||
}
|
||||
}
|
||||
|
||||
/// Loads a typed value that is a vertex/edge/path. Part of the
|
||||
/// deserialization process, populates the temporary data caches which are
|
||||
/// processed later.
|
||||
template <class TArchive>
|
||||
void LoadGraphElement(TArchive &ar, query::TypedValue::Type type,
|
||||
query::TypedValue &value) {
|
||||
auto load_edge = [](auto &ar) {
|
||||
bool exists;
|
||||
ar >> exists;
|
||||
return exists ? LoadEdge(ar) : nullptr;
|
||||
};
|
||||
auto load_vertex = [](auto &ar) {
|
||||
bool exists;
|
||||
ar >> exists;
|
||||
return exists ? LoadVertex(ar) : nullptr;
|
||||
};
|
||||
|
||||
switch (type) {
|
||||
case query::TypedValue::Type::Vertex: {
|
||||
storage::VertexAddress::StorageT address;
|
||||
ar >> address;
|
||||
vertices.emplace_back(storage::VertexAddress(address), load_vertex(ar),
|
||||
load_vertex(ar), &value);
|
||||
break;
|
||||
}
|
||||
case query::TypedValue::Type::Edge: {
|
||||
storage::VertexAddress::StorageT address;
|
||||
ar >> address;
|
||||
edges.emplace_back(storage::EdgeAddress(address), load_edge(ar),
|
||||
load_edge(ar), &value);
|
||||
break;
|
||||
}
|
||||
case query::TypedValue::Type::Path: {
|
||||
size_t path_size;
|
||||
ar >> path_size;
|
||||
|
||||
paths.emplace_back(&value);
|
||||
auto &path_data = paths.back();
|
||||
|
||||
storage::VertexAddress::StorageT vertex_address;
|
||||
storage::EdgeAddress::StorageT edge_address;
|
||||
ar >> vertex_address;
|
||||
path_data.vertices.emplace_back(storage::VertexAddress(vertex_address),
|
||||
load_vertex(ar), load_vertex(ar),
|
||||
nullptr);
|
||||
for (size_t i = 0; i < path_size; ++i) {
|
||||
ar >> edge_address;
|
||||
path_data.edges.emplace_back(storage::EdgeAddress(edge_address),
|
||||
load_edge(ar), load_edge(ar), nullptr);
|
||||
ar >> vertex_address;
|
||||
path_data.vertices.emplace_back(
|
||||
storage::VertexAddress(vertex_address), load_vertex(ar),
|
||||
load_vertex(ar), nullptr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOG(FATAL) << "Unsupported graph element type: " << type;
|
||||
}
|
||||
}
|
||||
cpp<#)
|
||||
(:private
|
||||
#>cpp
|
||||
@ -436,28 +317,6 @@ cpp<#)
|
||||
(plan-id :int64_t)
|
||||
(command-id "tx::CommandId")
|
||||
(params "Parameters"
|
||||
:save-fun
|
||||
"
|
||||
ar << params.size();
|
||||
for (auto &kv : params) {
|
||||
ar << kv.first;
|
||||
// Params never contain a vertex/edge, so save plan TypedValue.
|
||||
utils::SaveTypedValue(ar, kv.second);
|
||||
}
|
||||
"
|
||||
:load-fun
|
||||
"
|
||||
size_t params_size;
|
||||
ar >> params_size;
|
||||
for (size_t i = 0; i < params_size; ++i) {
|
||||
int token_pos;
|
||||
ar >> token_pos;
|
||||
query::TypedValue param;
|
||||
// Params never contain a vertex/edge, so load plan TypedValue.
|
||||
utils::LoadTypedValue(ar, param);
|
||||
params.Add(token_pos, param);
|
||||
}
|
||||
"
|
||||
:capnp-type "Utils.Map(Utils.BoxInt64, Dis.TypedValue)"
|
||||
:capnp-save
|
||||
(lambda (builder member)
|
||||
@ -490,46 +349,7 @@ cpp<#)
|
||||
(send-old :bool)
|
||||
(send-new :bool)))
|
||||
(:response
|
||||
((data "PullResData" :initarg :move
|
||||
:save-fun
|
||||
"
|
||||
ar << data.pull_state;
|
||||
ar << data.frames.size();
|
||||
// We need to indicate how many values are in each frame.
|
||||
// Assume all the frames have an equal number of elements.
|
||||
ar << (data.frames.size() == 0 ? 0 : data.frames[0].size());
|
||||
for (const auto &frame : data.frames) {
|
||||
for (const auto &value : frame) {
|
||||
utils::SaveTypedValue<TArchive>(
|
||||
ar, value, [this](TArchive &ar, const query::TypedValue &value) {
|
||||
data.SaveGraphElement(ar, value);
|
||||
});
|
||||
}
|
||||
}
|
||||
"
|
||||
:load-fun
|
||||
"
|
||||
ar >> data.pull_state;
|
||||
size_t frame_count;
|
||||
ar >> frame_count;
|
||||
data.frames.reserve(frame_count);
|
||||
size_t frame_size;
|
||||
ar >> frame_size;
|
||||
for (size_t i = 0; i < frame_count; ++i) {
|
||||
data.frames.emplace_back();
|
||||
auto ¤t_frame = data.frames.back();
|
||||
current_frame.reserve(frame_size);
|
||||
for (size_t j = 0; j < frame_size; ++j) {
|
||||
current_frame.emplace_back();
|
||||
utils::LoadTypedValue<TArchive>(
|
||||
ar, current_frame.back(),
|
||||
[this](TArchive &ar, query::TypedValue::TypedValue::Type type,
|
||||
query::TypedValue &value) {
|
||||
data.LoadGraphElement(ar, type, value);
|
||||
});
|
||||
}
|
||||
}
|
||||
"))
|
||||
((data "PullResData" :initarg :move))
|
||||
(:serialize :capnp :base t :load-args '((dba "database::GraphDbAccessor *")
|
||||
(data-manager "distributed::DataManager *")))))
|
||||
|
||||
|
@ -66,26 +66,6 @@ cpp<#
|
||||
:capnp-save (lcp:capnp-save-vector "storage::capnp::Common" "storage::Label")
|
||||
:capnp-load (lcp:capnp-load-vector "storage::capnp::Common" "storage::Label"))
|
||||
(properties "std::unordered_map<storage::Property, query::TypedValue>"
|
||||
:save-fun
|
||||
#>cpp
|
||||
ar << properties.size();
|
||||
for (auto &kv : properties) {
|
||||
ar << kv.first;
|
||||
utils::SaveTypedValue(ar, kv.second);
|
||||
}
|
||||
cpp<#
|
||||
:load-fun
|
||||
#>cpp
|
||||
size_t props_size;
|
||||
ar >> props_size;
|
||||
for (size_t i = 0; i < props_size; ++i) {
|
||||
storage::Property p;
|
||||
ar >> p;
|
||||
query::TypedValue tv;
|
||||
utils::LoadTypedValue(ar, tv);
|
||||
properties.emplace(p, std::move(tv));
|
||||
}
|
||||
cpp<#
|
||||
:capnp-type "Utils.Map(Storage.Common, Dis.TypedValue)"
|
||||
:capnp-save
|
||||
(lambda (builder member)
|
||||
|
@ -219,14 +219,12 @@ produces:
|
||||
;; TODO: Support giving a name for reader function.
|
||||
(reader nil :type boolean :read-only t)
|
||||
(documentation nil :type (or null string) :read-only t)
|
||||
;; Custom saving and loading code. May be a function which takes 2
|
||||
;; args: (archive member-name) and needs to return C++ code.
|
||||
(save-fun nil :type (or null string raw-cpp function) :read-only t)
|
||||
(load-fun nil :type (or null string raw-cpp function) :read-only t)
|
||||
;; CAPNP-TYPE may be a string specifying the type, or a list of
|
||||
;; (member-symbol "capnp-type") specifying a union type.
|
||||
(capnp-type nil :type (or null string list) :read-only t)
|
||||
(capnp-init t :type boolean :read-only t)
|
||||
;; Custom saving and loading code. May be a function which takes 2
|
||||
;; args: (builder-or-reader member-name) and needs to return C++ code.
|
||||
(capnp-save nil :type (or null function (eql :dont-save)) :read-only t)
|
||||
(capnp-load nil :type (or null function) :read-only t))
|
||||
|
||||
@ -1319,8 +1317,16 @@ slot-options are keyword arguments. Currently supported options are:
|
||||
* :reader -- if t, generates a public getter for the member.
|
||||
* :scope -- class scope of the member, either :public, :protected or :private (default).
|
||||
* :documentation -- Doxygen documentation of the member.
|
||||
* :save-fun -- Custom code for serializing this member.
|
||||
* :load-fun -- Custom code for deserializing this member.
|
||||
* :capnp-type -- String or list specifying which Cap'n Proto type to use for
|
||||
serialization. If a list of (member-symbol \"capnp-type\") then a union
|
||||
type is specified.
|
||||
* :capnp-init -- Boolean indicating whether the member needs to be
|
||||
initialized in Cap'n Proto structure, by calling `builder.init<member>`.
|
||||
This is T by default, you may need to set it to NIL if the LCP doesn't
|
||||
correctly recognize a primitive type or you wish to call `init<member>`
|
||||
yourself.
|
||||
* :capnp-save -- Custom code for serializing this member.
|
||||
* :capnp-load -- Custom code for deserializing this member.
|
||||
|
||||
Currently supported class-options are:
|
||||
* :documentation -- Doxygen documentation of the class.
|
||||
|
Loading…
Reference in New Issue
Block a user