diff --git a/CMakeLists.txt b/CMakeLists.txt index f348de1a1..37c2a2e74 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -401,7 +401,6 @@ EXECUTE_PROCESS( # TODO: create separate static library from bolt code set(memgraph_src_files - ${src_dir}/barrier/barrier.cpp ${src_dir}/utils/string/transform.cpp ${src_dir}/utils/string/join.cpp ${src_dir}/utils/string/file.cpp @@ -455,6 +454,9 @@ set(memgraph_src_files ${src_dir}/storage/record_accessor.cpp ) +set(barrier_src_files + ${src_dir}/barrier/barrier.cpp) + # STATIC library used by memgraph executables add_library(memgraph STATIC ${memgraph_src_files}) @@ -462,6 +464,8 @@ add_library(memgraph STATIC ${memgraph_src_files}) add_library(memgraph_pic STATIC ${memgraph_src_files}) set_property(TARGET memgraph_pic PROPERTY POSITION_INDEPENDENT_CODE TRUE) +add_library(barrier STATIC ${barrier_src_files}) + # tests if (TESTS) enable_testing() diff --git a/include/barrier/barrier.hpp b/include/barrier/barrier.hpp index d86dbce82..e66676b30 100644 --- a/include/barrier/barrier.hpp +++ b/include/barrier/barrier.hpp @@ -120,6 +120,7 @@ public: template VertexAccessor(T &&d); + VertexAccessor(VertexAccessor &other); VertexAccessor(const VertexAccessor &other); VertexAccessor(VertexAccessor &&other); VertexAccessor(VertexAccessor const &&other); @@ -190,6 +191,7 @@ public: template EdgeAccessor(T &&d); + EdgeAccessor(EdgeAccessor &other); EdgeAccessor(const EdgeAccessor &other); EdgeAccessor(EdgeAccessor &&other); EdgeAccessor(EdgeAccessor const &&other); @@ -404,7 +406,7 @@ public: VertexPropertyType(const VertexPropertyType &other) = default; VertexPropertyType(VertexPropertyType &&other) = default; - ~VertexPropertyType(); + ~VertexPropertyType(){}; VertexPropertyType &operator=(const VertexPropertyType &other) = default; VertexPropertyType &operator=(VertexPropertyType &&other) = default; @@ -419,7 +421,7 @@ public: EdgePropertyType(const EdgePropertyType &other) = default; EdgePropertyType(EdgePropertyType &&other) = default; - ~EdgePropertyType(); + ~EdgePropertyType(){}; EdgePropertyType &operator=(const EdgePropertyType &other) = default; EdgePropertyType &operator=(EdgePropertyType &&other) = default; @@ -511,6 +513,10 @@ public: class EdgeType : protected Unsized { public: + friend bool operator<(const EdgeType &lhs, const EdgeType &rhs); + + friend bool operator==(const EdgeType &lhs, const EdgeType &rhs); + EdgeIndex &index() const; }; diff --git a/include/barrier/trans.hpp b/include/barrier/trans.hpp new file mode 100644 index 000000000..9caa9e202 --- /dev/null +++ b/include/barrier/trans.hpp @@ -0,0 +1,265 @@ +#pragma once +#include "barrier/barrier.hpp" + +// This is the place for imports from memgraph .hpp +#include "communication/bolt/v1/serialization/bolt_serializer.hpp" +#include "database/db.hpp" +#include "database/db_accessor.hpp" +#include "storage/edge_type/edge_type.hpp" +#include "storage/label/label.hpp" + +// This is the place for imports from memgraph .cpp +// #include "database/db_accessor.cpp" +#include "storage/vertex_accessor.cpp" + +// TODO: Extract trans functions to other hpp for easy including into other +// code. + +// **************************** HELPER DEFINES *******************************// +// returns transformed pointer +#define THIS (trans(this)) +// Performs call x on transformed border class. +#define HALF_CALL(x) (THIS->x) +// Performs call x on transformed border class and returns transformed output. +#define CALL(x) trans(HALF_CALL(x)) + +#define TRANSFORM_REF(x, y) \ + x &trans(y &l) { return ref_as(l); } \ + x const &trans(y const &l) { return ref_as(l); } \ + y &trans(x &l) { return ref_as(l); } \ + y const &trans(x const &l) { return ref_as(l); } \ + x *trans(y *l) { return ptr_as(l); } \ + x const *trans(y const *l) { return ptr_as(l); } \ + y *trans(x *l) { return ptr_as(l); } \ + y const *trans(x const *l) { return ptr_as(l); } + +#define TRANSFORM_REF_TEMPLATED(x, y) \ + x &trans(y &l) { return ref_as(l); } \ + template \ + x const &trans(y const &l) \ + { \ + return ref_as(l); \ + } \ + template \ + y &trans(x &l) \ + { \ + return ref_as(l); \ + } \ + template \ + y const &trans(x const &l) \ + { \ + return ref_as(l); \ + } \ + template \ + x *trans(y *l) \ + { \ + return ptr_as(l); \ + } \ + template \ + const x *trans(const y *l) \ + { \ + return ptr_as(l); \ + } \ + template \ + y *trans(x *l) \ + { \ + return ptr_as(l); \ + } \ + template \ + const y *trans(const x *l) \ + { \ + return ptr_as(l); \ + } +#define DESTRUCTOR(x, y) \ + x::~x() { HALF_CALL(~y()); } +#define COPY_CONSTRUCTOR_MUT(x, y) \ + x::x(x &other) : Sized(y(trans(other))) {} +#define COPY_CONSTRUCTOR(x, y) \ + x::x(const x &other) : Sized(y(trans(other))) {} +#define MOVE_CONSTRUCTOR(x) \ + x::x(x &&other) : Sized(trans(std::move(other))) {} +#define MOVE_CONST_CONSTRUCTOR(x) \ + x::x(x const &&other) : Sized(trans(std::move(other))) {} + +// For certain classes trans evaluates into ref which doesnt work for Sized +// constructor. This Move forces type. +#define MOVE_CONSTRUCTOR_FORCED(x, y) \ + x::x(x &&other) : Sized(value_as(std::move(other))) {} + +#define COPY_OPERATOR(x) \ + x &x::operator=(const x &other) \ + { \ + HALF_CALL(operator=(trans(other))); \ + return *this; \ + } +#define MOVE_OPERATOR(x) \ + x &x::operator=(x &&other) \ + { \ + HALF_CALL(operator=(trans(std::move(other)))); \ + return *this; \ + } + +#define VALID_CONSTRUCTION(x, y) \ + template <> \ + barrier::x::x(y &&d) : Sized(std::move(d)) \ + { \ + } + +#define VALID_CONSTRUCTION_CONST(x, y) \ + template <> \ + barrier::x::x(y const &&d) : Sized(std::move(d)) \ + { \ + } + +// Generates transformation function from original class to border class. +#define TRANSFORM_VALUE_ONE_RAW(x, y) \ + x trans(y &&d) { return x(std::move(d)); } + +// Generates transformation function from original class to border class. +#define TRANSFORM_VALUE_ONE(x, y) \ + VALID_CONSTRUCTION(x, y) \ + x trans(y &&d) { return x(std::move(d)); } + +// Generates transformation functions between border class x and original class +// y by value. Only mutable values. +#define TRANSFORM_VALUE_MUT(x, y) \ + TRANSFORM_VALUE_ONE(x, y) \ + y trans(x &&d) { return value_as(std::move(d)); } + +// Generates transformation functions between border class x and original class +// y by value. +#define TRANSFORM_VALUE(x, y) \ + TRANSFORM_VALUE_MUT(x, y) \ + VALID_CONSTRUCTION_CONST(x, y) \ + const x trans(const y &&d) { return x(std::move(d)); } \ + const y trans(const x &&d) { return value_as(std::move(d)); } + +// Duplicates given first name to call second given with name and ::name +#define DUP(x, y) y(x, ::x) + +// ********************** TYPES OF AUTO +using vertex_access_iterator_t = + decltype(((::DbAccessor *)(std::nullptr_t()))->vertex_access()); + +using out_edge_iterator_t = + decltype(((::VertexAccessor *)(std::nullptr_t()))->out()); + +using in_edge_iterator_t = + decltype(((::VertexAccessor *)(std::nullptr_t()))->in()); + +// This file should contain all implementations of methods from barrier classes +// defined in barrier.hpp. +// Implementations should follow the form: +// border_return_type border_class::method_name(arguments){ +// return +// CALL(method_name(trans(arguments)))/HALF_CALL(method_name(trans(arguments))); +// } + +// ********************** ALL VALID CONVERSIONS ***************************** // +// Implementations must use exclusivly trans functions to cast between types. + +// ******************** OVERLOADED trans FUNCTIONS. +// This enclosure is the only dangerous part of barrier except of Sized class in +// common.hpp +namespace barrier +{ +// Blueprint for valid transformation of references: +// TRANSFORM_REF(, ::); +// template TRANSFORM_REF_TEMPLATED(,::); + +// ***************** TRANSFORMS of reference +DUP(Label, TRANSFORM_REF); +DUP(EdgeType, TRANSFORM_REF); +DUP(VertexPropertyFamily, TRANSFORM_REF); +DUP(EdgePropertyFamily, TRANSFORM_REF); +DUP(VertexAccessor, TRANSFORM_REF); +DUP(EdgeAccessor, TRANSFORM_REF); +DUP(Db, TRANSFORM_REF); +DUP(DbAccessor, TRANSFORM_REF); +TRANSFORM_REF(std::vector, std::vector<::label_ref_t>); +TRANSFORM_REF(VertexPropertyKey, + ::VertexPropertyFamily::PropertyType::PropertyFamilyKey); +TRANSFORM_REF(EdgePropertyKey, + ::EdgePropertyFamily::PropertyType::PropertyFamilyKey); +TRANSFORM_REF(VertexIterator, + std::unique_ptr>); +TRANSFORM_REF(EdgeIterator, + std::unique_ptr>); +TRANSFORM_REF(VertexAccessIterator, vertex_access_iterator_t); +TRANSFORM_REF(OutEdgesIterator, out_edge_iterator_t); +TRANSFORM_REF(InEdgesIterator, in_edge_iterator_t); + +template +TRANSFORM_REF_TEMPLATED(VertexIndex, VertexIndexBase); +template +TRANSFORM_REF_TEMPLATED(EdgeIndex, EdgeIndexBase); +template +TRANSFORM_REF_TEMPLATED(BoltSerializer, ::bolt::BoltSerializer); + +template +TRANSFORM_REF_TEMPLATED( + VertexPropertyType, + ::VertexPropertyFamily::PropertyType::PropertyTypeKey); + +template +TRANSFORM_REF_TEMPLATED(EdgePropertyType, + ::EdgePropertyFamily::PropertyType::PropertyTypeKey); + +// ****************** TRANSFORMS of value +// Blueprint for valid transformation of value: +// TRANSFORM_VALUE(, ::); +DUP(VertexAccessor, TRANSFORM_VALUE); +DUP(EdgeAccessor, TRANSFORM_VALUE); +TRANSFORM_VALUE(EdgePropertyKey, + ::EdgePropertyFamily::PropertyType::PropertyFamilyKey); +TRANSFORM_VALUE(VertexPropertyKey, + ::VertexPropertyFamily::PropertyType::PropertyFamilyKey); +TRANSFORM_VALUE_ONE(VertexAccessIterator, vertex_access_iterator_t); +MOVE_CONSTRUCTOR_FORCED(VertexAccessIterator, vertex_access_iterator_t); +TRANSFORM_VALUE_ONE(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>); +MOVE_CONSTRUCTOR_FORCED(VertexIterator, + std::unique_ptr>); +TRANSFORM_VALUE_ONE(EdgeIterator, + std::unique_ptr>); +MOVE_CONSTRUCTOR_FORCED(EdgeIterator, + std::unique_ptr>); + +template +TRANSFORM_VALUE_ONE_RAW( + VertexPropertyType, + ::VertexPropertyFamily::PropertyType::PropertyTypeKey); +template +TRANSFORM_VALUE_ONE_RAW(EdgePropertyType, + ::EdgePropertyFamily::PropertyType::PropertyTypeKey) + +template +TRANSFORM_VALUE_ONE_RAW(BoltSerializer, ::bolt::BoltSerializer) + +// ********************* SPECIAL SIZED CONSTRUCTORS +#define VertexPropertyType_constructor(x) \ + template <> \ + template <> \ + VertexPropertyType::VertexPropertyType( \ + ::VertexPropertyFamily::PropertyType::PropertyTypeKey &&d) \ + : Sized(std::move(d)) \ + { \ + } +INSTANTIATE_FOR_PROPERTY(VertexPropertyType_constructor); + +#define EdgePropertyType_constructor(x) \ + template <> \ + template <> \ + EdgePropertyType::EdgePropertyType( \ + ::EdgePropertyFamily::PropertyType::PropertyTypeKey &&d) \ + : Sized(std::move(d)) \ + { \ + } +INSTANTIATE_FOR_PROPERTY(EdgePropertyType_constructor); + +DbAccessor::DbAccessor(Db &db) : Sized(::DbAccessor(trans(db))) {} +} diff --git a/include/storage/model/properties/property_family.hpp b/include/storage/model/properties/property_family.hpp index b71db0c7d..9272a5093 100644 --- a/include/storage/model/properties/property_family.hpp +++ b/include/storage/model/properties/property_family.hpp @@ -5,6 +5,8 @@ #include "data_structures/concurrent/concurrent_map.hpp" #include "storage/indexes/index_holder.hpp" #include "storage/model/properties/flags.hpp" +#include "storage/type_group_edge.hpp" +#include "storage/type_group_vertex.hpp" #include "utils/option.hpp" #include "utils/total_ordering.hpp" #include "utils/underlying_cast.hpp" @@ -192,6 +194,17 @@ private: ConcurrentMap> types; }; +using VertexPropertyKey = + PropertyFamily::PropertyType::PropertyFamilyKey; +using EdgePropertyKey = + PropertyFamily::PropertyType::PropertyFamilyKey; +template +using VertexPropertyType = + PropertyFamily::PropertyType::PropertyTypeKey; +template +using EdgePropertyType = + PropertyFamily::PropertyType::PropertyTypeKey; + template class PropertyHash { diff --git a/poc/CMakeLists.txt b/poc/CMakeLists.txt index 37d6a7213..ca14301e7 100644 --- a/poc/CMakeLists.txt +++ b/poc/CMakeLists.txt @@ -2,6 +2,8 @@ cmake_minimum_required(VERSION 3.1) project(memgraph_poc) +include_directories(${CMAKE_SOURCE_DIR}/poc) + add_executable(poc_astar astar.cpp) target_link_libraries(poc_astar memgraph) target_link_libraries(poc_astar Threads::Threads) @@ -9,10 +11,11 @@ target_link_libraries(poc_astar ${fmt_static_lib}) add_executable(profile profile.cpp) target_link_libraries(profile memgraph) +target_link_libraries(profile barrier) target_link_libraries(profile Threads::Threads) target_link_libraries(profile ${fmt_static_lib}) -include_directories(${CMAKE_SOURCE_DIR}/poc) + add_executable(isolation isolation.cpp isolation/header.cpp) target_link_libraries(isolation ${fmt_static_lib}) diff --git a/poc/profile.cpp b/poc/profile.cpp index 5ad9e419d..90a6a3bd5 100644 --- a/poc/profile.cpp +++ b/poc/profile.cpp @@ -1,3 +1,7 @@ +#include "profile.hpp" + +#include "barrier/barrier.cpp" + #include "database/db.hpp" #include "database/db_accessor.hpp" @@ -6,352 +10,18 @@ #include #include #include -#include "database/db_accessor.cpp" #include "import/csv_import.hpp" -#include "storage/indexes/impl/nonunique_unordered_index.cpp" -#include "storage/model/properties/properties.cpp" -#include "storage/record_accessor.cpp" -#include "storage/vertex_accessor.cpp" +// #include "storage/indexes/impl/nonunique_unordered_index.cpp" +// #include "storage/model/properties/properties.cpp" +// #include "storage/record_accessor.cpp" +// #include "storage/vertex_accessor.cpp" #include "utils/command_line/arguments.hpp" +// #include "barrier/trans.hpp" +// #include "barrier/barrier.cpp" + using namespace std; -// TODO: Turn next template, expand on it, standardize it, and use it for query -// generation. - -template -void fill_to_fill(EdgeAccessor &e, const EdgeType &type, C &&consumer) -{ - if (e.fill() && e.edge_type() == type) { - auto to = e.to(); - if (to.fill()) { - consumer(to); - } - } -} - -template -void fill_from_fill(EdgeAccessor &e, const EdgeType &type, C &&consumer) -{ - if (e.fill() && e.edge_type() == type) { - auto from = e.from(); - if (from.fill()) { - consumer(from); - } - } -} - -template -void fill_to_fill(EdgeAccessor &e, C &&consumer) -{ - if (e.fill()) { - auto to = e.to(); - if (to.fill()) { - consumer(to); - } - } -} - -template -void to_fill(EdgeAccessor &e, C &&consumer) -{ - auto to = e.to(); - if (to.fill()) { - consumer(to); - } -} - -template -void to_fill(EdgeAccessor &e, const Label &label, C &&consumer) -{ - auto to = e.to(); - if (to.fill() && to.has_label(label)) { - consumer(to); - } -} - -template -void to_fill(EdgeAccessor &e, const EdgeType &type, const Label &label, - C &&consumer) -{ - if (e.edge_type() == type) { - auto to = e.to(); - if (to.fill() && to.has_label(label)) { - consumer(to); - } - } -} - -template -void from_fill(EdgeAccessor &e, const EdgeType &type, C &&consumer) -{ - if (e.edge_type() == type) { - auto from = e.from(); - if (from.fill()) { - consumer(from); - } - } -} - -template -void fill_from_fill(EdgeAccessor &e, C &&consumer) -{ - if (e.fill()) { - auto from = e.from(); - if (from.fill()) { - consumer(from); - } - } -} - -namespace iter -{ -template -void for_all_fill(I iter, C &&consumer) -{ - auto e = iter.next(); - while (e.is_present()) { - if (e.get().fill()) consumer(e.take()); - e = iter.next(); - } -} - -template -void find(I iter, C &&consumer) -{ - auto e = iter.next(); - while (e.is_present()) { - - if (consumer(e.take())) { - return; - } - e = iter.next(); - } -} - -template -void find_fill(I iter, C &&consumer) -{ - auto e = iter.next(); - while (e.is_present()) { - if (e.get().fill()) { - if (consumer(e.take())) { - return; - } - } - e = iter.next(); - } -} -} - -void fill_with_bt( - unordered_map &values, VertexAccessor &com, double weight, - VertexPropertyFamily::PropertyType::PropertyTypeKey - &prop_vertex_business_types) -{ - auto bus_t = com.at(prop_vertex_business_types); - if (bus_t.is_present()) { - for (auto &bt : bus_t.get()->value) { - values[bt] += weight; - } - } -} - -void oportunity_employe_company( - VertexAccessor &va, unordered_map &values, double weight, - VertexPropertyFamily::PropertyType::PropertyTypeKey - &prop_vertex_business_types, - const EdgeType &type_created, const EdgeType &type_works_in, - const Label &label_company) -{ - iter::for_all_fill(va.in(), [&](auto opp_e) { - // cout << " oec.in()" << endl; - from_fill(opp_e, type_created, [&](auto creator) { - // cout << " type_created" << endl; - iter::for_all_fill(creator.out(), [&](auto creator_e) { - // cout << " creator.out()" << - // endl; - to_fill(creator_e, type_works_in, label_company, - [&](auto end_com) { - // cout << " fill_bt" - // << endl; - fill_with_bt(values, end_com, weight, - prop_vertex_business_types); - }); - }); - - }); - }); -} - -auto query(DbAccessor &t, const Id &start_id) -{ - // DbAccessor t(db); - unordered_map values; - - const Label &label_company = t.label_find_or_create("Company"); - const Label &label_opportunuty = t.label_find_or_create("Opportunity"); - - const EdgeType &type_works_in = t.type_find_or_create("Works_In"); - const EdgeType &type_reached_to = t.type_find_or_create("Reached_To"); - const EdgeType &type_partnered_with = - t.type_find_or_create("Partnered_With"); - const EdgeType &type_interested_in = t.type_find_or_create("Interested_In"); - const EdgeType &type_viewed = t.type_find_or_create("Viewed"); - const EdgeType &type_has_match = t.type_find_or_create("Has_Match"); - const EdgeType &type_searched_and_clicked = - t.type_find_or_create("Searched_And_Clicked"); - const EdgeType &type_is_employee = t.type_find_or_create("Is_Employee"); - const EdgeType &type_created = t.type_find_or_create("Created"); - - auto prop_edge_status = t.edge_property_family_get("status") - .get(Flags::String) - .type_key(); - auto prop_edge_count = - t.edge_property_family_get("count").get(Flags::Int32).type_key(); - auto prop_edge_feedback = t.edge_property_family_get("feedback") - .get(Flags::String) - .type_key(); - - auto prop_vertex_business_types = - t.vertex_property_family_get("business_types") - .get(Flags::ArrayString) - .type_key(); - - auto osva = t.vertex_find(start_id); - if (!option_fill(osva)) { - cout << "Illegal start vertex" << endl; - return values; - } - auto start = osva.take(); - - // PARTNERS - iter::for_all_fill(start.out(), [&](auto e) { - // cout << "start.out()" << endl; - to_fill(e, type_partnered_with, label_company, [&](auto end_com) { - fill_with_bt(values, end_com, 0.9, prop_vertex_business_types); - }); - }); - - // PERSONELS - iter::for_all(start.in(), [&](auto e) { - // cout << "start.in()" << endl; - fill_from_fill(e, type_works_in, [&](auto employ) { - // cout << " type_works_in" << endl; - iter::for_all_fill(employ.out(), [&](auto employ_edge) { - // cout << " employ.out()" << endl; - auto &ee_type = employ_edge.edge_type(); - // cout << " ee_type: " << ee_type << endl; - - if (ee_type == type_interested_in) { - // cout << " type_interested_in" << endl; - // INTERESTED IN OPPORTUNUTIES - to_fill(employ_edge, label_opportunuty, [&](auto opp) { - oportunity_employe_company( - opp, values, 1, prop_vertex_business_types, - type_created, type_works_in, label_company); - - }); - - } else if (ee_type == type_created) { - // cout << " type_created" << endl; - // CREATED OPPORTUNUTIES - to_fill(employ_edge, label_opportunuty, [&](auto opp) { - iter::for_all_fill(opp.out(), [&](auto edge) { - auto feedback = edge.at(prop_edge_feedback); - if (!feedback.is_present()) { - return; - } - - auto str = feedback.get()->value.c_str(); - double weight = 0; - if (strcasecmp(str, "like") == 0) { - weight = 1; - } else if (strcasecmp(str, "dislike") == 0) { - weight = -1; - } else { - return; - } - - to_fill(edge, label_company, [&](auto end_com) { - fill_with_bt(values, end_com, weight, - prop_vertex_business_types); - }); - }); - }); - - } else { - // cout << " company" << endl; - // COMPANY - double weight = 0; - if (ee_type == type_reached_to) { - auto os = employ_edge.at(prop_edge_status); - if (!os.is_present()) { - return; - } - auto str = os.get()->value.c_str(); - - if (strcasecmp(str, "pending") == 0) { - weight = 0.5; - } else if (strcasecmp(str, "connected") == 0) { - weight = 1; - } else if (strcasecmp(str, "unreachable") == 0) { - weight = 0.5; - } else if (strcasecmp(str, "not_a_match") == 0) { - weight = -1; - } else { - cout << "unknown status: " << str << endl; - } - } else if (ee_type == type_viewed || - ee_type == type_searched_and_clicked) { - auto count = employ_edge.at(prop_edge_count); - if (count.is_present()) { - weight = 0.01 * (count.get()->value); - } - } - - // TARGET COMPANY - if (weight != 0) { - to_fill(employ_edge, [&](auto t_com) { - fill_with_bt(values, t_com, weight, - prop_vertex_business_types); - }); - } - } - }); - }); - }); - - return values; -} - -Option find_company(DbAccessor &t, int64_t cid) -{ - // DbAccessor t(db); - - Option found; - - auto prop_vertex_company_id = t.vertex_property_family_get("company_id") - .get(Flags::Int64) - .type_key(); - const Label &label_company = t.label_find_or_create("Company"); - - iter::find_fill(label_company.index().for_range_exact(t), [&](auto v) { - if (v.has_label(label_company)) { - auto id = v.at(prop_vertex_company_id); - if (id.is_present()) { - if ((*id.get()) == cid) { - found = Option(v.id()); - return true; - } - } - } - return false; - }); - - return found; -} - int main(int argc, char **argv) { auto para = all_arguments(argc, argv); @@ -362,20 +32,12 @@ int main(int argc, char **argv) { DbAccessor t(db); - int n = 300 * 1000; - vector>> coll; + vector>> + coll; // QUERY BENCHMARK auto begin = clock(); - int i = 0; - iter::find_fill( - t.label_find_or_create("Company").index().for_range_exact(t), - [&](auto v) { - coll.push_back(make_pair(v, query(t, v.id()))); - i++; - return false; - }); - n = i; + int n = for_all_companys(barrier::trans(t), coll); clock_t end = clock(); double elapsed_s = (double(end - begin) / CLOCKS_PER_SEC); @@ -395,11 +57,10 @@ int main(int argc, char **argv) res = coll.back(); } - auto prop_vertex_id = t.vertex_property_family_get("company_id") - .get(Flags::Int64) - .type_key(); + auto prop_vertex_id = t.vertex_property_key("company_id"); cout << endl - << "Example: " << *res.first.at(prop_vertex_id).get() << endl; + << "Example: " + << *barrier::trans(res.first).at(prop_vertex_id).get() << endl; for (auto e : res.second) { cout << e.first << " = " << e.second << endl; } diff --git a/poc/profile.hpp b/poc/profile.hpp new file mode 100644 index 000000000..9e4548f21 --- /dev/null +++ b/poc/profile.hpp @@ -0,0 +1,356 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include "barrier/barrier.hpp" + +using namespace std; + +namespace barrier +{ + +// TODO: Turn next template, expand on it, standardize it, and use it for query +// generation. + +template +void fill_to_fill(EdgeAccessor &e, const EdgeType &type, C &&consumer) +{ + if (e.fill() && e.edge_type() == type) { + auto to = e.to(); + if (to.fill()) { + consumer(to); + } + } +} + +template +void fill_from_fill(EdgeAccessor &e, const EdgeType &type, C &&consumer) +{ + if (e.fill() && e.edge_type() == type) { + auto from = e.from(); + if (from.fill()) { + consumer(from); + } + } +} + +template +void fill_to_fill(EdgeAccessor &e, C &&consumer) +{ + if (e.fill()) { + auto to = e.to(); + if (to.fill()) { + consumer(to); + } + } +} + +template +void to_fill(EdgeAccessor &e, C &&consumer) +{ + auto to = e.to(); + if (to.fill()) { + consumer(to); + } +} + +template +void to_fill(EdgeAccessor &e, const Label &label, C &&consumer) +{ + auto to = e.to(); + if (to.fill() && to.has_label(label)) { + consumer(to); + } +} + +template +void to_fill(EdgeAccessor &e, const EdgeType &type, const Label &label, + C &&consumer) +{ + if (e.edge_type() == type) { + auto to = e.to(); + if (to.fill() && to.has_label(label)) { + consumer(to); + } + } +} + +template +void from_fill(EdgeAccessor &e, const EdgeType &type, C &&consumer) +{ + if (e.edge_type() == type) { + auto from = e.from(); + if (from.fill()) { + consumer(from); + } + } +} + +template +void fill_from_fill(EdgeAccessor &e, C &&consumer) +{ + if (e.fill()) { + auto from = e.from(); + if (from.fill()) { + consumer(from); + } + } +} + +namespace iter +{ +template +void for_all_fill(I iter, C &&consumer) +{ + auto e = iter.next(); + while (e.is_present()) { + if (e.get().fill()) consumer(e.take()); + e = iter.next(); + } +} + +template +void find(I iter, C &&consumer) +{ + auto e = iter.next(); + while (e.is_present()) { + + if (consumer(e.take())) { + return; + } + e = iter.next(); + } +} + +template +void find_fill(I iter, C &&consumer) +{ + auto e = iter.next(); + while (e.is_present()) { + if (e.get().fill()) { + if (consumer(e.take())) { + return; + } + } + e = iter.next(); + } +} +} + +void fill_with_bt(unordered_map &values, VertexAccessor &com, + double weight, + VertexPropertyType &prop_vertex_business_types) +{ + auto bus_t = com.at(prop_vertex_business_types); + if (bus_t.is_present()) { + for (auto &bt : bus_t.get()->value) { + values[bt] += weight; + } + } +} + +void oportunity_employe_company( + VertexAccessor &va, unordered_map &values, double weight, + VertexPropertyType &prop_vertex_business_types, + const EdgeType &type_created, const EdgeType &type_works_in, + const Label &label_company) +{ + iter::for_all_fill(va.in(), [&](auto opp_e) { + // cout << " oec.in()" << endl; + from_fill(opp_e, type_created, [&](auto creator) { + // cout << " type_created" << endl; + iter::for_all_fill(creator.out(), [&](auto creator_e) { + // cout << " creator.out()" << + // endl; + to_fill(creator_e, type_works_in, label_company, + [&](auto end_com) { + // cout << " fill_bt" + // << endl; + fill_with_bt(values, end_com, weight, + prop_vertex_business_types); + }); + }); + + }); + }); +} + +auto query(DbAccessor &t, const Id &start_id) +{ + // DbAccessor t(db); + unordered_map values; + + const Label &label_company = t.label_find_or_create("Company"); + const Label &label_opportunuty = t.label_find_or_create("Opportunity"); + + const EdgeType &type_works_in = t.type_find_or_create("Works_In"); + const EdgeType &type_reached_to = t.type_find_or_create("Reached_To"); + const EdgeType &type_partnered_with = + t.type_find_or_create("Partnered_With"); + const EdgeType &type_interested_in = t.type_find_or_create("Interested_In"); + const EdgeType &type_viewed = t.type_find_or_create("Viewed"); + const EdgeType &type_has_match = t.type_find_or_create("Has_Match"); + const EdgeType &type_searched_and_clicked = + t.type_find_or_create("Searched_And_Clicked"); + const EdgeType &type_is_employee = t.type_find_or_create("Is_Employee"); + const EdgeType &type_created = t.type_find_or_create("Created"); + + auto prop_edge_status = t.edge_property_key("status"); + auto prop_edge_count = t.edge_property_key("count"); + auto prop_edge_feedback = t.edge_property_key("feedback"); + + auto prop_vertex_business_types = + t.vertex_property_key("business_types"); + + auto osva = t.vertex_find(start_id); + if (!option_fill(osva)) { + cout << "Illegal start vertex" << endl; + return values; + } + auto start = osva.take(); + + // PARTNERS + iter::for_all_fill(start.out(), [&](auto e) { + // cout << "start.out()" << endl; + to_fill(e, type_partnered_with, label_company, [&](auto end_com) { + fill_with_bt(values, end_com, 0.9, prop_vertex_business_types); + }); + }); + + // PERSONELS + ::iter::for_all(start.in(), [&](auto e) { + // cout << "start.in()" << endl; + fill_from_fill(e, type_works_in, [&](auto employ) { + // cout << " type_works_in" << endl; + iter::for_all_fill(employ.out(), [&](auto employ_edge) { + // cout << " employ.out()" << endl; + auto &ee_type = employ_edge.edge_type(); + // cout << " ee_type: " << ee_type << endl; + + if (ee_type == type_interested_in) { + // cout << " type_interested_in" << endl; + // INTERESTED IN OPPORTUNUTIES + to_fill(employ_edge, label_opportunuty, [&](auto opp) { + oportunity_employe_company( + opp, values, 1, prop_vertex_business_types, + type_created, type_works_in, label_company); + + }); + + } else if (ee_type == type_created) { + // cout << " type_created" << endl; + // CREATED OPPORTUNUTIES + to_fill(employ_edge, label_opportunuty, [&](auto opp) { + iter::for_all_fill(opp.out(), [&](auto edge) { + auto feedback = edge.at(prop_edge_feedback); + if (!feedback.is_present()) { + return; + } + + auto str = feedback.get()->value.c_str(); + double weight = 0; + if (strcasecmp(str, "like") == 0) { + weight = 1; + } else if (strcasecmp(str, "dislike") == 0) { + weight = -1; + } else { + return; + } + + to_fill(edge, label_company, [&](auto end_com) { + fill_with_bt(values, end_com, weight, + prop_vertex_business_types); + }); + }); + }); + + } else { + // cout << " company" << endl; + // COMPANY + double weight = 0; + if (ee_type == type_reached_to) { + auto os = employ_edge.at(prop_edge_status); + if (!os.is_present()) { + return; + } + auto str = os.get()->value.c_str(); + + if (strcasecmp(str, "pending") == 0) { + weight = 0.5; + } else if (strcasecmp(str, "connected") == 0) { + weight = 1; + } else if (strcasecmp(str, "unreachable") == 0) { + weight = 0.5; + } else if (strcasecmp(str, "not_a_match") == 0) { + weight = -1; + } else { + cout << "unknown status: " << str << endl; + } + } else if (ee_type == type_viewed || + ee_type == type_searched_and_clicked) { + auto count = employ_edge.at(prop_edge_count); + if (count.is_present()) { + weight = 0.01 * (count.get()->value); + } + } + + // TARGET COMPANY + if (weight != 0) { + to_fill(employ_edge, [&](auto t_com) { + fill_with_bt(values, t_com, weight, + prop_vertex_business_types); + }); + } + } + }); + }); + }); + + return values; +} + +Option find_company(DbAccessor &t, int64_t cid) +{ + // DbAccessor t(db); + + Option found; + + auto prop_vertex_company_id = t.vertex_property_key("company_id"); + const Label &label_company = t.label_find_or_create("Company"); + + iter::find_fill(label_company.index().for_range(t), [&](auto v) { + if (v.has_label(label_company)) { + auto id = v.at(prop_vertex_company_id); + if (id.is_present()) { + if ((*id.get()) == cid) { + found = Option(v.id()); + return true; + } + } + } + return false; + }); + + return found; +} + +size_t for_all_companys( + DbAccessor &t, + vector>> &coll) +{ + int i = 0; + iter::for_all_fill( + t.label_find_or_create("Company").index().for_range(t), [&](auto v) { + coll.push_back(make_pair(v, barrier::query(t, v.id()))); + i++; + return false; + }); + return i; +} +} diff --git a/src/barrier/barrier.cpp b/src/barrier/barrier.cpp index bad485470..ce9b99d39 100644 --- a/src/barrier/barrier.cpp +++ b/src/barrier/barrier.cpp @@ -1,292 +1,42 @@ #include "barrier/barrier.hpp" - -// This is the place for imports from memgraph .hpp -#include "communication/bolt/v1/serialization/bolt_serializer.hpp" -#include "database/db.hpp" -#include "database/db_accessor.hpp" -#include "storage/edge_type/edge_type.hpp" -#include "storage/label/label.hpp" - -// This is the place for imports from memgraph .cpp -// #include "database/db_accessor.cpp" -#include "storage/vertex_accessor.cpp" - -// TODO: Extract trans functions to other hpp for easy including into other -// code. - -// **************************** HELPER DEFINES *******************************// -// returns transformed pointer -#define THIS (trans(this)) -// Performs call x on transformed border class. -#define HALF_CALL(x) (THIS->x) -// Performs call x on transformed border class and returns transformed output. -#define CALL(x) trans(HALF_CALL(x)) - -#define TRANSFORM_REF(x, y) \ - x &trans(y &l) { return ref_as(l); } \ - x const &trans(y const &l) { return ref_as(l); } \ - y &trans(x &l) { return ref_as(l); } \ - y const &trans(x const &l) { return ref_as(l); } \ - x *trans(y *l) { return ptr_as(l); } \ - x const *trans(y const *l) { return ptr_as(l); } \ - y *trans(x *l) { return ptr_as(l); } \ - y const *trans(x const *l) { return ptr_as(l); } - -#define TRANSFORM_REF_TEMPLATED(x, y) \ - x &trans(y &l) { return ref_as(l); } \ - template \ - x const &trans(y const &l) \ - { \ - return ref_as(l); \ - } \ - template \ - y &trans(x &l) \ - { \ - return ref_as(l); \ - } \ - template \ - y const &trans(x const &l) \ - { \ - return ref_as(l); \ - } \ - template \ - x *trans(y *l) \ - { \ - return ptr_as(l); \ - } \ - template \ - const x *trans(const y *l) \ - { \ - return ptr_as(l); \ - } \ - template \ - y *trans(x *l) \ - { \ - return ptr_as(l); \ - } \ - template \ - const y *trans(const x *l) \ - { \ - return ptr_as(l); \ - } -#define DESTRUCTOR(x, y) \ - x::~x() { HALF_CALL(~y()); } -#define COPY_CONSTRUCTOR(x, y) \ - x::x(const x &other) : Sized(y(trans(other))) {} -#define MOVE_CONSTRUCTOR(x) \ - x::x(x &&other) : Sized(trans(std::move(other))) {} -#define MOVE_CONST_CONSTRUCTOR(x) \ - x::x(x const &&other) : Sized(trans(std::move(other))) {} - -// For certain classes trans evaluates into ref which doesnt work for Sized -// constructor. This Move forces type. -#define MOVE_CONSTRUCTOR_FORCED(x, y) \ - x::x(x &&other) : Sized(value_as(std::move(other))) {} - -#define COPY_OPERATOR(x) \ - x &x::operator=(const x &other) \ - { \ - HALF_CALL(operator=(trans(other))); \ - return *this; \ - } -#define MOVE_OPERATOR(x) \ - x &x::operator=(x &&other) \ - { \ - HALF_CALL(operator=(trans(std::move(other)))); \ - return *this; \ - } - -#define VALID_CONSTRUCTION(x, y) \ - template <> \ - barrier::x::x(y &&d) : Sized(std::move(d)) \ - { \ - } - -#define VALID_CONSTRUCTION_CONST(x, y) \ - template <> \ - barrier::x::x(y const &&d) : Sized(std::move(d)) \ - { \ - } - -// Generates transformation function from original class to border class. -#define TRANSFORM_VALUE_ONE_RAW(x, y) \ - x trans(y &&d) { return x(std::move(d)); } - -// Generates transformation function from original class to border class. -#define TRANSFORM_VALUE_ONE(x, y) \ - VALID_CONSTRUCTION(x, y) \ - x trans(y &&d) { return x(std::move(d)); } - -// Generates transformation functions between border class x and original class -// y by value. Only mutable values. -#define TRANSFORM_VALUE_MUT(x, y) \ - TRANSFORM_VALUE_ONE(x, y) \ - y trans(x &&d) { return value_as(std::move(d)); } - -// Generates transformation functions between border class x and original class -// y by value. -#define TRANSFORM_VALUE(x, y) \ - TRANSFORM_VALUE_MUT(x, y) \ - VALID_CONSTRUCTION_CONST(x, y) \ - const x trans(const y &&d) { return x(std::move(d)); } \ - const y trans(const x &&d) { return value_as(std::move(d)); } - -// Duplicates given first name to call second given with name and ::name -#define DUP(x, y) y(x, ::x) - -// ********************** TYPES OF AUTO -using vertex_access_iterator_t = - decltype(((::DbAccessor *)(std::nullptr_t()))->vertex_access()); - -using out_edge_iterator_t = - decltype(((::VertexAccessor *)(std::nullptr_t()))->out()); - -using in_edge_iterator_t = - decltype(((::VertexAccessor *)(std::nullptr_t()))->in()); - -// This file should contain all implementations of methods from barrier classes -// defined in barrier.hpp. -// Implementations should follow the form: -// border_return_type border_class::method_name(arguments){ -// return -// CALL(method_name(trans(arguments)))/HALF_CALL(method_name(trans(arguments))); -// } - -// ********************** ALL VALID CONVERSIONS ***************************** // -// Implementations must use exclusivly trans functions to cast between types. - -// ******************** OVERLOADED trans FUNCTIONS. -// This enclosure is the only dangerous part of barrier except of Sized class in -// common.hpp -namespace barrier -{ -// Blueprint for valid transformation of references: -// TRANSFORM_REF(, ::); -// template TRANSFORM_REF_TEMPLATED(,::); - -// ***************** TRANSFORMS of reference -DUP(Label, TRANSFORM_REF); -DUP(EdgeType, TRANSFORM_REF); -DUP(VertexPropertyFamily, TRANSFORM_REF); -DUP(EdgePropertyFamily, TRANSFORM_REF); -DUP(VertexAccessor, TRANSFORM_REF); -DUP(EdgeAccessor, TRANSFORM_REF); -DUP(Db, TRANSFORM_REF); -DUP(DbAccessor, TRANSFORM_REF); -TRANSFORM_REF(std::vector, std::vector<::label_ref_t>); -TRANSFORM_REF(VertexPropertyKey, - ::VertexPropertyFamily::PropertyType::PropertyFamilyKey); -TRANSFORM_REF(EdgePropertyKey, - ::EdgePropertyFamily::PropertyType::PropertyFamilyKey); -TRANSFORM_REF(VertexIterator, - std::unique_ptr>); -TRANSFORM_REF(EdgeIterator, - std::unique_ptr>); -TRANSFORM_REF(VertexAccessIterator, vertex_access_iterator_t); -TRANSFORM_REF(OutEdgesIterator, out_edge_iterator_t); -TRANSFORM_REF(InEdgesIterator, in_edge_iterator_t); - -template -TRANSFORM_REF_TEMPLATED(VertexIndex, VertexIndexBase); -template -TRANSFORM_REF_TEMPLATED(EdgeIndex, EdgeIndexBase); -template -TRANSFORM_REF_TEMPLATED(BoltSerializer, ::bolt::BoltSerializer); - -template -TRANSFORM_REF_TEMPLATED( - VertexPropertyType, - ::VertexPropertyFamily::PropertyType::PropertyTypeKey); - -template -TRANSFORM_REF_TEMPLATED(EdgePropertyType, - ::EdgePropertyFamily::PropertyType::PropertyTypeKey); - -// ****************** TRANSFORMS of value -// Blueprint for valid transformation of value: -// TRANSFORM_VALUE(, ::); -DUP(VertexAccessor, TRANSFORM_VALUE); -DUP(EdgeAccessor, TRANSFORM_VALUE); -TRANSFORM_VALUE(EdgePropertyKey, - ::EdgePropertyFamily::PropertyType::PropertyFamilyKey); -TRANSFORM_VALUE(VertexPropertyKey, - ::VertexPropertyFamily::PropertyType::PropertyFamilyKey); -TRANSFORM_VALUE_ONE(VertexAccessIterator, vertex_access_iterator_t); -MOVE_CONSTRUCTOR_FORCED(VertexAccessIterator, vertex_access_iterator_t); -TRANSFORM_VALUE_ONE(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>); -MOVE_CONSTRUCTOR_FORCED(VertexIterator, - std::unique_ptr>); -TRANSFORM_VALUE_ONE(EdgeIterator, - std::unique_ptr>); -MOVE_CONSTRUCTOR_FORCED(EdgeIterator, - std::unique_ptr>); - -template -TRANSFORM_VALUE_ONE_RAW( - VertexPropertyType, - ::VertexPropertyFamily::PropertyType::PropertyTypeKey); -template -TRANSFORM_VALUE_ONE_RAW(EdgePropertyType, - ::EdgePropertyFamily::PropertyType::PropertyTypeKey) - -template -TRANSFORM_VALUE_ONE_RAW(BoltSerializer, ::bolt::BoltSerializer) - -// ********************* SPECIAL SIZED CONSTRUCTORS -#define VertexPropertyType_constructor(x) \ - template <> \ - template <> \ - VertexPropertyType::VertexPropertyType( \ - ::VertexPropertyFamily::PropertyType::PropertyTypeKey &&d) \ - : Sized(std::move(d)) \ - { \ - } -INSTANTIATE_FOR_PROPERTY(VertexPropertyType_constructor); - -#define EdgePropertyType_constructor(x) \ - template <> \ - template <> \ - EdgePropertyType::EdgePropertyType( \ - ::EdgePropertyFamily::PropertyType::PropertyTypeKey &&d) \ - : Sized(std::move(d)) \ - { \ - } -INSTANTIATE_FOR_PROPERTY(EdgePropertyType_constructor); - -DbAccessor::DbAccessor(Db &db) : Sized(::DbAccessor(trans(db))) {} -} +#include "barrier/trans.hpp" // ************************* Implementations namespace barrier { // ************************* EdgePropertyType -#define FOR_ALL_PROPS_delete_EdgePropertyType(x) \ - template <> \ - EdgePropertyType::~EdgePropertyType() \ - { \ - HALF_CALL(~PropertyTypeKey()); \ - } -INSTANTIATE_FOR_PROPERTY(FOR_ALL_PROPS_delete_EdgePropertyType) +// #define FOR_ALL_PROPS_delete_EdgePropertyType(x) \ +// template <> \ +// EdgePropertyType::~EdgePropertyType() \ +// { \ +// HALF_CALL(~PropertyTypeKey()); \ +// } +// INSTANTIATE_FOR_PROPERTY(FOR_ALL_PROPS_delete_EdgePropertyType) // ************************* VertexPropertyType -#define FOR_ALL_PROPS_delete_VertexPropertyType(x) \ - template <> \ - VertexPropertyType::~VertexPropertyType() \ - { \ - HALF_CALL(~PropertyTypeKey()); \ - } -INSTANTIATE_FOR_PROPERTY(FOR_ALL_PROPS_delete_VertexPropertyType) +// #define FOR_ALL_PROPS_delete_VertexPropertyType(x) \ +// template <> \ +// VertexPropertyType::~VertexPropertyType() \ +// { \ +// HALF_CALL(~PropertyTypeKey()); \ +// } +// // INSTANTIATE_FOR_PROPERTY(FOR_ALL/_PROPS_delete_VertexPropertyType) // ***************** Label VertexIndex &Label::index() const { return CALL(index()); } // **************** EdgeType +bool operator<(const EdgeType &lhs, const EdgeType &rhs) +{ + return trans(lhs) < trans(rhs); +} + +bool operator==(const EdgeType &lhs, const EdgeType &rhs) +{ + return trans(lhs) == trans(rhs); +} + EdgeIndex &EdgeType::index() const { return CALL(index()); } // **************** VertexIndex @@ -424,6 +174,7 @@ void DbAccessor::abort() { HALF_CALL(abort()); } // ************************** VertexAccessor DUP(VertexAccessor, COPY_CONSTRUCTOR); +DUP(VertexAccessor, COPY_CONSTRUCTOR_MUT); MOVE_CONSTRUCTOR(VertexAccessor); MOVE_CONST_CONSTRUCTOR(VertexAccessor); DESTRUCTOR(VertexAccessor, VertexAccessor); @@ -537,6 +288,7 @@ bool operator!=(const VertexAccessor &a, const VertexAccessor &b) // ************************** EdgeAccessor DUP(EdgeAccessor, COPY_CONSTRUCTOR); +DUP(EdgeAccessor, COPY_CONSTRUCTOR_MUT); MOVE_CONSTRUCTOR(EdgeAccessor); MOVE_CONST_CONSTRUCTOR(EdgeAccessor); DESTRUCTOR(EdgeAccessor, EdgeAccessor); diff --git a/tests/integration/queries.cpp b/tests/integration/queries.cpp index d133df022..ad649fd75 100644 --- a/tests/integration/queries.cpp +++ b/tests/integration/queries.cpp @@ -4,11 +4,11 @@ #include "database/db.hpp" #include "query_engine/query_stripper.hpp" -#include "storage/edges.cpp" -#include "storage/edges.hpp" -#include "storage/vertices.cpp" -#include "storage/vertices.hpp" -#include "utils/assert.hpp" +// #include "storage/edges.cpp" +// #include "storage/edges.hpp" +// #include "storage/vertices.cpp" +// #include "storage/vertices.hpp" +// #include "utils/assert.hpp" int main(void) {