Introduce VertexData
This commit is contained in:
parent
32322d39b8
commit
0cf440519e
@ -17,6 +17,7 @@ set(storage_v3_src_files
|
|||||||
shard_rsm.cpp
|
shard_rsm.cpp
|
||||||
bindings/typed_value.cpp
|
bindings/typed_value.cpp
|
||||||
expr.cpp
|
expr.cpp
|
||||||
|
vertex.cpp
|
||||||
request_helper.cpp)
|
request_helper.cpp)
|
||||||
|
|
||||||
# ######################
|
# ######################
|
||||||
|
@ -15,13 +15,13 @@
|
|||||||
#include "storage/v3/edge_ref.hpp"
|
#include "storage/v3/edge_ref.hpp"
|
||||||
#include "storage/v3/id_types.hpp"
|
#include "storage/v3/id_types.hpp"
|
||||||
#include "storage/v3/property_value.hpp"
|
#include "storage/v3/property_value.hpp"
|
||||||
|
#include "storage/v3/vertex.hpp"
|
||||||
#include "storage/v3/vertex_id.hpp"
|
#include "storage/v3/vertex_id.hpp"
|
||||||
#include "utils/logging.hpp"
|
#include "utils/logging.hpp"
|
||||||
|
|
||||||
namespace memgraph::storage::v3 {
|
namespace memgraph::storage::v3 {
|
||||||
|
|
||||||
// Forward declarations because we only store pointers here.
|
// Forward declarations because we only store pointers here.
|
||||||
struct Vertex;
|
|
||||||
struct Edge;
|
struct Edge;
|
||||||
struct Delta;
|
struct Delta;
|
||||||
struct CommitInfo;
|
struct CommitInfo;
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
namespace memgraph::storage::v3 {
|
namespace memgraph::storage::v3 {
|
||||||
|
|
||||||
struct Vertex;
|
using EdgeContainer = std::map<Gid, Edge>;
|
||||||
|
|
||||||
struct Edge {
|
struct Edge {
|
||||||
Edge(Gid gid, Delta *delta) : gid(gid), deleted(false), delta(delta) {
|
Edge(Gid gid, Delta *delta) : gid(gid), deleted(false), delta(delta) {
|
||||||
@ -34,13 +34,13 @@ struct Edge {
|
|||||||
PropertyStore properties;
|
PropertyStore properties;
|
||||||
|
|
||||||
bool deleted;
|
bool deleted;
|
||||||
// uint8_t PAD;
|
uint8_t PAD;
|
||||||
// uint16_t PAD;
|
// uint16_t PAD;
|
||||||
|
|
||||||
Delta *delta;
|
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; }
|
||||||
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; }
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
|
|
||||||
namespace memgraph::storage::v3 {
|
namespace memgraph::storage::v3 {
|
||||||
|
|
||||||
struct Vertex;
|
|
||||||
class VertexAccessor;
|
class VertexAccessor;
|
||||||
struct Indices;
|
struct Indices;
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "storage/v3/mvcc.hpp"
|
#include "storage/v3/mvcc.hpp"
|
||||||
#include "storage/v3/property_value.hpp"
|
#include "storage/v3/property_value.hpp"
|
||||||
#include "storage/v3/schemas.hpp"
|
#include "storage/v3/schemas.hpp"
|
||||||
|
#include "storage/v3/vertex.hpp"
|
||||||
#include "utils/bound.hpp"
|
#include "utils/bound.hpp"
|
||||||
#include "utils/logging.hpp"
|
#include "utils/logging.hpp"
|
||||||
#include "utils/memory_tracker.hpp"
|
#include "utils/memory_tracker.hpp"
|
||||||
@ -57,9 +58,9 @@ bool AnyVersionHasLabel(const Vertex &vertex, LabelId label, uint64_t timestamp)
|
|||||||
bool deleted{false};
|
bool deleted{false};
|
||||||
const Delta *delta{nullptr};
|
const Delta *delta{nullptr};
|
||||||
{
|
{
|
||||||
has_label = utils::Contains(vertex.labels, label);
|
has_label = utils::Contains(vertex.second.labels, label);
|
||||||
deleted = vertex.deleted;
|
deleted = vertex.second.deleted;
|
||||||
delta = vertex.delta;
|
delta = vertex.second.delta;
|
||||||
}
|
}
|
||||||
if (!deleted && has_label) {
|
if (!deleted && has_label) {
|
||||||
return true;
|
return true;
|
||||||
@ -109,10 +110,10 @@ bool AnyVersionHasLabelProperty(const Vertex &vertex, LabelId label, PropertyId
|
|||||||
bool deleted{false};
|
bool deleted{false};
|
||||||
const Delta *delta{nullptr};
|
const Delta *delta{nullptr};
|
||||||
{
|
{
|
||||||
has_label = utils::Contains(vertex.labels, label);
|
has_label = utils::Contains(vertex.second.labels, label);
|
||||||
current_value_equal_to_value = vertex.properties.IsPropertyEqual(key, value);
|
current_value_equal_to_value = vertex.second.properties.IsPropertyEqual(key, value);
|
||||||
deleted = vertex.deleted;
|
deleted = vertex.second.deleted;
|
||||||
delta = vertex.delta;
|
delta = vertex.second.delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!deleted && has_label && current_value_equal_to_value) {
|
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};
|
bool has_label{false};
|
||||||
const Delta *delta{nullptr};
|
const Delta *delta{nullptr};
|
||||||
{
|
{
|
||||||
deleted = vertex.deleted;
|
deleted = vertex.second.deleted;
|
||||||
has_label = utils::Contains(vertex.labels, label);
|
has_label = utils::Contains(vertex.second.labels, label);
|
||||||
delta = vertex.delta;
|
delta = vertex.second.delta;
|
||||||
}
|
}
|
||||||
ApplyDeltasForRead(transaction, delta, view, [&deleted, &has_label, label](const Delta &delta) {
|
ApplyDeltasForRead(transaction, delta, view, [&deleted, &has_label, label](const Delta &delta) {
|
||||||
switch (delta.action) {
|
switch (delta.action) {
|
||||||
@ -218,10 +219,10 @@ bool CurrentVersionHasLabelProperty(const Vertex &vertex, LabelId label, Propert
|
|||||||
bool current_value_equal_to_value = value.IsNull();
|
bool current_value_equal_to_value = value.IsNull();
|
||||||
const Delta *delta{nullptr};
|
const Delta *delta{nullptr};
|
||||||
{
|
{
|
||||||
deleted = vertex.deleted;
|
deleted = vertex.second.deleted;
|
||||||
has_label = utils::Contains(vertex.labels, label);
|
has_label = utils::Contains(vertex.second.labels, label);
|
||||||
current_value_equal_to_value = vertex.properties.IsPropertyEqual(key, value);
|
current_value_equal_to_value = vertex.second.properties.IsPropertyEqual(key, value);
|
||||||
delta = vertex.delta;
|
delta = vertex.second.delta;
|
||||||
}
|
}
|
||||||
ApplyDeltasForRead(transaction, delta, view,
|
ApplyDeltasForRead(transaction, delta, view,
|
||||||
[&deleted, &has_label, ¤t_value_equal_to_value, key, label, &value](const Delta &delta) {
|
[&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 {
|
try {
|
||||||
auto acc = it->second.access();
|
auto acc = it->second.access();
|
||||||
for ([[maybe_unused]] auto &[pk, vertex] : vertices) {
|
for ([[maybe_unused]] auto &vertex : vertices) {
|
||||||
if (vertex.deleted || !utils::Contains(vertex.labels, label)) {
|
if (vertex.second.deleted || !VertexHasLabel(vertex, label)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
acc.insert(Entry{&vertex, 0});
|
acc.insert(Entry{&vertex, 0});
|
||||||
@ -395,7 +396,7 @@ void LabelPropertyIndex::UpdateOnAddLabel(LabelId label, Vertex *vertex, const T
|
|||||||
if (label_prop.first != label) {
|
if (label_prop.first != label) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto prop_value = vertex->properties.GetProperty(label_prop.second);
|
auto prop_value = vertex->second.properties.GetProperty(label_prop.second);
|
||||||
if (!prop_value.IsNull()) {
|
if (!prop_value.IsNull()) {
|
||||||
index.emplace(prop_value, Entry{prop_value, vertex, tx.start_timestamp.logical_id});
|
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) {
|
if (label_prop.second != property) {
|
||||||
continue;
|
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});
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
for ([[maybe_unused]] auto &[pk, vertex] : vertices) {
|
for ([[maybe_unused]] auto &vertex : vertices) {
|
||||||
if (vertex.deleted || !utils::Contains(vertex.labels, label)) {
|
if (vertex.second.deleted || !VertexHasLabel(vertex, label)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto value = vertex.properties.GetProperty(property);
|
auto value = vertex.second.properties.GetProperty(property);
|
||||||
if (value.IsNull()) {
|
if (value.IsNull()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "storage/v3/config.hpp"
|
#include "storage/v3/config.hpp"
|
||||||
#include "storage/v3/containers.hpp"
|
|
||||||
#include "storage/v3/property_value.hpp"
|
#include "storage/v3/property_value.hpp"
|
||||||
#include "storage/v3/transaction.hpp"
|
#include "storage/v3/transaction.hpp"
|
||||||
#include "storage/v3/vertex_accessor.hpp"
|
#include "storage/v3/vertex_accessor.hpp"
|
||||||
|
@ -11,9 +11,13 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
#include "storage/v3/edge.hpp"
|
||||||
#include "storage/v3/property_value.hpp"
|
#include "storage/v3/property_value.hpp"
|
||||||
#include "storage/v3/transaction.hpp"
|
#include "storage/v3/transaction.hpp"
|
||||||
|
#include "storage/v3/vertex.hpp"
|
||||||
#include "storage/v3/view.hpp"
|
#include "storage/v3/view.hpp"
|
||||||
|
#include "utils/concepts.hpp"
|
||||||
|
|
||||||
namespace memgraph::storage::v3 {
|
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
|
/// transaction) and returns a `bool` value indicating whether the caller can
|
||||||
/// proceed with a write operation.
|
/// proceed with a write operation.
|
||||||
template <typename TObj>
|
template <typename TObj>
|
||||||
|
requires utils::SameAsAnyOf<TObj, Edge, Vertex>
|
||||||
inline bool PrepareForWrite(Transaction *transaction, TObj *object) {
|
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 ||
|
if (delta_commit_info.start_or_commit_timestamp == transaction->commit_info->start_or_commit_timestamp ||
|
||||||
(delta_commit_info.is_locally_committed &&
|
(delta_commit_info.is_locally_committed &&
|
||||||
delta_commit_info.start_or_commit_timestamp < transaction->start_timestamp)) {
|
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.
|
/// the delta into the object's delta list.
|
||||||
/// @throw std::bad_alloc
|
/// @throw std::bad_alloc
|
||||||
template <typename TObj, class... Args>
|
template <typename TObj, class... Args>
|
||||||
|
requires utils::SameAsAnyOf<TObj, Edge, Vertex>
|
||||||
inline void CreateAndLinkDelta(Transaction *transaction, TObj *object, Args &&...args) {
|
inline void CreateAndLinkDelta(Transaction *transaction, TObj *object, Args &&...args) {
|
||||||
auto delta = &transaction->deltas.emplace_back(std::forward<Args>(args)..., transaction->commit_info.get(),
|
auto delta = &transaction->deltas.emplace_back(std::forward<Args>(args)..., transaction->commit_info.get(),
|
||||||
transaction->command_id);
|
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`
|
// 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
|
// 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
|
// TODO(antaljanosbenjamin): clang-tidy detects (in my opinion a false positive) issue in
|
||||||
// `Shard::Accessor::CreateEdge`.
|
// `Shard::Accessor::CreateEdge`.
|
||||||
// NOLINTNEXTLINE(clang-analyzer-core.NullDereference)
|
// 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.
|
// 2. We need to set the previous delta of the new delta to the object.
|
||||||
delta->prev.Set(object);
|
delta->prev.Set(object);
|
||||||
// 3. We need to set the previous delta of the existing delta to the new
|
// 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. 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.
|
// delta but won't modify it until we are done with all of our modifications.
|
||||||
if (object->delta) {
|
if (delta_holder->delta) {
|
||||||
object->delta->prev.Set(delta);
|
delta_holder->delta->prev.Set(delta);
|
||||||
}
|
}
|
||||||
// 4. Finally, we need to set the object's delta to the new delta. The garbage
|
// 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
|
// 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
|
// 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
|
// modification is being done, everybody else will wait until we are fully
|
||||||
// done with our modification before they read the object's delta value.
|
// done with our modification before they read the object's delta value.
|
||||||
object->delta = delta;
|
delta_holder->delta = delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace memgraph::storage::v3
|
} // namespace memgraph::storage::v3
|
||||||
|
@ -26,7 +26,6 @@
|
|||||||
|
|
||||||
#include "io/network/endpoint.hpp"
|
#include "io/network/endpoint.hpp"
|
||||||
#include "io/time.hpp"
|
#include "io/time.hpp"
|
||||||
#include "storage/v3/containers.hpp"
|
|
||||||
#include "storage/v3/edge_accessor.hpp"
|
#include "storage/v3/edge_accessor.hpp"
|
||||||
#include "storage/v3/id_types.hpp"
|
#include "storage/v3/id_types.hpp"
|
||||||
#include "storage/v3/indices.hpp"
|
#include "storage/v3/indices.hpp"
|
||||||
@ -39,6 +38,7 @@
|
|||||||
#include "storage/v3/transaction.hpp"
|
#include "storage/v3/transaction.hpp"
|
||||||
#include "storage/v3/vertex.hpp"
|
#include "storage/v3/vertex.hpp"
|
||||||
#include "storage/v3/vertex_accessor.hpp"
|
#include "storage/v3/vertex_accessor.hpp"
|
||||||
|
#include "storage/v3/view.hpp"
|
||||||
#include "utils/exceptions.hpp"
|
#include "utils/exceptions.hpp"
|
||||||
#include "utils/file.hpp"
|
#include "utils/file.hpp"
|
||||||
#include "utils/logging.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,
|
std::optional<VertexAccessor> *vertex, Transaction *tx, View view, Indices *indices,
|
||||||
Config::Items config, const VertexValidator &vertex_validator) {
|
Config::Items config, const VertexValidator &vertex_validator) {
|
||||||
while (it != end) {
|
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) {
|
if (!*vertex) {
|
||||||
++it;
|
++it;
|
||||||
continue;
|
continue;
|
||||||
@ -346,7 +346,7 @@ Shard::Accessor::Accessor(Shard &shard, Transaction &transaction)
|
|||||||
: shard_(&shard), transaction_(&transaction), config_(shard_->config_.items) {}
|
: shard_(&shard), transaction_(&transaction), config_(shard_->config_.items) {}
|
||||||
|
|
||||||
ShardResult<VertexAccessor> Shard::Accessor::CreateVertexAndValidate(
|
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) {
|
const std::vector<std::pair<PropertyId, PropertyValue>> &properties) {
|
||||||
OOMExceptionEnabler oom_exception;
|
OOMExceptionEnabler oom_exception;
|
||||||
const auto schema = shard_->GetSchema(shard_->primary_label_)->second;
|
const auto schema = shard_->GetSchema(shard_->primary_label_)->second;
|
||||||
@ -358,10 +358,10 @@ ShardResult<VertexAccessor> Shard::Accessor::CreateVertexAndValidate(
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto *delta = CreateDeleteObjectDelta(transaction_);
|
auto *delta = CreateDeleteObjectDelta(transaction_);
|
||||||
auto [it, inserted] = shard_->vertices_.emplace(primary_properties, Vertex(delta, primary_properties));
|
auto [it, inserted] = shard_->vertices_.emplace(primary_properties, VertexData{delta});
|
||||||
delta->prev.Set(&it->second);
|
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) {
|
if (!inserted) {
|
||||||
return SHARD_ERROR(ErrorCode::VERTEX_ALREADY_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()) {
|
if (it == shard_->vertices_.end()) {
|
||||||
return std::nullopt;
|
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) {
|
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 (!PrepareForWrite(transaction_, vertex_ptr)) return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR);
|
||||||
|
|
||||||
if (vertex_ptr->deleted) {
|
if (vertex_ptr->second.deleted) {
|
||||||
return std::optional<VertexAccessor>{};
|
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());
|
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_,
|
return std::make_optional<VertexAccessor>(vertex_ptr, transaction_, &shard_->indices_, config_,
|
||||||
shard_->vertex_validator_, true);
|
shard_->vertex_validator_, true);
|
||||||
@ -422,20 +423,20 @@ ShardResult<std::optional<std::pair<VertexAccessor, std::vector<EdgeAccessor>>>>
|
|||||||
"accessor when deleting a vertex!");
|
"accessor when deleting a vertex!");
|
||||||
auto *vertex_ptr = vertex->vertex_;
|
auto *vertex_ptr = vertex->vertex_;
|
||||||
|
|
||||||
std::vector<Vertex::EdgeLink> in_edges;
|
std::vector<VertexData::EdgeLink> in_edges;
|
||||||
std::vector<Vertex::EdgeLink> out_edges;
|
std::vector<VertexData::EdgeLink> out_edges;
|
||||||
|
|
||||||
{
|
{
|
||||||
if (!PrepareForWrite(transaction_, vertex_ptr)) return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR);
|
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;
|
in_edges = vertex_ptr->second.in_edges;
|
||||||
out_edges = vertex_ptr->out_edges;
|
out_edges = vertex_ptr->second.out_edges;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<EdgeAccessor> deleted_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) {
|
for (const auto &item : in_edges) {
|
||||||
auto [edge_type, from_vertex, edge] = item;
|
auto [edge_type, from_vertex, edge] = item;
|
||||||
EdgeAccessor e(edge, edge_type, from_vertex, vertex_id, transaction_, &shard_->indices_, config_);
|
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);
|
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());
|
CreateAndLinkDelta(transaction_, vertex_ptr, Delta::RecreateObjectTag());
|
||||||
vertex_ptr->deleted = true;
|
vertex_ptr->second.deleted = true;
|
||||||
|
|
||||||
return std::make_optional<ReturnType>(
|
return std::make_optional<ReturnType>(
|
||||||
VertexAccessor{vertex_ptr, transaction_, &shard_->indices_, config_, shard_->vertex_validator_, true},
|
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) {
|
if (from_is_local) {
|
||||||
auto it = vertices.find(from_vertex_id.primary_key);
|
auto it = vertices.find(from_vertex_id.primary_key);
|
||||||
MG_ASSERT(it != vertices.end(), "Cannot find local vertex");
|
MG_ASSERT(it != vertices.end(), "Cannot find local vertex");
|
||||||
from_vertex = &it->second;
|
from_vertex = &*it;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (to_is_local) {
|
if (to_is_local) {
|
||||||
auto it = vertices.find(to_vertex_id.primary_key);
|
auto it = vertices.find(to_vertex_id.primary_key);
|
||||||
MG_ASSERT(it != vertices.end(), "Cannot find local vertex");
|
MG_ASSERT(it != vertices.end(), "Cannot find local vertex");
|
||||||
to_vertex = &it->second;
|
to_vertex = &*it;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (from_is_local) {
|
if (from_is_local) {
|
||||||
if (!PrepareForWrite(transaction_, from_vertex)) return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR);
|
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 (to_is_local && to_vertex != from_vertex) {
|
||||||
if (!PrepareForWrite(transaction_, to_vertex)) return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR);
|
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);
|
EdgeRef edge(gid);
|
||||||
@ -524,11 +525,11 @@ ShardResult<EdgeAccessor> Shard::Accessor::CreateEdge(VertexId from_vertex_id, V
|
|||||||
|
|
||||||
if (from_is_local) {
|
if (from_is_local) {
|
||||||
CreateAndLinkDelta(transaction_, from_vertex, Delta::RemoveOutEdgeTag(), edge_type, to_vertex_id, edge);
|
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) {
|
if (to_is_local) {
|
||||||
CreateAndLinkDelta(transaction_, to_vertex, Delta::RemoveInEdgeTag(), edge_type, from_vertex_id, edge);
|
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.
|
// Increment edge count.
|
||||||
++shard_->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,
|
ShardResult<std::optional<EdgeAccessor>> Shard::Accessor::DeleteEdge(VertexId from_vertex_id, VertexId to_vertex_id,
|
||||||
const Gid edge_id) {
|
const Gid edge_id) {
|
||||||
Vertex *from_vertex{nullptr};
|
VertexContainer::value_type *from_vertex{nullptr};
|
||||||
Vertex *to_vertex{nullptr};
|
VertexContainer::value_type *to_vertex{nullptr};
|
||||||
|
|
||||||
auto &vertices = shard_->vertices_;
|
auto &vertices = shard_->vertices_;
|
||||||
|
|
||||||
@ -550,13 +551,13 @@ ShardResult<std::optional<EdgeAccessor>> Shard::Accessor::DeleteEdge(VertexId fr
|
|||||||
if (from_is_local) {
|
if (from_is_local) {
|
||||||
auto it = vertices.find(from_vertex_id.primary_key);
|
auto it = vertices.find(from_vertex_id.primary_key);
|
||||||
MG_ASSERT(it != vertices.end(), "Cannot find local vertex");
|
MG_ASSERT(it != vertices.end(), "Cannot find local vertex");
|
||||||
from_vertex = &it->second;
|
from_vertex = &*it;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (to_is_local) {
|
if (to_is_local) {
|
||||||
auto it = vertices.find(to_vertex_id.primary_key);
|
auto it = vertices.find(to_vertex_id.primary_key);
|
||||||
MG_ASSERT(it != vertices.end(), "Cannot find local vertex");
|
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");
|
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)) {
|
if (!PrepareForWrite(transaction_, from_vertex)) {
|
||||||
return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR);
|
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 (to_is_local && to_vertex != from_vertex) {
|
||||||
if (!PrepareForWrite(transaction_, to_vertex)) {
|
if (!PrepareForWrite(transaction_, to_vertex)) {
|
||||||
return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR);
|
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 {
|
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{};
|
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(),
|
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) {
|
if (config_.properties_on_edges) {
|
||||||
MG_ASSERT(it != edges.end(), "Invalid database state!");
|
MG_ASSERT(it != edges.end(), "Invalid database state!");
|
||||||
} else if (it == edges.end()) {
|
} else if (it == edges.end()) {
|
||||||
@ -598,8 +599,8 @@ ShardResult<std::optional<EdgeAccessor>> Shard::Accessor::DeleteEdge(VertexId fr
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
// NOLINTNEXTLINE(clang-analyzer-core.NonNullParamChecker)
|
// NOLINTNEXTLINE(clang-analyzer-core.NonNullParamChecker)
|
||||||
auto success_on_to = to_is_local ? delete_edge_from_storage(to_vertex->in_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->out_edges) : false;
|
auto success_on_from = from_is_local ? delete_edge_from_storage(from_vertex->second.out_edges) : false;
|
||||||
|
|
||||||
if (config_.properties_on_edges) {
|
if (config_.properties_on_edges) {
|
||||||
// Because of the check above, we are sure that the vertex exists.
|
// 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");
|
MG_ASSERT(edge_type.has_value(), "Edge type is not determined");
|
||||||
|
|
||||||
if (from_is_local) {
|
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) {
|
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.
|
// Decrement edge count.
|
||||||
@ -690,41 +691,41 @@ void Shard::Accessor::Abort() {
|
|||||||
auto prev = delta.prev.Get();
|
auto prev = delta.prev.Get();
|
||||||
switch (prev.type) {
|
switch (prev.type) {
|
||||||
case PreviousPtr::Type::VERTEX: {
|
case PreviousPtr::Type::VERTEX: {
|
||||||
auto *vertex = prev.vertex;
|
auto &[pk, vertex] = *prev.vertex;
|
||||||
Delta *current = vertex->delta;
|
Delta *current = vertex.delta;
|
||||||
while (current != nullptr && current->commit_info->start_or_commit_timestamp == transaction_->start_timestamp) {
|
while (current != nullptr && current->commit_info->start_or_commit_timestamp == transaction_->start_timestamp) {
|
||||||
switch (current->action) {
|
switch (current->action) {
|
||||||
case Delta::Action::REMOVE_LABEL: {
|
case Delta::Action::REMOVE_LABEL: {
|
||||||
auto it = std::find(vertex->labels.begin(), vertex->labels.end(), current->label);
|
auto it = std::find(vertex.labels.begin(), vertex.labels.end(), current->label);
|
||||||
MG_ASSERT(it != vertex->labels.end(), "Invalid database state!");
|
MG_ASSERT(it != vertex.labels.end(), "Invalid database state!");
|
||||||
std::swap(*it, *vertex->labels.rbegin());
|
std::swap(*it, *vertex.labels.rbegin());
|
||||||
vertex->labels.pop_back();
|
vertex.labels.pop_back();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Delta::Action::ADD_LABEL: {
|
case Delta::Action::ADD_LABEL: {
|
||||||
auto it = std::find(vertex->labels.begin(), vertex->labels.end(), current->label);
|
auto it = std::find(vertex.labels.begin(), vertex.labels.end(), current->label);
|
||||||
MG_ASSERT(it == vertex->labels.end(), "Invalid database state!");
|
MG_ASSERT(it == vertex.labels.end(), "Invalid database state!");
|
||||||
vertex->labels.push_back(current->label);
|
vertex.labels.push_back(current->label);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Delta::Action::SET_PROPERTY: {
|
case Delta::Action::SET_PROPERTY: {
|
||||||
vertex->properties.SetProperty(current->property.key, current->property.value);
|
vertex.properties.SetProperty(current->property.key, current->property.value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Delta::Action::ADD_IN_EDGE: {
|
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};
|
current->vertex_edge.edge};
|
||||||
auto it = std::find(vertex->in_edges.begin(), vertex->in_edges.end(), link);
|
auto it = std::find(vertex.in_edges.begin(), vertex.in_edges.end(), link);
|
||||||
MG_ASSERT(it == vertex->in_edges.end(), "Invalid database state!");
|
MG_ASSERT(it == vertex.in_edges.end(), "Invalid database state!");
|
||||||
vertex->in_edges.push_back(link);
|
vertex.in_edges.push_back(link);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Delta::Action::ADD_OUT_EDGE: {
|
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};
|
current->vertex_edge.edge};
|
||||||
auto it = std::find(vertex->out_edges.begin(), vertex->out_edges.end(), link);
|
auto it = std::find(vertex.out_edges.begin(), vertex.out_edges.end(), link);
|
||||||
MG_ASSERT(it == vertex->out_edges.end(), "Invalid database state!");
|
MG_ASSERT(it == vertex.out_edges.end(), "Invalid database state!");
|
||||||
vertex->out_edges.push_back(link);
|
vertex.out_edges.push_back(link);
|
||||||
// Increment edge count. We only increment the count here because
|
// Increment edge count. We only increment the count here because
|
||||||
// the information in `ADD_IN_EDGE` and `Edge/RECREATE_OBJECT` is
|
// the information in `ADD_IN_EDGE` and `Edge/RECREATE_OBJECT` is
|
||||||
// redundant. Also, `Edge/RECREATE_OBJECT` isn't available when
|
// redundant. Also, `Edge/RECREATE_OBJECT` isn't available when
|
||||||
@ -733,21 +734,21 @@ void Shard::Accessor::Abort() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Delta::Action::REMOVE_IN_EDGE: {
|
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};
|
current->vertex_edge.edge};
|
||||||
auto it = std::find(vertex->in_edges.begin(), vertex->in_edges.end(), link);
|
auto it = std::find(vertex.in_edges.begin(), vertex.in_edges.end(), link);
|
||||||
MG_ASSERT(it != vertex->in_edges.end(), "Invalid database state!");
|
MG_ASSERT(it != vertex.in_edges.end(), "Invalid database state!");
|
||||||
std::swap(*it, *vertex->in_edges.rbegin());
|
std::swap(*it, *vertex.in_edges.rbegin());
|
||||||
vertex->in_edges.pop_back();
|
vertex.in_edges.pop_back();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Delta::Action::REMOVE_OUT_EDGE: {
|
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};
|
current->vertex_edge.edge};
|
||||||
auto it = std::find(vertex->out_edges.begin(), vertex->out_edges.end(), link);
|
auto it = std::find(vertex.out_edges.begin(), vertex.out_edges.end(), link);
|
||||||
MG_ASSERT(it != vertex->out_edges.end(), "Invalid database state!");
|
MG_ASSERT(it != vertex.out_edges.end(), "Invalid database state!");
|
||||||
std::swap(*it, *vertex->out_edges.rbegin());
|
std::swap(*it, *vertex.out_edges.rbegin());
|
||||||
vertex->out_edges.pop_back();
|
vertex.out_edges.pop_back();
|
||||||
// Decrement edge count. We only decrement the count here because
|
// Decrement edge count. We only decrement the count here because
|
||||||
// the information in `REMOVE_IN_EDGE` and `Edge/DELETE_OBJECT` is
|
// the information in `REMOVE_IN_EDGE` and `Edge/DELETE_OBJECT` is
|
||||||
// redundant. Also, `Edge/DELETE_OBJECT` isn't available when edge
|
// redundant. Also, `Edge/DELETE_OBJECT` isn't available when edge
|
||||||
@ -756,20 +757,20 @@ void Shard::Accessor::Abort() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Delta::Action::DELETE_OBJECT: {
|
case Delta::Action::DELETE_OBJECT: {
|
||||||
vertex->deleted = true;
|
vertex.deleted = true;
|
||||||
shard_->deleted_vertices_.push_back(vertex->keys);
|
shard_->deleted_vertices_.push_back(&pk);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Delta::Action::RECREATE_OBJECT: {
|
case Delta::Action::RECREATE_OBJECT: {
|
||||||
vertex->deleted = false;
|
vertex.deleted = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
current = current->next;
|
current = current->next;
|
||||||
}
|
}
|
||||||
vertex->delta = current;
|
vertex.delta = current;
|
||||||
if (current != nullptr) {
|
if (current != nullptr) {
|
||||||
current->prev.Set(vertex);
|
current->prev.Set(prev.vertex);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -964,10 +965,12 @@ void Shard::CollectGarbage(const io::Time current_time) {
|
|||||||
auto prev = delta.prev.Get();
|
auto prev = delta.prev.Get();
|
||||||
switch (prev.type) {
|
switch (prev.type) {
|
||||||
case PreviousPtr::Type::VERTEX: {
|
case PreviousPtr::Type::VERTEX: {
|
||||||
Vertex *vertex = prev.vertex;
|
// Here we need to get pk from prev pointer, and that is why change
|
||||||
vertex->delta = nullptr;
|
// to the PrevPtr so it points to pair of pk and vertex
|
||||||
if (vertex->deleted) {
|
auto &[pk, vertex] = *prev.vertex;
|
||||||
deleted_vertices_.push_back(vertex->keys);
|
vertex.delta = nullptr;
|
||||||
|
if (vertex.deleted) {
|
||||||
|
deleted_vertices_.push_back(&pk);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1015,7 +1018,7 @@ void Shard::CollectGarbage(const io::Time current_time) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (const auto &vertex : deleted_vertices_) {
|
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();
|
deleted_vertices_.clear();
|
||||||
{
|
{
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
#include "io/time.hpp"
|
#include "io/time.hpp"
|
||||||
#include "kvstore/kvstore.hpp"
|
#include "kvstore/kvstore.hpp"
|
||||||
#include "storage/v3/config.hpp"
|
#include "storage/v3/config.hpp"
|
||||||
#include "storage/v3/containers.hpp"
|
|
||||||
#include "storage/v3/edge.hpp"
|
#include "storage/v3/edge.hpp"
|
||||||
#include "storage/v3/edge_accessor.hpp"
|
#include "storage/v3/edge_accessor.hpp"
|
||||||
#include "storage/v3/id_types.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
|
// Vertices that are logically deleted but still have to be removed from
|
||||||
// indices before removing them from the main storage.
|
// 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
|
// Edges that are logically deleted and wait to be removed from the main
|
||||||
// storage.
|
// storage.
|
||||||
|
@ -9,16 +9,22 @@
|
|||||||
// by the Apache License, Version 2.0, included in the file
|
// by the Apache License, Version 2.0, included in the file
|
||||||
// licenses/APL.txt.
|
// 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 "storage/v3/vertex.hpp"
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
#include <tuple>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "storage/v3/delta.hpp"
|
||||||
|
|
||||||
namespace memgraph::storage::v3 {
|
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
|
} // namespace memgraph::storage::v3
|
@ -16,7 +16,6 @@
|
|||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "storage/v3/delta.hpp"
|
|
||||||
#include "storage/v3/edge_ref.hpp"
|
#include "storage/v3/edge_ref.hpp"
|
||||||
#include "storage/v3/id_types.hpp"
|
#include "storage/v3/id_types.hpp"
|
||||||
#include "storage/v3/key_store.hpp"
|
#include "storage/v3/key_store.hpp"
|
||||||
@ -28,17 +27,12 @@
|
|||||||
|
|
||||||
namespace memgraph::storage::v3 {
|
namespace memgraph::storage::v3 {
|
||||||
|
|
||||||
struct Vertex {
|
struct Delta;
|
||||||
|
|
||||||
|
struct VertexData {
|
||||||
using EdgeLink = std::tuple<EdgeTypeId, VertexId, EdgeRef>;
|
using EdgeLink = std::tuple<EdgeTypeId, VertexId, EdgeRef>;
|
||||||
|
|
||||||
Vertex(Delta *delta, PrimaryKey primary_properties) : keys{std::move(primary_properties)}, delta{delta} {
|
explicit VertexData(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;
|
|
||||||
|
|
||||||
std::vector<LabelId> labels;
|
std::vector<LabelId> labels;
|
||||||
PropertyStore properties;
|
PropertyStore properties;
|
||||||
@ -52,8 +46,11 @@ struct Vertex {
|
|||||||
Delta *delta;
|
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
|
} // namespace memgraph::storage::v3
|
||||||
|
@ -36,8 +36,8 @@ std::pair<bool, bool> IsVisible(Vertex *vertex, Transaction *transaction, View v
|
|||||||
bool deleted = false;
|
bool deleted = false;
|
||||||
Delta *delta = nullptr;
|
Delta *delta = nullptr;
|
||||||
{
|
{
|
||||||
deleted = vertex->deleted;
|
deleted = vertex->second.deleted;
|
||||||
delta = vertex->delta;
|
delta = vertex->second.delta;
|
||||||
}
|
}
|
||||||
ApplyDeltasForRead(transaction, delta, view, [&](const Delta &delta) {
|
ApplyDeltasForRead(transaction, delta, view, [&](const Delta &delta) {
|
||||||
switch (delta.action) {
|
switch (delta.action) {
|
||||||
@ -85,13 +85,14 @@ ShardResult<bool> VertexAccessor::AddLabel(LabelId label) {
|
|||||||
|
|
||||||
if (!PrepareForWrite(transaction_, vertex_)) return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR);
|
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);
|
CreateAndLinkDelta(transaction_, vertex_, Delta::RemoveLabelTag(), label);
|
||||||
|
|
||||||
vertex_->labels.push_back(label);
|
vertex_->second.labels.push_back(label);
|
||||||
|
|
||||||
UpdateOnAddLabel(indices_, label, vertex_, *transaction_);
|
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 (!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);
|
CreateAndLinkDelta(transaction_, vertex_, Delta::RemoveLabelTag(), label);
|
||||||
|
|
||||||
vertex_->labels.push_back(label);
|
vertex_->second.labels.push_back(label);
|
||||||
|
|
||||||
UpdateOnAddLabel(indices_, label, vertex_, *transaction_);
|
UpdateOnAddLabel(indices_, label, vertex_, *transaction_);
|
||||||
|
|
||||||
@ -122,15 +124,15 @@ ShardResult<bool> VertexAccessor::AddLabelAndValidate(LabelId label) {
|
|||||||
ShardResult<bool> VertexAccessor::RemoveLabel(LabelId label) {
|
ShardResult<bool> VertexAccessor::RemoveLabel(LabelId label) {
|
||||||
if (!PrepareForWrite(transaction_, vertex_)) return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR);
|
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);
|
auto it = std::find(vertex_->second.labels.begin(), vertex_->second.labels.end(), label);
|
||||||
if (it == vertex_->labels.end()) return false;
|
if (it == vertex_->second.labels.end()) return false;
|
||||||
|
|
||||||
CreateAndLinkDelta(transaction_, vertex_, Delta::AddLabelTag(), label);
|
CreateAndLinkDelta(transaction_, vertex_, Delta::AddLabelTag(), label);
|
||||||
|
|
||||||
std::swap(*it, *vertex_->labels.rbegin());
|
std::swap(*it, *vertex_->second.labels.rbegin());
|
||||||
vertex_->labels.pop_back();
|
vertex_->second.labels.pop_back();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,15 +144,15 @@ ShardResult<bool> VertexAccessor::RemoveLabelAndValidate(LabelId label) {
|
|||||||
|
|
||||||
if (!PrepareForWrite(transaction_, vertex_)) return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR);
|
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);
|
auto it = std::find(vertex_->second.labels.begin(), vertex_->second.labels.end(), label);
|
||||||
if (it == vertex_->labels.end()) return false;
|
if (it == vertex_->second.labels.end()) return false;
|
||||||
|
|
||||||
CreateAndLinkDelta(transaction_, vertex_, Delta::AddLabelTag(), label);
|
CreateAndLinkDelta(transaction_, vertex_, Delta::AddLabelTag(), label);
|
||||||
|
|
||||||
std::swap(*it, *vertex_->labels.rbegin());
|
std::swap(*it, *vertex_->second.labels.rbegin());
|
||||||
vertex_->labels.pop_back();
|
vertex_->second.labels.pop_back();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,9 +164,9 @@ ShardResult<bool> VertexAccessor::HasLabel(LabelId label, View view) const {
|
|||||||
bool has_label = false;
|
bool has_label = false;
|
||||||
Delta *delta = nullptr;
|
Delta *delta = nullptr;
|
||||||
{
|
{
|
||||||
deleted = vertex_->deleted;
|
deleted = vertex_->second.deleted;
|
||||||
has_label = label == vertex_validator_->primary_label_ || VertexHasLabel(*vertex_, label);
|
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) {
|
ApplyDeltasForRead(transaction_, delta, view, [&exists, &deleted, &has_label, label](const Delta &delta) {
|
||||||
switch (delta.action) {
|
switch (delta.action) {
|
||||||
@ -215,14 +217,14 @@ ShardResult<PrimaryKey> VertexAccessor::PrimaryKey(const View view) const {
|
|||||||
if (const auto result = CheckVertexExistence(view); result.HasError()) {
|
if (const auto result = CheckVertexExistence(view); result.HasError()) {
|
||||||
return result.GetError();
|
return result.GetError();
|
||||||
}
|
}
|
||||||
return vertex_->keys;
|
return vertex_->first;
|
||||||
}
|
}
|
||||||
|
|
||||||
ShardResult<VertexId> VertexAccessor::Id(View view) const {
|
ShardResult<VertexId> VertexAccessor::Id(View view) const {
|
||||||
if (const auto result = CheckVertexExistence(view); result.HasError()) {
|
if (const auto result = CheckVertexExistence(view); result.HasError()) {
|
||||||
return result.GetError();
|
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 {
|
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;
|
std::vector<LabelId> labels;
|
||||||
Delta *delta = nullptr;
|
Delta *delta = nullptr;
|
||||||
{
|
{
|
||||||
deleted = vertex_->deleted;
|
deleted = vertex_->second.deleted;
|
||||||
labels = vertex_->labels;
|
labels = vertex_->second.labels;
|
||||||
delta = vertex_->delta;
|
delta = vertex_->second.delta;
|
||||||
}
|
}
|
||||||
ApplyDeltasForRead(transaction_, delta, view, [&exists, &deleted, &labels](const Delta &delta) {
|
ApplyDeltasForRead(transaction_, delta, view, [&exists, &deleted, &labels](const Delta &delta) {
|
||||||
switch (delta.action) {
|
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 (!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
|
// 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
|
// 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
|
// 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
|
// "modify in-place". Additionally, the created delta will make other
|
||||||
// transactions get a SERIALIZATION_ERROR.
|
// transactions get a SERIALIZATION_ERROR.
|
||||||
CreateAndLinkDelta(transaction_, vertex_, Delta::SetPropertyTag(), property, current_value);
|
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_);
|
UpdateOnSetProperty(indices_, property, value, vertex_, *transaction_);
|
||||||
|
|
||||||
@ -300,8 +302,8 @@ ShardResult<void> VertexAccessor::CheckVertexExistence(View view) const {
|
|||||||
bool deleted = false;
|
bool deleted = false;
|
||||||
Delta *delta = nullptr;
|
Delta *delta = nullptr;
|
||||||
{
|
{
|
||||||
deleted = vertex_->deleted;
|
deleted = vertex_->second.deleted;
|
||||||
delta = vertex_->delta;
|
delta = vertex_->second.delta;
|
||||||
}
|
}
|
||||||
ApplyDeltasForRead(transaction_, delta, view, [&exists, &deleted](const Delta &delta) {
|
ApplyDeltasForRead(transaction_, delta, view, [&exists, &deleted](const Delta &delta) {
|
||||||
switch (delta.action) {
|
switch (delta.action) {
|
||||||
@ -343,11 +345,11 @@ ShardResult<PropertyValue> VertexAccessor::SetPropertyAndValidate(PropertyId pro
|
|||||||
return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR);
|
return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vertex_->deleted) {
|
if (vertex_->second.deleted) {
|
||||||
return SHARD_ERROR(ErrorCode::DELETED_OBJECT);
|
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
|
// 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
|
// 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
|
// 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
|
// "modify in-place". Additionally, the created delta will make other
|
||||||
// transactions get a SERIALIZATION_ERROR.
|
// transactions get a SERIALIZATION_ERROR.
|
||||||
CreateAndLinkDelta(transaction_, vertex_, Delta::SetPropertyTag(), property, current_value);
|
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_);
|
UpdateOnSetProperty(indices_, property, value, vertex_, *transaction_);
|
||||||
|
|
||||||
@ -365,15 +367,15 @@ ShardResult<PropertyValue> VertexAccessor::SetPropertyAndValidate(PropertyId pro
|
|||||||
ShardResult<std::map<PropertyId, PropertyValue>> VertexAccessor::ClearProperties() {
|
ShardResult<std::map<PropertyId, PropertyValue>> VertexAccessor::ClearProperties() {
|
||||||
if (!PrepareForWrite(transaction_, vertex_)) return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR);
|
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) {
|
for (const auto &property : properties) {
|
||||||
CreateAndLinkDelta(transaction_, vertex_, Delta::SetPropertyTag(), property.first, property.second);
|
CreateAndLinkDelta(transaction_, vertex_, Delta::SetPropertyTag(), property.first, property.second);
|
||||||
UpdateOnSetProperty(indices_, property.first, PropertyValue(), vertex_, *transaction_);
|
UpdateOnSetProperty(indices_, property.first, PropertyValue(), vertex_, *transaction_);
|
||||||
}
|
}
|
||||||
|
|
||||||
vertex_->properties.ClearProperties();
|
vertex_->second.properties.ClearProperties();
|
||||||
|
|
||||||
return std::move(properties);
|
return std::move(properties);
|
||||||
}
|
}
|
||||||
@ -396,11 +398,11 @@ PropertyValue VertexAccessor::GetPropertyValue(PropertyId property, View view) c
|
|||||||
// Find PropertyId index in keystore
|
// Find PropertyId index in keystore
|
||||||
for (size_t property_index{0}; property_index < schema->second.size(); ++property_index) {
|
for (size_t property_index{0}; property_index < schema->second.size(); ++property_index) {
|
||||||
if (schema->second[property_index].property_id == property) {
|
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 {
|
ShardResult<PropertyValue> VertexAccessor::GetProperty(PropertyId property, View view) const {
|
||||||
@ -409,9 +411,9 @@ ShardResult<PropertyValue> VertexAccessor::GetProperty(PropertyId property, View
|
|||||||
PropertyValue value;
|
PropertyValue value;
|
||||||
Delta *delta = nullptr;
|
Delta *delta = nullptr;
|
||||||
{
|
{
|
||||||
deleted = vertex_->deleted;
|
deleted = vertex_->second.deleted;
|
||||||
value = GetPropertyValue(property, view);
|
value = GetPropertyValue(property, view);
|
||||||
delta = vertex_->delta;
|
delta = vertex_->second.delta;
|
||||||
}
|
}
|
||||||
ApplyDeltasForRead(transaction_, delta, view, [&exists, &deleted, &value, property](const Delta &delta) {
|
ApplyDeltasForRead(transaction_, delta, view, [&exists, &deleted, &value, property](const Delta &delta) {
|
||||||
switch (delta.action) {
|
switch (delta.action) {
|
||||||
@ -453,10 +455,10 @@ ShardResult<std::map<PropertyId, PropertyValue>> VertexAccessor::Properties(View
|
|||||||
std::map<PropertyId, PropertyValue> properties;
|
std::map<PropertyId, PropertyValue> properties;
|
||||||
Delta *delta = nullptr;
|
Delta *delta = nullptr;
|
||||||
{
|
{
|
||||||
deleted = vertex_->deleted;
|
deleted = vertex_->second.deleted;
|
||||||
// TODO(antaljanosbenjamin): Should this also return the primary key?
|
// TODO(antaljanosbenjamin): Should this also return the primary key?
|
||||||
properties = vertex_->properties.Properties();
|
properties = vertex_->second.properties.Properties();
|
||||||
delta = vertex_->delta;
|
delta = vertex_->second.delta;
|
||||||
}
|
}
|
||||||
ApplyDeltasForRead(transaction_, delta, view, [&exists, &deleted, &properties](const Delta &delta) {
|
ApplyDeltasForRead(transaction_, delta, view, [&exists, &deleted, &properties](const Delta &delta) {
|
||||||
switch (delta.action) {
|
switch (delta.action) {
|
||||||
@ -501,14 +503,14 @@ ShardResult<std::vector<EdgeAccessor>> VertexAccessor::InEdges(View view, const
|
|||||||
const VertexId *destination_id) const {
|
const VertexId *destination_id) const {
|
||||||
bool exists = true;
|
bool exists = true;
|
||||||
bool deleted = false;
|
bool deleted = false;
|
||||||
std::vector<Vertex::EdgeLink> in_edges;
|
std::vector<VertexData::EdgeLink> in_edges;
|
||||||
Delta *delta = nullptr;
|
Delta *delta = nullptr;
|
||||||
{
|
{
|
||||||
deleted = vertex_->deleted;
|
deleted = vertex_->second.deleted;
|
||||||
if (edge_types.empty() && nullptr == destination_id) {
|
if (edge_types.empty() && nullptr == destination_id) {
|
||||||
in_edges = vertex_->in_edges;
|
in_edges = vertex_->second.in_edges;
|
||||||
} else {
|
} else {
|
||||||
for (const auto &item : vertex_->in_edges) {
|
for (const auto &item : vertex_->second.in_edges) {
|
||||||
const auto &[edge_type, from_vertex, edge] = item;
|
const auto &[edge_type, from_vertex, edge] = item;
|
||||||
if (nullptr != destination_id && from_vertex != *destination_id) {
|
if (nullptr != destination_id && from_vertex != *destination_id) {
|
||||||
continue;
|
continue;
|
||||||
@ -518,7 +520,7 @@ ShardResult<std::vector<EdgeAccessor>> VertexAccessor::InEdges(View view, const
|
|||||||
in_edges.push_back(item);
|
in_edges.push_back(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delta = vertex_->delta;
|
delta = vertex_->second.delta;
|
||||||
}
|
}
|
||||||
ApplyDeltasForRead(
|
ApplyDeltasForRead(
|
||||||
transaction_, delta, view, [&exists, &deleted, &in_edges, &edge_types, destination_id](const Delta &delta) {
|
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())
|
std::find(edge_types.begin(), edge_types.end(), delta.vertex_edge.edge_type) == edge_types.end())
|
||||||
break;
|
break;
|
||||||
// Add the edge because we don't see the removal.
|
// 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);
|
auto it = std::find(in_edges.begin(), in_edges.end(), link);
|
||||||
MG_ASSERT(it == in_edges.end(), "Invalid database state!");
|
MG_ASSERT(it == in_edges.end(), "Invalid database state!");
|
||||||
in_edges.push_back(link);
|
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())
|
std::find(edge_types.begin(), edge_types.end(), delta.vertex_edge.edge_type) == edge_types.end())
|
||||||
break;
|
break;
|
||||||
// Remove the label because we don't see the addition.
|
// 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);
|
auto it = std::find(in_edges.begin(), in_edges.end(), link);
|
||||||
MG_ASSERT(it != in_edges.end(), "Invalid database state!");
|
MG_ASSERT(it != in_edges.end(), "Invalid database state!");
|
||||||
std::swap(*it, *in_edges.rbegin());
|
std::swap(*it, *in_edges.rbegin());
|
||||||
@ -571,7 +573,7 @@ ShardResult<std::vector<EdgeAccessor>> VertexAccessor::InEdges(View view, const
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
ret.reserve(in_edges.size());
|
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) {
|
for (const auto &item : in_edges) {
|
||||||
const auto &[edge_type, from_vertex, edge] = item;
|
const auto &[edge_type, from_vertex, edge] = item;
|
||||||
ret.emplace_back(edge, edge_type, from_vertex, id, transaction_, indices_, config_);
|
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 {
|
const VertexId *destination_id) const {
|
||||||
bool exists = true;
|
bool exists = true;
|
||||||
bool deleted = false;
|
bool deleted = false;
|
||||||
std::vector<Vertex::EdgeLink> out_edges;
|
std::vector<VertexData::EdgeLink> out_edges;
|
||||||
Delta *delta = nullptr;
|
Delta *delta = nullptr;
|
||||||
{
|
{
|
||||||
deleted = vertex_->deleted;
|
deleted = vertex_->second.deleted;
|
||||||
if (edge_types.empty() && nullptr == destination_id) {
|
if (edge_types.empty() && nullptr == destination_id) {
|
||||||
out_edges = vertex_->out_edges;
|
out_edges = vertex_->second.out_edges;
|
||||||
} else {
|
} else {
|
||||||
for (const auto &item : vertex_->out_edges) {
|
for (const auto &item : vertex_->second.out_edges) {
|
||||||
const auto &[edge_type, to_vertex, edge] = item;
|
const auto &[edge_type, to_vertex, edge] = item;
|
||||||
if (nullptr != destination_id && to_vertex != *destination_id) continue;
|
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())
|
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);
|
out_edges.push_back(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delta = vertex_->delta;
|
delta = vertex_->second.delta;
|
||||||
}
|
}
|
||||||
ApplyDeltasForRead(
|
ApplyDeltasForRead(
|
||||||
transaction_, delta, view, [&exists, &deleted, &out_edges, &edge_types, destination_id](const Delta &delta) {
|
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())
|
std::find(edge_types.begin(), edge_types.end(), delta.vertex_edge.edge_type) == edge_types.end())
|
||||||
break;
|
break;
|
||||||
// Add the edge because we don't see the removal.
|
// 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);
|
auto it = std::find(out_edges.begin(), out_edges.end(), link);
|
||||||
MG_ASSERT(it == out_edges.end(), "Invalid database state!");
|
MG_ASSERT(it == out_edges.end(), "Invalid database state!");
|
||||||
out_edges.push_back(link);
|
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())
|
std::find(edge_types.begin(), edge_types.end(), delta.vertex_edge.edge_type) == edge_types.end())
|
||||||
break;
|
break;
|
||||||
// Remove the label because we don't see the addition.
|
// 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);
|
auto it = std::find(out_edges.begin(), out_edges.end(), link);
|
||||||
MG_ASSERT(it != out_edges.end(), "Invalid database state!");
|
MG_ASSERT(it != out_edges.end(), "Invalid database state!");
|
||||||
std::swap(*it, *out_edges.rbegin());
|
std::swap(*it, *out_edges.rbegin());
|
||||||
@ -651,7 +653,7 @@ ShardResult<std::vector<EdgeAccessor>> VertexAccessor::OutEdges(View view, const
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
ret.reserve(out_edges.size());
|
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) {
|
for (const auto &item : out_edges) {
|
||||||
const auto &[edge_type, to_vertex, edge] = item;
|
const auto &[edge_type, to_vertex, edge] = item;
|
||||||
ret.emplace_back(edge, edge_type, id, to_vertex, transaction_, indices_, config_);
|
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;
|
size_t degree = 0;
|
||||||
Delta *delta = nullptr;
|
Delta *delta = nullptr;
|
||||||
{
|
{
|
||||||
deleted = vertex_->deleted;
|
deleted = vertex_->second.deleted;
|
||||||
degree = vertex_->in_edges.size();
|
degree = vertex_->second.in_edges.size();
|
||||||
delta = vertex_->delta;
|
delta = vertex_->second.delta;
|
||||||
}
|
}
|
||||||
ApplyDeltasForRead(transaction_, delta, view, [&exists, &deleted, °ree](const Delta &delta) {
|
ApplyDeltasForRead(transaction_, delta, view, [&exists, &deleted, °ree](const Delta &delta) {
|
||||||
switch (delta.action) {
|
switch (delta.action) {
|
||||||
@ -702,9 +704,9 @@ ShardResult<size_t> VertexAccessor::OutDegree(View view) const {
|
|||||||
size_t degree = 0;
|
size_t degree = 0;
|
||||||
Delta *delta = nullptr;
|
Delta *delta = nullptr;
|
||||||
{
|
{
|
||||||
deleted = vertex_->deleted;
|
deleted = vertex_->second.deleted;
|
||||||
degree = vertex_->out_edges.size();
|
degree = vertex_->second.out_edges.size();
|
||||||
delta = vertex_->delta;
|
delta = vertex_->second.delta;
|
||||||
}
|
}
|
||||||
ApplyDeltasForRead(transaction_, delta, view, [&exists, &deleted, °ree](const Delta &delta) {
|
ApplyDeltasForRead(transaction_, delta, view, [&exists, &deleted, °ree](const Delta &delta) {
|
||||||
switch (delta.action) {
|
switch (delta.action) {
|
||||||
|
Loading…
Reference in New Issue
Block a user