diff --git a/src/storage/v3/CMakeLists.txt b/src/storage/v3/CMakeLists.txt index f371f7b7b..b3a3d68a9 100644 --- a/src/storage/v3/CMakeLists.txt +++ b/src/storage/v3/CMakeLists.txt @@ -17,6 +17,7 @@ set(storage_v3_src_files shard_rsm.cpp bindings/typed_value.cpp expr.cpp + vertex.cpp request_helper.cpp) # ###################### diff --git a/src/storage/v3/delta.hpp b/src/storage/v3/delta.hpp index 9548be146..1c6e57d2b 100644 --- a/src/storage/v3/delta.hpp +++ b/src/storage/v3/delta.hpp @@ -15,13 +15,13 @@ #include "storage/v3/edge_ref.hpp" #include "storage/v3/id_types.hpp" #include "storage/v3/property_value.hpp" +#include "storage/v3/vertex.hpp" #include "storage/v3/vertex_id.hpp" #include "utils/logging.hpp" namespace memgraph::storage::v3 { // Forward declarations because we only store pointers here. -struct Vertex; struct Edge; struct Delta; struct CommitInfo; diff --git a/src/storage/v3/edge.hpp b/src/storage/v3/edge.hpp index df47b8416..c5cf6c6f7 100644 --- a/src/storage/v3/edge.hpp +++ b/src/storage/v3/edge.hpp @@ -21,7 +21,7 @@ namespace memgraph::storage::v3 { -struct Vertex; +using EdgeContainer = std::map<Gid, Edge>; struct Edge { Edge(Gid gid, Delta *delta) : gid(gid), deleted(false), delta(delta) { @@ -34,13 +34,13 @@ struct Edge { PropertyStore properties; bool deleted; - // uint8_t PAD; + uint8_t PAD; // uint16_t PAD; Delta *delta; }; -static_assert(alignof(Edge) >= 8, "The Edge should be aligned to at least 8!"); +// static_assert(alignof(Edge) >= 8, "The Edge should be aligned to at least 8!"); inline bool operator==(const Edge &first, const Edge &second) { return first.gid == second.gid; } inline bool operator<(const Edge &first, const Edge &second) { return first.gid < second.gid; } diff --git a/src/storage/v3/edge_accessor.hpp b/src/storage/v3/edge_accessor.hpp index bc143c1e3..b57beeb96 100644 --- a/src/storage/v3/edge_accessor.hpp +++ b/src/storage/v3/edge_accessor.hpp @@ -25,7 +25,6 @@ namespace memgraph::storage::v3 { -struct Vertex; class VertexAccessor; struct Indices; diff --git a/src/storage/v3/indices.cpp b/src/storage/v3/indices.cpp index fc546b594..84097a26a 100644 --- a/src/storage/v3/indices.cpp +++ b/src/storage/v3/indices.cpp @@ -21,6 +21,7 @@ #include "storage/v3/mvcc.hpp" #include "storage/v3/property_value.hpp" #include "storage/v3/schemas.hpp" +#include "storage/v3/vertex.hpp" #include "utils/bound.hpp" #include "utils/logging.hpp" #include "utils/memory_tracker.hpp" @@ -57,9 +58,9 @@ bool AnyVersionHasLabel(const Vertex &vertex, LabelId label, uint64_t timestamp) bool deleted{false}; const Delta *delta{nullptr}; { - has_label = utils::Contains(vertex.labels, label); - deleted = vertex.deleted; - delta = vertex.delta; + has_label = utils::Contains(vertex.second.labels, label); + deleted = vertex.second.deleted; + delta = vertex.second.delta; } if (!deleted && has_label) { return true; @@ -109,10 +110,10 @@ bool AnyVersionHasLabelProperty(const Vertex &vertex, LabelId label, PropertyId bool deleted{false}; const Delta *delta{nullptr}; { - has_label = utils::Contains(vertex.labels, label); - current_value_equal_to_value = vertex.properties.IsPropertyEqual(key, value); - deleted = vertex.deleted; - delta = vertex.delta; + has_label = utils::Contains(vertex.second.labels, label); + current_value_equal_to_value = vertex.second.properties.IsPropertyEqual(key, value); + deleted = vertex.second.deleted; + delta = vertex.second.delta; } if (!deleted && has_label && current_value_equal_to_value) { @@ -167,9 +168,9 @@ bool CurrentVersionHasLabel(const Vertex &vertex, LabelId label, Transaction *tr bool has_label{false}; const Delta *delta{nullptr}; { - deleted = vertex.deleted; - has_label = utils::Contains(vertex.labels, label); - delta = vertex.delta; + deleted = vertex.second.deleted; + has_label = utils::Contains(vertex.second.labels, label); + delta = vertex.second.delta; } ApplyDeltasForRead(transaction, delta, view, [&deleted, &has_label, label](const Delta &delta) { switch (delta.action) { @@ -218,10 +219,10 @@ bool CurrentVersionHasLabelProperty(const Vertex &vertex, LabelId label, Propert bool current_value_equal_to_value = value.IsNull(); const Delta *delta{nullptr}; { - deleted = vertex.deleted; - has_label = utils::Contains(vertex.labels, label); - current_value_equal_to_value = vertex.properties.IsPropertyEqual(key, value); - delta = vertex.delta; + deleted = vertex.second.deleted; + has_label = utils::Contains(vertex.second.labels, label); + current_value_equal_to_value = vertex.second.properties.IsPropertyEqual(key, value); + delta = vertex.second.delta; } ApplyDeltasForRead(transaction, delta, view, [&deleted, &has_label, ¤t_value_equal_to_value, key, label, &value](const Delta &delta) { @@ -282,8 +283,8 @@ bool LabelIndex::CreateIndex(LabelId label, VertexContainer &vertices) { } try { auto acc = it->second.access(); - for ([[maybe_unused]] auto &[pk, vertex] : vertices) { - if (vertex.deleted || !utils::Contains(vertex.labels, label)) { + for ([[maybe_unused]] auto &vertex : vertices) { + if (vertex.second.deleted || !VertexHasLabel(vertex, label)) { continue; } acc.insert(Entry{&vertex, 0}); @@ -395,7 +396,7 @@ void LabelPropertyIndex::UpdateOnAddLabel(LabelId label, Vertex *vertex, const T if (label_prop.first != label) { continue; } - auto prop_value = vertex->properties.GetProperty(label_prop.second); + auto prop_value = vertex->second.properties.GetProperty(label_prop.second); if (!prop_value.IsNull()) { index.emplace(prop_value, Entry{prop_value, vertex, tx.start_timestamp.logical_id}); } @@ -411,7 +412,7 @@ void LabelPropertyIndex::UpdateOnSetProperty(PropertyId property, const Property if (label_prop.second != property) { continue; } - if (utils::Contains(vertex->labels, label_prop.first)) { + if (VertexHasLabel(*vertex, label_prop.first)) { index.emplace(value, Entry{value, vertex, tx.start_timestamp.logical_id}); } } @@ -426,11 +427,11 @@ bool LabelPropertyIndex::CreateIndex(LabelId label, PropertyId property, VertexC return false; } try { - for ([[maybe_unused]] auto &[pk, vertex] : vertices) { - if (vertex.deleted || !utils::Contains(vertex.labels, label)) { + for ([[maybe_unused]] auto &vertex : vertices) { + if (vertex.second.deleted || !VertexHasLabel(vertex, label)) { continue; } - auto value = vertex.properties.GetProperty(property); + auto value = vertex.second.properties.GetProperty(property); if (value.IsNull()) { continue; } diff --git a/src/storage/v3/indices.hpp b/src/storage/v3/indices.hpp index d46fb7f38..425c9da13 100644 --- a/src/storage/v3/indices.hpp +++ b/src/storage/v3/indices.hpp @@ -18,7 +18,6 @@ #include <utility> #include "storage/v3/config.hpp" -#include "storage/v3/containers.hpp" #include "storage/v3/property_value.hpp" #include "storage/v3/transaction.hpp" #include "storage/v3/vertex_accessor.hpp" diff --git a/src/storage/v3/mvcc.hpp b/src/storage/v3/mvcc.hpp index 219491635..001f57003 100644 --- a/src/storage/v3/mvcc.hpp +++ b/src/storage/v3/mvcc.hpp @@ -11,9 +11,13 @@ #pragma once +#include <type_traits> +#include "storage/v3/edge.hpp" #include "storage/v3/property_value.hpp" #include "storage/v3/transaction.hpp" +#include "storage/v3/vertex.hpp" #include "storage/v3/view.hpp" +#include "utils/concepts.hpp" namespace memgraph::storage::v3 { @@ -77,10 +81,18 @@ inline void ApplyDeltasForRead(Transaction *transaction, const Delta *delta, Vie /// transaction) and returns a `bool` value indicating whether the caller can /// proceed with a write operation. template <typename TObj> +requires utils::SameAsAnyOf<TObj, Edge, Vertex> inline bool PrepareForWrite(Transaction *transaction, TObj *object) { - if (object->delta == nullptr) return true; + auto *delta_holder = std::invoke([object]() -> auto * { + if constexpr (std::is_same_v<TObj, Vertex>) { + return &object->second; + } else { + return object; + } + }); + if (delta_holder->delta == nullptr) return true; - const auto &delta_commit_info = *object->delta->commit_info; + const auto &delta_commit_info = *delta_holder->delta->commit_info; if (delta_commit_info.start_or_commit_timestamp == transaction->commit_info->start_or_commit_timestamp || (delta_commit_info.is_locally_committed && delta_commit_info.start_or_commit_timestamp < transaction->start_timestamp)) { @@ -105,9 +117,17 @@ inline Delta *CreateDeleteObjectDelta(Transaction *transaction) { /// the delta into the object's delta list. /// @throw std::bad_alloc template <typename TObj, class... Args> +requires utils::SameAsAnyOf<TObj, Edge, Vertex> inline void CreateAndLinkDelta(Transaction *transaction, TObj *object, Args &&...args) { auto delta = &transaction->deltas.emplace_back(std::forward<Args>(args)..., transaction->commit_info.get(), transaction->command_id); + auto *delta_holder = std::invoke([object]() -> auto * { + if constexpr (std::is_same_v<TObj, Vertex>) { + return &object->second; + } else { + return object; + } + }); // The operations are written in such order so that both `next` and `prev` // chains are valid at all times. The chains must be valid at all times @@ -118,21 +138,21 @@ inline void CreateAndLinkDelta(Transaction *transaction, TObj *object, Args &&.. // TODO(antaljanosbenjamin): clang-tidy detects (in my opinion a false positive) issue in // `Shard::Accessor::CreateEdge`. // NOLINTNEXTLINE(clang-analyzer-core.NullDereference) - delta->next = object->delta; + delta->next = delta_holder->delta; // 2. We need to set the previous delta of the new delta to the object. delta->prev.Set(object); // 3. We need to set the previous delta of the existing delta to the new // delta. After this point the garbage collector will be able to see the new // delta but won't modify it until we are done with all of our modifications. - if (object->delta) { - object->delta->prev.Set(delta); + if (delta_holder->delta) { + delta_holder->delta->prev.Set(delta); } // 4. Finally, we need to set the object's delta to the new delta. The garbage // collector and other transactions will acquire the object lock to read the // delta from the object. Because the lock is held during the whole time this // modification is being done, everybody else will wait until we are fully // done with our modification before they read the object's delta value. - object->delta = delta; + delta_holder->delta = delta; } } // namespace memgraph::storage::v3 diff --git a/src/storage/v3/shard.cpp b/src/storage/v3/shard.cpp index a77f42a76..2573110c4 100644 --- a/src/storage/v3/shard.cpp +++ b/src/storage/v3/shard.cpp @@ -26,7 +26,6 @@ #include "io/network/endpoint.hpp" #include "io/time.hpp" -#include "storage/v3/containers.hpp" #include "storage/v3/edge_accessor.hpp" #include "storage/v3/id_types.hpp" #include "storage/v3/indices.hpp" @@ -39,6 +38,7 @@ #include "storage/v3/transaction.hpp" #include "storage/v3/vertex.hpp" #include "storage/v3/vertex_accessor.hpp" +#include "storage/v3/view.hpp" #include "utils/exceptions.hpp" #include "utils/file.hpp" #include "utils/logging.hpp" @@ -79,7 +79,7 @@ auto AdvanceToVisibleVertex(VertexContainer::iterator it, VertexContainer::itera std::optional<VertexAccessor> *vertex, Transaction *tx, View view, Indices *indices, Config::Items config, const VertexValidator &vertex_validator) { while (it != end) { - *vertex = VertexAccessor::Create(&it->second, tx, indices, config, vertex_validator, view); + *vertex = VertexAccessor::Create(&*it, tx, indices, config, vertex_validator, view); if (!*vertex) { ++it; continue; @@ -346,7 +346,7 @@ Shard::Accessor::Accessor(Shard &shard, Transaction &transaction) : shard_(&shard), transaction_(&transaction), config_(shard_->config_.items) {} ShardResult<VertexAccessor> Shard::Accessor::CreateVertexAndValidate( - const std::vector<LabelId> &labels, const std::vector<PropertyValue> &primary_properties, + const std::vector<LabelId> &labels, const PrimaryKey &primary_properties, const std::vector<std::pair<PropertyId, PropertyValue>> &properties) { OOMExceptionEnabler oom_exception; const auto schema = shard_->GetSchema(shard_->primary_label_)->second; @@ -358,10 +358,10 @@ ShardResult<VertexAccessor> Shard::Accessor::CreateVertexAndValidate( } auto *delta = CreateDeleteObjectDelta(transaction_); - auto [it, inserted] = shard_->vertices_.emplace(primary_properties, Vertex(delta, primary_properties)); - delta->prev.Set(&it->second); + auto [it, inserted] = shard_->vertices_.emplace(primary_properties, VertexData{delta}); + delta->prev.Set(&*it); - VertexAccessor vertex_acc{&it->second, transaction_, &shard_->indices_, config_, shard_->vertex_validator_}; + VertexAccessor vertex_acc{&*it, transaction_, &shard_->indices_, config_, shard_->vertex_validator_}; if (!inserted) { return SHARD_ERROR(ErrorCode::VERTEX_ALREADY_INSERTED); } @@ -389,7 +389,7 @@ std::optional<VertexAccessor> Shard::Accessor::FindVertex(std::vector<PropertyVa if (it == shard_->vertices_.end()) { return std::nullopt; } - return VertexAccessor::Create(&it->second, transaction_, &shard_->indices_, config_, shard_->vertex_validator_, view); + return VertexAccessor::Create(&*it, transaction_, &shard_->indices_, config_, shard_->vertex_validator_, view); } ShardResult<std::optional<VertexAccessor>> Shard::Accessor::DeleteVertex(VertexAccessor *vertex) { @@ -400,14 +400,15 @@ ShardResult<std::optional<VertexAccessor>> Shard::Accessor::DeleteVertex(VertexA if (!PrepareForWrite(transaction_, vertex_ptr)) return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR); - if (vertex_ptr->deleted) { + if (vertex_ptr->second.deleted) { return std::optional<VertexAccessor>{}; } - if (!vertex_ptr->in_edges.empty() || !vertex_ptr->out_edges.empty()) return SHARD_ERROR(ErrorCode::VERTEX_HAS_EDGES); + if (!vertex_ptr->second.in_edges.empty() || !vertex_ptr->second.out_edges.empty()) + return SHARD_ERROR(ErrorCode::VERTEX_HAS_EDGES); CreateAndLinkDelta(transaction_, vertex_ptr, Delta::RecreateObjectTag()); - vertex_ptr->deleted = true; + vertex_ptr->second.deleted = true; return std::make_optional<VertexAccessor>(vertex_ptr, transaction_, &shard_->indices_, config_, shard_->vertex_validator_, true); @@ -422,20 +423,20 @@ ShardResult<std::optional<std::pair<VertexAccessor, std::vector<EdgeAccessor>>>> "accessor when deleting a vertex!"); auto *vertex_ptr = vertex->vertex_; - std::vector<Vertex::EdgeLink> in_edges; - std::vector<Vertex::EdgeLink> out_edges; + std::vector<VertexData::EdgeLink> in_edges; + std::vector<VertexData::EdgeLink> out_edges; { if (!PrepareForWrite(transaction_, vertex_ptr)) return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR); - if (vertex_ptr->deleted) return std::optional<ReturnType>{}; + if (vertex_ptr->second.deleted) return std::optional<ReturnType>{}; - in_edges = vertex_ptr->in_edges; - out_edges = vertex_ptr->out_edges; + in_edges = vertex_ptr->second.in_edges; + out_edges = vertex_ptr->second.out_edges; } std::vector<EdgeAccessor> deleted_edges; - const VertexId vertex_id{shard_->primary_label_, vertex_ptr->keys}; + const VertexId vertex_id{shard_->primary_label_, *vertex->PrimaryKey(View::OLD)}; // TODO Replace for (const auto &item : in_edges) { auto [edge_type, from_vertex, edge] = item; EdgeAccessor e(edge, edge_type, from_vertex, vertex_id, transaction_, &shard_->indices_, config_); @@ -469,10 +470,10 @@ ShardResult<std::optional<std::pair<VertexAccessor, std::vector<EdgeAccessor>>>> if (!PrepareForWrite(transaction_, vertex_ptr)) return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR); - MG_ASSERT(!vertex_ptr->deleted, "Invalid database state!"); + MG_ASSERT(!vertex_ptr->second.deleted, "Invalid database state!"); CreateAndLinkDelta(transaction_, vertex_ptr, Delta::RecreateObjectTag()); - vertex_ptr->deleted = true; + vertex_ptr->second.deleted = true; return std::make_optional<ReturnType>( VertexAccessor{vertex_ptr, transaction_, &shard_->indices_, config_, shard_->vertex_validator_, true}, @@ -494,22 +495,22 @@ ShardResult<EdgeAccessor> Shard::Accessor::CreateEdge(VertexId from_vertex_id, V if (from_is_local) { auto it = vertices.find(from_vertex_id.primary_key); MG_ASSERT(it != vertices.end(), "Cannot find local vertex"); - from_vertex = &it->second; + from_vertex = &*it; } if (to_is_local) { auto it = vertices.find(to_vertex_id.primary_key); MG_ASSERT(it != vertices.end(), "Cannot find local vertex"); - to_vertex = &it->second; + to_vertex = &*it; } if (from_is_local) { if (!PrepareForWrite(transaction_, from_vertex)) return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR); - if (from_vertex->deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT); + if (from_vertex->second.deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT); } if (to_is_local && to_vertex != from_vertex) { if (!PrepareForWrite(transaction_, to_vertex)) return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR); - if (to_vertex->deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT); + if (to_vertex->second.deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT); } EdgeRef edge(gid); @@ -524,11 +525,11 @@ ShardResult<EdgeAccessor> Shard::Accessor::CreateEdge(VertexId from_vertex_id, V if (from_is_local) { CreateAndLinkDelta(transaction_, from_vertex, Delta::RemoveOutEdgeTag(), edge_type, to_vertex_id, edge); - from_vertex->out_edges.emplace_back(edge_type, to_vertex_id, edge); + from_vertex->second.out_edges.emplace_back(edge_type, to_vertex_id, edge); } if (to_is_local) { CreateAndLinkDelta(transaction_, to_vertex, Delta::RemoveInEdgeTag(), edge_type, from_vertex_id, edge); - to_vertex->in_edges.emplace_back(edge_type, from_vertex_id, edge); + from_vertex->second.in_edges.emplace_back(edge_type, from_vertex_id, edge); } // Increment edge count. ++shard_->edge_count_; @@ -539,8 +540,8 @@ ShardResult<EdgeAccessor> Shard::Accessor::CreateEdge(VertexId from_vertex_id, V ShardResult<std::optional<EdgeAccessor>> Shard::Accessor::DeleteEdge(VertexId from_vertex_id, VertexId to_vertex_id, const Gid edge_id) { - Vertex *from_vertex{nullptr}; - Vertex *to_vertex{nullptr}; + VertexContainer::value_type *from_vertex{nullptr}; + VertexContainer::value_type *to_vertex{nullptr}; auto &vertices = shard_->vertices_; @@ -550,13 +551,13 @@ ShardResult<std::optional<EdgeAccessor>> Shard::Accessor::DeleteEdge(VertexId fr if (from_is_local) { auto it = vertices.find(from_vertex_id.primary_key); MG_ASSERT(it != vertices.end(), "Cannot find local vertex"); - from_vertex = &it->second; + from_vertex = &*it; } if (to_is_local) { auto it = vertices.find(to_vertex_id.primary_key); MG_ASSERT(it != vertices.end(), "Cannot find local vertex"); - to_vertex = &it->second; + to_vertex = &*it; } MG_ASSERT(from_is_local || to_is_local, "Trying to delete an edge without having a local vertex"); @@ -565,13 +566,13 @@ ShardResult<std::optional<EdgeAccessor>> Shard::Accessor::DeleteEdge(VertexId fr if (!PrepareForWrite(transaction_, from_vertex)) { return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR); } - MG_ASSERT(!from_vertex->deleted, "Invalid database state!"); + MG_ASSERT(!from_vertex->second.deleted, "Invalid database state!"); } if (to_is_local && to_vertex != from_vertex) { if (!PrepareForWrite(transaction_, to_vertex)) { return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR); } - MG_ASSERT(!to_vertex->deleted, "Invalid database state!"); + MG_ASSERT(!to_vertex->second.deleted, "Invalid database state!"); } const auto edge_ref = std::invoke([edge_id, this]() -> EdgeRef { @@ -584,9 +585,9 @@ ShardResult<std::optional<EdgeAccessor>> Shard::Accessor::DeleteEdge(VertexId fr }); std::optional<EdgeTypeId> edge_type{}; - auto delete_edge_from_storage = [&edge_type, &edge_ref, this](std::vector<Vertex::EdgeLink> &edges) mutable { + auto delete_edge_from_storage = [&edge_type, &edge_ref, this](std::vector<VertexData::EdgeLink> &edges) mutable { auto it = std::find_if(edges.begin(), edges.end(), - [&edge_ref](const Vertex::EdgeLink &link) { return std::get<2>(link) == edge_ref; }); + [&edge_ref](const VertexData::EdgeLink &link) { return std::get<2>(link) == edge_ref; }); if (config_.properties_on_edges) { MG_ASSERT(it != edges.end(), "Invalid database state!"); } else if (it == edges.end()) { @@ -598,8 +599,8 @@ ShardResult<std::optional<EdgeAccessor>> Shard::Accessor::DeleteEdge(VertexId fr return true; }; // NOLINTNEXTLINE(clang-analyzer-core.NonNullParamChecker) - auto success_on_to = to_is_local ? delete_edge_from_storage(to_vertex->in_edges) : false; - auto success_on_from = from_is_local ? delete_edge_from_storage(from_vertex->out_edges) : false; + auto success_on_to = to_is_local ? delete_edge_from_storage(to_vertex->second.in_edges) : false; + auto success_on_from = from_is_local ? delete_edge_from_storage(from_vertex->second.out_edges) : false; if (config_.properties_on_edges) { // Because of the check above, we are sure that the vertex exists. @@ -625,10 +626,10 @@ ShardResult<std::optional<EdgeAccessor>> Shard::Accessor::DeleteEdge(VertexId fr MG_ASSERT(edge_type.has_value(), "Edge type is not determined"); if (from_is_local) { - CreateAndLinkDelta(transaction_, from_vertex, Delta::AddOutEdgeTag(), *edge_type, to_vertex_id, edge_ref); + CreateAndLinkDelta(transaction_, &*from_vertex, Delta::AddOutEdgeTag(), *edge_type, to_vertex_id, edge_ref); } if (to_is_local) { - CreateAndLinkDelta(transaction_, to_vertex, Delta::AddInEdgeTag(), *edge_type, from_vertex_id, edge_ref); + CreateAndLinkDelta(transaction_, &*to_vertex, Delta::AddInEdgeTag(), *edge_type, from_vertex_id, edge_ref); } // Decrement edge count. @@ -690,41 +691,41 @@ void Shard::Accessor::Abort() { auto prev = delta.prev.Get(); switch (prev.type) { case PreviousPtr::Type::VERTEX: { - auto *vertex = prev.vertex; - Delta *current = vertex->delta; + auto &[pk, vertex] = *prev.vertex; + Delta *current = vertex.delta; while (current != nullptr && current->commit_info->start_or_commit_timestamp == transaction_->start_timestamp) { switch (current->action) { case Delta::Action::REMOVE_LABEL: { - auto it = std::find(vertex->labels.begin(), vertex->labels.end(), current->label); - MG_ASSERT(it != vertex->labels.end(), "Invalid database state!"); - std::swap(*it, *vertex->labels.rbegin()); - vertex->labels.pop_back(); + auto it = std::find(vertex.labels.begin(), vertex.labels.end(), current->label); + MG_ASSERT(it != vertex.labels.end(), "Invalid database state!"); + std::swap(*it, *vertex.labels.rbegin()); + vertex.labels.pop_back(); break; } case Delta::Action::ADD_LABEL: { - auto it = std::find(vertex->labels.begin(), vertex->labels.end(), current->label); - MG_ASSERT(it == vertex->labels.end(), "Invalid database state!"); - vertex->labels.push_back(current->label); + auto it = std::find(vertex.labels.begin(), vertex.labels.end(), current->label); + MG_ASSERT(it == vertex.labels.end(), "Invalid database state!"); + vertex.labels.push_back(current->label); break; } case Delta::Action::SET_PROPERTY: { - vertex->properties.SetProperty(current->property.key, current->property.value); + vertex.properties.SetProperty(current->property.key, current->property.value); break; } case Delta::Action::ADD_IN_EDGE: { - Vertex::EdgeLink link{current->vertex_edge.edge_type, current->vertex_edge.vertex_id, - current->vertex_edge.edge}; - auto it = std::find(vertex->in_edges.begin(), vertex->in_edges.end(), link); - MG_ASSERT(it == vertex->in_edges.end(), "Invalid database state!"); - vertex->in_edges.push_back(link); + VertexData::EdgeLink link{current->vertex_edge.edge_type, current->vertex_edge.vertex_id, + current->vertex_edge.edge}; + auto it = std::find(vertex.in_edges.begin(), vertex.in_edges.end(), link); + MG_ASSERT(it == vertex.in_edges.end(), "Invalid database state!"); + vertex.in_edges.push_back(link); break; } case Delta::Action::ADD_OUT_EDGE: { - Vertex::EdgeLink link{current->vertex_edge.edge_type, current->vertex_edge.vertex_id, - current->vertex_edge.edge}; - auto it = std::find(vertex->out_edges.begin(), vertex->out_edges.end(), link); - MG_ASSERT(it == vertex->out_edges.end(), "Invalid database state!"); - vertex->out_edges.push_back(link); + VertexData::EdgeLink link{current->vertex_edge.edge_type, current->vertex_edge.vertex_id, + current->vertex_edge.edge}; + auto it = std::find(vertex.out_edges.begin(), vertex.out_edges.end(), link); + MG_ASSERT(it == vertex.out_edges.end(), "Invalid database state!"); + vertex.out_edges.push_back(link); // Increment edge count. We only increment the count here because // the information in `ADD_IN_EDGE` and `Edge/RECREATE_OBJECT` is // redundant. Also, `Edge/RECREATE_OBJECT` isn't available when @@ -733,21 +734,21 @@ void Shard::Accessor::Abort() { break; } case Delta::Action::REMOVE_IN_EDGE: { - Vertex::EdgeLink link{current->vertex_edge.edge_type, current->vertex_edge.vertex_id, - current->vertex_edge.edge}; - auto it = std::find(vertex->in_edges.begin(), vertex->in_edges.end(), link); - MG_ASSERT(it != vertex->in_edges.end(), "Invalid database state!"); - std::swap(*it, *vertex->in_edges.rbegin()); - vertex->in_edges.pop_back(); + VertexData::EdgeLink link{current->vertex_edge.edge_type, current->vertex_edge.vertex_id, + current->vertex_edge.edge}; + auto it = std::find(vertex.in_edges.begin(), vertex.in_edges.end(), link); + MG_ASSERT(it != vertex.in_edges.end(), "Invalid database state!"); + std::swap(*it, *vertex.in_edges.rbegin()); + vertex.in_edges.pop_back(); break; } case Delta::Action::REMOVE_OUT_EDGE: { - Vertex::EdgeLink link{current->vertex_edge.edge_type, current->vertex_edge.vertex_id, - current->vertex_edge.edge}; - auto it = std::find(vertex->out_edges.begin(), vertex->out_edges.end(), link); - MG_ASSERT(it != vertex->out_edges.end(), "Invalid database state!"); - std::swap(*it, *vertex->out_edges.rbegin()); - vertex->out_edges.pop_back(); + VertexData::EdgeLink link{current->vertex_edge.edge_type, current->vertex_edge.vertex_id, + current->vertex_edge.edge}; + auto it = std::find(vertex.out_edges.begin(), vertex.out_edges.end(), link); + MG_ASSERT(it != vertex.out_edges.end(), "Invalid database state!"); + std::swap(*it, *vertex.out_edges.rbegin()); + vertex.out_edges.pop_back(); // Decrement edge count. We only decrement the count here because // the information in `REMOVE_IN_EDGE` and `Edge/DELETE_OBJECT` is // redundant. Also, `Edge/DELETE_OBJECT` isn't available when edge @@ -756,20 +757,20 @@ void Shard::Accessor::Abort() { break; } case Delta::Action::DELETE_OBJECT: { - vertex->deleted = true; - shard_->deleted_vertices_.push_back(vertex->keys); + vertex.deleted = true; + shard_->deleted_vertices_.push_back(&pk); break; } case Delta::Action::RECREATE_OBJECT: { - vertex->deleted = false; + vertex.deleted = false; break; } } current = current->next; } - vertex->delta = current; + vertex.delta = current; if (current != nullptr) { - current->prev.Set(vertex); + current->prev.Set(prev.vertex); } break; @@ -964,10 +965,12 @@ void Shard::CollectGarbage(const io::Time current_time) { auto prev = delta.prev.Get(); switch (prev.type) { case PreviousPtr::Type::VERTEX: { - Vertex *vertex = prev.vertex; - vertex->delta = nullptr; - if (vertex->deleted) { - deleted_vertices_.push_back(vertex->keys); + // Here we need to get pk from prev pointer, and that is why change + // to the PrevPtr so it points to pair of pk and vertex + auto &[pk, vertex] = *prev.vertex; + vertex.delta = nullptr; + if (vertex.deleted) { + deleted_vertices_.push_back(&pk); } break; } @@ -1015,7 +1018,7 @@ void Shard::CollectGarbage(const io::Time current_time) { } for (const auto &vertex : deleted_vertices_) { - MG_ASSERT(vertices_.erase(vertex), "Invalid database state!"); + MG_ASSERT(vertices_.erase(*vertex), "Invalid database state!"); } deleted_vertices_.clear(); { diff --git a/src/storage/v3/shard.hpp b/src/storage/v3/shard.hpp index b998c06cc..8542d47eb 100644 --- a/src/storage/v3/shard.hpp +++ b/src/storage/v3/shard.hpp @@ -25,7 +25,6 @@ #include "io/time.hpp" #include "kvstore/kvstore.hpp" #include "storage/v3/config.hpp" -#include "storage/v3/containers.hpp" #include "storage/v3/edge.hpp" #include "storage/v3/edge_accessor.hpp" #include "storage/v3/id_types.hpp" @@ -387,7 +386,7 @@ class Shard final { // Vertices that are logically deleted but still have to be removed from // indices before removing them from the main storage. - std::list<PrimaryKey> deleted_vertices_; + std::list<const PrimaryKey *> deleted_vertices_; // Edges that are logically deleted and wait to be removed from the main // storage. diff --git a/src/storage/v3/containers.hpp b/src/storage/v3/vertex.cpp similarity index 59% rename from src/storage/v3/containers.hpp rename to src/storage/v3/vertex.cpp index 918cf3568..0dc80ad65 100644 --- a/src/storage/v3/containers.hpp +++ b/src/storage/v3/vertex.cpp @@ -9,16 +9,22 @@ // by the Apache License, Version 2.0, included in the file // licenses/APL.txt. -#pragma once - -#include <map> - -#include "storage/v3/edge.hpp" -#include "storage/v3/id_types.hpp" -#include "storage/v3/key_store.hpp" #include "storage/v3/vertex.hpp" +#include <limits> +#include <tuple> +#include <type_traits> +#include <vector> + +#include "storage/v3/delta.hpp" + namespace memgraph::storage::v3 { -using VertexContainer = std::map<PrimaryKey, Vertex>; -using EdgeContainer = std::map<Gid, Edge>; + +VertexData::VertexData(Delta *delta) : delta{delta} { + MG_ASSERT(delta == nullptr || delta->action == Delta::Action::DELETE_OBJECT, + "Vertex must be created with an initial DELETE_OBJECT delta!"); +} + +bool VertexHasLabel(const Vertex &vertex, const LabelId label) { return utils::Contains(vertex.second.labels, label); } + } // namespace memgraph::storage::v3 diff --git a/src/storage/v3/vertex.hpp b/src/storage/v3/vertex.hpp index 565e39d1a..f8caaa399 100644 --- a/src/storage/v3/vertex.hpp +++ b/src/storage/v3/vertex.hpp @@ -16,7 +16,6 @@ #include <type_traits> #include <vector> -#include "storage/v3/delta.hpp" #include "storage/v3/edge_ref.hpp" #include "storage/v3/id_types.hpp" #include "storage/v3/key_store.hpp" @@ -28,17 +27,12 @@ namespace memgraph::storage::v3 { -struct Vertex { +struct Delta; + +struct VertexData { using EdgeLink = std::tuple<EdgeTypeId, VertexId, EdgeRef>; - Vertex(Delta *delta, PrimaryKey primary_properties) : keys{std::move(primary_properties)}, delta{delta} { - MG_ASSERT(delta == nullptr || delta->action == Delta::Action::DELETE_OBJECT, - "Vertex must be created with an initial DELETE_OBJECT delta!"); - } - - friend bool operator==(const Vertex &vertex, const PrimaryKey &primary_key) { return vertex.keys == primary_key; } - - PrimaryKey keys; + explicit VertexData(Delta *delta); std::vector<LabelId> labels; PropertyStore properties; @@ -52,8 +46,11 @@ struct Vertex { Delta *delta; }; -static_assert(alignof(Vertex) >= 8, "The Vertex should be aligned to at least 8!"); +// static_assert(alignof(Vertex) >= 8, "The Vertex should be aligned to at least 8!"); -inline bool VertexHasLabel(const Vertex &vertex, const LabelId label) { return utils::Contains(vertex.labels, label); } +using VertexContainer = std::map<PrimaryKey, VertexData>; +using Vertex = VertexContainer::value_type; + +bool VertexHasLabel(const Vertex &vertex, LabelId label); } // namespace memgraph::storage::v3 diff --git a/src/storage/v3/vertex_accessor.cpp b/src/storage/v3/vertex_accessor.cpp index 3f3d01efb..95e0524ea 100644 --- a/src/storage/v3/vertex_accessor.cpp +++ b/src/storage/v3/vertex_accessor.cpp @@ -36,8 +36,8 @@ std::pair<bool, bool> IsVisible(Vertex *vertex, Transaction *transaction, View v bool deleted = false; Delta *delta = nullptr; { - deleted = vertex->deleted; - delta = vertex->delta; + deleted = vertex->second.deleted; + delta = vertex->second.delta; } ApplyDeltasForRead(transaction, delta, view, [&](const Delta &delta) { switch (delta.action) { @@ -85,13 +85,14 @@ ShardResult<bool> VertexAccessor::AddLabel(LabelId label) { if (!PrepareForWrite(transaction_, vertex_)) return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR); - if (vertex_->deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT); + if (vertex_->second.deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT); - if (std::find(vertex_->labels.begin(), vertex_->labels.end(), label) != vertex_->labels.end()) return false; + if (std::find(vertex_->second.labels.begin(), vertex_->second.labels.end(), label) != vertex_->second.labels.end()) + return false; CreateAndLinkDelta(transaction_, vertex_, Delta::RemoveLabelTag(), label); - vertex_->labels.push_back(label); + vertex_->second.labels.push_back(label); UpdateOnAddLabel(indices_, label, vertex_, *transaction_); @@ -106,13 +107,14 @@ ShardResult<bool> VertexAccessor::AddLabelAndValidate(LabelId label) { if (!PrepareForWrite(transaction_, vertex_)) return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR); - if (vertex_->deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT); + if (vertex_->second.deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT); - if (std::find(vertex_->labels.begin(), vertex_->labels.end(), label) != vertex_->labels.end()) return false; + if (std::find(vertex_->second.labels.begin(), vertex_->second.labels.end(), label) != vertex_->second.labels.end()) + return false; CreateAndLinkDelta(transaction_, vertex_, Delta::RemoveLabelTag(), label); - vertex_->labels.push_back(label); + vertex_->second.labels.push_back(label); UpdateOnAddLabel(indices_, label, vertex_, *transaction_); @@ -122,15 +124,15 @@ ShardResult<bool> VertexAccessor::AddLabelAndValidate(LabelId label) { ShardResult<bool> VertexAccessor::RemoveLabel(LabelId label) { if (!PrepareForWrite(transaction_, vertex_)) return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR); - if (vertex_->deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT); + if (vertex_->second.deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT); - auto it = std::find(vertex_->labels.begin(), vertex_->labels.end(), label); - if (it == vertex_->labels.end()) return false; + auto it = std::find(vertex_->second.labels.begin(), vertex_->second.labels.end(), label); + if (it == vertex_->second.labels.end()) return false; CreateAndLinkDelta(transaction_, vertex_, Delta::AddLabelTag(), label); - std::swap(*it, *vertex_->labels.rbegin()); - vertex_->labels.pop_back(); + std::swap(*it, *vertex_->second.labels.rbegin()); + vertex_->second.labels.pop_back(); return true; } @@ -142,15 +144,15 @@ ShardResult<bool> VertexAccessor::RemoveLabelAndValidate(LabelId label) { if (!PrepareForWrite(transaction_, vertex_)) return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR); - if (vertex_->deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT); + if (vertex_->second.deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT); - auto it = std::find(vertex_->labels.begin(), vertex_->labels.end(), label); - if (it == vertex_->labels.end()) return false; + auto it = std::find(vertex_->second.labels.begin(), vertex_->second.labels.end(), label); + if (it == vertex_->second.labels.end()) return false; CreateAndLinkDelta(transaction_, vertex_, Delta::AddLabelTag(), label); - std::swap(*it, *vertex_->labels.rbegin()); - vertex_->labels.pop_back(); + std::swap(*it, *vertex_->second.labels.rbegin()); + vertex_->second.labels.pop_back(); return true; } @@ -162,9 +164,9 @@ ShardResult<bool> VertexAccessor::HasLabel(LabelId label, View view) const { bool has_label = false; Delta *delta = nullptr; { - deleted = vertex_->deleted; + deleted = vertex_->second.deleted; has_label = label == vertex_validator_->primary_label_ || VertexHasLabel(*vertex_, label); - delta = vertex_->delta; + delta = vertex_->second.delta; } ApplyDeltasForRead(transaction_, delta, view, [&exists, &deleted, &has_label, label](const Delta &delta) { switch (delta.action) { @@ -215,14 +217,14 @@ ShardResult<PrimaryKey> VertexAccessor::PrimaryKey(const View view) const { if (const auto result = CheckVertexExistence(view); result.HasError()) { return result.GetError(); } - return vertex_->keys; + return vertex_->first; } ShardResult<VertexId> VertexAccessor::Id(View view) const { if (const auto result = CheckVertexExistence(view); result.HasError()) { return result.GetError(); } - return VertexId{vertex_validator_->primary_label_, vertex_->keys}; + return VertexId{vertex_validator_->primary_label_, vertex_->first}; }; ShardResult<std::vector<LabelId>> VertexAccessor::Labels(View view) const { @@ -231,9 +233,9 @@ ShardResult<std::vector<LabelId>> VertexAccessor::Labels(View view) const { std::vector<LabelId> labels; Delta *delta = nullptr; { - deleted = vertex_->deleted; - labels = vertex_->labels; - delta = vertex_->delta; + deleted = vertex_->second.deleted; + labels = vertex_->second.labels; + delta = vertex_->second.delta; } ApplyDeltasForRead(transaction_, delta, view, [&exists, &deleted, &labels](const Delta &delta) { switch (delta.action) { @@ -278,9 +280,9 @@ ShardResult<PropertyValue> VertexAccessor::SetProperty(PropertyId property, cons if (!PrepareForWrite(transaction_, vertex_)) return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR); - if (vertex_->deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT); + if (vertex_->second.deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT); - auto current_value = vertex_->properties.GetProperty(property); + auto current_value = vertex_->second.properties.GetProperty(property); // We could skip setting the value if the previous one is the same to the new // one. This would save some memory as a delta would not be created as well as // avoid copying the value. The reason we are not doing that is because the @@ -288,7 +290,7 @@ ShardResult<PropertyValue> VertexAccessor::SetProperty(PropertyId property, cons // "modify in-place". Additionally, the created delta will make other // transactions get a SERIALIZATION_ERROR. CreateAndLinkDelta(transaction_, vertex_, Delta::SetPropertyTag(), property, current_value); - vertex_->properties.SetProperty(property, value); + vertex_->second.properties.SetProperty(property, value); UpdateOnSetProperty(indices_, property, value, vertex_, *transaction_); @@ -300,8 +302,8 @@ ShardResult<void> VertexAccessor::CheckVertexExistence(View view) const { bool deleted = false; Delta *delta = nullptr; { - deleted = vertex_->deleted; - delta = vertex_->delta; + deleted = vertex_->second.deleted; + delta = vertex_->second.delta; } ApplyDeltasForRead(transaction_, delta, view, [&exists, &deleted](const Delta &delta) { switch (delta.action) { @@ -343,11 +345,11 @@ ShardResult<PropertyValue> VertexAccessor::SetPropertyAndValidate(PropertyId pro return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR); } - if (vertex_->deleted) { + if (vertex_->second.deleted) { return SHARD_ERROR(ErrorCode::DELETED_OBJECT); } - auto current_value = vertex_->properties.GetProperty(property); + auto current_value = vertex_->second.properties.GetProperty(property); // We could skip setting the value if the previous one is the same to the new // one. This would save some memory as a delta would not be created as well as // avoid copying the value. The reason we are not doing that is because the @@ -355,7 +357,7 @@ ShardResult<PropertyValue> VertexAccessor::SetPropertyAndValidate(PropertyId pro // "modify in-place". Additionally, the created delta will make other // transactions get a SERIALIZATION_ERROR. CreateAndLinkDelta(transaction_, vertex_, Delta::SetPropertyTag(), property, current_value); - vertex_->properties.SetProperty(property, value); + vertex_->second.properties.SetProperty(property, value); UpdateOnSetProperty(indices_, property, value, vertex_, *transaction_); @@ -365,15 +367,15 @@ ShardResult<PropertyValue> VertexAccessor::SetPropertyAndValidate(PropertyId pro ShardResult<std::map<PropertyId, PropertyValue>> VertexAccessor::ClearProperties() { if (!PrepareForWrite(transaction_, vertex_)) return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR); - if (vertex_->deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT); + if (vertex_->second.deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT); - auto properties = vertex_->properties.Properties(); + auto properties = vertex_->second.properties.Properties(); for (const auto &property : properties) { CreateAndLinkDelta(transaction_, vertex_, Delta::SetPropertyTag(), property.first, property.second); UpdateOnSetProperty(indices_, property.first, PropertyValue(), vertex_, *transaction_); } - vertex_->properties.ClearProperties(); + vertex_->second.properties.ClearProperties(); return std::move(properties); } @@ -396,11 +398,11 @@ PropertyValue VertexAccessor::GetPropertyValue(PropertyId property, View view) c // Find PropertyId index in keystore for (size_t property_index{0}; property_index < schema->second.size(); ++property_index) { if (schema->second[property_index].property_id == property) { - return vertex_->keys[property_index]; + return vertex_->first[property_index]; } } - return value = vertex_->properties.GetProperty(property); + return value = vertex_->second.properties.GetProperty(property); } ShardResult<PropertyValue> VertexAccessor::GetProperty(PropertyId property, View view) const { @@ -409,9 +411,9 @@ ShardResult<PropertyValue> VertexAccessor::GetProperty(PropertyId property, View PropertyValue value; Delta *delta = nullptr; { - deleted = vertex_->deleted; + deleted = vertex_->second.deleted; value = GetPropertyValue(property, view); - delta = vertex_->delta; + delta = vertex_->second.delta; } ApplyDeltasForRead(transaction_, delta, view, [&exists, &deleted, &value, property](const Delta &delta) { switch (delta.action) { @@ -453,10 +455,10 @@ ShardResult<std::map<PropertyId, PropertyValue>> VertexAccessor::Properties(View std::map<PropertyId, PropertyValue> properties; Delta *delta = nullptr; { - deleted = vertex_->deleted; + deleted = vertex_->second.deleted; // TODO(antaljanosbenjamin): Should this also return the primary key? - properties = vertex_->properties.Properties(); - delta = vertex_->delta; + properties = vertex_->second.properties.Properties(); + delta = vertex_->second.delta; } ApplyDeltasForRead(transaction_, delta, view, [&exists, &deleted, &properties](const Delta &delta) { switch (delta.action) { @@ -501,14 +503,14 @@ ShardResult<std::vector<EdgeAccessor>> VertexAccessor::InEdges(View view, const const VertexId *destination_id) const { bool exists = true; bool deleted = false; - std::vector<Vertex::EdgeLink> in_edges; + std::vector<VertexData::EdgeLink> in_edges; Delta *delta = nullptr; { - deleted = vertex_->deleted; + deleted = vertex_->second.deleted; if (edge_types.empty() && nullptr == destination_id) { - in_edges = vertex_->in_edges; + in_edges = vertex_->second.in_edges; } else { - for (const auto &item : vertex_->in_edges) { + for (const auto &item : vertex_->second.in_edges) { const auto &[edge_type, from_vertex, edge] = item; if (nullptr != destination_id && from_vertex != *destination_id) { continue; @@ -518,7 +520,7 @@ ShardResult<std::vector<EdgeAccessor>> VertexAccessor::InEdges(View view, const in_edges.push_back(item); } } - delta = vertex_->delta; + delta = vertex_->second.delta; } ApplyDeltasForRead( transaction_, delta, view, [&exists, &deleted, &in_edges, &edge_types, destination_id](const Delta &delta) { @@ -529,7 +531,7 @@ ShardResult<std::vector<EdgeAccessor>> VertexAccessor::InEdges(View view, const std::find(edge_types.begin(), edge_types.end(), delta.vertex_edge.edge_type) == edge_types.end()) break; // Add the edge because we don't see the removal. - Vertex::EdgeLink link{delta.vertex_edge.edge_type, delta.vertex_edge.vertex_id, delta.vertex_edge.edge}; + VertexData::EdgeLink link{delta.vertex_edge.edge_type, delta.vertex_edge.vertex_id, delta.vertex_edge.edge}; auto it = std::find(in_edges.begin(), in_edges.end(), link); MG_ASSERT(it == in_edges.end(), "Invalid database state!"); in_edges.push_back(link); @@ -541,7 +543,7 @@ ShardResult<std::vector<EdgeAccessor>> VertexAccessor::InEdges(View view, const std::find(edge_types.begin(), edge_types.end(), delta.vertex_edge.edge_type) == edge_types.end()) break; // Remove the label because we don't see the addition. - Vertex::EdgeLink link{delta.vertex_edge.edge_type, delta.vertex_edge.vertex_id, delta.vertex_edge.edge}; + VertexData::EdgeLink link{delta.vertex_edge.edge_type, delta.vertex_edge.vertex_id, delta.vertex_edge.edge}; auto it = std::find(in_edges.begin(), in_edges.end(), link); MG_ASSERT(it != in_edges.end(), "Invalid database state!"); std::swap(*it, *in_edges.rbegin()); @@ -571,7 +573,7 @@ ShardResult<std::vector<EdgeAccessor>> VertexAccessor::InEdges(View view, const return ret; } ret.reserve(in_edges.size()); - const auto id = VertexId{vertex_validator_->primary_label_, vertex_->keys}; + const auto id = VertexId{vertex_validator_->primary_label_, vertex_->first}; for (const auto &item : in_edges) { const auto &[edge_type, from_vertex, edge] = item; ret.emplace_back(edge, edge_type, from_vertex, id, transaction_, indices_, config_); @@ -583,14 +585,14 @@ ShardResult<std::vector<EdgeAccessor>> VertexAccessor::OutEdges(View view, const const VertexId *destination_id) const { bool exists = true; bool deleted = false; - std::vector<Vertex::EdgeLink> out_edges; + std::vector<VertexData::EdgeLink> out_edges; Delta *delta = nullptr; { - deleted = vertex_->deleted; + deleted = vertex_->second.deleted; if (edge_types.empty() && nullptr == destination_id) { - out_edges = vertex_->out_edges; + out_edges = vertex_->second.out_edges; } else { - for (const auto &item : vertex_->out_edges) { + for (const auto &item : vertex_->second.out_edges) { const auto &[edge_type, to_vertex, edge] = item; if (nullptr != destination_id && to_vertex != *destination_id) continue; if (!edge_types.empty() && std::find(edge_types.begin(), edge_types.end(), edge_type) == edge_types.end()) @@ -598,7 +600,7 @@ ShardResult<std::vector<EdgeAccessor>> VertexAccessor::OutEdges(View view, const out_edges.push_back(item); } } - delta = vertex_->delta; + delta = vertex_->second.delta; } ApplyDeltasForRead( transaction_, delta, view, [&exists, &deleted, &out_edges, &edge_types, destination_id](const Delta &delta) { @@ -609,7 +611,7 @@ ShardResult<std::vector<EdgeAccessor>> VertexAccessor::OutEdges(View view, const std::find(edge_types.begin(), edge_types.end(), delta.vertex_edge.edge_type) == edge_types.end()) break; // Add the edge because we don't see the removal. - Vertex::EdgeLink link{delta.vertex_edge.edge_type, delta.vertex_edge.vertex_id, delta.vertex_edge.edge}; + VertexData::EdgeLink link{delta.vertex_edge.edge_type, delta.vertex_edge.vertex_id, delta.vertex_edge.edge}; auto it = std::find(out_edges.begin(), out_edges.end(), link); MG_ASSERT(it == out_edges.end(), "Invalid database state!"); out_edges.push_back(link); @@ -621,7 +623,7 @@ ShardResult<std::vector<EdgeAccessor>> VertexAccessor::OutEdges(View view, const std::find(edge_types.begin(), edge_types.end(), delta.vertex_edge.edge_type) == edge_types.end()) break; // Remove the label because we don't see the addition. - Vertex::EdgeLink link{delta.vertex_edge.edge_type, delta.vertex_edge.vertex_id, delta.vertex_edge.edge}; + VertexData::EdgeLink link{delta.vertex_edge.edge_type, delta.vertex_edge.vertex_id, delta.vertex_edge.edge}; auto it = std::find(out_edges.begin(), out_edges.end(), link); MG_ASSERT(it != out_edges.end(), "Invalid database state!"); std::swap(*it, *out_edges.rbegin()); @@ -651,7 +653,7 @@ ShardResult<std::vector<EdgeAccessor>> VertexAccessor::OutEdges(View view, const return ret; } ret.reserve(out_edges.size()); - const auto id = VertexId{vertex_validator_->primary_label_, vertex_->keys}; + const auto id = VertexId{vertex_validator_->primary_label_, vertex_->first}; for (const auto &item : out_edges) { const auto &[edge_type, to_vertex, edge] = item; ret.emplace_back(edge, edge_type, id, to_vertex, transaction_, indices_, config_); @@ -665,9 +667,9 @@ ShardResult<size_t> VertexAccessor::InDegree(View view) const { size_t degree = 0; Delta *delta = nullptr; { - deleted = vertex_->deleted; - degree = vertex_->in_edges.size(); - delta = vertex_->delta; + deleted = vertex_->second.deleted; + degree = vertex_->second.in_edges.size(); + delta = vertex_->second.delta; } ApplyDeltasForRead(transaction_, delta, view, [&exists, &deleted, °ree](const Delta &delta) { switch (delta.action) { @@ -702,9 +704,9 @@ ShardResult<size_t> VertexAccessor::OutDegree(View view) const { size_t degree = 0; Delta *delta = nullptr; { - deleted = vertex_->deleted; - degree = vertex_->out_edges.size(); - delta = vertex_->delta; + deleted = vertex_->second.deleted; + degree = vertex_->second.out_edges.size(); + delta = vertex_->second.delta; } ApplyDeltasForRead(transaction_, delta, view, [&exists, &deleted, °ree](const Delta &delta) { switch (delta.action) {