Introduce VertexData

This commit is contained in:
jbajic 2022-12-12 12:39:49 +01:00
parent 32322d39b8
commit 0cf440519e
12 changed files with 226 additions and 199 deletions

View File

@ -17,6 +17,7 @@ set(storage_v3_src_files
shard_rsm.cpp
bindings/typed_value.cpp
expr.cpp
vertex.cpp
request_helper.cpp)
# ######################

View File

@ -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;

View File

@ -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; }

View File

@ -25,7 +25,6 @@
namespace memgraph::storage::v3 {
struct Vertex;
class VertexAccessor;
struct Indices;

View File

@ -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, &current_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;
}

View File

@ -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"

View File

@ -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

View File

@ -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,
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);
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,
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);
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,
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();
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,
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();
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();
{

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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, &degree](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, &degree](const Delta &delta) {
switch (delta.action) {