Replace skiplist with std::set
This commit is contained in:
parent
7d52eedb21
commit
976e6ff0a6
@ -9,8 +9,6 @@ set(storage_v3_src_files
|
|||||||
temporal.cpp
|
temporal.cpp
|
||||||
edge_accessor.cpp
|
edge_accessor.cpp
|
||||||
indices.cpp
|
indices.cpp
|
||||||
key_store.cpp
|
|
||||||
lexicographically_ordered_vertex.cpp
|
|
||||||
property_store.cpp
|
property_store.cpp
|
||||||
vertex_accessor.cpp
|
vertex_accessor.cpp
|
||||||
schemas.cpp
|
schemas.cpp
|
||||||
|
@ -17,6 +17,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/vertices_container.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"
|
||||||
@ -269,7 +270,7 @@ void LabelIndex::UpdateOnAddLabel(LabelId label, Vertex *vertex, const Transacti
|
|||||||
acc.insert(Entry{vertex, tx.start_timestamp.logical_id});
|
acc.insert(Entry{vertex, tx.start_timestamp.logical_id});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LabelIndex::CreateIndex(LabelId label, VerticesSkipList::Accessor vertices) {
|
bool LabelIndex::CreateIndex(LabelId label, VertexContainer vertices) {
|
||||||
utils::MemoryTracker::OutOfMemoryExceptionEnabler oom_exception;
|
utils::MemoryTracker::OutOfMemoryExceptionEnabler oom_exception;
|
||||||
auto [it, emplaced] = index_.emplace(std::piecewise_construct, std::forward_as_tuple(label), std::forward_as_tuple());
|
auto [it, emplaced] = index_.emplace(std::piecewise_construct, std::forward_as_tuple(label), std::forward_as_tuple());
|
||||||
if (!emplaced) {
|
if (!emplaced) {
|
||||||
@ -278,8 +279,7 @@ bool LabelIndex::CreateIndex(LabelId label, VerticesSkipList::Accessor vertices)
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
auto acc = it->second.access();
|
auto acc = it->second.access();
|
||||||
for (auto &lgo_vertex : vertices) {
|
for ([[maybe_unused]] auto &[pk, vertex] : vertices) {
|
||||||
auto &vertex = lgo_vertex.vertex;
|
|
||||||
if (vertex.deleted || !utils::Contains(vertex.labels, label)) {
|
if (vertex.deleted || !utils::Contains(vertex.labels, label)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -416,7 +416,7 @@ void LabelPropertyIndex::UpdateOnSetProperty(PropertyId property, const Property
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LabelPropertyIndex::CreateIndex(LabelId label, PropertyId property, VerticesSkipList::Accessor vertices) {
|
bool LabelPropertyIndex::CreateIndex(LabelId label, PropertyId property, VertexContainer vertices) {
|
||||||
utils::MemoryTracker::OutOfMemoryExceptionEnabler oom_exception;
|
utils::MemoryTracker::OutOfMemoryExceptionEnabler oom_exception;
|
||||||
auto [it, emplaced] =
|
auto [it, emplaced] =
|
||||||
index_.emplace(std::piecewise_construct, std::forward_as_tuple(label, property), std::forward_as_tuple());
|
index_.emplace(std::piecewise_construct, std::forward_as_tuple(label, property), std::forward_as_tuple());
|
||||||
@ -426,8 +426,7 @@ bool LabelPropertyIndex::CreateIndex(LabelId label, PropertyId property, Vertice
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
auto acc = it->second.access();
|
auto acc = it->second.access();
|
||||||
for (auto &lgo_vertex : vertices) {
|
for ([[maybe_unused]] auto &[pk, vertex] : vertices) {
|
||||||
auto &vertex = lgo_vertex.vertex;
|
|
||||||
if (vertex.deleted || !utils::Contains(vertex.labels, label)) {
|
if (vertex.deleted || !utils::Contains(vertex.labels, label)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
#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"
|
||||||
#include "storage/v3/vertices_skip_list.hpp"
|
#include "storage/v3/vertices_container.hpp"
|
||||||
#include "utils/bound.hpp"
|
#include "utils/bound.hpp"
|
||||||
#include "utils/logging.hpp"
|
#include "utils/logging.hpp"
|
||||||
#include "utils/skip_list.hpp"
|
#include "utils/skip_list.hpp"
|
||||||
@ -59,7 +59,7 @@ class LabelIndex {
|
|||||||
void UpdateOnAddLabel(LabelId label, Vertex *vertex, const Transaction &tx);
|
void UpdateOnAddLabel(LabelId label, Vertex *vertex, const Transaction &tx);
|
||||||
|
|
||||||
/// @throw std::bad_alloc
|
/// @throw std::bad_alloc
|
||||||
bool CreateIndex(LabelId label, VerticesSkipList::Accessor vertices);
|
bool CreateIndex(LabelId label, VertexContainer vertices);
|
||||||
|
|
||||||
/// Returns false if there was no index to drop
|
/// Returns false if there was no index to drop
|
||||||
bool DropIndex(LabelId label) { return index_.erase(label) > 0; }
|
bool DropIndex(LabelId label) { return index_.erase(label) > 0; }
|
||||||
@ -157,7 +157,7 @@ class LabelPropertyIndex {
|
|||||||
void UpdateOnSetProperty(PropertyId property, const PropertyValue &value, Vertex *vertex, const Transaction &tx);
|
void UpdateOnSetProperty(PropertyId property, const PropertyValue &value, Vertex *vertex, const Transaction &tx);
|
||||||
|
|
||||||
/// @throw std::bad_alloc
|
/// @throw std::bad_alloc
|
||||||
bool CreateIndex(LabelId label, PropertyId property, VerticesSkipList::Accessor vertices);
|
bool CreateIndex(LabelId label, PropertyId property, VertexContainer vertices);
|
||||||
|
|
||||||
bool DropIndex(LabelId label, PropertyId property) { return index_.erase({label, property}) > 0; }
|
bool DropIndex(LabelId label, PropertyId property) { return index_.erase({label, property}) > 0; }
|
||||||
|
|
||||||
|
@ -1,43 +0,0 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
|
||||||
//
|
|
||||||
// Use of this software is governed by the Business Source License
|
|
||||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
|
||||||
// License, and you may not use this file except in compliance with the Business Source License.
|
|
||||||
//
|
|
||||||
// As of the Change Date specified in that file, in accordance with
|
|
||||||
// the Business Source License, use of this software will be governed
|
|
||||||
// by the Apache License, Version 2.0, included in the file
|
|
||||||
// licenses/APL.txt.
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <iterator>
|
|
||||||
#include <ranges>
|
|
||||||
|
|
||||||
#include "storage/v3/id_types.hpp"
|
|
||||||
#include "storage/v3/key_store.hpp"
|
|
||||||
#include "storage/v3/property_value.hpp"
|
|
||||||
|
|
||||||
namespace memgraph::storage::v3 {
|
|
||||||
|
|
||||||
KeyStore::KeyStore(const PrimaryKey &key_values) {
|
|
||||||
for (auto i = 0; i < key_values.size(); ++i) {
|
|
||||||
MG_ASSERT(!key_values[i].IsNull());
|
|
||||||
store_.SetProperty(PropertyId::FromInt(i), key_values[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PropertyValue KeyStore::GetKey(const size_t index) const { return store_.GetProperty(PropertyId::FromUint(index)); }
|
|
||||||
|
|
||||||
PropertyValue KeyStore::GetKey(const PropertyId property_id) const { return store_.GetProperty(property_id); }
|
|
||||||
|
|
||||||
PrimaryKey KeyStore::Keys() const {
|
|
||||||
auto keys_map = store_.Properties();
|
|
||||||
PrimaryKey keys;
|
|
||||||
keys.reserve(keys_map.size());
|
|
||||||
std::ranges::transform(
|
|
||||||
keys_map, std::back_inserter(keys),
|
|
||||||
[](std::pair<const PropertyId, PropertyValue> &id_and_value) { return std::move(id_and_value.second); });
|
|
||||||
return keys;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace memgraph::storage::v3
|
|
@ -11,12 +11,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <compare>
|
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
#include "storage/v3/id_types.hpp"
|
|
||||||
#include "storage/v3/property_store.hpp"
|
|
||||||
#include "storage/v3/property_value.hpp"
|
#include "storage/v3/property_value.hpp"
|
||||||
|
|
||||||
namespace memgraph::storage::v3 {
|
namespace memgraph::storage::v3 {
|
||||||
@ -24,39 +18,4 @@ namespace memgraph::storage::v3 {
|
|||||||
// Primary key is a collection of primary properties.
|
// Primary key is a collection of primary properties.
|
||||||
using PrimaryKey = std::vector<PropertyValue>;
|
using PrimaryKey = std::vector<PropertyValue>;
|
||||||
|
|
||||||
class KeyStore {
|
|
||||||
public:
|
|
||||||
explicit KeyStore(const PrimaryKey &key_values);
|
|
||||||
|
|
||||||
KeyStore(const KeyStore &) = delete;
|
|
||||||
KeyStore(KeyStore &&other) noexcept = default;
|
|
||||||
KeyStore &operator=(const KeyStore &) = delete;
|
|
||||||
KeyStore &operator=(KeyStore &&other) noexcept = default;
|
|
||||||
|
|
||||||
~KeyStore() = default;
|
|
||||||
|
|
||||||
PropertyValue GetKey(size_t index) const;
|
|
||||||
|
|
||||||
PropertyValue GetKey(PropertyId property) const;
|
|
||||||
|
|
||||||
PrimaryKey Keys() const;
|
|
||||||
|
|
||||||
friend bool operator<(const KeyStore &lhs, const KeyStore &rhs) {
|
|
||||||
return std::ranges::lexicographical_compare(lhs.Keys(), rhs.Keys(), std::less<PropertyValue>{});
|
|
||||||
}
|
|
||||||
|
|
||||||
friend bool operator==(const KeyStore &lhs, const KeyStore &rhs) {
|
|
||||||
return std::ranges::equal(lhs.Keys(), rhs.Keys());
|
|
||||||
}
|
|
||||||
|
|
||||||
friend bool operator<(const KeyStore &lhs, const PrimaryKey &rhs) {
|
|
||||||
return std::ranges::lexicographical_compare(lhs.Keys(), rhs, std::less<PropertyValue>{});
|
|
||||||
}
|
|
||||||
|
|
||||||
friend bool operator==(const KeyStore &lhs, const PrimaryKey &rhs) { return std::ranges::equal(lhs.Keys(), rhs); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
PropertyStore store_;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace memgraph::storage::v3
|
} // namespace memgraph::storage::v3
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
|
||||||
//
|
|
||||||
// Use of this software is governed by the Business Source License
|
|
||||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
|
||||||
// License, and you may not use this file except in compliance with the Business Source License.
|
|
||||||
//
|
|
||||||
// As of the Change Date specified in that file, in accordance with
|
|
||||||
// the Business Source License, use of this software will be governed
|
|
||||||
// by the Apache License, Version 2.0, included in the file
|
|
||||||
// licenses/APL.txt.
|
|
||||||
|
|
||||||
#include "storage/v3/lexicographically_ordered_vertex.hpp"
|
|
||||||
|
|
||||||
namespace memgraph::storage::v3 {} // namespace memgraph::storage::v3
|
|
@ -1,42 +0,0 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
|
||||||
//
|
|
||||||
// Use of this software is governed by the Business Source License
|
|
||||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
|
||||||
// License, and you may not use this file except in compliance with the Business Source License.
|
|
||||||
//
|
|
||||||
// As of the Change Date specified in that file, in accordance with
|
|
||||||
// the Business Source License, use of this software will be governed
|
|
||||||
// by the Apache License, Version 2.0, included in the file
|
|
||||||
// licenses/APL.txt.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <concepts>
|
|
||||||
#include <type_traits>
|
|
||||||
|
|
||||||
#include "storage/v3/vertex.hpp"
|
|
||||||
#include "utils/concepts.hpp"
|
|
||||||
|
|
||||||
namespace memgraph::storage::v3 {
|
|
||||||
|
|
||||||
struct LexicographicallyOrderedVertex {
|
|
||||||
Vertex vertex;
|
|
||||||
|
|
||||||
friend bool operator==(const LexicographicallyOrderedVertex &lhs, const LexicographicallyOrderedVertex &rhs) {
|
|
||||||
return lhs.vertex.keys == rhs.vertex.keys;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend bool operator<(const LexicographicallyOrderedVertex &lhs, const LexicographicallyOrderedVertex &rhs) {
|
|
||||||
return lhs.vertex.keys < rhs.vertex.keys;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(antaljanosbenjamin): maybe it worth to overload this for std::array to avoid heap construction of the vector
|
|
||||||
friend bool operator==(const LexicographicallyOrderedVertex &lhs, const std::vector<PropertyValue> &rhs) {
|
|
||||||
return lhs.vertex.keys == rhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend bool operator<(const LexicographicallyOrderedVertex &lhs, const std::vector<PropertyValue> &rhs) {
|
|
||||||
return lhs.vertex.keys < rhs;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // namespace memgraph::storage::v3
|
|
@ -928,11 +928,22 @@ void SetSizeData(uint8_t *buffer, uint64_t size, uint8_t *data) {
|
|||||||
|
|
||||||
PropertyStore::PropertyStore() { memset(buffer_, 0, sizeof(buffer_)); }
|
PropertyStore::PropertyStore() { memset(buffer_, 0, sizeof(buffer_)); }
|
||||||
|
|
||||||
|
// PropertyStore::PropertyStore(const PropertyStore &other) { memcpy(buffer_, other.buffer_, sizeof(buffer_)); }
|
||||||
|
|
||||||
PropertyStore::PropertyStore(PropertyStore &&other) noexcept {
|
PropertyStore::PropertyStore(PropertyStore &&other) noexcept {
|
||||||
memcpy(buffer_, other.buffer_, sizeof(buffer_));
|
memcpy(buffer_, other.buffer_, sizeof(buffer_));
|
||||||
memset(other.buffer_, 0, sizeof(other.buffer_));
|
memset(other.buffer_, 0, sizeof(other.buffer_));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PropertyStore &PropertyStore::operator=(const PropertyStore &other) {
|
||||||
|
// if (buffer_ == other.buffer_) [[unlikely]] {
|
||||||
|
// return *this;
|
||||||
|
// }
|
||||||
|
// memcpy(buffer_, other.buffer_, sizeof(buffer_));
|
||||||
|
|
||||||
|
// return *this;
|
||||||
|
// }
|
||||||
|
|
||||||
PropertyStore &PropertyStore::operator=(PropertyStore &&other) noexcept {
|
PropertyStore &PropertyStore::operator=(PropertyStore &&other) noexcept {
|
||||||
uint64_t size{0};
|
uint64_t size{0};
|
||||||
uint8_t *data{nullptr};
|
uint8_t *data{nullptr};
|
||||||
|
@ -38,7 +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/vertices_skip_list.hpp"
|
#include "storage/v3/vertices_container.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"
|
||||||
@ -75,11 +75,11 @@ uint64_t GetCleanupBeforeTimestamp(const std::map<uint64_t, std::unique_ptr<Tran
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
auto AdvanceToVisibleVertex(VerticesSkipList::Iterator it, VerticesSkipList::Iterator end,
|
auto AdvanceToVisibleVertex(VertexContainer::iterator it, VertexContainer::iterator end,
|
||||||
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->vertex, tx, indices, config, vertex_validator, view);
|
*vertex = VertexAccessor::Create(&it->second, tx, indices, config, vertex_validator, view);
|
||||||
if (!*vertex) {
|
if (!*vertex) {
|
||||||
++it;
|
++it;
|
||||||
continue;
|
continue;
|
||||||
@ -89,7 +89,7 @@ auto AdvanceToVisibleVertex(VerticesSkipList::Iterator it, VerticesSkipList::Ite
|
|||||||
return it;
|
return it;
|
||||||
}
|
}
|
||||||
|
|
||||||
AllVerticesIterable::Iterator::Iterator(AllVerticesIterable *self, VerticesSkipList::Iterator it)
|
AllVerticesIterable::Iterator::Iterator(AllVerticesIterable *self, VertexContainer::iterator it)
|
||||||
: self_(self),
|
: self_(self),
|
||||||
it_(AdvanceToVisibleVertex(it, self->vertices_accessor_.end(), &self->vertex_, self->transaction_, self->view_,
|
it_(AdvanceToVisibleVertex(it, self->vertices_accessor_.end(), &self->vertex_, self->transaction_, self->view_,
|
||||||
self->indices_, self->config_, *self_->vertex_validator_)) {}
|
self->indices_, self->config_, *self_->vertex_validator_)) {}
|
||||||
@ -357,16 +357,15 @@ ShardResult<VertexAccessor> Shard::Accessor::CreateVertexAndValidate(
|
|||||||
return {std::move(maybe_schema_violation.GetError())};
|
return {std::move(maybe_schema_violation.GetError())};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto acc = shard_->vertices_.access();
|
|
||||||
auto *delta = CreateDeleteObjectDelta(transaction_);
|
auto *delta = CreateDeleteObjectDelta(transaction_);
|
||||||
auto [it, inserted] = acc.insert({Vertex{delta, primary_properties}});
|
auto [it, inserted] = shard_->vertices_.emplace(primary_properties, Vertex(delta, primary_properties));
|
||||||
delta->prev.Set(&it->vertex);
|
delta->prev.Set(&it->second);
|
||||||
|
|
||||||
VertexAccessor vertex_acc{&it->vertex, transaction_, &shard_->indices_, config_, shard_->vertex_validator_};
|
VertexAccessor vertex_acc{&it->second, 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);
|
||||||
}
|
}
|
||||||
MG_ASSERT(it != acc.end(), "Invalid Vertex accessor!");
|
MG_ASSERT(it != shard_->vertices_.end(), "Invalid Vertex accessor!");
|
||||||
|
|
||||||
// TODO(jbajic) Improve, maybe delay index update
|
// TODO(jbajic) Improve, maybe delay index update
|
||||||
for (const auto &[property_id, property_value] : properties) {
|
for (const auto &[property_id, property_value] : properties) {
|
||||||
@ -386,13 +385,11 @@ ShardResult<VertexAccessor> Shard::Accessor::CreateVertexAndValidate(
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::optional<VertexAccessor> Shard::Accessor::FindVertex(std::vector<PropertyValue> primary_key, View view) {
|
std::optional<VertexAccessor> Shard::Accessor::FindVertex(std::vector<PropertyValue> primary_key, View view) {
|
||||||
auto acc = shard_->vertices_.access();
|
auto it = shard_->vertices_.find(primary_key);
|
||||||
// Later on use label space
|
if (it == shard_->vertices_.end()) {
|
||||||
auto it = acc.find(primary_key);
|
|
||||||
if (it == acc.end()) {
|
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
return VertexAccessor::Create(&it->vertex, transaction_, &shard_->indices_, config_, shard_->vertex_validator_, view);
|
return VertexAccessor::Create(&it->second, 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) {
|
||||||
@ -438,7 +435,7 @@ ShardResult<std::optional<std::pair<VertexAccessor, std::vector<EdgeAccessor>>>>
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<EdgeAccessor> deleted_edges;
|
std::vector<EdgeAccessor> deleted_edges;
|
||||||
const VertexId vertex_id{shard_->primary_label_, vertex_ptr->keys.Keys()};
|
const VertexId vertex_id{shard_->primary_label_, vertex_ptr->keys};
|
||||||
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_);
|
||||||
@ -488,22 +485,22 @@ ShardResult<EdgeAccessor> Shard::Accessor::CreateEdge(VertexId from_vertex_id, V
|
|||||||
Vertex *from_vertex{nullptr};
|
Vertex *from_vertex{nullptr};
|
||||||
Vertex *to_vertex{nullptr};
|
Vertex *to_vertex{nullptr};
|
||||||
|
|
||||||
auto acc = shard_->vertices_.access();
|
auto &vertices = shard_->vertices_;
|
||||||
|
|
||||||
const auto from_is_local = shard_->IsVertexBelongToShard(from_vertex_id);
|
const auto from_is_local = shard_->IsVertexBelongToShard(from_vertex_id);
|
||||||
const auto to_is_local = shard_->IsVertexBelongToShard(to_vertex_id);
|
const auto to_is_local = shard_->IsVertexBelongToShard(to_vertex_id);
|
||||||
MG_ASSERT(from_is_local || to_is_local, "Trying to create an edge without having a local vertex");
|
MG_ASSERT(from_is_local || to_is_local, "Trying to create an edge without having a local vertex");
|
||||||
|
|
||||||
if (from_is_local) {
|
if (from_is_local) {
|
||||||
auto it = acc.find(from_vertex_id.primary_key);
|
auto it = vertices.find(from_vertex_id.primary_key);
|
||||||
MG_ASSERT(it != acc.end(), "Cannot find local vertex");
|
MG_ASSERT(it != vertices.end(), "Cannot find local vertex");
|
||||||
from_vertex = &it->vertex;
|
from_vertex = &it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (to_is_local) {
|
if (to_is_local) {
|
||||||
auto it = acc.find(to_vertex_id.primary_key);
|
auto it = vertices.find(to_vertex_id.primary_key);
|
||||||
MG_ASSERT(it != acc.end(), "Cannot find local vertex");
|
MG_ASSERT(it != vertices.end(), "Cannot find local vertex");
|
||||||
to_vertex = &it->vertex;
|
to_vertex = &it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (from_is_local) {
|
if (from_is_local) {
|
||||||
@ -546,21 +543,21 @@ ShardResult<std::optional<EdgeAccessor>> Shard::Accessor::DeleteEdge(VertexId fr
|
|||||||
Vertex *from_vertex{nullptr};
|
Vertex *from_vertex{nullptr};
|
||||||
Vertex *to_vertex{nullptr};
|
Vertex *to_vertex{nullptr};
|
||||||
|
|
||||||
auto acc = shard_->vertices_.access();
|
auto &vertices = shard_->vertices_;
|
||||||
|
|
||||||
const auto from_is_local = shard_->IsVertexBelongToShard(from_vertex_id);
|
const auto from_is_local = shard_->IsVertexBelongToShard(from_vertex_id);
|
||||||
const auto to_is_local = shard_->IsVertexBelongToShard(to_vertex_id);
|
const auto to_is_local = shard_->IsVertexBelongToShard(to_vertex_id);
|
||||||
|
|
||||||
if (from_is_local) {
|
if (from_is_local) {
|
||||||
auto it = acc.find(from_vertex_id.primary_key);
|
auto it = vertices.find(from_vertex_id.primary_key);
|
||||||
MG_ASSERT(it != acc.end(), "Cannot find local vertex");
|
MG_ASSERT(it != vertices.end(), "Cannot find local vertex");
|
||||||
from_vertex = &it->vertex;
|
from_vertex = &it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (to_is_local) {
|
if (to_is_local) {
|
||||||
auto it = acc.find(to_vertex_id.primary_key);
|
auto it = vertices.find(to_vertex_id.primary_key);
|
||||||
MG_ASSERT(it != acc.end(), "Cannot find local vertex");
|
MG_ASSERT(it != vertices.end(), "Cannot find local vertex");
|
||||||
to_vertex = &it->vertex;
|
to_vertex = &it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
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");
|
||||||
@ -762,7 +759,7 @@ void Shard::Accessor::Abort() {
|
|||||||
}
|
}
|
||||||
case Delta::Action::DELETE_OBJECT: {
|
case Delta::Action::DELETE_OBJECT: {
|
||||||
vertex->deleted = true;
|
vertex->deleted = true;
|
||||||
shard_->deleted_vertices_.push_back(vertex->keys.Keys());
|
shard_->deleted_vertices_.push_back(vertex->keys);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Delta::Action::RECREATE_OBJECT: {
|
case Delta::Action::RECREATE_OBJECT: {
|
||||||
@ -851,10 +848,7 @@ const std::string &Shard::EdgeTypeToName(EdgeTypeId edge_type) const {
|
|||||||
|
|
||||||
bool Shard::CreateIndex(LabelId label, const std::optional<uint64_t> /*desired_commit_timestamp*/) {
|
bool Shard::CreateIndex(LabelId label, const std::optional<uint64_t> /*desired_commit_timestamp*/) {
|
||||||
// TODO(jbajic) response should be different when label == primary_label
|
// TODO(jbajic) response should be different when label == primary_label
|
||||||
if (label == primary_label_ || !indices_.label_index.CreateIndex(label, vertices_.access())) {
|
return !(label == primary_label_ || !indices_.label_index.CreateIndex(label, vertices_));
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Shard::CreateIndex(LabelId label, PropertyId property,
|
bool Shard::CreateIndex(LabelId label, PropertyId property,
|
||||||
@ -865,7 +859,7 @@ bool Shard::CreateIndex(LabelId label, PropertyId property,
|
|||||||
// Index already exists on primary key
|
// Index already exists on primary key
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!indices_.label_property_index.CreateIndex(label, property, vertices_.access())) {
|
if (!indices_.label_property_index.CreateIndex(label, property, vertices_)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -975,7 +969,7 @@ void Shard::CollectGarbage(const io::Time current_time) {
|
|||||||
Vertex *vertex = prev.vertex;
|
Vertex *vertex = prev.vertex;
|
||||||
vertex->delta = nullptr;
|
vertex->delta = nullptr;
|
||||||
if (vertex->deleted) {
|
if (vertex->deleted) {
|
||||||
deleted_vertices_.push_back(vertex->keys.Keys());
|
deleted_vertices_.push_back(vertex->keys);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1022,9 +1016,8 @@ void Shard::CollectGarbage(const io::Time current_time) {
|
|||||||
RemoveObsoleteEntries(&indices_, clean_up_before_timestamp);
|
RemoveObsoleteEntries(&indices_, clean_up_before_timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto vertex_acc = vertices_.access();
|
|
||||||
for (const auto &vertex : deleted_vertices_) {
|
for (const auto &vertex : deleted_vertices_) {
|
||||||
MG_ASSERT(vertex_acc.remove(vertex), "Invalid database state!");
|
MG_ASSERT(vertices_.erase(vertex), "Invalid database state!");
|
||||||
}
|
}
|
||||||
deleted_vertices_.clear();
|
deleted_vertices_.clear();
|
||||||
{
|
{
|
||||||
|
@ -31,7 +31,6 @@
|
|||||||
#include "storage/v3/indices.hpp"
|
#include "storage/v3/indices.hpp"
|
||||||
#include "storage/v3/isolation_level.hpp"
|
#include "storage/v3/isolation_level.hpp"
|
||||||
#include "storage/v3/key_store.hpp"
|
#include "storage/v3/key_store.hpp"
|
||||||
#include "storage/v3/lexicographically_ordered_vertex.hpp"
|
|
||||||
#include "storage/v3/mvcc.hpp"
|
#include "storage/v3/mvcc.hpp"
|
||||||
#include "storage/v3/name_id_mapper.hpp"
|
#include "storage/v3/name_id_mapper.hpp"
|
||||||
#include "storage/v3/property_value.hpp"
|
#include "storage/v3/property_value.hpp"
|
||||||
@ -42,7 +41,7 @@
|
|||||||
#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/vertex_id.hpp"
|
#include "storage/v3/vertex_id.hpp"
|
||||||
#include "storage/v3/vertices_skip_list.hpp"
|
#include "storage/v3/vertices_container.hpp"
|
||||||
#include "storage/v3/view.hpp"
|
#include "storage/v3/view.hpp"
|
||||||
#include "utils/exceptions.hpp"
|
#include "utils/exceptions.hpp"
|
||||||
#include "utils/file_locker.hpp"
|
#include "utils/file_locker.hpp"
|
||||||
@ -65,7 +64,7 @@ namespace memgraph::storage::v3 {
|
|||||||
/// An instance of this will be usually be wrapped inside VerticesIterable for
|
/// An instance of this will be usually be wrapped inside VerticesIterable for
|
||||||
/// generic, public use.
|
/// generic, public use.
|
||||||
class AllVerticesIterable final {
|
class AllVerticesIterable final {
|
||||||
VerticesSkipList::Accessor vertices_accessor_;
|
VertexContainer vertices_accessor_;
|
||||||
Transaction *transaction_;
|
Transaction *transaction_;
|
||||||
View view_;
|
View view_;
|
||||||
Indices *indices_;
|
Indices *indices_;
|
||||||
@ -76,10 +75,10 @@ class AllVerticesIterable final {
|
|||||||
public:
|
public:
|
||||||
class Iterator final {
|
class Iterator final {
|
||||||
AllVerticesIterable *self_;
|
AllVerticesIterable *self_;
|
||||||
VerticesSkipList::Iterator it_;
|
VertexContainer::iterator it_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Iterator(AllVerticesIterable *self, VerticesSkipList::Iterator it);
|
Iterator(AllVerticesIterable *self, VertexContainer::iterator it);
|
||||||
|
|
||||||
VertexAccessor operator*() const;
|
VertexAccessor operator*() const;
|
||||||
|
|
||||||
@ -90,8 +89,8 @@ class AllVerticesIterable final {
|
|||||||
bool operator!=(const Iterator &other) const { return !(*this == other); }
|
bool operator!=(const Iterator &other) const { return !(*this == other); }
|
||||||
};
|
};
|
||||||
|
|
||||||
AllVerticesIterable(VerticesSkipList::Accessor vertices_accessor, Transaction *transaction, View view,
|
AllVerticesIterable(VertexContainer vertices_accessor, Transaction *transaction, View view, Indices *indices,
|
||||||
Indices *indices, Config::Items config, const VertexValidator &vertex_validator)
|
Config::Items config, const VertexValidator &vertex_validator)
|
||||||
: vertices_accessor_(std::move(vertices_accessor)),
|
: vertices_accessor_(std::move(vertices_accessor)),
|
||||||
transaction_(transaction),
|
transaction_(transaction),
|
||||||
view_(view),
|
view_(view),
|
||||||
@ -213,7 +212,7 @@ class Shard final {
|
|||||||
std::optional<VertexAccessor> FindVertex(std::vector<PropertyValue> primary_key, View view);
|
std::optional<VertexAccessor> FindVertex(std::vector<PropertyValue> primary_key, View view);
|
||||||
|
|
||||||
VerticesIterable Vertices(View view) {
|
VerticesIterable Vertices(View view) {
|
||||||
return VerticesIterable(AllVerticesIterable(shard_->vertices_.access(), transaction_, view, &shard_->indices_,
|
return VerticesIterable(AllVerticesIterable(shard_->vertices_, transaction_, view, &shard_->indices_,
|
||||||
shard_->config_.items, shard_->vertex_validator_));
|
shard_->config_.items, shard_->vertex_validator_));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -377,7 +376,7 @@ class Shard final {
|
|||||||
// The shard's range is [min, max)
|
// The shard's range is [min, max)
|
||||||
PrimaryKey min_primary_key_;
|
PrimaryKey min_primary_key_;
|
||||||
std::optional<PrimaryKey> max_primary_key_;
|
std::optional<PrimaryKey> max_primary_key_;
|
||||||
VerticesSkipList vertices_;
|
VertexContainer vertices_;
|
||||||
utils::SkipList<Edge> edges_;
|
utils::SkipList<Edge> edges_;
|
||||||
// Even though the edge count is already kept in the `edges_` SkipList, the
|
// Even though the edge count is already kept in the `edges_` SkipList, the
|
||||||
// list is used only when properties are enabled for edges. Because of that we
|
// list is used only when properties are enabled for edges. Because of that we
|
||||||
|
@ -31,14 +31,14 @@ namespace memgraph::storage::v3 {
|
|||||||
struct Vertex {
|
struct Vertex {
|
||||||
using EdgeLink = std::tuple<EdgeTypeId, VertexId, EdgeRef>;
|
using EdgeLink = std::tuple<EdgeTypeId, VertexId, EdgeRef>;
|
||||||
|
|
||||||
Vertex(Delta *delta, const std::vector<PropertyValue> &primary_properties) : keys{primary_properties}, delta{delta} {
|
Vertex(Delta *delta, PrimaryKey primary_properties) : keys{std::move(primary_properties)}, delta{delta} {
|
||||||
MG_ASSERT(delta == nullptr || delta->action == Delta::Action::DELETE_OBJECT,
|
MG_ASSERT(delta == nullptr || delta->action == Delta::Action::DELETE_OBJECT,
|
||||||
"Vertex must be created with an initial DELETE_OBJECT delta!");
|
"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; }
|
friend bool operator==(const Vertex &vertex, const PrimaryKey &primary_key) { return vertex.keys == primary_key; }
|
||||||
|
|
||||||
KeyStore keys;
|
PrimaryKey keys;
|
||||||
|
|
||||||
std::vector<LabelId> labels;
|
std::vector<LabelId> labels;
|
||||||
PropertyStore properties;
|
PropertyStore properties;
|
||||||
|
@ -215,14 +215,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.Keys();
|
return vertex_->keys;
|
||||||
}
|
}
|
||||||
|
|
||||||
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.Keys()};
|
return VertexId{vertex_validator_->primary_label_, vertex_->keys};
|
||||||
};
|
};
|
||||||
|
|
||||||
ShardResult<std::vector<LabelId>> VertexAccessor::Labels(View view) const {
|
ShardResult<std::vector<LabelId>> VertexAccessor::Labels(View view) const {
|
||||||
@ -401,7 +401,7 @@ PropertyValue VertexAccessor::GetPropertyValue(PropertyId property, View view) c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
value = vertex_->keys.GetKey(property_index);
|
value = vertex_->keys[property_index];
|
||||||
if (value.IsNull()) {
|
if (value.IsNull()) {
|
||||||
value = vertex_->properties.GetProperty(property);
|
value = vertex_->properties.GetProperty(property);
|
||||||
}
|
}
|
||||||
@ -572,7 +572,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.Keys()};
|
const auto id = VertexId{vertex_validator_->primary_label_, vertex_->keys};
|
||||||
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_);
|
||||||
@ -652,7 +652,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.Keys()};
|
const auto id = VertexId{vertex_validator_->primary_label_, vertex_->keys};
|
||||||
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_);
|
||||||
|
@ -11,9 +11,11 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "storage/v3/lexicographically_ordered_vertex.hpp"
|
#include <map>
|
||||||
#include "utils/skip_list.hpp"
|
|
||||||
|
#include "storage/v3/key_store.hpp"
|
||||||
|
#include "storage/v3/vertex.hpp"
|
||||||
|
|
||||||
namespace memgraph::storage::v3 {
|
namespace memgraph::storage::v3 {
|
||||||
using VerticesSkipList = utils::SkipList<LexicographicallyOrderedVertex>;
|
using VertexContainer = std::map<PrimaryKey, Vertex>;
|
||||||
} // namespace memgraph::storage::v3
|
} // namespace memgraph::storage::v3
|
Loading…
Reference in New Issue
Block a user