diff --git a/include/barrier/barrier.hpp b/include/barrier/barrier.hpp index fe848c88d..74b645a67 100644 --- a/include/barrier/barrier.hpp +++ b/include/barrier/barrier.hpp @@ -283,8 +283,9 @@ public: void abort(); }; -class VertexIterator : public Sized<8, 8>, - public IteratorBase<const VertexAccessor> +class VertexIterator + : public Sized<8, 8>, + public iter::Composable<const VertexAccessor, VertexIterator> { public: template <class T> @@ -296,14 +297,15 @@ public: VertexIterator &operator=(const VertexIterator &other) = delete; VertexIterator &operator=(VertexIterator &&other) = delete; - Option<const VertexAccessor> next() final; + Option<const VertexAccessor> next(); - Count count() final; + Count count(); }; // TODO: Find reasons of such great size ant try to decrease it. -class VertexAccessIterator : public Sized<560, 8>, - public IteratorBase<const VertexAccessor> +class VertexAccessIterator + : public Sized<560, 8>, + public iter::Composable<const VertexAccessor, VertexAccessIterator> { public: template <class T> @@ -315,14 +317,15 @@ public: VertexAccessIterator &operator=(const VertexAccessIterator &other) = delete; VertexAccessIterator &operator=(VertexAccessIterator &&other) = delete; - Option<const VertexAccessor> next() final; + Option<const VertexAccessor> next(); - Count count() final; + Count count(); }; // TODO: Find reasons of such great size ant try to decrease it. -class EdgeAccessIterator : public Sized<560, 8>, - public IteratorBase<const EdgeAccessor> +class EdgeAccessIterator + : public Sized<560, 8>, + public iter::Composable<const EdgeAccessor, EdgeAccessIterator> { public: template <class T> @@ -334,13 +337,14 @@ public: EdgeAccessIterator &operator=(const EdgeAccessIterator &other) = delete; EdgeAccessIterator &operator=(EdgeAccessIterator &&other) = delete; - Option<const EdgeAccessor> next() final; + Option<const EdgeAccessor> next(); - Count count() final; + Count count(); }; -class OutEdgesIterator : public Sized<48, 8>, - public IteratorBase<const EdgeAccessor> +class OutEdgesIterator + : public Sized<48, 8>, + public iter::Composable<const EdgeAccessor, OutEdgesIterator> { public: template <class T> @@ -352,13 +356,14 @@ public: OutEdgesIterator &operator=(const OutEdgesIterator &other) = delete; OutEdgesIterator &operator=(OutEdgesIterator &&other) = delete; - Option<const EdgeAccessor> next() final; + Option<const EdgeAccessor> next(); - Count count() final; + Count count(); }; -class InEdgesIterator : public Sized<64, 8>, - public IteratorBase<const EdgeAccessor> +class InEdgesIterator + : public Sized<64, 8>, + public iter::Composable<const EdgeAccessor, InEdgesIterator> { public: template <class T> @@ -370,12 +375,13 @@ public: InEdgesIterator &operator=(const InEdgesIterator &other) = delete; InEdgesIterator &operator=(InEdgesIterator &&other) = delete; - Option<const EdgeAccessor> next() final; + Option<const EdgeAccessor> next(); - Count count() final; + Count count(); }; -class EdgeIterator : public Sized<8, 8>, public IteratorBase<const EdgeAccessor> +class EdgeIterator : public Sized<8, 8>, + public iter::Composable<const EdgeAccessor, EdgeIterator> { public: template <class T> @@ -387,9 +393,9 @@ public: EdgeIterator &operator=(const EdgeIterator &other) = delete; EdgeIterator &operator=(EdgeIterator &&other) = delete; - Option<const EdgeAccessor> next() final; + Option<const EdgeAccessor> next(); - Count count() final; + Count count(); EdgeIterator &operator->() { return *this; } }; diff --git a/include/barrier/trans.hpp b/include/barrier/trans.hpp index 1e474903f..0552138e5 100644 --- a/include/barrier/trans.hpp +++ b/include/barrier/trans.hpp @@ -177,14 +177,12 @@ TRANSFORM_REF(EdgePropertyKey, ::EdgePropertyFamily::PropertyType::PropertyFamilyKey); // ITERATORS -TRANSFORM_REF_SIZED(VertexIterator, - std::unique_ptr<IteratorBase<const ::VertexAccessor>>); -TRANSFORM_REF_SIZED(EdgeIterator, - std::unique_ptr<IteratorBase<const ::EdgeAccessor>>); -TRANSFORM_REF_SIZED(VertexAccessIterator, vertex_access_iterator_t); -TRANSFORM_REF_SIZED(EdgeAccessIterator, edge_access_iterator_t); -TRANSFORM_REF_SIZED(OutEdgesIterator, out_edge_iterator_t); -TRANSFORM_REF_SIZED(InEdgesIterator, in_edge_iterator_t); +TRANSFORM_REF(VertexIterator, ::iter::Virtual<const ::VertexAccessor>); +TRANSFORM_REF(EdgeIterator, ::iter::Virtual<const ::EdgeAccessor>); +TRANSFORM_REF(VertexAccessIterator, vertex_access_iterator_t); +TRANSFORM_REF(EdgeAccessIterator, edge_access_iterator_t); +TRANSFORM_REF(OutEdgesIterator, out_edge_iterator_t); +TRANSFORM_REF(InEdgesIterator, in_edge_iterator_t); template <class T> TRANSFORM_REF_TEMPLATED(VertexIndex<T>, VertexIndexBase<T>); @@ -212,22 +210,18 @@ TRANSFORM_VALUE(EdgePropertyKey, TRANSFORM_VALUE(VertexPropertyKey, ::VertexPropertyFamily::PropertyType::PropertyFamilyKey); TRANSFORM_VALUE_ONE(VertexAccessIterator, vertex_access_iterator_t); -// MOVE_CONSTRUCTOR_FORCED(VertexAccessIterator, vertex_access_iterator_t); +MOVE_CONSTRUCTOR_FORCED(VertexAccessIterator, vertex_access_iterator_t); TRANSFORM_VALUE_ONE(EdgeAccessIterator, edge_access_iterator_t); -// MOVE_CONSTRUCTOR_FORCED(EdgeAccessIterator, edge_access_iterator_t); +MOVE_CONSTRUCTOR_FORCED(EdgeAccessIterator, edge_access_iterator_t); TRANSFORM_VALUE_ONE(OutEdgesIterator, out_edge_iterator_t); -// MOVE_CONSTRUCTOR_FORCED(OutEdgesIterator, out_edge_iterator_t); +MOVE_CONSTRUCTOR_FORCED(OutEdgesIterator, out_edge_iterator_t); TRANSFORM_VALUE_ONE(InEdgesIterator, in_edge_iterator_t); -// MOVE_CONSTRUCTOR_FORCED(InEdgesIterator, in_edge_iterator_t); -TRANSFORM_VALUE_ONE(VertexIterator, - std::unique_ptr<IteratorBase<const ::VertexAccessor>>); -// MOVE_CONSTRUCTOR_FORCED(VertexIterator, -// std::unique_ptr<IteratorBase<const -// ::VertexAccessor>>); -TRANSFORM_VALUE_ONE(EdgeIterator, - std::unique_ptr<IteratorBase<const ::EdgeAccessor>>); -// MOVE_CONSTRUCTOR_FORCED(EdgeIterator, -// std::unique_ptr<IteratorBase<const ::EdgeAccessor>>); +MOVE_CONSTRUCTOR_FORCED(InEdgesIterator, in_edge_iterator_t); +TRANSFORM_VALUE_ONE(VertexIterator, ::iter::Virtual<const ::VertexAccessor>); +MOVE_CONSTRUCTOR_FORCED(VertexIterator, + ::iter::Virtual<const ::VertexAccessor>); +TRANSFORM_VALUE_ONE(EdgeIterator, ::iter::Virtual<const ::EdgeAccessor>); +MOVE_CONSTRUCTOR_FORCED(EdgeIterator, ::iter::Virtual<const ::EdgeAccessor>); template <class T> TRANSFORM_VALUE_ONE_RAW( diff --git a/include/data_structures/concurrent/concurrent_list.hpp b/include/data_structures/concurrent/concurrent_list.hpp index 0dfdd41e2..55ac5f337 100644 --- a/include/data_structures/concurrent/concurrent_list.hpp +++ b/include/data_structures/concurrent/concurrent_list.hpp @@ -5,6 +5,7 @@ #include <utility> #include "utils/crtp.hpp" +// TODO: reimplement this template <class T> class List { @@ -186,19 +187,23 @@ private: private: void find_and_disconnect() { - auto it = It(list); + Node *bef = nullptr; + auto now = load(list->head); auto next = load(curr->next); - while (it.valid()) { - if (it.curr == curr) { - if (it.disconnect()) { + while (now != nullptr) { + if (now == curr) { + prev = bef; + if (disconnect()) { return; } - it.reset(); - } else if (it.curr == next) { // Comparison with next is - // optimization for early return. + bef = nullptr; + now = load(list->head); + } else if (now == next) { // Comparison with next is + // optimization for early return. return; } else { - it++; + bef = now; + now = load(now->next); } } } diff --git a/include/query_engine/hardcode/queries.hpp b/include/query_engine/hardcode/queries.hpp index 8aa8c79a2..00b822a92 100644 --- a/include/query_engine/hardcode/queries.hpp +++ b/include/query_engine/hardcode/queries.hpp @@ -36,6 +36,18 @@ auto load_queries(Db &db) return t.commit(); }; + auto create_labeled_and_named_node_v2 = [&db](const properties_t &args) { + DbAccessor t(db); + auto prop_key = t.vertex_property_key("name", args[0]->flags); + auto &label = t.label_find_or_create("OTHER"); + + auto vertex_accessor = t.vertex_insert(); + vertex_accessor.set(prop_key, args[0]); + vertex_accessor.add_label(label); + // cout_properties(vertex_accessor.properties()); + return t.commit(); + }; + auto create_account = [&db](const properties_t &args) { DbAccessor t(db); auto prop_id = t.vertex_property_key("id", args[0]->flags); @@ -400,6 +412,7 @@ auto load_queries(Db &db) queries[15648836733456301916u] = create_edge_v2; queries[10597108978382323595u] = create_account; queries[5397556489557792025u] = create_labeled_and_named_node; + queries[16090682663946456821u] = create_labeled_and_named_node_v2; queries[7939106225150551899u] = create_edge; queries[6579425155585886196u] = create_edge; queries[11198568396549106428u] = find_node_by_internal_id; @@ -412,8 +425,8 @@ auto load_queries(Db &db) queries[14897166600223619735u] = match_edge_all_delete; queries[16888549834923624215u] = match_edge_type_delete; queries[11675960684124428508u] = match_id_type_return; - queries[1554436524951961398u] = match_name_type_return; - queries[8537338362659537296u] = match_name_type_return_cross; + queries[15698881472054193835u] = match_name_type_return; + queries[12595102442911913761u] = match_name_type_return_cross; queries[8918221081398321263u] = match_label_type_return; return queries; diff --git a/include/storage/indexes/impl/nonunique_unordered_index.hpp b/include/storage/indexes/impl/nonunique_unordered_index.hpp index 6cd52ae55..6fba48e75 100644 --- a/include/storage/indexes/impl/nonunique_unordered_index.hpp +++ b/include/storage/indexes/impl/nonunique_unordered_index.hpp @@ -24,7 +24,7 @@ public: // Returns iterator which returns valid records in range. // ordered==None => doesn't guarantee any order of submitting records. - std::unique_ptr<IteratorBase<const typename TG::accessor_t>> + iter::Virtual<const typename TG::accessor_t> for_range(DbAccessor &t, Border<K> from = Border<K>(), Border<K> to = Border<K>()) final; diff --git a/include/storage/indexes/impl/unique_ordered_index.hpp b/include/storage/indexes/impl/unique_ordered_index.hpp index d4519e6d9..bdc0f560f 100644 --- a/include/storage/indexes/impl/unique_ordered_index.hpp +++ b/include/storage/indexes/impl/unique_ordered_index.hpp @@ -22,7 +22,7 @@ public: // Returns iterator which returns valid records in range. // ordered==None => doesn't guarantee any order of submitting records. - std::unique_ptr<IteratorBase<const typename T::accessor_t>> + iter::Virtual<const typename T::accessor_t> for_range(DbAccessor &t, Border<K> from = Border<K>(), Border<K> to = Border<K>()) final; diff --git a/include/storage/indexes/index_base.hpp b/include/storage/indexes/index_base.hpp index be4d98612..08270d5ab 100644 --- a/include/storage/indexes/index_base.hpp +++ b/include/storage/indexes/index_base.hpp @@ -8,7 +8,7 @@ // #include "storage/indexes/index_record.hpp" #include "storage/garbage/delete_sensitive.hpp" #include "utils/border.hpp" -#include "utils/iterator/iterator_base.hpp" +#include "utils/iterator/virtual_iter.hpp" #include "utils/order.hpp" template <class TG, class K> @@ -50,7 +50,7 @@ public: // order==Descending => guarantees order of returned records will be from // largest to smallest. // Range must be from<=to - virtual std::unique_ptr<IteratorBase<const typename TG::accessor_t>> + virtual iter::Virtual<const typename TG::accessor_t> for_range(DbAccessor &, Border<K> from = Border<K>(), Border<K> to = Border<K>()) = 0; diff --git a/include/utils/iterator/composable.hpp b/include/utils/iterator/composable.hpp new file mode 100644 index 000000000..857dbd4f8 --- /dev/null +++ b/include/utils/iterator/composable.hpp @@ -0,0 +1,146 @@ +#pragma once + +#include "utils/crtp.hpp" +#include "utils/iterator/count.hpp" +#include "utils/option.hpp" + +// class EdgeType; + +namespace iter +{ +template <class I, class OP> +auto make_map(I &&iter, OP &&op); + +template <class I, class OP> +auto make_filter(I &&iter, OP &&op); + +template <class I, class C> +void for_all(I &&iter, C &&consumer); + +template <class I, class OP> +auto make_flat_map(I &&iter, OP &&op); + +template <class I, class OP> +auto make_inspect(I &&iter, OP &&op); + +template <class I, class OP> +auto make_limited_map(I &&iter, OP &&op); + +template <class I, class OP> +auto make_virtual(I &&iter); + +// Class for creating easy composable iterators fo querying. +// Derived - type of derived class +// T - return type +template <class T, class Derived> +class Composable : public Crtp<Derived> +{ + // Moves self + Derived &&move() { return std::move(this->derived()); } +public: + auto virtualize() { return iter::make_virtual(move()); } + + template <class OP> + auto map(OP &&op) + { + return iter::make_map<Derived, OP>(move(), std::move(op)); + } + + template <class OP> + auto filter(OP &&op) + { + return iter::make_filter<Derived, OP>(move(), std::move(op)); + } + + // Replaces every item with item taken from n if it exists. + template <class R> + auto replace(Option<R> &n) + { + return iter::make_limited_map<Derived>( + move(), [&](auto v) mutable { return std::move(n); }); + } + + // Maps with call to method to() and filters with call to fill. + auto to() + { + return map([](auto er) { return er.to(); }).fill(); + } + + // Maps with call to method from() and filters with call to fill. + auto from() + { + return map([](auto er) { return er.from(); }).fill(); + } + + // Combines out iterators into one iterator. + auto out() + { + return iter::make_flat_map<Derived>( + move(), [](auto vr) { return vr.out().fill(); }); + } + + // Filters with label on from vertex. + template <class LABEL> + auto from_label(LABEL const &label) + { + return filter([&](auto &ra) { + auto va = ra.from(); + return va.fill() && va.has_label(label); + }); + } + + // Filters with property under given key + template <class KEY, class PROP> + auto has_property(KEY &key, PROP const &prop) + { + return filter([&](auto &va) { return va.at(key) == prop; }); + } + + // Copy-s all pasing value to t before they are returned. + // auto clone_to(Option<T> &t) + // { + // return iter::make_inspect<decltype(std::move(*this))>( + // std::move(*this), [&](auto &v) { t = Option<T>(v); }); + // } + + // Copy-s pasing value to t before they are returned. + auto clone_to(Option<const T> &t) + { + return iter::make_inspect<Derived>( + move(), [&](auto &v) mutable { t = Option<const T>(v); }); + } + + // Filters with call to method fill() + auto fill() + { + return filter([](auto &ra) { return ra.fill(); }); + } + + // Filters with type + template <class TYPE> + auto type(TYPE const &type) + { + return filter([&](auto &ra) { return ra.edge_type() == type; }); + } + + // Filters with label. + template <class LABEL> + auto label(LABEL const &label) + { + return filter([&](auto &va) { return va.has_label(label); }); + } + + // Filters out vertices which are connected. + auto isolated() + { + return filter([&](auto &ra) { return ra.isolated(); }); + } + + // For all items calls OP. + template <class OP> + void for_all(OP &&op) + { + iter::for_all(move(), std::move(op)); + } +}; +} diff --git a/include/utils/iterator/count.hpp b/include/utils/iterator/count.hpp index 074f4a44d..7beffb1a0 100644 --- a/include/utils/iterator/count.hpp +++ b/include/utils/iterator/count.hpp @@ -12,11 +12,7 @@ public: Count(size_t min, size_t max) : min(min), max(max) {} - Count &min_zero() - { - min = 0; - return *this; - } + Count min_zero() const { return Count(0, max); } size_t avg() const { return ((max - min) >> 1) + min; } diff --git a/include/utils/iterator/filter.hpp b/include/utils/iterator/filter.hpp index f0c430309..2c87bbf46 100644 --- a/include/utils/iterator/filter.hpp +++ b/include/utils/iterator/filter.hpp @@ -1,7 +1,7 @@ #pragma once +#include "utils/iterator/composable.hpp" #include "utils/iterator/iterator_base.hpp" -#include "utils/option.hpp" namespace iter { @@ -12,7 +12,7 @@ namespace iter // I - iterator type // OP - type of filter function. OP: T& -> bool template <class T, class I, class OP> -class Filter : public IteratorBase<T> +class Filter : public IteratorBase<T>, public Composable<T, Filter<T, I, OP>> { public: diff --git a/include/utils/iterator/flat_map.hpp b/include/utils/iterator/flat_map.hpp index 9fc748740..655d4b226 100644 --- a/include/utils/iterator/flat_map.hpp +++ b/include/utils/iterator/flat_map.hpp @@ -1,5 +1,8 @@ #pragma once +#include "utils/iterator/composable.hpp" +#include "utils/iterator/iterator_base.hpp" + namespace iter { @@ -12,7 +15,8 @@ namespace iter // J - iterator type returned from OP // OP - type of mapper function template <class T, class I, class J, class OP> -class FlatMap : public IteratorBase<T> +class FlatMap : public IteratorBase<T>, + public Composable<T, FlatMap<T, I, J, OP>> { public: diff --git a/include/utils/iterator/inspect.hpp b/include/utils/iterator/inspect.hpp index 8fba73b37..73c30088f 100644 --- a/include/utils/iterator/inspect.hpp +++ b/include/utils/iterator/inspect.hpp @@ -1,7 +1,7 @@ #pragma once +#include "utils/iterator/composable.hpp" #include "utils/iterator/iterator_base.hpp" -#include "utils/option.hpp" namespace iter { @@ -13,7 +13,7 @@ namespace iter // I - iterator type // OP - type of inspector function. OP: T&->void template <class T, class I, class OP> -class Inspect : public IteratorBase<T> +class Inspect : public IteratorBase<T>, public Composable<T, Inspect<T, I, OP>> { public: diff --git a/include/utils/iterator/iterator.hpp b/include/utils/iterator/iterator.hpp index 44091046b..a540dff0d 100644 --- a/include/utils/iterator/iterator.hpp +++ b/include/utils/iterator/iterator.hpp @@ -12,3 +12,4 @@ #include "utils/iterator/limited_map.hpp" #include "utils/iterator/map.hpp" #include "utils/iterator/range_iterator.hpp" +#include "utils/iterator/virtual_iter.hpp" diff --git a/include/utils/iterator/iterator_accessor.hpp b/include/utils/iterator/iterator_accessor.hpp index 2acd960d3..32d496102 100644 --- a/include/utils/iterator/iterator_accessor.hpp +++ b/include/utils/iterator/iterator_accessor.hpp @@ -1,7 +1,7 @@ #pragma once +#include "utils/iterator/composable.hpp" #include "utils/iterator/iterator_base.hpp" -#include "utils/option.hpp" namespace iter { @@ -11,7 +11,8 @@ namespace iter // I - iterator type gotten from accessor // A - accessor type template <class T, class I, class A> -class IteratorAccessor : public IteratorBase<T> +class IteratorAccessor : public IteratorBase<T>, + public Composable<T, IteratorAccessor<T, I, A>> { public: IteratorAccessor() = delete; diff --git a/include/utils/iterator/iterator_base.hpp b/include/utils/iterator/iterator_base.hpp index 019aeb5f2..610126901 100644 --- a/include/utils/iterator/iterator_base.hpp +++ b/include/utils/iterator/iterator_base.hpp @@ -3,29 +3,6 @@ #include "utils/iterator/count.hpp" #include "utils/option.hpp" -class EdgeType; - -namespace iter -{ -template <class I, class OP> -auto make_map(I &&iter, OP &&op); - -template <class I, class OP> -auto make_filter(I &&iter, OP &&op); - -template <class I, class C> -void for_all(I &&iter, C &&consumer); - -template <class I, class OP> -auto make_flat_map(I &&iter, OP &&op); - -template <class I, class OP> -auto make_inspect(I &&iter, OP &&op); - -template <class I, class OP> -auto make_limited_map(I &&iter, OP &&op); -} - // Base iterator for next() kind iterator. // T - type of return value template <class T> @@ -36,110 +13,5 @@ public: virtual Option<T> next() = 0; - virtual Count count() { return Count(0, ~((size_t)0)); } - - template <class OP> - auto map(OP &&op) - { - return iter::make_map<decltype(std::move(*this)), OP>(std::move(*this), - std::move(op)); - } - - template <class OP> - auto filter(OP &&op) - { - return iter::make_filter<decltype(std::move(*this)), OP>( - std::move(*this), std::move(op)); - } - - // Replaces every item with item taken from n if it exists. - template <class R> - auto replace(Option<R> &n) - { - return iter::make_limited_map<decltype(std::move(*this))>( - std::move(*this), [&](auto v) mutable { return std::move(n); }); - } - - // Maps with call to method to() and filters with call to fill. - auto to() - { - return map([](auto er) { return er.to(); }).fill(); - } - - // Maps with call to method from() and filters with call to fill. - auto from() - { - return map([](auto er) { return er.from(); }).fill(); - } - - // Combines out iterators into one iterator. - auto out() - { - return iter::make_flat_map<decltype(std::move(*this))>( - std::move(*this), [](auto vr) { return vr.out().fill(); }); - } - - // Filters with label on from vertex. - template <class LABEL> - auto from_label(LABEL const &label) - { - return filter([&](auto &ra) { - auto va = ra.from(); - return va.fill() && va.has_label(label); - }); - } - - // Filters with property under given key - template <class KEY, class PROP> - auto has_property(KEY &key, PROP const &prop) - { - return filter([&](auto &va) { return va.at(key) == prop; }); - } - - // Copy-s all pasing value to t before they are returned. - // auto clone_to(Option<T> &t) - // { - // return iter::make_inspect<decltype(std::move(*this))>( - // std::move(*this), [&](auto &v) { t = Option<T>(v); }); - // } - - // Copy-s pasing value to t before they are returned. - auto clone_to(Option<const T> &t) - { - return iter::make_inspect<decltype(std::move(*this))>( - std::move(*this), [&](auto &v) mutable { t = Option<const T>(v); }); - } - - // Filters with call to method fill() - auto fill() - { - return filter([](auto &ra) { return ra.fill(); }); - } - - // Filters with type - template <class TYPE> - auto type(TYPE const &type) - { - return filter([&](auto &ra) { return ra.edge_type() == type; }); - } - - // Filters with label. - template <class LABEL> - auto label(LABEL const &label) - { - return filter([&](auto &va) { return va.has_label(label); }); - } - - // Filters out vertices which are connected. - auto isolated() - { - return filter([&](auto &ra) { return ra.isolated(); }); - } - - // For all items calls OP. - template <class OP> - void for_all(OP &&op) - { - iter::for_all(std::move(*this), std::move(op)); - } + virtual Count count() = 0; }; diff --git a/include/utils/iterator/lambda_iterator.hpp b/include/utils/iterator/lambda_iterator.hpp index cd130af31..cfae1c3d5 100644 --- a/include/utils/iterator/lambda_iterator.hpp +++ b/include/utils/iterator/lambda_iterator.hpp @@ -1,5 +1,6 @@ #pragma once +#include "utils/iterator/composable.hpp" #include "utils/iterator/iterator_base.hpp" namespace iter @@ -8,7 +9,8 @@ namespace iter // T - type of return value // F - type of wraped lambda template <class T, class F> -class LambdaIterator : public IteratorBase<T> +class LambdaIterator : public IteratorBase<T>, + public Composable<T, LambdaIterator<T, F>> { public: LambdaIterator(F &&f, size_t count) : func(std::move(f)), _count(count) {} diff --git a/include/utils/iterator/limited_map.hpp b/include/utils/iterator/limited_map.hpp index 83d4402e4..db2fb7333 100644 --- a/include/utils/iterator/limited_map.hpp +++ b/include/utils/iterator/limited_map.hpp @@ -1,7 +1,7 @@ #pragma once +#include "utils/iterator/composable.hpp" #include "utils/iterator/iterator_base.hpp" -#include "utils/option.hpp" namespace iter { @@ -12,7 +12,8 @@ namespace iter // I - iterator type // OP - type of mapper function. OP: V -> Option<T> template <class T, class I, class OP> -class LimitedMap : public IteratorBase<T> +class LimitedMap : public IteratorBase<T>, + public Composable<T, LimitedMap<T, I, OP>> { public: diff --git a/include/utils/iterator/map.hpp b/include/utils/iterator/map.hpp index 53cf52f46..df9f6b174 100644 --- a/include/utils/iterator/map.hpp +++ b/include/utils/iterator/map.hpp @@ -1,7 +1,7 @@ #pragma once +#include "utils/iterator/composable.hpp" #include "utils/iterator/iterator_base.hpp" -#include "utils/option.hpp" namespace iter { @@ -12,7 +12,7 @@ namespace iter // I - iterator type // OP - type of mapper function template <class T, class I, class OP> -class Map : public IteratorBase<T> +class Map : public IteratorBase<T>, public Composable<T, Map<T, I, OP>> { public: diff --git a/include/utils/iterator/virtual_iter.hpp b/include/utils/iterator/virtual_iter.hpp new file mode 100644 index 000000000..6bee1c73d --- /dev/null +++ b/include/utils/iterator/virtual_iter.hpp @@ -0,0 +1,48 @@ +#pragma once + +#include "utils/iterator/composable.hpp" +#include "utils/iterator/iterator_base.hpp" + +namespace iter +{ + +// Class which wraps iterator and hides it's type. It actualy does this by +// dynamicly allocating iterator on heap. +// T - type of return value +template <class T> +class Virtual : public Composable<T, Virtual<T>> +{ + +public: + Virtual() = delete; + + // Virtual operation is designed to be used in chained calls which operate + // on a + // iterator. Virtual will in that usecase receive other iterator by value + // and + // std::move is a optimization for it. + + template <class I> + Virtual(I &&iter) : it(std::make_unique<I>(std::move(iter))) + { + } + + Virtual(Virtual &&m) : it(std::move(m.it)) {} + + ~Virtual() {} + + Option<T> next() { return it.get()->next(); } + + Count count() { return it.get()->count(); } + +private: + std::unique_ptr<IteratorBase<T>> it; +}; + +template <class I> +auto make_virtual(I &&iter) +{ + // Compiler cant deduce type T. decltype is here to help with it. + return Virtual<decltype(iter.next().take())>(std::move(iter)); +} +} diff --git a/include/utils/random/xorshift128plus.hpp b/include/utils/random/xorshift128plus.hpp index f98c558bc..cccc001db 100644 --- a/include/utils/random/xorshift128plus.hpp +++ b/include/utils/random/xorshift128plus.hpp @@ -17,8 +17,12 @@ public: { // use a slow, more complex rnd generator to initialize a fast one // make sure to call this before requesting any random numbers! - std::random_device rd; - std::mt19937_64 gen(rd()); + + // NOTE: Valgird complanis to next instruction + // std::random_device rd; + // std::mt19937_64 gen(rd()); + std::mt19937_64 gen(time(0)); + std::uniform_int_distribution<unsigned long long> dist; // the number generated by MT can be full of zeros and xorshift diff --git a/src/barrier/barrier.cpp b/src/barrier/barrier.cpp index 65fc1f710..8287b77d7 100644 --- a/src/barrier/barrier.cpp +++ b/src/barrier/barrier.cpp @@ -432,24 +432,24 @@ bool operator!=(const EdgeAccessor &a, const EdgeAccessor &b) } // ************************* VertexIterator -DESTRUCTOR(VertexIterator, unique_ptr); +DESTRUCTOR(VertexIterator, Virtual); Option<const VertexAccessor> VertexIterator::next() { - return HALF_CALL(get()->next()).map<const VertexAccessor>(); + return HALF_CALL(next()).map<const VertexAccessor>(); } -Count VertexIterator::count() { return HALF_CALL(get()->count()); } +Count VertexIterator::count() { return HALF_CALL(count()); } // ************************* EdgeIterator -DESTRUCTOR(EdgeIterator, unique_ptr); +DESTRUCTOR(EdgeIterator, Virtual); Option<const EdgeAccessor> EdgeIterator::next() { - return HALF_CALL(get()->next()).map<const EdgeAccessor>(); + return HALF_CALL(next()).map<const EdgeAccessor>(); } -Count EdgeIterator::count() { return HALF_CALL(get()->count()); } +Count EdgeIterator::count() { return HALF_CALL(count()); } // ************************* OutEdgesIterator DESTRUCTOR(OutEdgesIterator, out_edge_iterator_t); diff --git a/src/dbms/cleaner.cpp b/src/dbms/cleaner.cpp index afb00eaa9..0a3f21649 100644 --- a/src/dbms/cleaner.cpp +++ b/src/dbms/cleaner.cpp @@ -22,7 +22,6 @@ Cleaning::Cleaning(ConcurrentMap<std::string, Db> &dbs) : dbms(dbs) for (auto &db : dbs.access()) { logger.info("Cleaning database \"{}\"", db.first); DbTransaction t(db.second); - try { logger.info("Cleaning edges"); t.clean_edge_section(); @@ -34,7 +33,6 @@ Cleaning::Cleaning(ConcurrentMap<std::string, Db> &dbs) : dbms(dbs) db.first); logger.error("{}", e.what()); } - t.trans.commit(); } last_clean = now; diff --git a/src/storage/indexes/impl/nonunique_unordered_index.cpp b/src/storage/indexes/impl/nonunique_unordered_index.cpp index 006ae702a..5a11ee8f5 100644 --- a/src/storage/indexes/impl/nonunique_unordered_index.cpp +++ b/src/storage/indexes/impl/nonunique_unordered_index.cpp @@ -32,12 +32,11 @@ bool NonUniqueUnorderedIndex<T, K>::insert(IndexRecord<T, K> &&value) } template <class T, class K> -std::unique_ptr<IteratorBase<const typename T::accessor_t>> +iter::Virtual<const typename T::accessor_t> NonUniqueUnorderedIndex<T, K>::for_range(DbAccessor &t, Border<K> from, Border<K> to) { - return std::make_unique<decltype( - for_range_exact(t, std::move(from), std::move(to)))>( + return iter::make_virtual( for_range_exact(t, std::move(from), std::move(to))); } diff --git a/src/storage/indexes/impl/unique_ordered_index.cpp b/src/storage/indexes/impl/unique_ordered_index.cpp index dc2e6ec83..9d4add4d0 100644 --- a/src/storage/indexes/impl/unique_ordered_index.cpp +++ b/src/storage/indexes/impl/unique_ordered_index.cpp @@ -39,11 +39,10 @@ bool UniqueOrderedIndex<T, K>::insert(IndexRecord<T, K> &&value) } template <class T, class K> -std::unique_ptr<IteratorBase<const typename T::accessor_t>> +iter::Virtual<const typename T::accessor_t> UniqueOrderedIndex<T, K>::for_range(DbAccessor &t, Border<K> from, Border<K> to) { - return std::make_unique<decltype( - for_range_exact(t, std::move(from), std::move(to)))>( + return iter::make_virtual( for_range_exact(t, std::move(from), std::move(to))); } diff --git a/src/storage/label/label.cpp b/src/storage/label/label.cpp index 14196f5ec..b532c2d52 100644 --- a/src/storage/label/label.cpp +++ b/src/storage/label/label.cpp @@ -2,8 +2,7 @@ #include "storage/label/label.hpp" Label::Label(const char *name) - : name(std::string(name)), - index_v(std::unique_ptr<label_index_t>(new label_index_t())) + : name(std::string(name)), index_v(std::make_unique<label_index_t>()) { } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 3897d862b..c893b2321 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -68,6 +68,14 @@ target_link_libraries(integration_queries ${fmt_static_lib}) add_test(NAME integration_queries COMMAND integration_queries) set_property(TARGET integration_queries PROPERTY CXX_STANDARD 14) +# test cleaning methods +add_executable(cleaning integration/cleaning.cpp) +target_link_libraries(cleaning memgraph) +target_link_libraries(cleaning Threads::Threads) +target_link_libraries(cleaning ${fmt_static_lib}) +add_test(NAME cleaning COMMAND cleaning) +set_property(TARGET cleaning PROPERTY CXX_STANDARD 14) + # test query engine add_executable(integration_query_engine integration/query_engine.cpp) target_link_libraries(integration_query_engine Threads::Threads) diff --git a/tests/integration/cleaning.cpp b/tests/integration/cleaning.cpp new file mode 100644 index 000000000..15ffed5f3 --- /dev/null +++ b/tests/integration/cleaning.cpp @@ -0,0 +1,96 @@ +#include "query_engine/hardcode/queries.hpp" + +#include "barrier/barrier.cpp" + +#include "logging/default.hpp" +#include "logging/streams/stdout.hpp" +#include "query_engine/query_stripper.hpp" +#include "utils/sysinfo/memory.hpp" + +template <class S, class Q> +void run(size_t n, std::string &query, S &stripper, Q &qf) +{ + auto stripped = stripper.strip(query); + std::cout << "Running query [" << stripped.hash << "] for " << n << " time." + << std::endl; + for (int i = 0; i < n; i++) { + assert(qf[stripped.hash](stripped.arguments)); + } +} + +void clean_vertex(Db &db) +{ + DbTransaction t(db); + t.clean_vertex_section(); + t.trans.commit(); +} + +int main(void) +{ + logging::init_async(); + logging::log->pipe(std::make_unique<Stdout>()); + + size_t cvl_n = 1000; + + Db db; + + auto query_functions = load_queries(barrier::trans(db)); + + auto stripper = make_query_stripper(TK_LONG, TK_FLOAT, TK_STR, TK_BOOL); + + std::string create_vertex_label = + "CREATE (n:LABEL {name: \"cleaner_test\"}) RETURN n"; + std::string create_vertex_other = + "CREATE (n:OTHER {name: \"cleaner_test\"}) RETURN n"; + std::string delete_label_vertices = "MATCH (n:LABEL) DELETE n"; + std::string delete_all_vertices = "MATCH (n) DELETE n"; + + // ******************************* TEST 1 ********************************// + // add vertices a + // clean vertices + // delete vertices a + // clean vertices + run(cvl_n, create_vertex_label, stripper, query_functions); + assert(db.graph.vertices.access().size() == cvl_n); + + clean_vertex(db); + assert(db.graph.vertices.access().size() == cvl_n); + + run(1, delete_label_vertices, stripper, query_functions); + assert(db.graph.vertices.access().size() == cvl_n); + + clean_vertex(db); + assert(db.graph.vertices.access().size() == 0); + + // ******************************* TEST 2 ********************************// + // add vertices a + // add vertices b + // clean vertices + // delete vertices a + // clean vertices + // delete vertices all + run(cvl_n, create_vertex_label, stripper, query_functions); + assert(db.graph.vertices.access().size() == cvl_n); + + run(cvl_n, create_vertex_other, stripper, query_functions); + assert(db.graph.vertices.access().size() == cvl_n * 2); + + clean_vertex(db); + assert(db.graph.vertices.access().size() == cvl_n * 2); + + run(1, delete_label_vertices, stripper, query_functions); + assert(db.graph.vertices.access().size() == cvl_n * 2); + + clean_vertex(db); + assert(db.graph.vertices.access().size() == cvl_n); + + run(1, delete_all_vertices, stripper, query_functions); + assert(db.graph.vertices.access().size() == cvl_n); + + clean_vertex(db); + assert(db.graph.vertices.access().size() == 0); + + // TODO: more tests + + return 0; +} diff --git a/tests/integration/queries.cpp b/tests/integration/queries.cpp index f8d94f8c9..d9379f39f 100644 --- a/tests/integration/queries.cpp +++ b/tests/integration/queries.cpp @@ -2,9 +2,9 @@ #include "barrier/barrier.cpp" +#include "communication/bolt/v1/serialization/bolt_serializer.hpp" #include "database/db.hpp" #include "query_engine/query_stripper.hpp" -#include "communication/bolt/v1/serialization/bolt_serializer.hpp" // #include "storage/edges.cpp" // #include "storage/edges.hpp" // #include "storage/vertices.cpp" @@ -24,6 +24,7 @@ int main(void) "CREATE (n:LABEL {name: \"TEST1\"}) RETURN n", "CREATE (n:LABEL {name: \"TEST2\"}) RETURN n", "CREATE (n:LABEL {name: \"TEST3\"}) RETURN n", + "CREATE (n:OTHER {name: \"TEST4\"}) RETURN n" "CREATE (n:ACCOUNT {id: 2322, name: \"TEST\", country: \"Croatia\", " "created_at: 2352352}) RETURN n", "MATCH (n {id: 0}) RETURN n", "MATCH (n {id: 1}) RETURN n", @@ -35,10 +36,21 @@ int main(void) "MATCH (n: {id: 0}) SET n.name = \"TEST100\" RETURN n", "MATCH (n: {id: 1}) SET n.name = \"TEST101\" RETURN n", "MATCH (n: {id: 0}) SET n.name = \"TEST102\" RETURN n", - "MATCH (n:LABEL) RETURN n"}; + "MATCH (n:LABEL) RETURN n", "MATCH (n1), (n2) WHERE ID(n1)=0 AND " + "ID(n2)=1 CREATE (n1)<-[r:IS {age: " + "25,weight: 70}]-(n2) RETURN r", + "MATCH (n) RETURN n", "MATCH (n:LABEL) RETURN n", "MATCH (n) DELETE n ", + "MATCH (n:LABEL) DELETE n", "MATCH (n) WHERE ID(n) = 0 DELETE n", + "MATCH ()-[r]-() WHERE ID(r) = 0 DELETE r", "MATCH ()-[r]-() DELETE r", + "MATCH ()-[r:TYPE]-() DELETE r", + "MATCH (n)-[:TYPE]->(m) WHERE ID(n) = 0 RETURN m", + "MATCH (n)-[:TYPE]->(m) WHERE n.name = \"kruno\" RETURN m", + "MATCH (n)-[:TYPE]->(m) WHERE n.name = \"kruno\" RETURN n,m", + "MATCH (n:LABEL)-[:TYPE]->(m) RETURN n"}; for (auto &query : queries) { auto stripped = stripper.strip(query); + std::cout << "Query hash: " << stripped.hash << std::endl; auto result = query_functions[stripped.hash](stripped.arguments); permanent_assert(result == true, "Result retured from query function is not true");