diff --git a/src/storage/v3/CMakeLists.txt b/src/storage/v3/CMakeLists.txt index 2b3a7c861..b3a3d68a9 100644 --- a/src/storage/v3/CMakeLists.txt +++ b/src/storage/v3/CMakeLists.txt @@ -9,8 +9,6 @@ set(storage_v3_src_files temporal.cpp edge_accessor.cpp indices.cpp - key_store.cpp - lexicographically_ordered_vertex.cpp property_store.cpp vertex_accessor.cpp schemas.cpp @@ -19,6 +17,7 @@ set(storage_v3_src_files shard_rsm.cpp bindings/typed_value.cpp expr.cpp + vertex.cpp request_helper.cpp) # ###################### diff --git a/src/storage/v3/delta.hpp b/src/storage/v3/delta.hpp index 9548be146..0bc58f5ef 100644 --- a/src/storage/v3/delta.hpp +++ b/src/storage/v3/delta.hpp @@ -11,17 +11,18 @@ #pragma once +#include <cstdint> #include <memory> #include "storage/v3/edge_ref.hpp" #include "storage/v3/id_types.hpp" #include "storage/v3/property_value.hpp" +#include "storage/v3/vertex.hpp" #include "storage/v3/vertex_id.hpp" #include "utils/logging.hpp" namespace memgraph::storage::v3 { // Forward declarations because we only store pointers here. -struct Vertex; struct Edge; struct Delta; struct CommitInfo; @@ -129,7 +130,7 @@ inline bool operator==(const PreviousPtr::Pointer &a, const PreviousPtr::Pointer inline bool operator!=(const PreviousPtr::Pointer &a, const PreviousPtr::Pointer &b) { return !(a == b); } struct Delta { - enum class Action { + enum class Action : uint8_t { // Used for both Vertex and Edge DELETE_OBJECT, RECREATE_OBJECT, diff --git a/src/storage/v3/edge.hpp b/src/storage/v3/edge.hpp index df47b8416..db2964b68 100644 --- a/src/storage/v3/edge.hpp +++ b/src/storage/v3/edge.hpp @@ -21,7 +21,7 @@ namespace memgraph::storage::v3 { -struct Vertex; +using EdgeContainer = std::map<Gid, Edge>; struct Edge { Edge(Gid gid, Delta *delta) : gid(gid), deleted(false), delta(delta) { diff --git a/src/storage/v3/edge_accessor.hpp b/src/storage/v3/edge_accessor.hpp index bc143c1e3..b57beeb96 100644 --- a/src/storage/v3/edge_accessor.hpp +++ b/src/storage/v3/edge_accessor.hpp @@ -25,7 +25,6 @@ namespace memgraph::storage::v3 { -struct Vertex; class VertexAccessor; struct Indices; diff --git a/src/storage/v3/indices.cpp b/src/storage/v3/indices.cpp index b6a01b81a..2f11a35ec 100644 --- a/src/storage/v3/indices.cpp +++ b/src/storage/v3/indices.cpp @@ -11,12 +11,16 @@ #include "indices.hpp" +#include <algorithm> +#include <functional> #include <limits> +#include "storage/v3/delta.hpp" #include "storage/v3/id_types.hpp" #include "storage/v3/mvcc.hpp" #include "storage/v3/property_value.hpp" #include "storage/v3/schemas.hpp" +#include "storage/v3/vertex.hpp" #include "utils/bound.hpp" #include "utils/logging.hpp" #include "utils/memory_tracker.hpp" @@ -53,9 +57,9 @@ bool AnyVersionHasLabel(const Vertex &vertex, LabelId label, uint64_t timestamp) bool deleted{false}; const Delta *delta{nullptr}; { - has_label = utils::Contains(vertex.labels, label); - deleted = vertex.deleted; - delta = vertex.delta; + has_label = utils::Contains(vertex.second.labels, label); + deleted = vertex.second.deleted; + delta = vertex.second.delta; } if (!deleted && has_label) { return true; @@ -105,10 +109,10 @@ bool AnyVersionHasLabelProperty(const Vertex &vertex, LabelId label, PropertyId bool deleted{false}; const Delta *delta{nullptr}; { - has_label = utils::Contains(vertex.labels, label); - current_value_equal_to_value = vertex.properties.IsPropertyEqual(key, value); - deleted = vertex.deleted; - delta = vertex.delta; + has_label = utils::Contains(vertex.second.labels, label); + current_value_equal_to_value = vertex.second.properties.IsPropertyEqual(key, value); + deleted = vertex.second.deleted; + delta = vertex.second.delta; } if (!deleted && has_label && current_value_equal_to_value) { @@ -163,9 +167,9 @@ bool CurrentVersionHasLabel(const Vertex &vertex, LabelId label, Transaction *tr bool has_label{false}; const Delta *delta{nullptr}; { - deleted = vertex.deleted; - has_label = utils::Contains(vertex.labels, label); - delta = vertex.delta; + deleted = vertex.second.deleted; + has_label = utils::Contains(vertex.second.labels, label); + delta = vertex.second.delta; } ApplyDeltasForRead(transaction, delta, view, [&deleted, &has_label, label](const Delta &delta) { switch (delta.action) { @@ -214,10 +218,10 @@ bool CurrentVersionHasLabelProperty(const Vertex &vertex, LabelId label, Propert bool current_value_equal_to_value = value.IsNull(); const Delta *delta{nullptr}; { - deleted = vertex.deleted; - has_label = utils::Contains(vertex.labels, label); - current_value_equal_to_value = vertex.properties.IsPropertyEqual(key, value); - delta = vertex.delta; + deleted = vertex.second.deleted; + has_label = utils::Contains(vertex.second.labels, label); + current_value_equal_to_value = vertex.second.properties.IsPropertyEqual(key, value); + delta = vertex.second.delta; } ApplyDeltasForRead(transaction, delta, view, [&deleted, &has_label, ¤t_value_equal_to_value, key, label, &value](const Delta &delta) { @@ -265,11 +269,10 @@ bool CurrentVersionHasLabelProperty(const Vertex &vertex, LabelId label, Propert void LabelIndex::UpdateOnAddLabel(LabelId label, Vertex *vertex, const Transaction &tx) { auto it = index_.find(label); if (it == index_.end()) return; - auto acc = it->second.access(); - acc.insert(Entry{vertex, tx.start_timestamp.logical_id}); + it->second.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; auto [it, emplaced] = index_.emplace(std::piecewise_construct, std::forward_as_tuple(label), std::forward_as_tuple()); if (!emplaced) { @@ -277,13 +280,11 @@ bool LabelIndex::CreateIndex(LabelId label, VerticesSkipList::Accessor vertices) return false; } try { - auto acc = it->second.access(); - for (auto &lgo_vertex : vertices) { - auto &vertex = lgo_vertex.vertex; - if (vertex.deleted || !utils::Contains(vertex.labels, label)) { + for (auto &vertex : vertices) { + if (vertex.second.deleted || !VertexHasLabel(vertex, label)) { continue; } - acc.insert(Entry{&vertex, 0}); + it->second.insert(Entry{&vertex, 0}); } } catch (const utils::OutOfMemoryException &) { utils::MemoryTracker::OutOfMemoryExceptionBlocker oom_exception_blocker; @@ -304,7 +305,7 @@ std::vector<LabelId> LabelIndex::ListIndices() const { void LabelIndex::RemoveObsoleteEntries(const uint64_t clean_up_before_timestamp) { for (auto &label_storage : index_) { - auto vertices_acc = label_storage.second.access(); + auto &vertices_acc = label_storage.second; for (auto it = vertices_acc.begin(); it != vertices_acc.end();) { auto next_it = it; ++next_it; @@ -316,7 +317,7 @@ void LabelIndex::RemoveObsoleteEntries(const uint64_t clean_up_before_timestamp) if ((next_it != vertices_acc.end() && it->vertex == next_it->vertex) || !AnyVersionHasLabel(*it->vertex, label_storage.first, clean_up_before_timestamp)) { - vertices_acc.remove(*it); + vertices_acc.erase(*it); } it = next_it; @@ -324,7 +325,7 @@ void LabelIndex::RemoveObsoleteEntries(const uint64_t clean_up_before_timestamp) } } -LabelIndex::Iterable::Iterator::Iterator(Iterable *self, utils::SkipList<Entry>::Iterator index_iterator) +LabelIndex::Iterable::Iterator::Iterator(Iterable *self, LabelIndexContainer::iterator index_iterator) : self_(self), index_iterator_(index_iterator), current_vertex_accessor_(nullptr, nullptr, nullptr, self_->config_, *self_->vertex_validator_), @@ -339,7 +340,7 @@ LabelIndex::Iterable::Iterator &LabelIndex::Iterable::Iterator::operator++() { } void LabelIndex::Iterable::Iterator::AdvanceUntilValid() { - for (; index_iterator_ != self_->index_accessor_.end(); ++index_iterator_) { + for (; index_iterator_ != self_->index_container_->end(); ++index_iterator_) { if (index_iterator_->vertex == current_vertex_) { continue; } @@ -352,10 +353,9 @@ void LabelIndex::Iterable::Iterator::AdvanceUntilValid() { } } -LabelIndex::Iterable::Iterable(utils::SkipList<Entry>::Accessor index_accessor, LabelId label, View view, - Transaction *transaction, Indices *indices, Config::Items config, - const VertexValidator &vertex_validator) - : index_accessor_(std::move(index_accessor)), +LabelIndex::Iterable::Iterable(LabelIndexContainer &index_container, LabelId label, View view, Transaction *transaction, + Indices *indices, Config::Items config, const VertexValidator &vertex_validator) + : index_container_(&index_container), label_(label), view_(view), transaction_(transaction), @@ -363,12 +363,6 @@ LabelIndex::Iterable::Iterable(utils::SkipList<Entry>::Accessor index_accessor, config_(config), vertex_validator_(&vertex_validator) {} -void LabelIndex::RunGC() { - for (auto &index_entry : index_) { - index_entry.second.run_gc(); - } -} - bool LabelPropertyIndex::Entry::operator<(const Entry &rhs) const { if (value < rhs.value) { return true; @@ -388,14 +382,13 @@ bool LabelPropertyIndex::Entry::operator<(const PropertyValue &rhs) const { retu bool LabelPropertyIndex::Entry::operator==(const PropertyValue &rhs) const { return value == rhs; } void LabelPropertyIndex::UpdateOnAddLabel(LabelId label, Vertex *vertex, const Transaction &tx) { - for (auto &[label_prop, storage] : index_) { + for (auto &[label_prop, index] : index_) { if (label_prop.first != label) { continue; } - auto prop_value = vertex->properties.GetProperty(label_prop.second); + auto prop_value = vertex->second.properties.GetProperty(label_prop.second); if (!prop_value.IsNull()) { - auto acc = storage.access(); - acc.insert(Entry{std::move(prop_value), vertex, tx.start_timestamp.logical_id}); + index.emplace(Entry{prop_value, vertex, tx.start_timestamp.logical_id}); } } } @@ -405,18 +398,17 @@ void LabelPropertyIndex::UpdateOnSetProperty(PropertyId property, const Property if (value.IsNull()) { return; } - for (auto &[label_prop, storage] : index_) { + for (auto &[label_prop, index] : index_) { if (label_prop.second != property) { continue; } - if (utils::Contains(vertex->labels, label_prop.first)) { - auto acc = storage.access(); - acc.insert(Entry{value, vertex, tx.start_timestamp.logical_id}); + if (VertexHasLabel(*vertex, label_prop.first)) { + index.emplace(Entry{value, vertex, tx.start_timestamp.logical_id}); } } } -bool LabelPropertyIndex::CreateIndex(LabelId label, PropertyId property, VerticesSkipList::Accessor vertices) { +bool LabelPropertyIndex::CreateIndex(LabelId label, PropertyId property, VertexContainer &vertices) { utils::MemoryTracker::OutOfMemoryExceptionEnabler oom_exception; auto [it, emplaced] = index_.emplace(std::piecewise_construct, std::forward_as_tuple(label, property), std::forward_as_tuple()); @@ -425,17 +417,15 @@ bool LabelPropertyIndex::CreateIndex(LabelId label, PropertyId property, Vertice return false; } try { - auto acc = it->second.access(); - for (auto &lgo_vertex : vertices) { - auto &vertex = lgo_vertex.vertex; - if (vertex.deleted || !utils::Contains(vertex.labels, label)) { + for (auto &vertex : vertices) { + if (vertex.second.deleted || !VertexHasLabel(vertex, label)) { continue; } - auto value = vertex.properties.GetProperty(property); + auto value = vertex.second.properties.GetProperty(property); if (value.IsNull()) { continue; } - acc.insert(Entry{std::move(value), &vertex, 0}); + it->second.emplace(Entry{value, &vertex, 0}); } } catch (const utils::OutOfMemoryException &) { utils::MemoryTracker::OutOfMemoryExceptionBlocker oom_exception_blocker; @@ -456,8 +446,7 @@ std::vector<std::pair<LabelId, PropertyId>> LabelPropertyIndex::ListIndices() co void LabelPropertyIndex::RemoveObsoleteEntries(const uint64_t clean_up_before_timestamp) { for (auto &[label_property, index] : index_) { - auto index_acc = index.access(); - for (auto it = index_acc.begin(); it != index_acc.end();) { + for (auto it = index.begin(); it != index.end();) { auto next_it = it; ++next_it; @@ -466,17 +455,17 @@ void LabelPropertyIndex::RemoveObsoleteEntries(const uint64_t clean_up_before_ti continue; } - if ((next_it != index_acc.end() && it->vertex == next_it->vertex && it->value == next_it->value) || + if ((next_it != index.end() && it->vertex == next_it->vertex && it->value == next_it->value) || !AnyVersionHasLabelProperty(*it->vertex, label_property.first, label_property.second, it->value, clean_up_before_timestamp)) { - index_acc.remove(*it); + index.erase(it); } it = next_it; } } } -LabelPropertyIndex::Iterable::Iterator::Iterator(Iterable *self, utils::SkipList<Entry>::Iterator index_iterator) +LabelPropertyIndex::Iterable::Iterator::Iterator(Iterable *self, LabelPropertyIndexContainer::iterator index_iterator) : self_(self), index_iterator_(index_iterator), current_vertex_accessor_(nullptr, nullptr, nullptr, self_->config_, *self_->vertex_validator_), @@ -491,7 +480,7 @@ LabelPropertyIndex::Iterable::Iterator &LabelPropertyIndex::Iterable::Iterator:: } void LabelPropertyIndex::Iterable::Iterator::AdvanceUntilValid() { - for (; index_iterator_ != self_->index_accessor_.end(); ++index_iterator_) { + for (; index_iterator_ != self_->index_container_->end(); ++index_iterator_) { if (index_iterator_->vertex == current_vertex_) { continue; } @@ -506,11 +495,11 @@ void LabelPropertyIndex::Iterable::Iterator::AdvanceUntilValid() { } if (self_->upper_bound_) { if (self_->upper_bound_->value() < index_iterator_->value) { - index_iterator_ = self_->index_accessor_.end(); + index_iterator_ = self_->index_container_->end(); break; } if (!self_->upper_bound_->IsInclusive() && index_iterator_->value == self_->upper_bound_->value()) { - index_iterator_ = self_->index_accessor_.end(); + index_iterator_ = self_->index_container_->end(); break; } } @@ -537,13 +526,12 @@ const PropertyValue kSmallestMap = PropertyValue(std::map<std::string, PropertyV const PropertyValue kSmallestTemporalData = PropertyValue(TemporalData{static_cast<TemporalType>(0), std::numeric_limits<int64_t>::min()}); -LabelPropertyIndex::Iterable::Iterable(utils::SkipList<Entry>::Accessor index_accessor, LabelId label, - PropertyId property, +LabelPropertyIndex::Iterable::Iterable(LabelPropertyIndexContainer &index_container, LabelId label, PropertyId property, const std::optional<utils::Bound<PropertyValue>> &lower_bound, const std::optional<utils::Bound<PropertyValue>> &upper_bound, View view, Transaction *transaction, Indices *indices, Config::Items config, const VertexValidator &vertex_validator) - : index_accessor_(std::move(index_accessor)), + : index_container_(&index_container), label_(label), property_(property), lower_bound_(lower_bound), @@ -651,49 +639,55 @@ LabelPropertyIndex::Iterable::Iterator LabelPropertyIndex::Iterable::begin() { // If the bounds are set and don't have comparable types we don't yield any // items from the index. if (!bounds_valid_) { - return {this, index_accessor_.end()}; + return {this, index_container_->end()}; } - auto index_iterator = index_accessor_.begin(); if (lower_bound_) { - index_iterator = index_accessor_.find_equal_or_greater(lower_bound_->value()); + return {this, std::ranges::lower_bound(*index_container_, lower_bound_->value(), std::less{}, &Entry::value)}; } - return {this, index_iterator}; + return {this, index_container_->begin()}; } -LabelPropertyIndex::Iterable::Iterator LabelPropertyIndex::Iterable::end() { return {this, index_accessor_.end()}; } +LabelPropertyIndex::Iterable::Iterator LabelPropertyIndex::Iterable::end() { return {this, index_container_->end()}; } -int64_t LabelPropertyIndex::ApproximateVertexCount(LabelId label, PropertyId property, - const PropertyValue &value) const { +int64_t LabelPropertyIndex::VertexCount(LabelId label, PropertyId property, const PropertyValue &value) const { auto it = index_.find({label, property}); MG_ASSERT(it != index_.end(), "Index for label {} and property {} doesn't exist", label.AsUint(), property.AsUint()); - auto acc = it->second.access(); - if (!value.IsNull()) { - return static_cast<int64_t>( - acc.estimate_count(value, static_cast<int>(utils::SkipListLayerForCountEstimation(acc.size())))); - } - // The value `Null` won't ever appear in the index because it indicates that - // the property shouldn't exist. Instead, this value is used as an indicator - // to estimate the average number of equal elements in the list (for any - // given value). - return static_cast<int64_t>(acc.estimate_average_number_of_equals( - [](const auto &first, const auto &second) { return first.value == second.value; }, - static_cast<int>(utils::SkipListLayerForAverageEqualsEstimation(acc.size())))); -} + MG_ASSERT(!value.IsNull(), "Null is not supported!"); -int64_t LabelPropertyIndex::ApproximateVertexCount(LabelId label, PropertyId property, - const std::optional<utils::Bound<PropertyValue>> &lower, - const std::optional<utils::Bound<PropertyValue>> &upper) const { - auto it = index_.find({label, property}); - MG_ASSERT(it != index_.end(), "Index for label {} and property {} doesn't exist", label.AsUint(), property.AsUint()); - auto acc = it->second.access(); + // TODO(jbajic) This can be improved by exiting early + auto start_it = std::ranges::lower_bound(it->second, value, std::less{}, &Entry::value); return static_cast<int64_t>( - acc.estimate_range_count(lower, upper, static_cast<int>(utils::SkipListLayerForCountEstimation(acc.size())))); + std::ranges::count_if(start_it, it->second.end(), [&value](const auto &elem) { return elem.value == value; })); } -void LabelPropertyIndex::RunGC() { - for (auto &index_entry : index_) { - index_entry.second.run_gc(); - } +int64_t LabelPropertyIndex::VertexCount(LabelId label, PropertyId property, + const std::optional<utils::Bound<PropertyValue>> &lower, + const std::optional<utils::Bound<PropertyValue>> &upper) const { + auto it = index_.find({label, property}); + MG_ASSERT(it != index_.end(), "Index for label {} and property {} doesn't exist", label.AsUint(), property.AsUint()); + const auto lower_it = std::invoke( + [&index = it->second](const auto value, const auto def) { + if (value) { + if (value->IsInclusive()) { + return std::ranges::lower_bound(index, value->value(), std::less{}, &Entry::value); + } + return std::ranges::upper_bound(index, value->value(), std::less{}, &Entry::value); + } + return def; + }, + lower, it->second.begin()); + const auto upper_it = std::invoke( + [&index = it->second](const auto value, const auto def) { + if (value) { + if (value->IsInclusive()) { + return std::ranges::upper_bound(index, value->value(), std::less{}, &Entry::value); + } + return std::ranges::lower_bound(index, value->value(), std::less{}, &Entry::value); + } + return def; + }, + upper, it->second.end()); + return static_cast<int64_t>(std::distance(lower_it, upper_it)); } void RemoveObsoleteEntries(Indices *indices, const uint64_t clean_up_before_timestamp) { diff --git a/src/storage/v3/indices.hpp b/src/storage/v3/indices.hpp index 0dd09ce53..d8e491470 100644 --- a/src/storage/v3/indices.hpp +++ b/src/storage/v3/indices.hpp @@ -13,6 +13,7 @@ #include <cstdint> #include <optional> +#include <set> #include <tuple> #include <utility> @@ -20,7 +21,6 @@ #include "storage/v3/property_value.hpp" #include "storage/v3/transaction.hpp" #include "storage/v3/vertex_accessor.hpp" -#include "storage/v3/vertices_skip_list.hpp" #include "utils/bound.hpp" #include "utils/logging.hpp" #include "utils/skip_list.hpp" @@ -30,7 +30,6 @@ namespace memgraph::storage::v3 { struct Indices; class LabelIndex { - private: struct Entry { Vertex *vertex; uint64_t timestamp; @@ -41,17 +40,9 @@ class LabelIndex { bool operator==(const Entry &rhs) const { return vertex == rhs.vertex && timestamp == rhs.timestamp; } }; - struct LabelStorage { - LabelId label; - utils::SkipList<Entry> vertices; - - bool operator<(const LabelStorage &rhs) const { return label < rhs.label; } - bool operator<(LabelId rhs) const { return label < rhs; } - bool operator==(const LabelStorage &rhs) const { return label == rhs.label; } - bool operator==(LabelId rhs) const { return label == rhs; } - }; - public: + using LabelIndexContainer = std::set<Entry>; + LabelIndex(Indices *indices, Config::Items config, const VertexValidator &vertex_validator) : indices_(indices), config_(config), vertex_validator_{&vertex_validator} {} @@ -59,7 +50,7 @@ class LabelIndex { void UpdateOnAddLabel(LabelId label, Vertex *vertex, const Transaction &tx); /// @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 bool DropIndex(LabelId label) { return index_.erase(label) > 0; } @@ -72,12 +63,12 @@ class LabelIndex { class Iterable { public: - Iterable(utils::SkipList<Entry>::Accessor index_accessor, LabelId label, View view, Transaction *transaction, - Indices *indices, Config::Items config, const VertexValidator &vertex_validator); + Iterable(LabelIndexContainer &index_container, LabelId label, View view, Transaction *transaction, Indices *indices, + Config::Items config, const VertexValidator &vertex_validator); class Iterator { public: - Iterator(Iterable *self, utils::SkipList<Entry>::Iterator index_iterator); + Iterator(Iterable *self, LabelIndexContainer::iterator index_iterator); VertexAccessor operator*() const { return current_vertex_accessor_; } @@ -90,16 +81,16 @@ class LabelIndex { void AdvanceUntilValid(); Iterable *self_; - utils::SkipList<Entry>::Iterator index_iterator_; + LabelIndexContainer::iterator index_iterator_; VertexAccessor current_vertex_accessor_; Vertex *current_vertex_; }; - Iterator begin() { return {this, index_accessor_.begin()}; } - Iterator end() { return {this, index_accessor_.end()}; } + Iterator begin() { return {this, index_container_->begin()}; } + Iterator end() { return {this, index_container_->end()}; } private: - utils::SkipList<Entry>::Accessor index_accessor_; + LabelIndexContainer *index_container_; LabelId label_; View view_; Transaction *transaction_; @@ -112,7 +103,7 @@ class LabelIndex { Iterable Vertices(LabelId label, View view, Transaction *transaction) { auto it = index_.find(label); MG_ASSERT(it != index_.end(), "Index for label {} doesn't exist", label.AsUint()); - return {it->second.access(), label, view, transaction, indices_, config_, *vertex_validator_}; + return {it->second, label, view, transaction, indices_, config_, *vertex_validator_}; } int64_t ApproximateVertexCount(LabelId label) { @@ -123,17 +114,14 @@ class LabelIndex { void Clear() { index_.clear(); } - void RunGC(); - private: - std::map<LabelId, utils::SkipList<Entry>> index_; + std::map<LabelId, LabelIndexContainer> index_; Indices *indices_; Config::Items config_; const VertexValidator *vertex_validator_; }; class LabelPropertyIndex { - private: struct Entry { PropertyValue value; Vertex *vertex; @@ -147,6 +135,8 @@ class LabelPropertyIndex { }; public: + using LabelPropertyIndexContainer = std::set<Entry>; + LabelPropertyIndex(Indices *indices, Config::Items config, const VertexValidator &vertex_validator) : indices_(indices), config_(config), vertex_validator_{&vertex_validator} {} @@ -157,7 +147,7 @@ class LabelPropertyIndex { void UpdateOnSetProperty(PropertyId property, const PropertyValue &value, Vertex *vertex, const Transaction &tx); /// @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; } @@ -169,14 +159,14 @@ class LabelPropertyIndex { class Iterable { public: - Iterable(utils::SkipList<Entry>::Accessor index_accessor, LabelId label, PropertyId property, + Iterable(LabelPropertyIndexContainer &index_container, LabelId label, PropertyId property, const std::optional<utils::Bound<PropertyValue>> &lower_bound, const std::optional<utils::Bound<PropertyValue>> &upper_bound, View view, Transaction *transaction, Indices *indices, Config::Items config, const VertexValidator &vertex_validator); class Iterator { public: - Iterator(Iterable *self, utils::SkipList<Entry>::Iterator index_iterator); + Iterator(Iterable *self, LabelPropertyIndexContainer::iterator index_iterator); VertexAccessor operator*() const { return current_vertex_accessor_; } @@ -189,7 +179,7 @@ class LabelPropertyIndex { void AdvanceUntilValid(); Iterable *self_; - utils::SkipList<Entry>::Iterator index_iterator_; + LabelPropertyIndexContainer::iterator index_iterator_; VertexAccessor current_vertex_accessor_; Vertex *current_vertex_; }; @@ -198,7 +188,7 @@ class LabelPropertyIndex { Iterator end(); private: - utils::SkipList<Entry>::Accessor index_accessor_; + LabelPropertyIndexContainer *index_container_; LabelId label_; PropertyId property_; std::optional<utils::Bound<PropertyValue>> lower_bound_; @@ -217,11 +207,11 @@ class LabelPropertyIndex { auto it = index_.find({label, property}); MG_ASSERT(it != index_.end(), "Index for label {} and property {} doesn't exist", label.AsUint(), property.AsUint()); - return {it->second.access(), label, property, lower_bound, upper_bound, view, - transaction, indices_, config_, *vertex_validator_}; + return {it->second, label, property, lower_bound, upper_bound, + view, transaction, indices_, config_, *vertex_validator_}; } - int64_t ApproximateVertexCount(LabelId label, PropertyId property) const { + int64_t VertexCount(LabelId label, PropertyId property) const { auto it = index_.find({label, property}); MG_ASSERT(it != index_.end(), "Index for label {} and property {} doesn't exist", label.AsUint(), property.AsUint()); @@ -232,18 +222,15 @@ class LabelPropertyIndex { /// an estimated count of nodes which have their property's value set to /// `value`. If the `value` specified is `Null`, then an average number of /// equal elements is returned. - int64_t ApproximateVertexCount(LabelId label, PropertyId property, const PropertyValue &value) const; + int64_t VertexCount(LabelId label, PropertyId property, const PropertyValue &value) const; - int64_t ApproximateVertexCount(LabelId label, PropertyId property, - const std::optional<utils::Bound<PropertyValue>> &lower, - const std::optional<utils::Bound<PropertyValue>> &upper) const; + int64_t VertexCount(LabelId label, PropertyId property, const std::optional<utils::Bound<PropertyValue>> &lower, + const std::optional<utils::Bound<PropertyValue>> &upper) const; void Clear() { index_.clear(); } - void RunGC(); - private: - std::map<std::pair<LabelId, PropertyId>, utils::SkipList<Entry>> index_; + std::map<std::pair<LabelId, PropertyId>, LabelPropertyIndexContainer> index_; Indices *indices_; Config::Items config_; const VertexValidator *vertex_validator_; diff --git a/src/storage/v3/key_store.cpp b/src/storage/v3/key_store.cpp deleted file mode 100644 index 4e65f5fd1..000000000 --- a/src/storage/v3/key_store.cpp +++ /dev/null @@ -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 diff --git a/src/storage/v3/key_store.hpp b/src/storage/v3/key_store.hpp index 4bc3c25e3..5c6e97426 100644 --- a/src/storage/v3/key_store.hpp +++ b/src/storage/v3/key_store.hpp @@ -11,12 +11,6 @@ #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" namespace memgraph::storage::v3 { @@ -24,39 +18,4 @@ namespace memgraph::storage::v3 { // Primary key is a collection of primary properties. 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 diff --git a/src/storage/v3/lexicographically_ordered_vertex.cpp b/src/storage/v3/lexicographically_ordered_vertex.cpp deleted file mode 100644 index 04687f6e6..000000000 --- a/src/storage/v3/lexicographically_ordered_vertex.cpp +++ /dev/null @@ -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 diff --git a/src/storage/v3/lexicographically_ordered_vertex.hpp b/src/storage/v3/lexicographically_ordered_vertex.hpp deleted file mode 100644 index e039a2687..000000000 --- a/src/storage/v3/lexicographically_ordered_vertex.hpp +++ /dev/null @@ -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 diff --git a/src/storage/v3/mvcc.hpp b/src/storage/v3/mvcc.hpp index 219491635..6ce058d62 100644 --- a/src/storage/v3/mvcc.hpp +++ b/src/storage/v3/mvcc.hpp @@ -11,12 +11,21 @@ #pragma once +#include <type_traits> + +#include "storage/v3/edge.hpp" #include "storage/v3/property_value.hpp" #include "storage/v3/transaction.hpp" +#include "storage/v3/vertex.hpp" #include "storage/v3/view.hpp" +#include "utils/concepts.hpp" namespace memgraph::storage::v3 { +inline VertexData *GetDeltaHolder(Vertex *vertex) { return &vertex->second; } + +inline Edge *GetDeltaHolder(Edge *edge) { return edge; } + /// This function iterates through the undo buffers from an object (starting /// from the supplied delta) and determines what deltas should be applied to get /// the currently visible version of the object. When the function finds a delta @@ -77,10 +86,12 @@ inline void ApplyDeltasForRead(Transaction *transaction, const Delta *delta, Vie /// transaction) and returns a `bool` value indicating whether the caller can /// proceed with a write operation. template <typename TObj> +requires utils::SameAsAnyOf<TObj, Edge, Vertex> inline bool PrepareForWrite(Transaction *transaction, TObj *object) { - if (object->delta == nullptr) return true; + auto *delta_holder = GetDeltaHolder(object); + if (delta_holder->delta == nullptr) return true; - const auto &delta_commit_info = *object->delta->commit_info; + const auto &delta_commit_info = *delta_holder->delta->commit_info; if (delta_commit_info.start_or_commit_timestamp == transaction->commit_info->start_or_commit_timestamp || (delta_commit_info.is_locally_committed && delta_commit_info.start_or_commit_timestamp < transaction->start_timestamp)) { @@ -105,9 +116,11 @@ inline Delta *CreateDeleteObjectDelta(Transaction *transaction) { /// the delta into the object's delta list. /// @throw std::bad_alloc template <typename TObj, class... Args> +requires utils::SameAsAnyOf<TObj, Edge, Vertex> inline void CreateAndLinkDelta(Transaction *transaction, TObj *object, Args &&...args) { auto delta = &transaction->deltas.emplace_back(std::forward<Args>(args)..., transaction->commit_info.get(), transaction->command_id); + auto *delta_holder = GetDeltaHolder(object); // The operations are written in such order so that both `next` and `prev` // chains are valid at all times. The chains must be valid at all times @@ -118,21 +131,21 @@ inline void CreateAndLinkDelta(Transaction *transaction, TObj *object, Args &&.. // TODO(antaljanosbenjamin): clang-tidy detects (in my opinion a false positive) issue in // `Shard::Accessor::CreateEdge`. // NOLINTNEXTLINE(clang-analyzer-core.NullDereference) - delta->next = object->delta; + delta->next = delta_holder->delta; // 2. We need to set the previous delta of the new delta to the object. delta->prev.Set(object); // 3. We need to set the previous delta of the existing delta to the new // delta. After this point the garbage collector will be able to see the new // delta but won't modify it until we are done with all of our modifications. - if (object->delta) { - object->delta->prev.Set(delta); + if (delta_holder->delta) { + delta_holder->delta->prev.Set(delta); } // 4. Finally, we need to set the object's delta to the new delta. The garbage // collector and other transactions will acquire the object lock to read the // delta from the object. Because the lock is held during the whole time this // modification is being done, everybody else will wait until we are fully // done with our modification before they read the object's delta value. - object->delta = delta; + delta_holder->delta = delta; } } // namespace memgraph::storage::v3 diff --git a/src/storage/v3/shard.cpp b/src/storage/v3/shard.cpp index 5dd8e7256..5e16209d9 100644 --- a/src/storage/v3/shard.cpp +++ b/src/storage/v3/shard.cpp @@ -38,7 +38,7 @@ #include "storage/v3/transaction.hpp" #include "storage/v3/vertex.hpp" #include "storage/v3/vertex_accessor.hpp" -#include "storage/v3/vertices_skip_list.hpp" +#include "storage/v3/view.hpp" #include "utils/exceptions.hpp" #include "utils/file.hpp" #include "utils/logging.hpp" @@ -75,11 +75,11 @@ uint64_t GetCleanupBeforeTimestamp(const std::map<uint64_t, std::unique_ptr<Tran } // 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, Config::Items config, const VertexValidator &vertex_validator) { while (it != end) { - *vertex = VertexAccessor::Create(&it->vertex, tx, indices, config, vertex_validator, view); + *vertex = VertexAccessor::Create(&*it, tx, indices, config, vertex_validator, view); if (!*vertex) { ++it; continue; @@ -89,17 +89,17 @@ auto AdvanceToVisibleVertex(VerticesSkipList::Iterator it, VerticesSkipList::Ite return it; } -AllVerticesIterable::Iterator::Iterator(AllVerticesIterable *self, VerticesSkipList::Iterator it) +AllVerticesIterable::Iterator::Iterator(AllVerticesIterable *self, VertexContainer::iterator it) : 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_)) {} VertexAccessor AllVerticesIterable::Iterator::operator*() const { return *self_->vertex_; } AllVerticesIterable::Iterator &AllVerticesIterable::Iterator::operator++() { ++it_; - it_ = AdvanceToVisibleVertex(it_, self_->vertices_accessor_.end(), &self_->vertex_, self_->transaction_, self_->view_, - self_->indices_, self_->config_, *self_->vertex_validator_); + it_ = AdvanceToVisibleVertex(it_, self_->vertices_accessor_->end(), &self_->vertex_, self_->transaction_, + self_->view_, self_->indices_, self_->config_, *self_->vertex_validator_); return *this; } @@ -346,7 +346,7 @@ Shard::Accessor::Accessor(Shard &shard, Transaction &transaction) : shard_(&shard), transaction_(&transaction), config_(shard_->config_.items) {} ShardResult<VertexAccessor> Shard::Accessor::CreateVertexAndValidate( - const std::vector<LabelId> &labels, const std::vector<PropertyValue> &primary_properties, + const std::vector<LabelId> &labels, const PrimaryKey &primary_properties, const std::vector<std::pair<PropertyId, PropertyValue>> &properties) { OOMExceptionEnabler oom_exception; const auto schema = shard_->GetSchema(shard_->primary_label_)->second; @@ -357,16 +357,15 @@ ShardResult<VertexAccessor> Shard::Accessor::CreateVertexAndValidate( return {std::move(maybe_schema_violation.GetError())}; } - auto acc = shard_->vertices_.access(); auto *delta = CreateDeleteObjectDelta(transaction_); - auto [it, inserted] = acc.insert({Vertex{delta, primary_properties}}); - delta->prev.Set(&it->vertex); + auto [it, inserted] = shard_->vertices_.emplace(primary_properties, VertexData{delta}); + delta->prev.Set(&*it); - VertexAccessor vertex_acc{&it->vertex, transaction_, &shard_->indices_, config_, shard_->vertex_validator_}; + VertexAccessor vertex_acc{&*it, transaction_, &shard_->indices_, config_, shard_->vertex_validator_}; if (!inserted) { return SHARD_ERROR(ErrorCode::VERTEX_ALREADY_INSERTED); } - MG_ASSERT(it != acc.end(), "Invalid Vertex accessor!"); + MG_ASSERT(it != shard_->vertices_.end(), "Invalid Vertex accessor!"); // TODO(jbajic) Improve, maybe delay index update 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) { - auto acc = shard_->vertices_.access(); - // Later on use label space - auto it = acc.find(primary_key); - if (it == acc.end()) { + auto it = shard_->vertices_.find(primary_key); + if (it == shard_->vertices_.end()) { return std::nullopt; } - return VertexAccessor::Create(&it->vertex, 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) { @@ -403,14 +400,15 @@ ShardResult<std::optional<VertexAccessor>> Shard::Accessor::DeleteVertex(VertexA if (!PrepareForWrite(transaction_, vertex_ptr)) return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR); - if (vertex_ptr->deleted) { + if (vertex_ptr->second.deleted) { return std::optional<VertexAccessor>{}; } - if (!vertex_ptr->in_edges.empty() || !vertex_ptr->out_edges.empty()) return SHARD_ERROR(ErrorCode::VERTEX_HAS_EDGES); + if (!vertex_ptr->second.in_edges.empty() || !vertex_ptr->second.out_edges.empty()) + return SHARD_ERROR(ErrorCode::VERTEX_HAS_EDGES); CreateAndLinkDelta(transaction_, vertex_ptr, Delta::RecreateObjectTag()); - vertex_ptr->deleted = true; + vertex_ptr->second.deleted = true; return std::make_optional<VertexAccessor>(vertex_ptr, transaction_, &shard_->indices_, config_, shard_->vertex_validator_, true); @@ -425,20 +423,20 @@ ShardResult<std::optional<std::pair<VertexAccessor, std::vector<EdgeAccessor>>>> "accessor when deleting a vertex!"); auto *vertex_ptr = vertex->vertex_; - std::vector<Vertex::EdgeLink> in_edges; - std::vector<Vertex::EdgeLink> out_edges; + std::vector<VertexData::EdgeLink> in_edges; + std::vector<VertexData::EdgeLink> out_edges; { if (!PrepareForWrite(transaction_, vertex_ptr)) return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR); - if (vertex_ptr->deleted) return std::optional<ReturnType>{}; + if (vertex_ptr->second.deleted) return std::optional<ReturnType>{}; - in_edges = vertex_ptr->in_edges; - out_edges = vertex_ptr->out_edges; + in_edges = vertex_ptr->second.in_edges; + out_edges = vertex_ptr->second.out_edges; } std::vector<EdgeAccessor> deleted_edges; - const VertexId vertex_id{shard_->primary_label_, vertex_ptr->keys.Keys()}; + const VertexId vertex_id{shard_->primary_label_, *vertex->PrimaryKey(View::OLD)}; // TODO Replace for (const auto &item : in_edges) { auto [edge_type, from_vertex, edge] = item; EdgeAccessor e(edge, edge_type, from_vertex, vertex_id, transaction_, &shard_->indices_, config_); @@ -472,10 +470,10 @@ ShardResult<std::optional<std::pair<VertexAccessor, std::vector<EdgeAccessor>>>> if (!PrepareForWrite(transaction_, vertex_ptr)) return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR); - MG_ASSERT(!vertex_ptr->deleted, "Invalid database state!"); + MG_ASSERT(!vertex_ptr->second.deleted, "Invalid database state!"); CreateAndLinkDelta(transaction_, vertex_ptr, Delta::RecreateObjectTag()); - vertex_ptr->deleted = true; + vertex_ptr->second.deleted = true; return std::make_optional<ReturnType>( VertexAccessor{vertex_ptr, transaction_, &shard_->indices_, config_, shard_->vertex_validator_, true}, @@ -488,51 +486,50 @@ ShardResult<EdgeAccessor> Shard::Accessor::CreateEdge(VertexId from_vertex_id, V Vertex *from_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 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"); if (from_is_local) { - auto it = acc.find(from_vertex_id.primary_key); - MG_ASSERT(it != acc.end(), "Cannot find local vertex"); - from_vertex = &it->vertex; + auto it = vertices.find(from_vertex_id.primary_key); + MG_ASSERT(it != vertices.end(), "Cannot find local vertex"); + from_vertex = &*it; } if (to_is_local) { - auto it = acc.find(to_vertex_id.primary_key); - MG_ASSERT(it != acc.end(), "Cannot find local vertex"); - to_vertex = &it->vertex; + auto it = vertices.find(to_vertex_id.primary_key); + MG_ASSERT(it != vertices.end(), "Cannot find local vertex"); + to_vertex = &*it; } if (from_is_local) { if (!PrepareForWrite(transaction_, from_vertex)) return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR); - if (from_vertex->deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT); + if (from_vertex->second.deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT); } if (to_is_local && to_vertex != from_vertex) { if (!PrepareForWrite(transaction_, to_vertex)) return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR); - if (to_vertex->deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT); + if (to_vertex->second.deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT); } EdgeRef edge(gid); if (config_.properties_on_edges) { - auto acc = shard_->edges_.access(); auto *delta = CreateDeleteObjectDelta(transaction_); - auto [it, inserted] = acc.insert(Edge(gid, delta)); + auto [it, inserted] = shard_->edges_.emplace(gid, Edge{gid, delta}); MG_ASSERT(inserted, "The edge must be inserted here!"); - MG_ASSERT(it != acc.end(), "Invalid Edge accessor!"); - edge = EdgeRef(&*it); - delta->prev.Set(&*it); + MG_ASSERT(it != shard_->edges_.end(), "Invalid Edge accessor!"); + edge = EdgeRef(&it->second); + delta->prev.Set(&it->second); } if (from_is_local) { CreateAndLinkDelta(transaction_, from_vertex, Delta::RemoveOutEdgeTag(), edge_type, to_vertex_id, edge); - from_vertex->out_edges.emplace_back(edge_type, to_vertex_id, edge); + from_vertex->second.out_edges.emplace_back(edge_type, to_vertex_id, edge); } if (to_is_local) { CreateAndLinkDelta(transaction_, to_vertex, Delta::RemoveInEdgeTag(), edge_type, from_vertex_id, edge); - to_vertex->in_edges.emplace_back(edge_type, from_vertex_id, edge); + to_vertex->second.in_edges.emplace_back(edge_type, from_vertex_id, edge); } // Increment edge count. ++shard_->edge_count_; @@ -543,24 +540,24 @@ ShardResult<EdgeAccessor> Shard::Accessor::CreateEdge(VertexId from_vertex_id, V ShardResult<std::optional<EdgeAccessor>> Shard::Accessor::DeleteEdge(VertexId from_vertex_id, VertexId to_vertex_id, const Gid edge_id) { - Vertex *from_vertex{nullptr}; - Vertex *to_vertex{nullptr}; + VertexContainer::value_type *from_vertex{nullptr}; + VertexContainer::value_type *to_vertex{nullptr}; - auto acc = shard_->vertices_.access(); + auto &vertices = shard_->vertices_; const auto from_is_local = shard_->IsVertexBelongToShard(from_vertex_id); const auto to_is_local = shard_->IsVertexBelongToShard(to_vertex_id); if (from_is_local) { - auto it = acc.find(from_vertex_id.primary_key); - MG_ASSERT(it != acc.end(), "Cannot find local vertex"); - from_vertex = &it->vertex; + auto it = vertices.find(from_vertex_id.primary_key); + MG_ASSERT(it != vertices.end(), "Cannot find local vertex"); + from_vertex = &*it; } if (to_is_local) { - auto it = acc.find(to_vertex_id.primary_key); - MG_ASSERT(it != acc.end(), "Cannot find local vertex"); - to_vertex = &it->vertex; + auto it = vertices.find(to_vertex_id.primary_key); + MG_ASSERT(it != vertices.end(), "Cannot find local vertex"); + to_vertex = &*it; } MG_ASSERT(from_is_local || to_is_local, "Trying to delete an edge without having a local vertex"); @@ -569,29 +566,28 @@ ShardResult<std::optional<EdgeAccessor>> Shard::Accessor::DeleteEdge(VertexId fr if (!PrepareForWrite(transaction_, from_vertex)) { return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR); } - MG_ASSERT(!from_vertex->deleted, "Invalid database state!"); + MG_ASSERT(!from_vertex->second.deleted, "Invalid database state!"); } if (to_is_local && to_vertex != from_vertex) { if (!PrepareForWrite(transaction_, to_vertex)) { return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR); } - MG_ASSERT(!to_vertex->deleted, "Invalid database state!"); + MG_ASSERT(!to_vertex->second.deleted, "Invalid database state!"); } const auto edge_ref = std::invoke([edge_id, this]() -> EdgeRef { if (!config_.properties_on_edges) { return EdgeRef(edge_id); } - auto edge_acc = shard_->edges_.access(); - auto res = edge_acc.find(edge_id); - MG_ASSERT(res != edge_acc.end(), "Cannot find edge"); - return EdgeRef(&*res); + auto res = shard_->edges_.find(edge_id); + MG_ASSERT(res != shard_->edges_.end(), "Cannot find edge"); + return EdgeRef(&res->second); }); std::optional<EdgeTypeId> edge_type{}; - auto delete_edge_from_storage = [&edge_type, &edge_ref, this](std::vector<Vertex::EdgeLink> &edges) mutable { + auto delete_edge_from_storage = [&edge_type, &edge_ref, this](std::vector<VertexData::EdgeLink> &edges) mutable { auto it = std::find_if(edges.begin(), edges.end(), - [&edge_ref](const Vertex::EdgeLink &link) { return std::get<2>(link) == edge_ref; }); + [&edge_ref](const VertexData::EdgeLink &link) { return std::get<2>(link) == edge_ref; }); if (config_.properties_on_edges) { MG_ASSERT(it != edges.end(), "Invalid database state!"); } else if (it == edges.end()) { @@ -603,8 +599,8 @@ ShardResult<std::optional<EdgeAccessor>> Shard::Accessor::DeleteEdge(VertexId fr return true; }; // NOLINTNEXTLINE(clang-analyzer-core.NonNullParamChecker) - auto success_on_to = to_is_local ? delete_edge_from_storage(to_vertex->in_edges) : false; - auto success_on_from = from_is_local ? delete_edge_from_storage(from_vertex->out_edges) : false; + auto success_on_to = to_is_local ? delete_edge_from_storage(to_vertex->second.in_edges) : false; + auto success_on_from = from_is_local ? delete_edge_from_storage(from_vertex->second.out_edges) : false; if (config_.properties_on_edges) { // Because of the check above, we are sure that the vertex exists. @@ -630,10 +626,10 @@ ShardResult<std::optional<EdgeAccessor>> Shard::Accessor::DeleteEdge(VertexId fr MG_ASSERT(edge_type.has_value(), "Edge type is not determined"); if (from_is_local) { - CreateAndLinkDelta(transaction_, from_vertex, Delta::AddOutEdgeTag(), *edge_type, to_vertex_id, edge_ref); + CreateAndLinkDelta(transaction_, &*from_vertex, Delta::AddOutEdgeTag(), *edge_type, to_vertex_id, edge_ref); } if (to_is_local) { - CreateAndLinkDelta(transaction_, to_vertex, Delta::AddInEdgeTag(), *edge_type, from_vertex_id, edge_ref); + CreateAndLinkDelta(transaction_, &*to_vertex, Delta::AddInEdgeTag(), *edge_type, from_vertex_id, edge_ref); } // Decrement edge count. @@ -695,41 +691,41 @@ void Shard::Accessor::Abort() { auto prev = delta.prev.Get(); switch (prev.type) { case PreviousPtr::Type::VERTEX: { - auto *vertex = prev.vertex; - Delta *current = vertex->delta; + auto &[pk, vertex] = *prev.vertex; + Delta *current = vertex.delta; while (current != nullptr && current->commit_info->start_or_commit_timestamp == transaction_->start_timestamp) { switch (current->action) { case Delta::Action::REMOVE_LABEL: { - auto it = std::find(vertex->labels.begin(), vertex->labels.end(), current->label); - MG_ASSERT(it != vertex->labels.end(), "Invalid database state!"); - std::swap(*it, *vertex->labels.rbegin()); - vertex->labels.pop_back(); + auto it = std::find(vertex.labels.begin(), vertex.labels.end(), current->label); + MG_ASSERT(it != vertex.labels.end(), "Invalid database state!"); + std::swap(*it, *vertex.labels.rbegin()); + vertex.labels.pop_back(); break; } case Delta::Action::ADD_LABEL: { - auto it = std::find(vertex->labels.begin(), vertex->labels.end(), current->label); - MG_ASSERT(it == vertex->labels.end(), "Invalid database state!"); - vertex->labels.push_back(current->label); + auto it = std::find(vertex.labels.begin(), vertex.labels.end(), current->label); + MG_ASSERT(it == vertex.labels.end(), "Invalid database state!"); + vertex.labels.push_back(current->label); break; } case Delta::Action::SET_PROPERTY: { - vertex->properties.SetProperty(current->property.key, current->property.value); + vertex.properties.SetProperty(current->property.key, current->property.value); break; } case Delta::Action::ADD_IN_EDGE: { - Vertex::EdgeLink link{current->vertex_edge.edge_type, current->vertex_edge.vertex_id, - current->vertex_edge.edge}; - auto it = std::find(vertex->in_edges.begin(), vertex->in_edges.end(), link); - MG_ASSERT(it == vertex->in_edges.end(), "Invalid database state!"); - vertex->in_edges.push_back(link); + VertexData::EdgeLink link{current->vertex_edge.edge_type, current->vertex_edge.vertex_id, + current->vertex_edge.edge}; + auto it = std::find(vertex.in_edges.begin(), vertex.in_edges.end(), link); + MG_ASSERT(it == vertex.in_edges.end(), "Invalid database state!"); + vertex.in_edges.push_back(link); break; } case Delta::Action::ADD_OUT_EDGE: { - Vertex::EdgeLink link{current->vertex_edge.edge_type, current->vertex_edge.vertex_id, - current->vertex_edge.edge}; - auto it = std::find(vertex->out_edges.begin(), vertex->out_edges.end(), link); - MG_ASSERT(it == vertex->out_edges.end(), "Invalid database state!"); - vertex->out_edges.push_back(link); + VertexData::EdgeLink link{current->vertex_edge.edge_type, current->vertex_edge.vertex_id, + current->vertex_edge.edge}; + auto it = std::find(vertex.out_edges.begin(), vertex.out_edges.end(), link); + MG_ASSERT(it == vertex.out_edges.end(), "Invalid database state!"); + vertex.out_edges.push_back(link); // Increment edge count. We only increment the count here because // the information in `ADD_IN_EDGE` and `Edge/RECREATE_OBJECT` is // redundant. Also, `Edge/RECREATE_OBJECT` isn't available when @@ -738,21 +734,21 @@ void Shard::Accessor::Abort() { break; } case Delta::Action::REMOVE_IN_EDGE: { - Vertex::EdgeLink link{current->vertex_edge.edge_type, current->vertex_edge.vertex_id, - current->vertex_edge.edge}; - auto it = std::find(vertex->in_edges.begin(), vertex->in_edges.end(), link); - MG_ASSERT(it != vertex->in_edges.end(), "Invalid database state!"); - std::swap(*it, *vertex->in_edges.rbegin()); - vertex->in_edges.pop_back(); + VertexData::EdgeLink link{current->vertex_edge.edge_type, current->vertex_edge.vertex_id, + current->vertex_edge.edge}; + auto it = std::find(vertex.in_edges.begin(), vertex.in_edges.end(), link); + MG_ASSERT(it != vertex.in_edges.end(), "Invalid database state!"); + std::swap(*it, *vertex.in_edges.rbegin()); + vertex.in_edges.pop_back(); break; } case Delta::Action::REMOVE_OUT_EDGE: { - Vertex::EdgeLink link{current->vertex_edge.edge_type, current->vertex_edge.vertex_id, - current->vertex_edge.edge}; - auto it = std::find(vertex->out_edges.begin(), vertex->out_edges.end(), link); - MG_ASSERT(it != vertex->out_edges.end(), "Invalid database state!"); - std::swap(*it, *vertex->out_edges.rbegin()); - vertex->out_edges.pop_back(); + VertexData::EdgeLink link{current->vertex_edge.edge_type, current->vertex_edge.vertex_id, + current->vertex_edge.edge}; + auto it = std::find(vertex.out_edges.begin(), vertex.out_edges.end(), link); + MG_ASSERT(it != vertex.out_edges.end(), "Invalid database state!"); + std::swap(*it, *vertex.out_edges.rbegin()); + vertex.out_edges.pop_back(); // Decrement edge count. We only decrement the count here because // the information in `REMOVE_IN_EDGE` and `Edge/DELETE_OBJECT` is // redundant. Also, `Edge/DELETE_OBJECT` isn't available when edge @@ -761,20 +757,20 @@ void Shard::Accessor::Abort() { break; } case Delta::Action::DELETE_OBJECT: { - vertex->deleted = true; - shard_->deleted_vertices_.push_back(vertex->keys.Keys()); + vertex.deleted = true; + shard_->deleted_vertices_.push_back(&pk); break; } case Delta::Action::RECREATE_OBJECT: { - vertex->deleted = false; + vertex.deleted = false; break; } } current = current->next; } - vertex->delta = current; + vertex.delta = current; if (current != nullptr) { - current->prev.Set(vertex); + current->prev.Set(prev.vertex); } break; @@ -851,10 +847,7 @@ const std::string &Shard::EdgeTypeToName(EdgeTypeId edge_type) const { bool Shard::CreateIndex(LabelId label, const std::optional<uint64_t> /*desired_commit_timestamp*/) { // TODO(jbajic) response should be different when label == primary_label - if (label == primary_label_ || !indices_.label_index.CreateIndex(label, vertices_.access())) { - return false; - } - return true; + return !(label == primary_label_ || !indices_.label_index.CreateIndex(label, vertices_)); } bool Shard::CreateIndex(LabelId label, PropertyId property, @@ -865,7 +858,7 @@ bool Shard::CreateIndex(LabelId label, PropertyId property, // Index already exists on primary key return false; } - if (!indices_.label_property_index.CreateIndex(label, property, vertices_.access())) { + if (!indices_.label_property_index.CreateIndex(label, property, vertices_)) { return false; } return true; @@ -972,10 +965,12 @@ void Shard::CollectGarbage(const io::Time current_time) { auto prev = delta.prev.Get(); switch (prev.type) { case PreviousPtr::Type::VERTEX: { - Vertex *vertex = prev.vertex; - vertex->delta = nullptr; - if (vertex->deleted) { - deleted_vertices_.push_back(vertex->keys.Keys()); + // Here we need to get pk from prev pointer, and that is why change + // to the PrevPtr so it points to pair of pk and vertex + auto &[pk, vertex] = *prev.vertex; + vertex.delta = nullptr; + if (vertex.deleted) { + deleted_vertices_.push_back(&pk); } break; } @@ -1022,15 +1017,13 @@ void Shard::CollectGarbage(const io::Time current_time) { RemoveObsoleteEntries(&indices_, clean_up_before_timestamp); } - auto vertex_acc = vertices_.access(); - for (const auto &vertex : deleted_vertices_) { - MG_ASSERT(vertex_acc.remove(vertex), "Invalid database state!"); + for (const auto *vertex : deleted_vertices_) { + MG_ASSERT(vertices_.erase(*vertex), "Invalid database state!"); } deleted_vertices_.clear(); { - auto edge_acc = edges_.access(); for (auto edge : deleted_edges_) { - MG_ASSERT(edge_acc.remove(edge), "Invalid database state!"); + MG_ASSERT(edges_.erase(edge), "Invalid database state!"); } } deleted_edges_.clear(); diff --git a/src/storage/v3/shard.hpp b/src/storage/v3/shard.hpp index 5c025ae57..16e2bf6be 100644 --- a/src/storage/v3/shard.hpp +++ b/src/storage/v3/shard.hpp @@ -31,7 +31,6 @@ #include "storage/v3/indices.hpp" #include "storage/v3/isolation_level.hpp" #include "storage/v3/key_store.hpp" -#include "storage/v3/lexicographically_ordered_vertex.hpp" #include "storage/v3/mvcc.hpp" #include "storage/v3/name_id_mapper.hpp" #include "storage/v3/property_value.hpp" @@ -42,7 +41,6 @@ #include "storage/v3/vertex.hpp" #include "storage/v3/vertex_accessor.hpp" #include "storage/v3/vertex_id.hpp" -#include "storage/v3/vertices_skip_list.hpp" #include "storage/v3/view.hpp" #include "utils/exceptions.hpp" #include "utils/file_locker.hpp" @@ -65,7 +63,7 @@ namespace memgraph::storage::v3 { /// An instance of this will be usually be wrapped inside VerticesIterable for /// generic, public use. class AllVerticesIterable final { - VerticesSkipList::Accessor vertices_accessor_; + VertexContainer *vertices_accessor_; Transaction *transaction_; View view_; Indices *indices_; @@ -76,10 +74,10 @@ class AllVerticesIterable final { public: class Iterator final { AllVerticesIterable *self_; - VerticesSkipList::Iterator it_; + VertexContainer::iterator it_; public: - Iterator(AllVerticesIterable *self, VerticesSkipList::Iterator it); + Iterator(AllVerticesIterable *self, VertexContainer::iterator it); VertexAccessor operator*() const; @@ -90,17 +88,17 @@ class AllVerticesIterable final { bool operator!=(const Iterator &other) const { return !(*this == other); } }; - AllVerticesIterable(VerticesSkipList::Accessor vertices_accessor, Transaction *transaction, View view, - Indices *indices, Config::Items config, const VertexValidator &vertex_validator) - : vertices_accessor_(std::move(vertices_accessor)), + AllVerticesIterable(VertexContainer &vertices_accessor, Transaction *transaction, View view, Indices *indices, + Config::Items config, const VertexValidator &vertex_validator) + : vertices_accessor_(&vertices_accessor), transaction_(transaction), view_(view), indices_(indices), config_(config), vertex_validator_{&vertex_validator} {} - Iterator begin() { return {this, vertices_accessor_.begin()}; } - Iterator end() { return {this, vertices_accessor_.end()}; } + Iterator begin() { return {this, vertices_accessor_->begin()}; } + Iterator end() { return {this, vertices_accessor_->end()}; } }; /// Generic access to different kinds of vertex iterations. @@ -213,7 +211,7 @@ class Shard final { std::optional<VertexAccessor> FindVertex(std::vector<PropertyValue> primary_key, 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_)); } @@ -236,18 +234,17 @@ class Shard final { int64_t ApproximateVertexCount(LabelId label) const { return shard_->indices_.label_index.ApproximateVertexCount(label); } - /// Return approximate number of vertices with the given label and property. /// Note that this is always an over-estimate and never an under-estimate. int64_t ApproximateVertexCount(LabelId label, PropertyId property) const { - return shard_->indices_.label_property_index.ApproximateVertexCount(label, property); + return shard_->indices_.label_property_index.VertexCount(label, property); } /// Return approximate number of vertices with the given label and the given - /// value for the given property. Note that this is always an over-estimate - /// and never an under-estimate. + /// value for the given property. + /// Note that this is always an over-estimate and never an under-estimate. int64_t ApproximateVertexCount(LabelId label, PropertyId property, const PropertyValue &value) const { - return shard_->indices_.label_property_index.ApproximateVertexCount(label, property, value); + return shard_->indices_.label_property_index.VertexCount(label, property, value); } /// Return approximate number of vertices with the given label and value for @@ -256,7 +253,7 @@ class Shard final { int64_t ApproximateVertexCount(LabelId label, PropertyId property, const std::optional<utils::Bound<PropertyValue>> &lower, const std::optional<utils::Bound<PropertyValue>> &upper) const { - return shard_->indices_.label_property_index.ApproximateVertexCount(label, property, lower, upper); + return shard_->indices_.label_property_index.VertexCount(label, property, lower, upper); } /// @return Accessor to the deleted vertex if a deletion took place, std::nullopt otherwise @@ -309,9 +306,6 @@ class Shard final { void Abort(); private: - /// @throw std::bad_alloc - VertexAccessor CreateVertex(Gid gid, LabelId primary_label); - Shard *shard_; Transaction *transaction_; Config::Items config_; @@ -377,8 +371,8 @@ class Shard final { // The shard's range is [min, max) PrimaryKey min_primary_key_; std::optional<PrimaryKey> max_primary_key_; - VerticesSkipList vertices_; - utils::SkipList<Edge> edges_; + VertexContainer vertices_; + EdgeContainer edges_; // 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 // keep a separate count of edges that is always updated. @@ -396,7 +390,7 @@ class Shard final { // Vertices that are logically deleted but still have to be removed from // indices before removing them from the main storage. - std::list<PrimaryKey> deleted_vertices_; + std::list<const PrimaryKey *> deleted_vertices_; // Edges that are logically deleted and wait to be removed from the main // storage. diff --git a/src/storage/v3/vertices_skip_list.hpp b/src/storage/v3/vertex.cpp similarity index 56% rename from src/storage/v3/vertices_skip_list.hpp rename to src/storage/v3/vertex.cpp index 283dd5aeb..0dc80ad65 100644 --- a/src/storage/v3/vertices_skip_list.hpp +++ b/src/storage/v3/vertex.cpp @@ -9,11 +9,22 @@ // by the Apache License, Version 2.0, included in the file // licenses/APL.txt. -#pragma once +#include "storage/v3/vertex.hpp" -#include "storage/v3/lexicographically_ordered_vertex.hpp" -#include "utils/skip_list.hpp" +#include <limits> +#include <tuple> +#include <type_traits> +#include <vector> + +#include "storage/v3/delta.hpp" namespace memgraph::storage::v3 { -using VerticesSkipList = utils::SkipList<LexicographicallyOrderedVertex>; + +VertexData::VertexData(Delta *delta) : delta{delta} { + MG_ASSERT(delta == nullptr || delta->action == Delta::Action::DELETE_OBJECT, + "Vertex must be created with an initial DELETE_OBJECT delta!"); +} + +bool VertexHasLabel(const Vertex &vertex, const LabelId label) { return utils::Contains(vertex.second.labels, label); } + } // namespace memgraph::storage::v3 diff --git a/src/storage/v3/vertex.hpp b/src/storage/v3/vertex.hpp index 2ed4c6e4c..66d7a38e8 100644 --- a/src/storage/v3/vertex.hpp +++ b/src/storage/v3/vertex.hpp @@ -16,7 +16,6 @@ #include <type_traits> #include <vector> -#include "storage/v3/delta.hpp" #include "storage/v3/edge_ref.hpp" #include "storage/v3/id_types.hpp" #include "storage/v3/key_store.hpp" @@ -28,17 +27,12 @@ namespace memgraph::storage::v3 { -struct Vertex { +struct Delta; + +struct VertexData { using EdgeLink = std::tuple<EdgeTypeId, VertexId, EdgeRef>; - Vertex(Delta *delta, const std::vector<PropertyValue> &primary_properties) : keys{primary_properties}, delta{delta} { - MG_ASSERT(delta == nullptr || delta->action == Delta::Action::DELETE_OBJECT, - "Vertex must be created with an initial DELETE_OBJECT delta!"); - } - - friend bool operator==(const Vertex &vertex, const PrimaryKey &primary_key) { return vertex.keys == primary_key; } - - KeyStore keys; + explicit VertexData(Delta *delta); std::vector<LabelId> labels; PropertyStore properties; @@ -52,8 +46,11 @@ struct Vertex { Delta *delta; }; -static_assert(alignof(Vertex) >= 8, "The Vertex should be aligned to at least 8!"); +static_assert(alignof(VertexData) >= 8, "The Vertex should be aligned to at least 8!"); -inline bool VertexHasLabel(const Vertex &vertex, const LabelId label) { return utils::Contains(vertex.labels, label); } +using VertexContainer = std::map<PrimaryKey, VertexData>; +using Vertex = VertexContainer::value_type; + +bool VertexHasLabel(const Vertex &vertex, LabelId label); } // namespace memgraph::storage::v3 diff --git a/src/storage/v3/vertex_accessor.cpp b/src/storage/v3/vertex_accessor.cpp index 1b0ba6340..95e0524ea 100644 --- a/src/storage/v3/vertex_accessor.cpp +++ b/src/storage/v3/vertex_accessor.cpp @@ -36,8 +36,8 @@ std::pair<bool, bool> IsVisible(Vertex *vertex, Transaction *transaction, View v bool deleted = false; Delta *delta = nullptr; { - deleted = vertex->deleted; - delta = vertex->delta; + deleted = vertex->second.deleted; + delta = vertex->second.delta; } ApplyDeltasForRead(transaction, delta, view, [&](const Delta &delta) { switch (delta.action) { @@ -85,13 +85,14 @@ ShardResult<bool> VertexAccessor::AddLabel(LabelId label) { if (!PrepareForWrite(transaction_, vertex_)) return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR); - if (vertex_->deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT); + if (vertex_->second.deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT); - if (std::find(vertex_->labels.begin(), vertex_->labels.end(), label) != vertex_->labels.end()) return false; + if (std::find(vertex_->second.labels.begin(), vertex_->second.labels.end(), label) != vertex_->second.labels.end()) + return false; CreateAndLinkDelta(transaction_, vertex_, Delta::RemoveLabelTag(), label); - vertex_->labels.push_back(label); + vertex_->second.labels.push_back(label); UpdateOnAddLabel(indices_, label, vertex_, *transaction_); @@ -106,13 +107,14 @@ ShardResult<bool> VertexAccessor::AddLabelAndValidate(LabelId label) { if (!PrepareForWrite(transaction_, vertex_)) return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR); - if (vertex_->deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT); + if (vertex_->second.deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT); - if (std::find(vertex_->labels.begin(), vertex_->labels.end(), label) != vertex_->labels.end()) return false; + if (std::find(vertex_->second.labels.begin(), vertex_->second.labels.end(), label) != vertex_->second.labels.end()) + return false; CreateAndLinkDelta(transaction_, vertex_, Delta::RemoveLabelTag(), label); - vertex_->labels.push_back(label); + vertex_->second.labels.push_back(label); UpdateOnAddLabel(indices_, label, vertex_, *transaction_); @@ -122,15 +124,15 @@ ShardResult<bool> VertexAccessor::AddLabelAndValidate(LabelId label) { ShardResult<bool> VertexAccessor::RemoveLabel(LabelId label) { if (!PrepareForWrite(transaction_, vertex_)) return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR); - if (vertex_->deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT); + if (vertex_->second.deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT); - auto it = std::find(vertex_->labels.begin(), vertex_->labels.end(), label); - if (it == vertex_->labels.end()) return false; + auto it = std::find(vertex_->second.labels.begin(), vertex_->second.labels.end(), label); + if (it == vertex_->second.labels.end()) return false; CreateAndLinkDelta(transaction_, vertex_, Delta::AddLabelTag(), label); - std::swap(*it, *vertex_->labels.rbegin()); - vertex_->labels.pop_back(); + std::swap(*it, *vertex_->second.labels.rbegin()); + vertex_->second.labels.pop_back(); return true; } @@ -142,15 +144,15 @@ ShardResult<bool> VertexAccessor::RemoveLabelAndValidate(LabelId label) { if (!PrepareForWrite(transaction_, vertex_)) return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR); - if (vertex_->deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT); + if (vertex_->second.deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT); - auto it = std::find(vertex_->labels.begin(), vertex_->labels.end(), label); - if (it == vertex_->labels.end()) return false; + auto it = std::find(vertex_->second.labels.begin(), vertex_->second.labels.end(), label); + if (it == vertex_->second.labels.end()) return false; CreateAndLinkDelta(transaction_, vertex_, Delta::AddLabelTag(), label); - std::swap(*it, *vertex_->labels.rbegin()); - vertex_->labels.pop_back(); + std::swap(*it, *vertex_->second.labels.rbegin()); + vertex_->second.labels.pop_back(); return true; } @@ -162,9 +164,9 @@ ShardResult<bool> VertexAccessor::HasLabel(LabelId label, View view) const { bool has_label = false; Delta *delta = nullptr; { - deleted = vertex_->deleted; + deleted = vertex_->second.deleted; has_label = label == vertex_validator_->primary_label_ || VertexHasLabel(*vertex_, label); - delta = vertex_->delta; + delta = vertex_->second.delta; } ApplyDeltasForRead(transaction_, delta, view, [&exists, &deleted, &has_label, label](const Delta &delta) { switch (delta.action) { @@ -215,14 +217,14 @@ ShardResult<PrimaryKey> VertexAccessor::PrimaryKey(const View view) const { if (const auto result = CheckVertexExistence(view); result.HasError()) { return result.GetError(); } - return vertex_->keys.Keys(); + return vertex_->first; } ShardResult<VertexId> VertexAccessor::Id(View view) const { if (const auto result = CheckVertexExistence(view); result.HasError()) { return result.GetError(); } - return VertexId{vertex_validator_->primary_label_, vertex_->keys.Keys()}; + return VertexId{vertex_validator_->primary_label_, vertex_->first}; }; ShardResult<std::vector<LabelId>> VertexAccessor::Labels(View view) const { @@ -231,9 +233,9 @@ ShardResult<std::vector<LabelId>> VertexAccessor::Labels(View view) const { std::vector<LabelId> labels; Delta *delta = nullptr; { - deleted = vertex_->deleted; - labels = vertex_->labels; - delta = vertex_->delta; + deleted = vertex_->second.deleted; + labels = vertex_->second.labels; + delta = vertex_->second.delta; } ApplyDeltasForRead(transaction_, delta, view, [&exists, &deleted, &labels](const Delta &delta) { switch (delta.action) { @@ -278,9 +280,9 @@ ShardResult<PropertyValue> VertexAccessor::SetProperty(PropertyId property, cons if (!PrepareForWrite(transaction_, vertex_)) return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR); - if (vertex_->deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT); + if (vertex_->second.deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT); - auto current_value = vertex_->properties.GetProperty(property); + auto current_value = vertex_->second.properties.GetProperty(property); // We could skip setting the value if the previous one is the same to the new // one. This would save some memory as a delta would not be created as well as // avoid copying the value. The reason we are not doing that is because the @@ -288,7 +290,7 @@ ShardResult<PropertyValue> VertexAccessor::SetProperty(PropertyId property, cons // "modify in-place". Additionally, the created delta will make other // transactions get a SERIALIZATION_ERROR. CreateAndLinkDelta(transaction_, vertex_, Delta::SetPropertyTag(), property, current_value); - vertex_->properties.SetProperty(property, value); + vertex_->second.properties.SetProperty(property, value); UpdateOnSetProperty(indices_, property, value, vertex_, *transaction_); @@ -300,8 +302,8 @@ ShardResult<void> VertexAccessor::CheckVertexExistence(View view) const { bool deleted = false; Delta *delta = nullptr; { - deleted = vertex_->deleted; - delta = vertex_->delta; + deleted = vertex_->second.deleted; + delta = vertex_->second.delta; } ApplyDeltasForRead(transaction_, delta, view, [&exists, &deleted](const Delta &delta) { switch (delta.action) { @@ -343,11 +345,11 @@ ShardResult<PropertyValue> VertexAccessor::SetPropertyAndValidate(PropertyId pro return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR); } - if (vertex_->deleted) { + if (vertex_->second.deleted) { return SHARD_ERROR(ErrorCode::DELETED_OBJECT); } - auto current_value = vertex_->properties.GetProperty(property); + auto current_value = vertex_->second.properties.GetProperty(property); // We could skip setting the value if the previous one is the same to the new // one. This would save some memory as a delta would not be created as well as // avoid copying the value. The reason we are not doing that is because the @@ -355,7 +357,7 @@ ShardResult<PropertyValue> VertexAccessor::SetPropertyAndValidate(PropertyId pro // "modify in-place". Additionally, the created delta will make other // transactions get a SERIALIZATION_ERROR. CreateAndLinkDelta(transaction_, vertex_, Delta::SetPropertyTag(), property, current_value); - vertex_->properties.SetProperty(property, value); + vertex_->second.properties.SetProperty(property, value); UpdateOnSetProperty(indices_, property, value, vertex_, *transaction_); @@ -365,15 +367,15 @@ ShardResult<PropertyValue> VertexAccessor::SetPropertyAndValidate(PropertyId pro ShardResult<std::map<PropertyId, PropertyValue>> VertexAccessor::ClearProperties() { if (!PrepareForWrite(transaction_, vertex_)) return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR); - if (vertex_->deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT); + if (vertex_->second.deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT); - auto properties = vertex_->properties.Properties(); + auto properties = vertex_->second.properties.Properties(); for (const auto &property : properties) { CreateAndLinkDelta(transaction_, vertex_, Delta::SetPropertyTag(), property.first, property.second); UpdateOnSetProperty(indices_, property.first, PropertyValue(), vertex_, *transaction_); } - vertex_->properties.ClearProperties(); + vertex_->second.properties.ClearProperties(); return std::move(properties); } @@ -394,18 +396,13 @@ PropertyValue VertexAccessor::GetPropertyValue(PropertyId property, View view) c return value; } // Find PropertyId index in keystore - size_t property_index{0}; - for (; 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) { - break; + return vertex_->first[property_index]; } } - value = vertex_->keys.GetKey(property_index); - if (value.IsNull()) { - value = vertex_->properties.GetProperty(property); - } - return value; + return value = vertex_->second.properties.GetProperty(property); } ShardResult<PropertyValue> VertexAccessor::GetProperty(PropertyId property, View view) const { @@ -414,9 +411,9 @@ ShardResult<PropertyValue> VertexAccessor::GetProperty(PropertyId property, View PropertyValue value; Delta *delta = nullptr; { - deleted = vertex_->deleted; + deleted = vertex_->second.deleted; value = GetPropertyValue(property, view); - delta = vertex_->delta; + delta = vertex_->second.delta; } ApplyDeltasForRead(transaction_, delta, view, [&exists, &deleted, &value, property](const Delta &delta) { switch (delta.action) { @@ -443,8 +440,12 @@ ShardResult<PropertyValue> VertexAccessor::GetProperty(PropertyId property, View break; } }); - if (!exists) return SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT); - if (!for_deleted_ && deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT); + if (!exists) { + return SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT); + } + if (!for_deleted_ && deleted) { + return SHARD_ERROR(ErrorCode::DELETED_OBJECT); + } return std::move(value); } @@ -454,10 +455,10 @@ ShardResult<std::map<PropertyId, PropertyValue>> VertexAccessor::Properties(View std::map<PropertyId, PropertyValue> properties; Delta *delta = nullptr; { - deleted = vertex_->deleted; + deleted = vertex_->second.deleted; // TODO(antaljanosbenjamin): Should this also return the primary key? - properties = vertex_->properties.Properties(); - delta = vertex_->delta; + properties = vertex_->second.properties.Properties(); + delta = vertex_->second.delta; } ApplyDeltasForRead(transaction_, delta, view, [&exists, &deleted, &properties](const Delta &delta) { switch (delta.action) { @@ -502,14 +503,14 @@ ShardResult<std::vector<EdgeAccessor>> VertexAccessor::InEdges(View view, const const VertexId *destination_id) const { bool exists = true; bool deleted = false; - std::vector<Vertex::EdgeLink> in_edges; + std::vector<VertexData::EdgeLink> in_edges; Delta *delta = nullptr; { - deleted = vertex_->deleted; + deleted = vertex_->second.deleted; if (edge_types.empty() && nullptr == destination_id) { - in_edges = vertex_->in_edges; + in_edges = vertex_->second.in_edges; } else { - for (const auto &item : vertex_->in_edges) { + for (const auto &item : vertex_->second.in_edges) { const auto &[edge_type, from_vertex, edge] = item; if (nullptr != destination_id && from_vertex != *destination_id) { continue; @@ -519,7 +520,7 @@ ShardResult<std::vector<EdgeAccessor>> VertexAccessor::InEdges(View view, const in_edges.push_back(item); } } - delta = vertex_->delta; + delta = vertex_->second.delta; } ApplyDeltasForRead( transaction_, delta, view, [&exists, &deleted, &in_edges, &edge_types, destination_id](const Delta &delta) { @@ -530,7 +531,7 @@ ShardResult<std::vector<EdgeAccessor>> VertexAccessor::InEdges(View view, const std::find(edge_types.begin(), edge_types.end(), delta.vertex_edge.edge_type) == edge_types.end()) break; // Add the edge because we don't see the removal. - Vertex::EdgeLink link{delta.vertex_edge.edge_type, delta.vertex_edge.vertex_id, delta.vertex_edge.edge}; + VertexData::EdgeLink link{delta.vertex_edge.edge_type, delta.vertex_edge.vertex_id, delta.vertex_edge.edge}; auto it = std::find(in_edges.begin(), in_edges.end(), link); MG_ASSERT(it == in_edges.end(), "Invalid database state!"); in_edges.push_back(link); @@ -542,7 +543,7 @@ ShardResult<std::vector<EdgeAccessor>> VertexAccessor::InEdges(View view, const std::find(edge_types.begin(), edge_types.end(), delta.vertex_edge.edge_type) == edge_types.end()) break; // Remove the label because we don't see the addition. - Vertex::EdgeLink link{delta.vertex_edge.edge_type, delta.vertex_edge.vertex_id, delta.vertex_edge.edge}; + VertexData::EdgeLink link{delta.vertex_edge.edge_type, delta.vertex_edge.vertex_id, delta.vertex_edge.edge}; auto it = std::find(in_edges.begin(), in_edges.end(), link); MG_ASSERT(it != in_edges.end(), "Invalid database state!"); std::swap(*it, *in_edges.rbegin()); @@ -572,7 +573,7 @@ ShardResult<std::vector<EdgeAccessor>> VertexAccessor::InEdges(View view, const return ret; } ret.reserve(in_edges.size()); - const auto id = VertexId{vertex_validator_->primary_label_, vertex_->keys.Keys()}; + const auto id = VertexId{vertex_validator_->primary_label_, vertex_->first}; for (const auto &item : in_edges) { const auto &[edge_type, from_vertex, edge] = item; ret.emplace_back(edge, edge_type, from_vertex, id, transaction_, indices_, config_); @@ -584,14 +585,14 @@ ShardResult<std::vector<EdgeAccessor>> VertexAccessor::OutEdges(View view, const const VertexId *destination_id) const { bool exists = true; bool deleted = false; - std::vector<Vertex::EdgeLink> out_edges; + std::vector<VertexData::EdgeLink> out_edges; Delta *delta = nullptr; { - deleted = vertex_->deleted; + deleted = vertex_->second.deleted; if (edge_types.empty() && nullptr == destination_id) { - out_edges = vertex_->out_edges; + out_edges = vertex_->second.out_edges; } else { - for (const auto &item : vertex_->out_edges) { + for (const auto &item : vertex_->second.out_edges) { const auto &[edge_type, to_vertex, edge] = item; if (nullptr != destination_id && to_vertex != *destination_id) continue; if (!edge_types.empty() && std::find(edge_types.begin(), edge_types.end(), edge_type) == edge_types.end()) @@ -599,7 +600,7 @@ ShardResult<std::vector<EdgeAccessor>> VertexAccessor::OutEdges(View view, const out_edges.push_back(item); } } - delta = vertex_->delta; + delta = vertex_->second.delta; } ApplyDeltasForRead( transaction_, delta, view, [&exists, &deleted, &out_edges, &edge_types, destination_id](const Delta &delta) { @@ -610,7 +611,7 @@ ShardResult<std::vector<EdgeAccessor>> VertexAccessor::OutEdges(View view, const std::find(edge_types.begin(), edge_types.end(), delta.vertex_edge.edge_type) == edge_types.end()) break; // Add the edge because we don't see the removal. - Vertex::EdgeLink link{delta.vertex_edge.edge_type, delta.vertex_edge.vertex_id, delta.vertex_edge.edge}; + VertexData::EdgeLink link{delta.vertex_edge.edge_type, delta.vertex_edge.vertex_id, delta.vertex_edge.edge}; auto it = std::find(out_edges.begin(), out_edges.end(), link); MG_ASSERT(it == out_edges.end(), "Invalid database state!"); out_edges.push_back(link); @@ -622,7 +623,7 @@ ShardResult<std::vector<EdgeAccessor>> VertexAccessor::OutEdges(View view, const std::find(edge_types.begin(), edge_types.end(), delta.vertex_edge.edge_type) == edge_types.end()) break; // Remove the label because we don't see the addition. - Vertex::EdgeLink link{delta.vertex_edge.edge_type, delta.vertex_edge.vertex_id, delta.vertex_edge.edge}; + VertexData::EdgeLink link{delta.vertex_edge.edge_type, delta.vertex_edge.vertex_id, delta.vertex_edge.edge}; auto it = std::find(out_edges.begin(), out_edges.end(), link); MG_ASSERT(it != out_edges.end(), "Invalid database state!"); std::swap(*it, *out_edges.rbegin()); @@ -652,7 +653,7 @@ ShardResult<std::vector<EdgeAccessor>> VertexAccessor::OutEdges(View view, const return ret; } ret.reserve(out_edges.size()); - const auto id = VertexId{vertex_validator_->primary_label_, vertex_->keys.Keys()}; + const auto id = VertexId{vertex_validator_->primary_label_, vertex_->first}; for (const auto &item : out_edges) { const auto &[edge_type, to_vertex, edge] = item; ret.emplace_back(edge, edge_type, id, to_vertex, transaction_, indices_, config_); @@ -666,9 +667,9 @@ ShardResult<size_t> VertexAccessor::InDegree(View view) const { size_t degree = 0; Delta *delta = nullptr; { - deleted = vertex_->deleted; - degree = vertex_->in_edges.size(); - delta = vertex_->delta; + deleted = vertex_->second.deleted; + degree = vertex_->second.in_edges.size(); + delta = vertex_->second.delta; } ApplyDeltasForRead(transaction_, delta, view, [&exists, &deleted, °ree](const Delta &delta) { switch (delta.action) { @@ -703,9 +704,9 @@ ShardResult<size_t> VertexAccessor::OutDegree(View view) const { size_t degree = 0; Delta *delta = nullptr; { - deleted = vertex_->deleted; - degree = vertex_->out_edges.size(); - delta = vertex_->delta; + deleted = vertex_->second.deleted; + degree = vertex_->second.out_edges.size(); + delta = vertex_->second.delta; } ApplyDeltasForRead(transaction_, delta, view, [&exists, &deleted, °ree](const Delta &delta) { switch (delta.action) { diff --git a/tests/benchmark/data_structures_common.hpp b/tests/benchmark/data_structures_common.hpp index 23fe394ee..4c2d41fc0 100644 --- a/tests/benchmark/data_structures_common.hpp +++ b/tests/benchmark/data_structures_common.hpp @@ -17,9 +17,9 @@ #include "coordinator/hybrid_logical_clock.hpp" #include "storage/v3/key_store.hpp" -#include "storage/v3/lexicographically_ordered_vertex.hpp" #include "storage/v3/mvcc.hpp" #include "storage/v3/transaction.hpp" +#include "storage/v3/vertex.hpp" #include "utils/skip_list.hpp" namespace memgraph::benchmark { @@ -40,9 +40,7 @@ inline void PrepareData(std::map<TKey, TValue> &std_map, const int64_t num_eleme storage::v3::Transaction transaction{start_timestamp, storage::v3::IsolationLevel::SNAPSHOT_ISOLATION}; auto *delta = storage::v3::CreateDeleteObjectDelta(&transaction); for (auto i{0}; i < num_elements; ++i) { - std_map.insert({storage::v3::PrimaryKey{storage::v3::PropertyValue{i}}, - storage::v3::LexicographicallyOrderedVertex{storage::v3::Vertex{ - delta, std::vector<storage::v3::PropertyValue>{storage::v3::PropertyValue{true}}}}}); + std_map.insert({storage::v3::PrimaryKey{storage::v3::PropertyValue{i}}, storage::v3::VertexData{delta}}); } } diff --git a/tests/benchmark/data_structures_contains.cpp b/tests/benchmark/data_structures_contains.cpp index 47af24a1b..679adee1f 100644 --- a/tests/benchmark/data_structures_contains.cpp +++ b/tests/benchmark/data_structures_contains.cpp @@ -25,7 +25,6 @@ #include "data_structures_common.hpp" #include "storage/v3/key_store.hpp" -#include "storage/v3/lexicographically_ordered_vertex.hpp" #include "storage/v3/mvcc.hpp" #include "storage/v3/property_value.hpp" #include "storage/v3/transaction.hpp" @@ -57,7 +56,7 @@ static void BM_BenchmarkContainsSkipList(::benchmark::State &state) { } static void BM_BenchmarkContainsStdMap(::benchmark::State &state) { - std::map<storage::v3::PrimaryKey, storage::v3::LexicographicallyOrderedVertex> std_map; + std::map<storage::v3::PrimaryKey, storage::v3::VertexData> std_map; PrepareData(std_map, state.range(0)); // So we can also have elements that does don't exist diff --git a/tests/benchmark/data_structures_find.cpp b/tests/benchmark/data_structures_find.cpp index d51771be5..fc0473909 100644 --- a/tests/benchmark/data_structures_find.cpp +++ b/tests/benchmark/data_structures_find.cpp @@ -25,7 +25,6 @@ #include "data_structures_common.hpp" #include "storage/v3/key_store.hpp" -#include "storage/v3/lexicographically_ordered_vertex.hpp" #include "storage/v3/mvcc.hpp" #include "storage/v3/property_value.hpp" #include "storage/v3/transaction.hpp" @@ -57,7 +56,7 @@ static void BM_BenchmarkFindSkipList(::benchmark::State &state) { } static void BM_BenchmarkFindStdMap(::benchmark::State &state) { - std::map<storage::v3::PrimaryKey, storage::v3::LexicographicallyOrderedVertex> std_map; + std::map<storage::v3::PrimaryKey, storage::v3::VertexData> std_map; PrepareData(std_map, state.range(0)); // So we can also have elements that does don't exist std::mt19937 i_generator(std::random_device{}()); diff --git a/tests/benchmark/data_structures_insert.cpp b/tests/benchmark/data_structures_insert.cpp index d83cbfe23..b5dc99f38 100644 --- a/tests/benchmark/data_structures_insert.cpp +++ b/tests/benchmark/data_structures_insert.cpp @@ -24,7 +24,6 @@ #include <gflags/gflags.h> #include "storage/v3/key_store.hpp" -#include "storage/v3/lexicographically_ordered_vertex.hpp" #include "storage/v3/mvcc.hpp" #include "storage/v3/property_value.hpp" #include "storage/v3/transaction.hpp" @@ -50,16 +49,14 @@ static void BM_BenchmarkInsertSkipList(::benchmark::State &state) { } static void BM_BenchmarkInsertStdMap(::benchmark::State &state) { - std::map<storage::v3::PrimaryKey, storage::v3::LexicographicallyOrderedVertex> std_map; + std::map<storage::v3::PrimaryKey, storage::v3::VertexData> std_map; coordinator::Hlc start_timestamp; storage::v3::Transaction transaction{start_timestamp, storage::v3::IsolationLevel::SNAPSHOT_ISOLATION}; auto *delta = storage::v3::CreateDeleteObjectDelta(&transaction); for (auto _ : state) { for (auto i{0}; i < state.range(0); ++i) { - std_map.insert({storage::v3::PrimaryKey{storage::v3::PropertyValue{i}}, - storage::v3::LexicographicallyOrderedVertex{storage::v3::Vertex{ - delta, std::vector<storage::v3::PropertyValue>{storage::v3::PropertyValue{true}}}}}); + std_map.insert({storage::v3::PrimaryKey{storage::v3::PropertyValue{i}}, storage::v3::VertexData{delta}}); } } } diff --git a/tests/benchmark/data_structures_remove.cpp b/tests/benchmark/data_structures_remove.cpp index 641ad9453..2d060961d 100644 --- a/tests/benchmark/data_structures_remove.cpp +++ b/tests/benchmark/data_structures_remove.cpp @@ -25,7 +25,6 @@ #include "data_structures_common.hpp" #include "storage/v3/key_store.hpp" -#include "storage/v3/lexicographically_ordered_vertex.hpp" #include "storage/v3/mvcc.hpp" #include "storage/v3/property_value.hpp" #include "storage/v3/transaction.hpp" @@ -58,7 +57,7 @@ static void BM_BenchmarkRemoveSkipList(::benchmark::State &state) { } static void BM_BenchmarkRemoveStdMap(::benchmark::State &state) { - std::map<storage::v3::PrimaryKey, storage::v3::LexicographicallyOrderedVertex> std_map; + std::map<storage::v3::PrimaryKey, storage::v3::VertexData> std_map; PrepareData(std_map, state.range(0)); // So we can also have elements that does don't exist diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index 188c6c1b0..5bfa26afd 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -328,9 +328,6 @@ target_link_libraries(${test_prefix}query_v2_dummy_test mg-query-v2) add_unit_test(storage_v3_property_store.cpp) target_link_libraries(${test_prefix}storage_v3_property_store mg-storage-v3 fmt) -add_unit_test(storage_v3_key_store.cpp) -target_link_libraries(${test_prefix}storage_v3_key_store mg-storage-v3 rapidcheck rapidcheck_gtest) - add_unit_test(storage_v3_indices.cpp) target_link_libraries(${test_prefix}storage_v3_indices mg-storage-v3) diff --git a/tests/unit/storage_v3_key_store.cpp b/tests/unit/storage_v3_key_store.cpp deleted file mode 100644 index 4e9ae4da1..000000000 --- a/tests/unit/storage_v3_key_store.cpp +++ /dev/null @@ -1,46 +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 <string> -#include <vector> - -/** - * gtest/gtest.h must be included before rapidcheck/gtest.h! - */ -#include <gtest/gtest.h> -#include <rapidcheck.h> -#include <rapidcheck/gtest.h> - -#include "storage/v3/id_types.hpp" -#include "storage/v3/key_store.hpp" -#include "storage/v3/property_value.hpp" - -namespace memgraph::storage::v3::test { - -RC_GTEST_PROP(KeyStore, KeyStore, (std::vector<std::string> values)) { - RC_PRE(!values.empty()); - - std::vector<PropertyValue> property_values; - property_values.reserve(values.size()); - std::transform(values.begin(), values.end(), std::back_inserter(property_values), - [](std::string &value) { return PropertyValue{std::move(value)}; }); - - KeyStore key_store{property_values}; - - const auto keys = key_store.Keys(); - RC_ASSERT(keys.size() == property_values.size()); - for (int i = 0; i < keys.size(); ++i) { - RC_ASSERT(keys[i] == property_values[i]); - RC_ASSERT(key_store.GetKey(i) == property_values[i]); - } -} -} // namespace memgraph::storage::v3::test