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}; };