From 61eccc28cebe6793c2dfacb1e95efd879c29b115 Mon Sep 17 00:00:00 2001 From: Kruno Tomola Fabro Date: Tue, 9 Aug 2016 20:29:03 +0100 Subject: [PATCH] Created EdgeRecord as class and changed in edge vector for map. EdgeRecord now contains from,to fields as immutables. Vertex in place of in vector of edges has in RbHashMultimap of edges. Astar exepriment now uses real filters based on before mentioned map. --- include/mvcc/edge_record.hpp | 38 +++++++++--- include/storage/model/edge_map.hpp | 2 + poc/astar.cpp | 67 +++++++++++++-------- src/data_structures/map/rh_hashmap.hpp | 16 +++++ src/data_structures/map/rh_hashmultimap.hpp | 31 ++++++---- src/mvcc/version_list.hpp | 2 +- src/query_engine/hardcode/queries.hpp | 33 ++++------ src/storage/edge_accessor.hpp | 26 ++++---- src/storage/edges.hpp | 57 +++++++++--------- src/storage/model/edge_list.hpp | 22 +++---- src/storage/model/edge_model.hpp | 5 +- src/storage/model/vertex_model.hpp | 4 +- src/storage/record_accessor.hpp | 47 ++++++--------- 13 files changed, 193 insertions(+), 157 deletions(-) diff --git a/include/mvcc/edge_record.hpp b/include/mvcc/edge_record.hpp index 0ee9eee80..d2e98e1a4 100644 --- a/include/mvcc/edge_record.hpp +++ b/include/mvcc/edge_record.hpp @@ -1,11 +1,33 @@ +#pragma once + #include "mvcc/version_list.hpp" #include "storage/edge.hpp" -// class EdgeRecord: public mvcc::VersionList{ -// public: -// using mvcc::VersionList; -// -// VertexRecord* get_key(){ -// //TODO -// } -// }; +class EdgeRecord : public mvcc::VersionList +{ +public: + EdgeRecord(Id id, VertexRecord *from, VertexRecord *to) + : from_v(from), to_v(to), VersionList(id) + { + } + EdgeRecord(const VersionList &) = delete; + + /* @brief Move constructs the version list + * Note: use only at the beginning of the "other's" lifecycle since this + * constructor doesn't move the RecordLock, but only the head pointer + */ + EdgeRecord(EdgeRecord &&other) + : from_v(other.from_v), to_v(other.to_v), VersionList(std::move(other)) + { + } + + VertexRecord *&get_key() { return from_v; } + + auto from() const { return this->from_v; } + + auto to() const { return this->to_v; } + +private: + VertexRecord *from_v; + VertexRecord *to_v; +}; diff --git a/include/storage/model/edge_map.hpp b/include/storage/model/edge_map.hpp index 69414f465..79de22e84 100644 --- a/include/storage/model/edge_map.hpp +++ b/include/storage/model/edge_map.hpp @@ -24,6 +24,8 @@ public: throw std::bad_function_call::bad_function_call(); } + bool contains(VertexRecord *vr) { return edges.contains(vr); } + void clear() { edges.clear(); } private: diff --git a/poc/astar.cpp b/poc/astar.cpp index c2fc542b4..b53b03ad7 100644 --- a/poc/astar.cpp +++ b/poc/astar.cpp @@ -1,3 +1,5 @@ +#include +#include #include #include #include @@ -20,10 +22,15 @@ public: double cost; int depth = {0}; Vertex *vertex; + VertexRecord *record; - Node(Vertex *va, double cost) : cost(cost), vertex(va) {} - Node(Vertex *va, double cost, Node *parent) - : cost(cost), vertex(va), parent(parent), depth(parent->depth + 1) + Node(Vertex *va, VertexRecord *record, double cost) + : cost(cost), vertex(va), record(record) + { + } + Node(Vertex *va, VertexRecord *record, double cost, Node *parent) + : cost(cost), vertex(va), parent(parent), depth(parent->depth + 1), + record(record) { } }; @@ -82,10 +89,10 @@ double calc_heuristic_cost_dummy(Edge *edge, Vertex *vertex) return 1 - vertex->data.props.at("score").as().value; } -typedef bool (*EdgeFilter)(tx::Transaction &t, Edge *, Node *before); +typedef bool (*EdgeFilter)(tx::Transaction &t, EdgeRecord *, Node *before); typedef bool (*VertexFilter)(tx::Transaction &t, Vertex *, Node *before); -bool edge_filter_dummy(tx::Transaction &t, Edge *e, Node *before) +bool edge_filter_dummy(tx::Transaction &t, EdgeRecord *e, Node *before) { return true; } @@ -104,9 +111,8 @@ bool vertex_filter_contained_dummy(tx::Transaction &t, Vertex *v, Node *before) if (before == nullptr) { return true; } - for (auto e : before->vertex->data.out) { - Edge *edge = e->find(t); - Vertex *e_v = edge->data.to->find(t); + for (auto edge : before->vertex->data.out) { + Vertex *e_v = edge->to()->find(t); if (e_v == v) { found = true; break; @@ -116,6 +122,19 @@ bool vertex_filter_contained_dummy(tx::Transaction &t, Vertex *v, Node *before) return false; } +bool vertex_filter_contained(tx::Transaction &t, Vertex *v, Node *before) +{ + bool found; + do { + found = false; + before = before->parent; + if (before == nullptr) { + return true; + } + } while (v->data.in.contains(before->record)); + return false; +} + // Vertex filter ima max_depth funkcija te edge filter ima max_depth funkcija. // Jedan za svaku dubinu. // Filtri vracaju true ako element zadovoljava uvjete. @@ -129,8 +148,8 @@ void a_star(Db &db, int64_t sys_id_start, uint max_depth, EdgeFilter e_filter[], auto cmp = [](Node *left, Node *right) { return left->cost > right->cost; }; std::priority_queue, decltype(cmp)> queue(cmp); - Node *start = - new Node(db.graph.vertices.find(t, sys_id_start).vlist->find(t), 0); + auto start_vr = db.graph.vertices.find(t, sys_id_start).vlist; + Node *start = new Node(start_vr->find(t), start_vr, 0); queue.push(start); int count = 0; do { @@ -145,13 +164,13 @@ void a_star(Db &db, int64_t sys_id_start, uint max_depth, EdgeFilter e_filter[], continue; } - for (auto e : now->vertex->data.out) { - Edge *edge = e->find(t); + for (auto edge : now->vertex->data.out) { if (e_filter[now->depth](t, edge, now)) { - Vertex *v = edge->data.to->find(t); + Vertex *v = edge->to()->find(t); if (v_filter[now->depth](t, v, now)) { Node *n = new Node( - v, now->cost + calc_heuristic_cost(edge, v), now); + v, edge->to(), + now->cost + calc_heuristic_cost(edge->find(t), v), now); queue.push(n); } } @@ -172,9 +191,14 @@ int main() // EdgeFilter e_filters[] = {&edge_filter_dummy, &edge_filter_dummy, &edge_filter_dummy, &edge_filter_dummy}; - VertexFilter f_filters[] = {&vertex_filter_dummy, &vertex_filter_dummy, - &vertex_filter_dummy, &vertex_filter_dummy}; + VertexFilter f_filters[] = { + &vertex_filter_contained, &vertex_filter_contained, + &vertex_filter_contained, &vertex_filter_contained}; + auto begin = clock(); a_star(db, 0, 3, e_filters, f_filters, &calc_heuristic_cost_dummy, 10); + clock_t end = clock(); + double elapsed_ms = (double(end - begin) / CLOCKS_PER_SEC) * 1000; + std::cout << "A-star: " << elapsed_ms << " [ms]\n"; return 0; } @@ -254,14 +278,11 @@ void load_csv(Db &db, char *file_path, char *edge_file_path) auto v2 = va[to - start_vertex_id]; - auto edge_accessor = db.graph.edges.insert(t); + auto edge_accessor = db.graph.edges.insert(t, v1.vlist, v2.vlist); v1.vlist->update(t)->data.out.add(edge_accessor.vlist); v2.vlist->update(t)->data.in.add(edge_accessor.vlist); - edge_accessor.from(v1.vlist); - edge_accessor.to(v2.vlist); - auto &edge_type = db.graph.edge_type_store.find_or_create(type); edge_accessor.edge_type(edge_type); }; @@ -299,14 +320,10 @@ void load_graph_dummy(Db &db) auto v2 = db.graph.vertices.find(t, va[to]); - auto edge_accessor = db.graph.edges.insert(t); - + auto edge_accessor = db.graph.edges.insert(t, v1.vlist, v2.vlist); v1.vlist->update(t)->data.out.add(edge_accessor.vlist); v2.vlist->update(t)->data.in.add(edge_accessor.vlist); - edge_accessor.from(v1.vlist); - edge_accessor.to(v2.vlist); - auto &edge_type = db.graph.edge_type_store.find_or_create(type); edge_accessor.edge_type(edge_type); }; diff --git a/src/data_structures/map/rh_hashmap.hpp b/src/data_structures/map/rh_hashmap.hpp index 7e28105ff..e902395de 100644 --- a/src/data_structures/map/rh_hashmap.hpp +++ b/src/data_structures/map/rh_hashmap.hpp @@ -130,6 +130,22 @@ public: RhHashMap() {} + RhHashMap(const RhHashMap &other) + { + capacity = other.capacity; + count = other.count; + if (capacity > 0) { + size_t bytes = sizeof(Combined) * capacity; + array = (Combined *)malloc(bytes); + memcpy(array, other.array, bytes); + + } else { + array = nullptr; + } + } + + ~RhHashMap() { this->clear(); } + Iterator begin() { return Iterator(this); } ConstIterator begin() const { return ConstIterator(this); } diff --git a/src/data_structures/map/rh_hashmultimap.hpp b/src/data_structures/map/rh_hashmultimap.hpp index 781938bda..3d1103171 100644 --- a/src/data_structures/map/rh_hashmultimap.hpp +++ b/src/data_structures/map/rh_hashmultimap.hpp @@ -1,5 +1,6 @@ #include "utils/crtp.hpp" #include "utils/option_ptr.hpp" +#include // HashMultiMap with RobinHood collision resolution policy. // Single threaded. @@ -165,16 +166,18 @@ public: } } - RhHashMultiMap(RhHashMultiMap &&other) - { - capacity = other.capacity; - count = other.count; - array = other.array; + // RhHashMultiMap(RhHashMultiMap &&other) + // { + // capacity = other.capacity; + // count = other.count; + // array = other.array; + // + // other.array = nullptr; + // other.capacity = 0; + // other.count = 0; + // } - other.array = nullptr; - other.capacity = 0; - other.count = 0; - } + ~RhHashMultiMap() { this->clear(); } Iterator begin() { return Iterator(this); } @@ -192,7 +195,7 @@ public: { size_t bytes = sizeof(Combined) * size; array = (Combined *)malloc(bytes); - memset(array, 0, bytes); + std::memset(array, 0, bytes); capacity = size; } @@ -219,6 +222,8 @@ public: free(a); } + bool contains(const K &key) { return find(key) != end(); } + Iterator find(const K &key) { size_t mask = this->mask(); @@ -227,7 +232,7 @@ public: bool bef_init = false; size_t before_off; - K before_key = key; + auto before_key = key; size_t border = 8 <= capacity ? 8 : capacity; while (off < border) { @@ -270,7 +275,7 @@ public: } // Inserts element with the given key. - void add(K key, D *data) + void add(K &key, D *data) { assert(key == data->get_key()); @@ -280,7 +285,7 @@ public: bool bef_init = false; size_t before_off; - K before_key = key; + auto before_key = key; size_t border = 8 <= capacity ? 8 : capacity; while (off < border) { diff --git a/src/mvcc/version_list.hpp b/src/mvcc/version_list.hpp index d0bbc12fc..e6126201f 100644 --- a/src/mvcc/version_list.hpp +++ b/src/mvcc/version_list.hpp @@ -172,4 +172,4 @@ class Vertex; class Edge; using VertexRecord = mvcc::VersionList; -using EdgeRecord = mvcc::VersionList; +// using EdgeRecord = mvcc::VersionList; diff --git a/src/query_engine/hardcode/queries.hpp b/src/query_engine/hardcode/queries.hpp index add155ee3..0c19af658 100644 --- a/src/query_engine/hardcode/queries.hpp +++ b/src/query_engine/hardcode/queries.hpp @@ -2,11 +2,11 @@ #include "database/db.hpp" #include "query_engine/query_stripper.hpp" +#include "query_engine/util.hpp" #include "storage/model/properties/property.hpp" #include "utils/command_line/arguments.hpp" -#include "query_engine/util.hpp" -auto load_queries(Db& db) +auto load_queries(Db &db) { std::map> queries; @@ -72,14 +72,11 @@ auto load_queries(Db& db) auto v2 = db.graph.vertices.find(t, args[1]->as().value); if (!v2) return t.commit(), false; - auto edge_accessor = db.graph.edges.insert(t); + auto edge_accessor = db.graph.edges.insert(t, v1.vlist, v2.vlist); v1.vlist->update(t)->data.out.add(edge_accessor.vlist); v2.vlist->update(t)->data.in.add(edge_accessor.vlist); - edge_accessor.from(v1.vlist); - edge_accessor.to(v2.vlist); - auto &edge_type = db.graph.edge_type_store.find_or_create("IS"); edge_accessor.edge_type(edge_type); @@ -127,31 +124,28 @@ auto load_queries(Db& db) return true; }; - // MATCH (n1), (n2) WHERE ID(n1)=0 AND ID(n2)=1 CREATE (n1)<-[r:IS {age: 25, weight: 70}]-(n2) RETURN r - auto create_edge_v2 = [&db](const properties_t &args) - { - auto& t = db.tx_engine.begin(); + // MATCH (n1), (n2) WHERE ID(n1)=0 AND ID(n2)=1 CREATE (n1)<-[r:IS {age: 25, + // weight: 70}]-(n2) RETURN r + auto create_edge_v2 = [&db](const properties_t &args) { + auto &t = db.tx_engine.begin(); auto n1 = db.graph.vertices.find(t, args[0]->as().value); if (!n1) return t.commit(), false; auto n2 = db.graph.vertices.find(t, args[1]->as().value); if (!n2) return t.commit(), false; - auto r = db.graph.edges.insert(t); + auto r = db.graph.edges.insert(t, n2.vlist, n1.vlist); r.property("age", args[2]); r.property("weight", args[3]); auto &IS = db.graph.edge_type_store.find_or_create("IS"); r.edge_type(IS); n2.vlist->update(t)->data.out.add(r.vlist); n1.vlist->update(t)->data.in.add(r.vlist); - r.from(n2.vlist); - r.to(n1.vlist); t.commit(); return true; }; queries[15648836733456301916u] = create_edge_v2; // MATCH (n) RETURN n - auto match_all_nodes = [&db](const properties_t &args) - { + auto match_all_nodes = [&db](const properties_t &args) { auto &t = db.tx_engine.begin(); auto vertices_accessor = db.graph.vertices.access(); @@ -160,7 +154,7 @@ auto load_queries(Db& db) if (vertex == nullptr) continue; cout_properties(vertex->data.props); } - + // TODO // db.graph.vertices.filter().all(t, handler); @@ -171,8 +165,7 @@ auto load_queries(Db& db) queries[15284086425088081497u] = match_all_nodes; // MATCH (n:LABEL) RETURN n - auto find_by_label = [&db](const properties_t &args) - { + auto find_by_label = [&db](const properties_t &args) { auto &t = db.tx_engine.begin(); auto &label = db.graph.label_store.find_or_create("LABEL"); @@ -181,10 +174,10 @@ auto load_queries(Db& db) db.graph.vertices.find_label_index(label); auto accessor = index_record_collection.access(); cout << "VERTICES" << endl; - for (auto& v : accessor) { + for (auto &v : accessor) { cout << v.record->data.props.at("name").as().value << endl; } - + // TODO // db.graph.vertices.fileter("LABEL").all(t, handler); diff --git a/src/storage/edge_accessor.hpp b/src/storage/edge_accessor.hpp index acb02d31b..bef5fdaee 100644 --- a/src/storage/edge_accessor.hpp +++ b/src/storage/edge_accessor.hpp @@ -1,5 +1,6 @@ #pragma once +#include "mvcc/edge_record.hpp" #include "storage/edge.hpp" #include "storage/record_accessor.hpp" #include "utils/assert.hpp" @@ -8,7 +9,8 @@ class Edges; // TODO: Edge, Db, Edge::Accessor -class Edge::Accessor : public RecordAccessor +class Edge::Accessor + : public RecordAccessor { public: using RecordAccessor::RecordAccessor; @@ -26,17 +28,17 @@ public: } // TODO: VertexAccessor - void from(VertexRecord *vertex_record) - { - this->record->data.from = vertex_record; - } + // void from(VertexRecord *vertex_record) + // { + // this->record->data.from = vertex_record; + // } + // + // void to(VertexRecord *vertex_record) + // { + // this->record->data.to = vertex_record; + // } - void to(VertexRecord *vertex_record) - { - this->record->data.to = vertex_record; - } + auto from() const { return this->vlist->from(); } - auto from() const { return this->record->data.from; } - - auto to() const { return this->record->data.to; } + auto to() const { return this->vlist->to(); } }; diff --git a/src/storage/edges.hpp b/src/storage/edges.hpp index 09c85ffdf..2126fa9b8 100644 --- a/src/storage/edges.hpp +++ b/src/storage/edges.hpp @@ -6,42 +6,43 @@ class Edges { - public: - Edge::Accessor find(tx::Transaction &t, const Id &id) - { - auto edges_accessor = edges.access(); - auto edges_iterator = edges_accessor.find(id); +public: + Edge::Accessor find(tx::Transaction &t, const Id &id) + { + auto edges_accessor = edges.access(); + auto edges_iterator = edges_accessor.find(id); - if (edges_iterator == edges_accessor.end()) return Edge::Accessor(); + if (edges_iterator == edges_accessor.end()) return Edge::Accessor(); - // find edge - auto edge = edges_iterator->second.find(t); + // find edge + auto edge = edges_iterator->second.find(t); - if (edge == nullptr) return Edge::Accessor(); + if (edge == nullptr) return Edge::Accessor(); - return Edge::Accessor(edge, &edges_iterator->second, this); - } + return Edge::Accessor(edge, &edges_iterator->second, this); + } - Edge::Accessor insert(tx::Transaction &t) - { - // get next vertex id - auto next = counter.next(std::memory_order_acquire); + Edge::Accessor insert(tx::Transaction &t, VertexRecord *from, + VertexRecord *to) + { + // get next vertex id + auto next = counter.next(std::memory_order_acquire); - // create new vertex record - EdgeRecord edge_record(next); + // create new vertex record + EdgeRecord edge_record(next, from, to); - // insert the new vertex record into the vertex store - auto edges_accessor = edges.access(); - auto result = edges_accessor.insert(next, std::move(edge_record)); + // insert the new vertex record into the vertex store + auto edges_accessor = edges.access(); + auto result = edges_accessor.insert(next, std::move(edge_record)); - // create new vertex - auto inserted_edge_record = result.first; - auto edge = inserted_edge_record->second.insert(t); + // create new vertex + auto inserted_edge_record = result.first; + auto edge = inserted_edge_record->second.insert(t); - return Edge::Accessor(edge, &inserted_edge_record->second, this); - } + return Edge::Accessor(edge, &inserted_edge_record->second, this); + } - private: - ConcurrentMap edges; - AtomicCounter counter; +private: + ConcurrentMap edges; + AtomicCounter counter; }; diff --git a/src/storage/model/edge_list.hpp b/src/storage/model/edge_list.hpp index fccafa7b4..49af91f68 100644 --- a/src/storage/model/edge_list.hpp +++ b/src/storage/model/edge_list.hpp @@ -1,7 +1,8 @@ #pragma once -#include +#include "mvcc/edge_record.hpp" #include "mvcc/version_list.hpp" +#include class EdgeList { @@ -14,26 +15,17 @@ public: auto end() const { return edges.end(); } auto cend() const { return edges.end(); } - void add(EdgeRecord* edge) - { - edges.push_back(edge); - } + void add(EdgeRecord *edge) { edges.push_back(edge); } - size_t degree() const - { - return edges.size(); - } + size_t degree() const { return edges.size(); } - void remove(EdgeRecord* edge) + void remove(EdgeRecord *edge) { edges.erase(std::remove(edges.begin(), edges.end(), edge), edges.end()); } - void clear() - { - edges.clear(); - } + void clear() { edges.clear(); } private: - std::vector edges; + std::vector edges; }; diff --git a/src/storage/model/edge_model.hpp b/src/storage/model/edge_model.hpp index 7903a0d1d..907e54ac0 100644 --- a/src/storage/model/edge_model.hpp +++ b/src/storage/model/edge_model.hpp @@ -7,11 +7,8 @@ class EdgeModel : public PropertyModel { public: - VertexRecord *from; - VertexRecord *to; - // TODO: here should be the reference // but something that is copyable // because this model is copied all the time (mvcc) - const EdgeType *edge_type {nullptr}; + const EdgeType *edge_type{nullptr}; }; diff --git a/src/storage/model/vertex_model.hpp b/src/storage/model/vertex_model.hpp index a6642df89..2a80a4bd5 100644 --- a/src/storage/model/vertex_model.hpp +++ b/src/storage/model/vertex_model.hpp @@ -3,12 +3,12 @@ #include "edge_list.hpp" #include "property_model.hpp" #include "storage/label/label_collection.hpp" -// #include "storage/model/edge_map.hpp" +#include "storage/model/edge_map.hpp" class VertexModel : public PropertyModel { public: EdgeList out; - EdgeList in; + EdgeMap in; LabelCollection labels; }; diff --git a/src/storage/record_accessor.hpp b/src/storage/record_accessor.hpp index 19552553d..327d43e27 100644 --- a/src/storage/record_accessor.hpp +++ b/src/storage/record_accessor.hpp @@ -1,20 +1,18 @@ #pragma once -#include "transactions/transaction.hpp" #include "mvcc/version_list.hpp" -#include "storage/model/properties/property.hpp" #include "storage/model/properties/properties.hpp" +#include "storage/model/properties/property.hpp" +#include "transactions/transaction.hpp" -template +template > class RecordAccessor { -protected: - using vlist_t = mvcc::VersionList; - public: RecordAccessor() = default; - RecordAccessor(T* record, vlist_t* vlist, Store* store) + RecordAccessor(T *record, vlist_t *vlist, Store *store) : record(record), vlist(vlist), store(store) { assert(record != nullptr); @@ -22,59 +20,50 @@ public: assert(store != nullptr); } - bool empty() const - { - return record == nullptr; - } + bool empty() const { return record == nullptr; } - const Id& id() const + const Id &id() const { assert(!empty()); return vlist->id; } - Derived update(tx::Transaction& t) const + Derived update(tx::Transaction &t) const { assert(!empty()); return Derived(vlist->update(t), vlist, store); } - bool remove(tx::Transaction& t) const + bool remove(tx::Transaction &t) const { assert(!empty()); return vlist->remove(record, t); } - const Property& property(const std::string& key) const + const Property &property(const std::string &key) const { return record->data.props.at(key); } template - void property(const std::string& key, Args&&... args) + void property(const std::string &key, Args &&... args) { record->data.props.template set(key, std::forward(args)...); } - void property(const std::string& key, Property::sptr value) + void property(const std::string &key, Property::sptr value) { record->data.props.set(key, std::move(value)); } - Properties& properties() const - { - return record->data.props; - } + Properties &properties() const { return record->data.props; } - explicit operator bool() const - { - return record != nullptr; - } + explicit operator bool() const { return record != nullptr; } -// protected: - T* const record {nullptr}; - vlist_t* const vlist {nullptr}; - Store* const store {nullptr}; + // protected: + T *const record{nullptr}; + vlist_t *const vlist{nullptr}; + Store *const store{nullptr}; };