From df0bf6fa5fa51c002019bb7fa052c9162c788514 Mon Sep 17 00:00:00 2001 From: Kruno Tomola Fabro Date: Mon, 15 Aug 2016 00:09:58 +0100 Subject: [PATCH] Database interface refactor. DbAccessor: -Guarantees that access to Vertex and Edge is possible only through Vertex::Accessor and Edge::Accessor. -Guarantees that changing Vertex and Edge is possible only using Vertex::Accessor returned by vertex_insert() method and Edge::Accessor returned by edge_insert() method. -Offers CRUD for Vertex and Edge except iterating over all edges. Squashed commit messages: First step in database accessor refactoring done. It's compiling. All tests with exception of integration_querys pass Tests now initialize logging facilities. Refactored accessors. RecordAccessor now has 3 states. From,To,Out,In in there respecive Accessors return unfilled RecordAccessor. Added iterator classes into utils/itearator/. --- CMakeLists.txt | 10 +- .../bolt/v1/serialization/bolt_serializer.hpp | 72 +++----- include/database/db.hpp | 13 +- include/database/db_accessor.hpp | 91 +++++++++++ include/database/db_transaction.hpp | 25 +++ include/query_engine/hardcode/queries.hpp | 101 ++++++------ include/storage/edge_accessor.hpp | 20 +-- include/storage/edge_record.hpp | 2 +- include/storage/edges.hpp | 7 +- include/storage/model/edge_map.hpp | 2 +- include/storage/record_accessor.hpp | 60 +++++-- include/storage/vertex.hpp | 19 +-- include/storage/vertex_accessor.hpp | 12 +- include/storage/vertices.hpp | 13 +- include/utils/iterator/accessor.hpp | 28 ++++ include/utils/iterator/for_all.hpp | 17 ++ include/utils/iterator/iter.hpp | 48 ++++++ include/utils/iterator/iterator.hpp | 7 + include/utils/iterator/map.hpp | 39 +++++ include/utils/iterator/wrap.hpp | 60 +++++++ include/utils/option.hpp | 95 +++++++++++ include/utils/placeholder.hpp | 21 +-- poc/astar.cpp | 154 +++++++++--------- src/cypher/tokenizer/cypher_lexer.hpp | 4 +- src/data_structures/map/rh_common.hpp | 9 +- src/data_structures/map/rh_hashmultimap.hpp | 35 +++- src/database/db.cpp | 6 + src/database/db_accessor.cpp | 75 +++++++++ src/database/db_transaction.cpp | 8 + src/storage/edge_accessor.cpp | 22 +++ src/storage/edges.cpp | 18 +- src/storage/vertex_accessor.cpp | 37 ++++- src/storage/vertices.cpp | 38 +---- tests/concurrent/common.h | 8 + tests/concurrent/linkedlist.cpp | 72 ++++---- tests/concurrent/sl_insert.cpp | 1 + tests/concurrent/sl_insert_competetive.cpp | 1 + tests/concurrent/sl_map.cpp | 1 + tests/concurrent/sl_memory.cpp | 26 +-- tests/concurrent/sl_memory_leak.cpp | 1 + tests/concurrent/sl_multiiterator.cpp | 1 + tests/concurrent/sl_multiiterator_remove.cpp | 1 + .../sl_multiiterator_remove_duplicates.cpp | 1 + tests/concurrent/sl_multimap.cpp | 1 + tests/concurrent/sl_multiset.cpp | 1 + tests/concurrent/sl_remove_competetive.cpp | 1 + tests/concurrent/sl_remove_disjoint.cpp | 1 + tests/concurrent/sl_remove_joint.cpp | 1 + tests/concurrent/sl_set.cpp | 1 + tests/concurrent/sl_simulation.cpp | 1 + tests/unit/chunked_encoder.cpp | 37 ++--- tests/unit/concurrent_map.cpp | 83 +++++----- tests/unit/concurrent_set.cpp | 4 + 53 files changed, 999 insertions(+), 413 deletions(-) create mode 100644 include/database/db_accessor.hpp create mode 100644 include/database/db_transaction.hpp create mode 100644 include/utils/iterator/accessor.hpp create mode 100644 include/utils/iterator/for_all.hpp create mode 100644 include/utils/iterator/iter.hpp create mode 100644 include/utils/iterator/iterator.hpp create mode 100644 include/utils/iterator/map.hpp create mode 100644 include/utils/iterator/wrap.hpp create mode 100644 include/utils/option.hpp create mode 100644 src/database/db.cpp create mode 100644 src/database/db_accessor.cpp create mode 100644 src/database/db_transaction.cpp create mode 100644 src/storage/edge_accessor.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 74df3c068..9efec42c3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,7 @@ find_package(Threads REQUIRED) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y") # glibcxx debug (useful for gdb) -# the problem is that the query engine doesn't work as it should work if +# the problem is that the query engine doesn't work as it should work if # this flag is present # TODO: find more appropriate way to use this flag only when it is needed # set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_GLIBCXX_DEBUG") @@ -288,7 +288,7 @@ endif() # release flags set(CMAKE_CXX_FLAGS_RELEASE - "${CMAKE_CXX_FLAGS_RELEASE} -march=native -Wall -Werror") + "${CMAKE_CXX_FLAGS_RELEASE} -march=native -Wall") # -- configure defines -- default is ON | true | enabled ---------------------- # -- logging ------------------------------------------------------------------ @@ -412,6 +412,10 @@ set(memgraph_src_files ${src_dir}/logging/default.cpp ${src_dir}/logging/log.cpp ${src_dir}/io/network/tls.cpp + ${src_dir}/database/db.cpp + ${src_dir}/database/db_accessor.cpp + ${src_dir}/database/db_transaction.cpp + ${src_dir}/storage/edge_accessor.cpp ) # STATIC library used by memgraph executables @@ -434,7 +438,7 @@ endif() # memgraph build name execute_process( - OUTPUT_VARIABLE COMMIT_NO + OUTPUT_VARIABLE COMMIT_NO COMMAND git rev-list --count HEAD ) execute_process( diff --git a/include/communication/bolt/v1/serialization/bolt_serializer.hpp b/include/communication/bolt/v1/serialization/bolt_serializer.hpp index 6d7248b6f..b50f3de8b 100644 --- a/include/communication/bolt/v1/serialization/bolt_serializer.hpp +++ b/include/communication/bolt/v1/serialization/bolt_serializer.hpp @@ -1,13 +1,13 @@ #pragma once -#include "communication/bolt/v1/transport/bolt_encoder.hpp" #include "communication/bolt/v1/packing/codes.hpp" +#include "communication/bolt/v1/transport/bolt_encoder.hpp" -#include "storage/vertex_accessor.hpp" #include "storage/edge_accessor.hpp" +#include "storage/vertex_accessor.hpp" -#include "storage/model/properties/properties.hpp" #include "storage/model/properties/all.hpp" +#include "storage/model/properties/properties.hpp" namespace bolt { @@ -22,7 +22,7 @@ class BoltSerializer // friend void accept(const Property &property, Handler &h); public: - BoltSerializer(Stream& stream) : encoder(stream) {} + BoltSerializer(Stream &stream) : encoder(stream) {} /* Serializes the vertex accessor into the packstream format * @@ -33,7 +33,7 @@ public: * } * */ - void write(const Vertex::Accessor& vertex) + void write(const Vertex::Accessor &vertex) { // write signatures for the node struct and node data type encoder.write_struct_header(3); @@ -47,7 +47,7 @@ public: encoder.write_list_header(labels.size()); - for(auto& label : labels) + for (auto &label : labels) encoder.write_string(label.get()); // write the property map @@ -55,7 +55,7 @@ public: encoder.write_map_header(props.size()); - for(auto& prop : props) { + for (auto &prop : props) { write(prop.first); write(*prop.second); } @@ -72,7 +72,7 @@ public: * } * */ - void write(const Edge::Accessor& edge) + void write(const Edge::Accessor &edge) { // write signatures for the edge struct and edge data type encoder.write_struct_header(5); @@ -82,8 +82,8 @@ public: encoder.write_integer(edge.id()); // TODO refactor when from() and to() start returning Accessors - encoder.write_integer(edge.from()->id); - encoder.write_integer(edge.to()->id); + encoder.write_integer(edge.from().id()); + encoder.write_integer(edge.to().id()); // write the type of the edge encoder.write_string(edge.edge_type()); @@ -93,65 +93,37 @@ public: encoder.write_map_header(props.size()); - for(auto& prop : props) { + for (auto &prop : props) { write(prop.first); write(*prop.second); } } - void write(const Property& prop) - { - accept(prop, *this); - } + void write(const Property &prop) { accept(prop, *this); } - void write_null() - { - encoder.write_null(); - } + void write_null() { encoder.write_null(); } - void write(const Bool& prop) - { - encoder.write_bool(prop.value()); - } + void write(const Bool &prop) { encoder.write_bool(prop.value()); } - void write(const Float& prop) - { - encoder.write_double(prop.value); - } + void write(const Float &prop) { encoder.write_double(prop.value); } - void write(const Double& prop) - { - encoder.write_double(prop.value); - } + void write(const Double &prop) { encoder.write_double(prop.value); } - void write(const Int32& prop) - { - encoder.write_integer(prop.value); - } + void write(const Int32 &prop) { encoder.write_integer(prop.value); } - void write(const Int64& prop) - { - encoder.write_integer(prop.value); - } + void write(const Int64 &prop) { encoder.write_integer(prop.value); } - void write(const std::string& value) - { - encoder.write_string(value); - } + void write(const std::string &value) { encoder.write_string(value); } - void write(const String& prop) - { - encoder.write_string(prop.value); - } + void write(const String &prop) { encoder.write_string(prop.value); } template - void handle(const T& prop) + void handle(const T &prop) { write(prop); } protected: - Stream& encoder; + Stream &encoder; }; - } diff --git a/include/database/db.hpp b/include/database/db.hpp index 8cee20063..626bb7dd7 100644 --- a/include/database/db.hpp +++ b/include/database/db.hpp @@ -1,25 +1,22 @@ #pragma once #include "storage/graph.hpp" +// #include "transactions/commit_log.hpp" #include "transactions/engine.hpp" -#include "transactions/commit_log.hpp" class Db { public: using sptr = std::shared_ptr; - Db() = default; - Db(const std::string& name) : name_(name) {} - Db(const Db& db) = delete; + Db(); + Db(const std::string &name); + Db(const Db &db) = delete; Graph graph; tx::Engine tx_engine; - std::string& name() - { - return name_; - } + std::string &name(); private: std::string name_; diff --git a/include/database/db_accessor.hpp b/include/database/db_accessor.hpp new file mode 100644 index 000000000..e4cbd86a6 --- /dev/null +++ b/include/database/db_accessor.hpp @@ -0,0 +1,91 @@ +#pragma once + +#include "database/db.hpp" +#include "database/db_accessor.hpp" +#include "storage/record_accessor.hpp" +#include "storage/vertex.hpp" +#include "storage/vertex_accessor.hpp" +#include "storage/vertices.hpp" +#include "transactions/transaction.hpp" +#include "utils/iterator/iterator.hpp" +#include "utils/option.hpp" + +/* +* DbAccessor +* -Guarantees that access to Vertex and Edge is possible only through +* Vertex::Accessor and Edge::Accessor. +* -Guarantees that changing Vertex and Edge is possible only using +* Vertex::Accessor returned by vertex_insert() method and +* Edge::Accessor returned by edge_insert() method. +* -Offers CRUD for Vertex and Edge except iterating over all edges. +* +* Vertex::Accessor +* By default Vertex::accessor is empty. Caller has to call fill() method +* to fetch valid data and check it's return value. fill() method returns +* true if there is valid data for current transaction false otherwise. +* Only exception to this rule is vertex_insert() method in DbAccessor +* which returns by default filled Vertex::Accessor. +* +* Edge::Accessor +* By default Edge::accessor is empty. Caller has to call fill() method +* to +* fetch valid data and check it's return value. fill() method returns +* true +* if there is valid data for current transaction false otherwise. +* Only exception to this rule is edge_insert() method in DbAccessor +* which +* returns by default filled Edge::Accessor. +*/ +class DbAccessor +{ + +public: + DbAccessor(Db &db); + + //*******************VERTEX METHODS + + auto vertex_access(); + + Option vertex_find(const Id &id); + + // Creates new Vertex and returns filled Vertex::Accessor. + Vertex::Accessor vertex_insert(); + + //*******************EDGE METHODS + + Option edge_find(const Id &id); + + // Creates new Edge and returns filled Edge::Accessor. + Edge::Accessor edge_insert(Vertex::Accessor const &from, + Vertex::Accessor const &to); + + //*******************LABEL METHODS + + const Label &label_find_or_create(const std::string &name); + + bool label_contains(const std::string &name); + + VertexIndexRecordCollection &label_find_index(const Label &label); + + //********************TYPE METHODS + + const EdgeType &type_find_or_create(const std::string &name); + + bool type_contains(const std::string &name); + + //********************TRANSACTION METHODS + + void commit(); + void abort(); + +private: + DbTransaction db; +}; + +//**********************CONVENIENT FUNCTIONS + +template +bool option_fill(Option &o) +{ + return o.is_present() && o.get().fill(); +} diff --git a/include/database/db_transaction.hpp b/include/database/db_transaction.hpp new file mode 100644 index 000000000..a7b862c82 --- /dev/null +++ b/include/database/db_transaction.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include "storage/indexes/index_record.hpp" +#include "storage/label/label.hpp" +#include "transactions/transaction.hpp" + +class Db; +class DbAccessor; + +// Inner structures local to transaction can hold ref to this structure and use +// its methods. +class DbTransaction +{ + friend DbAccessor; + +public: + DbTransaction(Db &db, tx::Transaction &trans) : db(db), trans(trans) {} + + void update_label_index(const Label &label, + VertexIndexRecord &&index_record); + + tx::Transaction &trans; + + Db &db; +}; diff --git a/include/query_engine/hardcode/queries.hpp b/include/query_engine/hardcode/queries.hpp index 0c19af658..5ef8dbfe5 100644 --- a/include/query_engine/hardcode/queries.hpp +++ b/include/query_engine/hardcode/queries.hpp @@ -1,6 +1,8 @@ #pragma once #include "database/db.hpp" +#include "database/db_accessor.cpp" +#include "database/db_accessor.hpp" #include "query_engine/query_stripper.hpp" #include "query_engine/util.hpp" #include "storage/model/properties/property.hpp" @@ -12,8 +14,8 @@ auto load_queries(Db &db) // CREATE (n {prop: 0}) RETURN n) auto create_node = [&db](const properties_t &args) { - auto &t = db.tx_engine.begin(); - auto vertex_accessor = db.graph.vertices.insert(t); + DbAccessor t(db); + auto vertex_accessor = t.vertex_insert(); vertex_accessor.property("prop", args[0]); t.commit(); return true; @@ -21,10 +23,10 @@ auto load_queries(Db &db) queries[11597417457737499503u] = create_node; auto create_labeled_and_named_node = [&db](const properties_t &args) { - auto &t = db.tx_engine.begin(); - auto vertex_accessor = db.graph.vertices.insert(t); + DbAccessor t(db); + auto vertex_accessor = t.vertex_insert(); vertex_accessor.property("name", args[0]); - auto &label = db.graph.label_store.find_or_create("LABEL"); + auto &label = t.label_find_or_create("LABEL"); vertex_accessor.add_label(label); cout_properties(vertex_accessor.properties()); t.commit(); @@ -32,13 +34,13 @@ auto load_queries(Db &db) }; auto create_account = [&db](const properties_t &args) { - auto &t = db.tx_engine.begin(); - auto vertex_accessor = db.graph.vertices.insert(t); + DbAccessor t(db); + auto vertex_accessor = t.vertex_insert(); vertex_accessor.property("id", args[0]); vertex_accessor.property("name", args[1]); vertex_accessor.property("country", args[2]); vertex_accessor.property("created_at", args[3]); - auto &label = db.graph.label_store.find_or_create("ACCOUNT"); + auto &label = t.label_find_or_create("ACCOUNT"); vertex_accessor.add_label(label); cout_properties(vertex_accessor.properties()); t.commit(); @@ -46,14 +48,15 @@ auto load_queries(Db &db) }; auto find_node_by_internal_id = [&db](const properties_t &args) { - auto &t = db.tx_engine.begin(); + DbAccessor t(db); auto id = static_cast(*args[0]); - auto vertex_accessor = db.graph.vertices.find(t, Id(id.value)); - if (!vertex_accessor) { + auto maybe_va = t.vertex_find(Id(id.value)); + if (!option_fill(maybe_va)) { cout << "vertex doesn't exist" << endl; t.commit(); return false; } + auto vertex_accessor = maybe_va.get(); cout_properties(vertex_accessor.properties()); cout << "LABELS:" << endl; for (auto label_ref : vertex_accessor.labels()) { @@ -64,20 +67,17 @@ auto load_queries(Db &db) }; auto create_edge = [&db](const properties_t &args) { - auto &t = db.tx_engine.begin(); + DbAccessor t(db); - auto v1 = db.graph.vertices.find(t, args[0]->as().value); - if (!v1) return t.commit(), false; + auto v1 = t.vertex_find(args[0]->as().value); + if (!option_fill(v1)) return t.commit(), false; - auto v2 = db.graph.vertices.find(t, args[1]->as().value); - if (!v2) return t.commit(), false; + auto v2 = t.vertex_find(args[1]->as().value); + if (!option_fill(v2)) return t.commit(), false; - auto edge_accessor = db.graph.edges.insert(t, v1.vlist, v2.vlist); + auto edge_accessor = t.edge_insert(v1.get(), v2.get()); - v1.vlist->update(t)->data.out.add(edge_accessor.vlist); - v2.vlist->update(t)->data.in.add(edge_accessor.vlist); - - auto &edge_type = db.graph.edge_type_store.find_or_create("IS"); + auto &edge_type = t.type_find_or_create("IS"); edge_accessor.edge_type(edge_type); t.commit(); @@ -90,20 +90,25 @@ auto load_queries(Db &db) }; auto find_edge_by_internal_id = [&db](const properties_t &args) { - auto &t = db.tx_engine.begin(); - auto edge_accessor = db.graph.edges.find(t, args[0]->as().value); - if (!edge_accessor) return t.commit(), false; + DbAccessor t(db); + auto maybe_ea = t.edge_find(args[0]->as().value); + if (!option_fill(maybe_ea)) return t.commit(), false; + auto edge_accessor = maybe_ea.get(); // print edge type and properties cout << "EDGE_TYPE: " << edge_accessor.edge_type() << endl; auto from = edge_accessor.from(); + if (!from.fill()) return t.commit(), false; + cout << "FROM:" << endl; - cout_properties(from->find(t)->data.props); + cout_properties(from->data.props); auto to = edge_accessor.to(); + if (!to.fill()) return t.commit(), false; + cout << "TO:" << endl; - cout_properties(to->find(t)->data.props); + cout_properties(to->data.props); t.commit(); @@ -111,10 +116,11 @@ auto load_queries(Db &db) }; auto update_node = [&db](const properties_t &args) { - auto &t = db.tx_engine.begin(); + DbAccessor t(db); - auto v = db.graph.vertices.find(t, args[0]->as().value); - if (!v) return t.commit(), false; + auto maybe_v = t.vertex_find(args[0]->as().value); + if (!option_fill(maybe_v)) return t.commit(), false; + auto v = maybe_v.get(); v.property("name", args[1]); cout_properties(v.properties()); @@ -127,18 +133,17 @@ auto load_queries(Db &db) // 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, n2.vlist, n1.vlist); + DbAccessor t(db); + auto n1 = t.vertex_find(args[0]->as().value); + if (!option_fill(n1)) return t.commit(), false; + auto n2 = t.vertex_find(args[1]->as().value); + if (!option_fill(n2)) return t.commit(), false; + auto r = t.edge_insert(n2.get(), n1.get()); r.property("age", args[2]); r.property("weight", args[3]); - auto &IS = db.graph.edge_type_store.find_or_create("IS"); + auto &IS = t.type_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); + t.commit(); return true; }; @@ -146,14 +151,13 @@ auto load_queries(Db &db) // MATCH (n) RETURN n auto match_all_nodes = [&db](const properties_t &args) { - auto &t = db.tx_engine.begin(); + DbAccessor t(db); - auto vertices_accessor = db.graph.vertices.access(); - for (auto &it : vertices_accessor) { - auto vertex = it.second.find(t); - if (vertex == nullptr) continue; - cout_properties(vertex->data.props); - } + iter::for_all(t.vertex_access(), [&](auto vertex) { + if (vertex.fill()) { + cout_properties(vertex->data.props); + } + }); // TODO // db.graph.vertices.filter().all(t, handler); @@ -166,12 +170,11 @@ auto load_queries(Db &db) // MATCH (n:LABEL) RETURN n auto find_by_label = [&db](const properties_t &args) { - auto &t = db.tx_engine.begin(); + DbAccessor t(db); - auto &label = db.graph.label_store.find_or_create("LABEL"); + auto &label = t.label_find_or_create("LABEL"); - auto &index_record_collection = - db.graph.vertices.find_label_index(label); + auto &index_record_collection = t.label_find_index(label); auto accessor = index_record_collection.access(); cout << "VERTICES" << endl; for (auto &v : accessor) { diff --git a/include/storage/edge_accessor.hpp b/include/storage/edge_accessor.hpp index 192ce2884..c65ea5e0c 100644 --- a/include/storage/edge_accessor.hpp +++ b/include/storage/edge_accessor.hpp @@ -3,31 +3,23 @@ #include "storage/edge.hpp" #include "storage/edge_record.hpp" #include "storage/record_accessor.hpp" +#include "storage/vertex_accessor.hpp" #include "utils/assert.hpp" #include "utils/reference_wrapper.hpp" class Edges; // TODO: Edge, Db, Edge::Accessor -class Edge::Accessor - : public RecordAccessor +class Edge::Accessor : public RecordAccessor { public: using RecordAccessor::RecordAccessor; - void edge_type(edge_type_ref_t edge_type) - { - this->record->data.edge_type = &edge_type.get(); - } + void edge_type(edge_type_ref_t edge_type); - edge_type_ref_t edge_type() const - { - runtime_assert(this->record->data.edge_type != nullptr, - "EdgeType is null"); - return edge_type_ref_t(*this->record->data.edge_type); - } + edge_type_ref_t edge_type() const; - auto from() const { return this->vlist->from(); } + Vertex::Accessor from() const; - auto to() const { return this->vlist->to(); } + Vertex::Accessor to() const; }; diff --git a/include/storage/edge_record.hpp b/include/storage/edge_record.hpp index e04cde31b..aa1471abe 100644 --- a/include/storage/edge_record.hpp +++ b/include/storage/edge_record.hpp @@ -27,7 +27,7 @@ public: auto to() const { return this->to_v; } -private: +protected: VertexRecord *from_v; VertexRecord *to_v; }; diff --git a/include/storage/edges.hpp b/include/storage/edges.hpp index 85e2e1cdd..660962be8 100644 --- a/include/storage/edges.hpp +++ b/include/storage/edges.hpp @@ -4,12 +4,15 @@ #include "mvcc/version_list.hpp" #include "storage/common.hpp" #include "storage/edge_accessor.hpp" +#include "utils/option.hpp" class Edges { public: - Edge::Accessor find(tx::Transaction &t, const Id &id); - Edge::Accessor insert(tx::Transaction &t, VertexRecord *from, + Option find(DbTransaction &t, const Id &id); + + // Creates new Edge and returns filled Edge::Accessor. + Edge::Accessor insert(DbTransaction &t, VertexRecord *from, VertexRecord *to); private: diff --git a/include/storage/model/edge_map.hpp b/include/storage/model/edge_map.hpp index 8195351aa..e8d109cc5 100644 --- a/include/storage/model/edge_map.hpp +++ b/include/storage/model/edge_map.hpp @@ -23,7 +23,7 @@ public: edges.remove(edge); // Currently the return is ignored } - bool contains(VertexRecord *vr) { return edges.contains(vr); } + bool contains(VertexRecord *vr) const { return edges.contains(vr); } void clear() { edges.clear(); } diff --git a/include/storage/record_accessor.hpp b/include/storage/record_accessor.hpp index 327d43e27..e07f6da6f 100644 --- a/include/storage/record_accessor.hpp +++ b/include/storage/record_accessor.hpp @@ -1,45 +1,60 @@ #pragma once +#include "database/db_transaction.hpp" #include "mvcc/version_list.hpp" #include "storage/model/properties/properties.hpp" #include "storage/model/properties/property.hpp" #include "transactions/transaction.hpp" -template > +template > class RecordAccessor { -public: - RecordAccessor() = default; + friend DbAccessor; - RecordAccessor(T *record, vlist_t *vlist, Store *store) - : record(record), vlist(vlist), store(store) +public: + RecordAccessor(vlist_t *vlist, DbTransaction &db) : vlist(vlist), db(db) + { + assert(vlist != nullptr); + } + + RecordAccessor(T *t, vlist_t *vlist, DbTransaction &db) + : record(t), vlist(vlist), db(db) { assert(record != nullptr); assert(vlist != nullptr); - assert(store != nullptr); } + RecordAccessor(RecordAccessor const &other) = default; + RecordAccessor(RecordAccessor &&other) = default; + bool empty() const { return record == nullptr; } + // Fills accessor and returns true if there is valid data for current + // transaction false otherwise. + bool fill() const + { + const_cast(this)->record = vlist->find(db.trans); + return record != nullptr; + } + const Id &id() const { assert(!empty()); return vlist->id; } - Derived update(tx::Transaction &t) const + Derived update() const { assert(!empty()); - return Derived(vlist->update(t), vlist, store); + return Derived(vlist->update(db.trans), vlist, db); } - bool remove(tx::Transaction &t) const + bool remove() const { assert(!empty()); - return vlist->remove(record, t); + return vlist->remove(record, db.trans); } const Property &property(const std::string &key) const @@ -62,8 +77,23 @@ public: explicit operator bool() const { return record != nullptr; } - // protected: - T *const record{nullptr}; - vlist_t *const vlist{nullptr}; - Store *const store{nullptr}; + T const *operator->() const { return record; } + T *operator->() { return record; } + + // Assumes same transaction + friend bool operator==(const RecordAccessor &a, const RecordAccessor &b) + { + return a.vlist == b.vlist; + } + + // Assumes same transaction + friend bool operator!=(const RecordAccessor &a, const RecordAccessor &b) + { + return !(a == b); + } + +protected: + T *record{nullptr}; + vlist_t *const vlist; + DbTransaction &db; }; diff --git a/include/storage/vertex.hpp b/include/storage/vertex.hpp index 9d8f8e294..d73b4f32d 100644 --- a/include/storage/vertex.hpp +++ b/include/storage/vertex.hpp @@ -1,8 +1,8 @@ #pragma once #include "mvcc/record.hpp" -#include "storage/model/vertex_model.hpp" #include "storage/model/properties/traversers/jsonwriter.hpp" +#include "storage/model/vertex_model.hpp" class Vertex : public mvcc::Record { @@ -10,19 +10,19 @@ public: class Accessor; Vertex() = default; - Vertex(const VertexModel& data) : data(data) {} - Vertex(VertexModel&& data) : data(std::move(data)) {} + Vertex(const VertexModel &data) : data(data) {} + Vertex(VertexModel &&data) : data(std::move(data)) {} - Vertex(const Vertex&) = delete; - Vertex(Vertex&&) = delete; + Vertex(const Vertex &) = delete; + Vertex(Vertex &&) = delete; - Vertex& operator=(const Vertex&) = delete; - Vertex& operator=(Vertex&&) = delete; + Vertex &operator=(const Vertex &) = delete; + Vertex &operator=(Vertex &&) = delete; VertexModel data; }; -inline std::ostream& operator<<(std::ostream& stream, const Vertex& record) +inline std::ostream &operator<<(std::ostream &stream, const Vertex &record) { StringBuffer buffer; JsonWriter writer(buffer); @@ -33,6 +33,5 @@ inline std::ostream& operator<<(std::ostream& stream, const Vertex& record) return stream << "Vertex" << "(cre = " << record.tx.cre() - << ", exp = " << record.tx.exp() - << "): " << buffer.str(); + << ", exp = " << record.tx.exp() << "): " << buffer.str(); } diff --git a/include/storage/vertex_accessor.hpp b/include/storage/vertex_accessor.hpp index 6c02f2595..0222413ed 100644 --- a/include/storage/vertex_accessor.hpp +++ b/include/storage/vertex_accessor.hpp @@ -5,8 +5,7 @@ class Vertices; -class Vertex::Accessor - : public RecordAccessor +class Vertex::Accessor : public RecordAccessor { public: using RecordAccessor::RecordAccessor; @@ -21,5 +20,12 @@ public: bool has_label(const Label &label) const; - const std::set& labels() const; + const std::set &labels() const; + + auto out() const; + + auto in() const; + + // True if there exists edge other->this + bool in_contains(Vertex::Accessor const &other) const; }; diff --git a/include/storage/vertices.hpp b/include/storage/vertices.hpp index 9b4909ebe..8f5b78299 100644 --- a/include/storage/vertices.hpp +++ b/include/storage/vertices.hpp @@ -1,10 +1,12 @@ #pragma once #include "data_structures/concurrent/concurrent_map.hpp" +#include "database/db_transaction.hpp" #include "storage/common.hpp" #include "storage/indexes/index.hpp" #include "storage/indexes/index_record_collection.hpp" #include "storage/vertex_accessor.hpp" +#include "utils/option.hpp" class Vertices { @@ -13,17 +15,16 @@ public: vertices_t::Accessor access(); - const Vertex::Accessor find(tx::Transaction &t, const Id &id); + Option find(DbTransaction &t, const Id &id); - const Vertex::Accessor first(tx::Transaction &t); - - Vertex::Accessor insert(tx::Transaction &t); + // Creates new Vertex and returns filled Vertex::Accessor. + Vertex::Accessor insert(DbTransaction &t); void update_label_index(const Label &label, VertexIndexRecord &&index_record); - VertexIndexRecordCollection& find_label_index(const Label& label); - + VertexIndexRecordCollection &find_label_index(const Label &label); + private: vertices_t vertices; Index label_index; diff --git a/include/utils/iterator/accessor.hpp b/include/utils/iterator/accessor.hpp new file mode 100644 index 000000000..88d5f32b6 --- /dev/null +++ b/include/utils/iterator/accessor.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include "utils/iterator/wrap.hpp" +#include "utils/option.hpp" + +namespace iter +{ +template +class OneTimeAccessor +{ +public: + OneTimeAccessor() : it(Option>()) {} + OneTimeAccessor(I &&it) : it(Wrap(std::move(it))) {} + + Wrap begin() { return it.take(); } + + Wrap end() { return Wrap(); } + +private: + Option> it; +}; + +template +auto make_one_time_accessor(I &&iter) +{ + return OneTimeAccessor(std::move(iter)); +} +} diff --git a/include/utils/iterator/for_all.hpp b/include/utils/iterator/for_all.hpp new file mode 100644 index 000000000..ba5b8f2dc --- /dev/null +++ b/include/utils/iterator/for_all.hpp @@ -0,0 +1,17 @@ + +#pragma once + +#include "utils/option.hpp" + +namespace iter +{ +template +void for_all(I &&iter, C &&consumer) +{ + auto e = iter.next(); + while (e.is_present()) { + consumer(e.take()); + e = iter.next(); + } +} +} diff --git a/include/utils/iterator/iter.hpp b/include/utils/iterator/iter.hpp new file mode 100644 index 000000000..cfb3c974a --- /dev/null +++ b/include/utils/iterator/iter.hpp @@ -0,0 +1,48 @@ +#pragma once + +#include "utils/option.hpp" + +namespace iter +{ +template +class Iter +{ +public: + Iter() = delete; + + Iter(A &&acc) : begin(std::move(acc.begin())), acc(std::forward(acc)) {} + // Iter(const Iter &other) = delete; + // Iter(Iter &&other) : + // begin(std::move(other.begin)),end(std::move(other.end)) {}; + + auto next() + { + if (begin != acc.end()) { + auto ret = Option(&(*(begin.operator->()))); + begin++; + return ret; + } else { + return Option(); + } + } + +private: + I begin; + A acc; +}; + +// TODO: Join to make functions into one +template +auto make_iter(A &&acc) +{ + return Iter()))), decltype(acc.begin()), + A>(std::move(acc)); +} + +template +auto make_iter_ref(A &acc) +{ + return Iter()))), decltype(acc.begin()), + A &>(acc); +} +} diff --git a/include/utils/iterator/iterator.hpp b/include/utils/iterator/iterator.hpp new file mode 100644 index 000000000..e3e8c1cd1 --- /dev/null +++ b/include/utils/iterator/iterator.hpp @@ -0,0 +1,7 @@ +#pragma once + +#include "utils/iterator/accessor.hpp" +#include "utils/iterator/for_all.hpp" +#include "utils/iterator/iter.hpp" +#include "utils/iterator/map.hpp" +#include "utils/iterator/wrap.hpp" diff --git a/include/utils/iterator/map.hpp b/include/utils/iterator/map.hpp new file mode 100644 index 000000000..7bc8ba474 --- /dev/null +++ b/include/utils/iterator/map.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include "utils/option.hpp" + +namespace iter +{ +template +class Map +{ + +public: + Map() = delete; + template + Map(IT &&iter, OP &&op) : iter(std::move(iter)), op(std::move(op)) + { + } + + auto next() + { + auto item = iter.next(); + if (item.is_present()) { + return Option(op(item.take())); + } else { + return Option(); + } + } + +private: + I iter; + MapOperator op; +}; + +template +auto make_map(I &&iter, OP &&op) +{ + return Map(std::move(iter), + std::move(op)); +} +} diff --git a/include/utils/iterator/wrap.hpp b/include/utils/iterator/wrap.hpp new file mode 100644 index 000000000..a39fe6d2c --- /dev/null +++ b/include/utils/iterator/wrap.hpp @@ -0,0 +1,60 @@ +#pragma once + +#include "utils/option.hpp" + +namespace iter +{ +template +class Wrap +{ + +public: + Wrap() : iter(Option()), value(Option()){}; + + Wrap(I &&iter) : value(iter.next()), iter(Option(std::move(iter))) {} + + T &operator*() + { + assert(value.is_present()); + return value.get(); + } + + T *operator->() + { + assert(value.is_present()); + return &value.get(); + } + + operator T &() + { + assert(value.is_present()); + return value.get(); + } + + Wrap &operator++() + { + assert(iter.is_present()); + value = iter.get().next(); + return (*this); + } + + Wrap &operator++(int) { return operator++(); } + + friend bool operator==(const Wrap &a, const Wrap &b) + { + return a.value.is_present() == b.value.is_present(); + } + + friend bool operator!=(const Wrap &a, const Wrap &b) { return !(a == b); } + +private: + Option iter; + Option value; +}; + +template +auto make_wrap(I &&iter) +{ + return Wrap(std::move(iter)); +} +} diff --git a/include/utils/option.hpp b/include/utils/option.hpp new file mode 100644 index 000000000..8e1b66d44 --- /dev/null +++ b/include/utils/option.hpp @@ -0,0 +1,95 @@ +#pragma once + +#include +#include + +template +class Option +{ +public: + Option() {} + + Option(T const &item) + { + new (data._M_addr()) T(item); + initialized = true; + } + + Option(T &&item) + { + new (data._M_addr()) T(std::move(item)); + initialized = true; + } + + Option(Option &other) = default; + Option(Option &&other) noexcept + { + if (other.initialized) { + data = std::move(other.data); + other.initialized = false; + initialized = true; + } + } + + ~Option() + { + if (initialized) get().~T(); + } + + Option &operator=(Option &&other) + { + if (initialized) { + get().~T(); + initialized = false; + } + + if (other.initialized) { + data = std::move(other.data); + other.initialized = false; + initialized = true; + } + + return *this; + } + + bool is_present() const { return initialized; } + + T &get() noexcept + { + assert(initialized); + return *data._M_ptr(); + } + + const T &get() const noexcept { assert(initialized); } + + T take() + { + assert(initialized); + initialized = false; + return std::move(*data._M_ptr()); + } + + explicit operator bool() const { return initialized; } + +private: + __gnu_cxx::__aligned_buffer data; + bool initialized = false; +}; + +template +auto make_option() +{ + return Option(); +} + +template +auto make_option(T &&data) +{ + return Option(std::move(data)); +} + +template +auto make_option_const(const T &&data) +{ + return Option(std::move(data)); +} diff --git a/include/utils/placeholder.hpp b/include/utils/placeholder.hpp index 2cdd5c2fa..a1eb889c8 100644 --- a/include/utils/placeholder.hpp +++ b/include/utils/placeholder.hpp @@ -1,7 +1,7 @@ #pragma once -#include #include +#include template class Placeholder @@ -9,40 +9,41 @@ class Placeholder public: Placeholder() = default; - Placeholder(Placeholder&) = delete; - Placeholder(Placeholder&&) = delete; + Placeholder(Placeholder &) = delete; + Placeholder(Placeholder &&) = delete; ~Placeholder() { - if(initialized) - get().~T(); + if (initialized) get().~T(); }; - T& get() noexcept + bool is_initialized() { return initialized; } + + T &get() noexcept { assert(initialized); return *data._M_ptr(); } - const T& get() const noexcept + const T &get() const noexcept { assert(initialized); return *data._M_ptr(); } - void set(const T& item) + void set(const T &item) { new (data._M_addr()) T(item); initialized = true; } - void set(T&& item) + void set(T &&item) { new (data._M_addr()) T(std::move(item)); initialized = true; } private: - __gnu_cxx::__aligned_buffer data; + __gnu_cxx::__aligned_buffer data; bool initialized = false; }; diff --git a/poc/astar.cpp b/poc/astar.cpp index f30f1664d..f22918129 100644 --- a/poc/astar.cpp +++ b/poc/astar.cpp @@ -10,9 +10,12 @@ #include "data_structures/map/rh_hashmap.hpp" #include "database/db.hpp" +#include "database/db_accessor.hpp" +#include "storage/vertex_accessor.cpp" +#include "storage/vertex_accessor.hpp" using namespace std; - +typedef Vertex::Accessor VertexAccessor; void load_graph_dummy(Db &db); void load_csv(Db &db, char *file_path, char *edge_file_path); @@ -22,20 +25,13 @@ public: Node *parent = {nullptr}; double cost; int depth = {0}; - Vertex *vertex; - VertexRecord *record; + VertexAccessor vacc; - Node(Vertex *va, VertexRecord *record, double cost) - : cost(cost), vertex(va), record(record) + Node(VertexAccessor vacc, double cost) : cost(cost), vacc(vacc) {} + Node(VertexAccessor vacc, double cost, Node *parent) + : cost(cost), vacc(vacc), parent(parent), depth(parent->depth + 1) { } - Node(Vertex *va, VertexRecord *record, double cost, Node *parent) - : cost(cost), vertex(va), parent(parent), depth(parent->depth + 1), - record(record) - { - } - - VertexRecord *&get_key() { return record; } }; // class Iterator : public Crtp @@ -82,59 +78,66 @@ void found_result(Node *bef) { std::cout << "{score: " << bef->cost << endl; while (bef != nullptr) { - std::cout << " " << *(bef->vertex) << endl; + std::cout << " " << *(bef->vacc.operator->()) << endl; bef = bef->parent; } } -double calc_heuristic_cost_dummy(Edge *edge, Vertex *vertex) +double calc_heuristic_cost_dummy(Edge::Accessor &edge, Vertex::Accessor &vertex) { + assert(!vertex.empty()); return 1 - vertex->data.props.at("score").as().value; } -typedef bool (*EdgeFilter)(tx::Transaction &t, EdgeRecord *, Node *before); -typedef bool (*VertexFilter)(tx::Transaction &t, Vertex *, Node *before); +typedef bool (*EdgeFilter)(DbAccessor &t, Edge::Accessor &, Node *before); +typedef bool (*VertexFilter)(DbAccessor &t, Vertex::Accessor &, Node *before); -bool edge_filter_dummy(tx::Transaction &t, EdgeRecord *e, Node *before) +bool edge_filter_dummy(DbAccessor &t, Edge::Accessor &e, Node *before) { return true; } -bool vertex_filter_dummy(tx::Transaction &t, Vertex *v, Node *before) +bool vertex_filter_dummy(DbAccessor &t, Vertex::Accessor &va, Node *before) { - return true; + return va.fill(); } -bool vertex_filter_contained_dummy(tx::Transaction &t, Vertex *v, Node *before) +bool vertex_filter_contained_dummy(DbAccessor &t, Vertex::Accessor &v, + Node *before) { - bool found; - do { - found = false; - before = before->parent; - if (before == nullptr) { - return true; - } - for (auto edge : before->vertex->data.out) { - Vertex *e_v = edge->to()->find(t); - if (e_v == v) { - found = true; - break; + if (v.fill()) { + bool found; + do { + found = false; + before = before->parent; + if (before == nullptr) { + return true; } - } - } while (found); + auto it = before->vacc.out(); + for (auto e = it.next(); e.is_present(); e = it.next()) { + VertexAccessor va = e.get().to(); + if (va == v) { + found = true; + break; + } + } + } while (found); + } return false; } -bool vertex_filter_contained(tx::Transaction &t, Vertex *v, Node *before) +bool vertex_filter_contained(DbAccessor &t, Vertex::Accessor &v, Node *before) { - bool found; - do { - found = false; - before = before->parent; - if (before == nullptr) { - return true; - } - } while (v->data.in.contains(before->record)); + if (v.fill()) { + bool found; + do { + found = false; + before = before->parent; + if (before == nullptr) { + return true; + } + } while (v.in_contains(before->vacc)); + } return false; } @@ -143,23 +146,24 @@ bool vertex_filter_contained(tx::Transaction &t, Vertex *v, Node *before) // Filtri vracaju true ako element zadovoljava uvjete. void a_star(Db &db, int64_t sys_id_start, uint max_depth, EdgeFilter e_filter[], VertexFilter v_filter[], - double (*calc_heuristic_cost)(Edge *edge, Vertex *vertex), + double (*calc_heuristic_cost)(Edge::Accessor &edge, + Vertex::Accessor &vertex), int limit) { - auto &t = db.tx_engine.begin(); - RhHashMap visited; + DbAccessor t(db); auto cmp = [](Node *left, Node *right) { return left->cost > right->cost; }; std::priority_queue, decltype(cmp)> queue(cmp); - auto start_vr = db.graph.vertices.find(t, sys_id_start).vlist; - Node *start = new Node(start_vr->find(t), start_vr, 0); + auto start_vr = t.vertex_find(sys_id_start); + assert(start_vr); + start_vr.get().fill(); + Node *start = new Node(start_vr.take(), 0); queue.push(start); int count = 0; do { auto now = queue.top(); queue.pop(); - // if(!visited.insert(now)){ // continue; // } @@ -173,17 +177,16 @@ void a_star(Db &db, int64_t sys_id_start, uint max_depth, EdgeFilter e_filter[], continue; } - for (auto edge : now->vertex->data.out) { + iter::for_all(now->vacc.out(), [&](auto edge) { if (e_filter[now->depth](t, edge, now)) { - Vertex *v = edge->to()->find(t); - if (v_filter[now->depth](t, v, now)) { - Node *n = new Node( - v, edge->to(), - now->cost + calc_heuristic_cost(edge->find(t), v), now); + VertexAccessor va = edge.to(); + if (v_filter[now->depth](t, va, now)) { + auto cost = calc_heuristic_cost(edge, va); + Node *n = new Node(va, now->cost + cost, now); queue.push(n); } } - } + }); } while (!queue.empty()); std::cout << "Found: " << count << " resoults\n"; // TODO: GUBI SE MEMORIJA JER SE NODOVI NEBRISU @@ -266,7 +269,7 @@ void load_csv(Db &db, char *file_path, char *edge_file_path) std::string line; - auto &t = db.tx_engine.begin(); + DbAccessor t(db); int max_score = 1000000; // VERTEX import @@ -276,7 +279,7 @@ void load_csv(Db &db, char *file_path, char *edge_file_path) start_vertex_id = id; } - auto vertex_accessor = db.graph.vertices.insert(t); + auto vertex_accessor = t.vertex_insert(); vertex_accessor.property("id", std::make_shared(id)); vertex_accessor.property("garment_id", std::make_shared(gar_id)); vertex_accessor.property("garment_category_id", @@ -286,10 +289,11 @@ void load_csv(Db &db, char *file_path, char *edge_file_path) "score", std::make_shared((std::rand() % max_score) / (max_score + 0.0))); for (auto l_name : labels) { - auto &label = db.graph.label_store.find_or_create(l_name); + auto &label = t.label_find_or_create(l_name); vertex_accessor.add_label(label); } - return vertex_accessor.id(); + + return vertex_accessor; }; std::getline(file, line); @@ -305,11 +309,12 @@ void load_csv(Db &db, char *file_path, char *edge_file_path) auto splited = split(line, ','); vector labels(splited.begin() + 1, splited.begin() + splited.size() - 2); - auto id = v(stoi(splited[0]), labels, stoi(splited[splited.size() - 2]), - stoi(splited[splited.size() - 1])); + auto vacs = + v(stoi(splited[0]), labels, stoi(splited[splited.size() - 2]), + stoi(splited[splited.size() - 1])); - assert(va.size() == (uint64_t)id); - va.push_back(db.graph.vertices.find(t, id)); + assert(va.size() == (uint64_t)vacs.id()); + va.push_back(vacs); } // EDGE IMPORT @@ -318,12 +323,9 @@ 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, v1.vlist, v2.vlist); + auto edge_accessor = t.edge_insert(v1, v2); - v1.vlist->update(t)->data.out.add(edge_accessor.vlist); - v2.vlist->update(t)->data.in.add(edge_accessor.vlist); - - auto &edge_type = db.graph.edge_type_store.find_or_create(type); + auto &edge_type = t.type_find_or_create(type); edge_accessor.edge_type(edge_type); }; @@ -343,9 +345,9 @@ void load_csv(Db &db, char *file_path, char *edge_file_path) void load_graph_dummy(Db &db) { - auto &t = db.tx_engine.begin(); + DbAccessor t(db); auto v = [&](auto id, auto score) { - auto vertex_accessor = db.graph.vertices.insert(t); + auto vertex_accessor = t.vertex_insert(); vertex_accessor.property("id", std::make_shared(id)); vertex_accessor.property("score", std::make_shared(score)); return vertex_accessor.id(); @@ -356,15 +358,13 @@ void load_graph_dummy(Db &db) }; auto e = [&](auto from, auto type, auto to) { - auto v1 = db.graph.vertices.find(t, va[from]); + auto v1 = t.vertex_find(va[from]); - auto v2 = db.graph.vertices.find(t, va[to]); + auto v2 = t.vertex_find(va[to]); - 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); + auto edge_accessor = t.edge_insert(v1.get(), v2.get()); - auto &edge_type = db.graph.edge_type_store.find_or_create(type); + auto &edge_type = t.type_find_or_create(type); edge_accessor.edge_type(edge_type); }; diff --git a/src/cypher/tokenizer/cypher_lexer.hpp b/src/cypher/tokenizer/cypher_lexer.hpp index 42b4783ee..ed83cddfc 100644 --- a/src/cypher/tokenizer/cypher_lexer.hpp +++ b/src/cypher/tokenizer/cypher_lexer.hpp @@ -73,6 +73,6 @@ public: build(); } - CypherLexer(CypherLexer& other) = delete; - CypherLexer(CypherLexer&& other) = default; + CypherLexer(CypherLexer &other) = delete; + CypherLexer(CypherLexer &&other) = default; }; diff --git a/src/data_structures/map/rh_common.hpp b/src/data_structures/map/rh_common.hpp index 648666e56..69593bdb0 100644 --- a/src/data_structures/map/rh_common.hpp +++ b/src/data_structures/map/rh_common.hpp @@ -1,8 +1,9 @@ #pragma once -#include "utils/crtp.hpp" -#include "utils/option_ptr.hpp" +#include #include #include +#include "utils/crtp.hpp" +#include "utils/option_ptr.hpp" // RobinHood base. // Entrys are POINTERS alligned to 8B. @@ -240,6 +241,10 @@ protected: } Iterator create_it(size_t index) { return Iterator(this, index); } + ConstIterator create_it(size_t index) const + { + return ConstIterator(this, index); + } public: void clear() diff --git a/src/data_structures/map/rh_hashmultimap.hpp b/src/data_structures/map/rh_hashmultimap.hpp index e32a2f076..d46fcbc2a 100644 --- a/src/data_structures/map/rh_hashmultimap.hpp +++ b/src/data_structures/map/rh_hashmultimap.hpp @@ -1,9 +1,10 @@ +#include +#include #include "rh_common.hpp" #include "utils/crtp.hpp" #include "utils/likely.hpp" +#include "utils/option.hpp" #include "utils/option_ptr.hpp" -#include -#include // HashMultiMap with RobinHood collision resolution policy. // Single threaded. @@ -45,9 +46,30 @@ public: using typename base::ConstIterator; using typename base::Iterator; - bool contains(const K &key) { return find(key) != end(); } + bool contains(const K &key) const { return find_index(key).is_present(); } Iterator find(const K &key_in) + { + auto index = find_index(key_in); + if (index) { + return create_it(index.get()); + } else { + return end(); + } + } + + ConstIterator find(const K &key_in) const + { + auto index = find_index(key_in); + if (index) { + return create_it(index.get()); + } else { + return end(); + } + } + +private: + Option find_index(const K &key_in) const { if (count > 0) { auto key = std::ref(key_in); @@ -59,7 +81,7 @@ public: while (other.valid() && off < border) { auto other_off = other.off(); if (other_off == off && key == other.ptr()->get_key()) { - return create_it(now); + return Option(now); } else if (other_off < off) { // Other is rich break; @@ -73,9 +95,10 @@ public: } } - return end(); + return Option(); } +public: // Inserts element. void add(D *data) { add(data->get_key(), data); } @@ -211,7 +234,7 @@ public: private: // Skips same key valus as other. true if whole map is full of same key // values. - bool skip(size_t &now, Combined &other, size_t other_off, size_t mask) + bool skip(size_t &now, Combined &other, size_t other_off, size_t mask) const { auto other_key = other.ptr()->get_key(); size_t start = now; diff --git a/src/database/db.cpp b/src/database/db.cpp new file mode 100644 index 000000000..9ceb50a77 --- /dev/null +++ b/src/database/db.cpp @@ -0,0 +1,6 @@ +#include "database/db.hpp" + +Db::Db() = default; +Db::Db(const std::string &name) : name_(name) {} + +std::string &Db::name() { return name_; } diff --git a/src/database/db_accessor.cpp b/src/database/db_accessor.cpp new file mode 100644 index 000000000..b3972e29a --- /dev/null +++ b/src/database/db_accessor.cpp @@ -0,0 +1,75 @@ +#include "database/db_accessor.hpp" + +DbAccessor::DbAccessor(Db &db) : db(DbTransaction(db, db.tx_engine.begin())) {} + +// VERTEX METHODS +auto DbAccessor::vertex_access() +{ + return iter::make_map( + iter::make_iter(this->db.db.graph.vertices.access()), + [&](auto e) -> auto { return Vertex::Accessor(&(e->second), db); }); +} + +Option DbAccessor::vertex_find(const Id &id) +{ + return this->db.db.graph.vertices.find(db, id); +} + +Vertex::Accessor DbAccessor::vertex_insert() +{ + return this->db.db.graph.vertices.insert(db); +} + +// EDGE METHODS + +Option DbAccessor::edge_find(const Id &id) +{ + return db.db.graph.edges.find(db, id); +} + +Edge::Accessor DbAccessor::edge_insert(Vertex::Accessor const &from, + Vertex::Accessor const &to) +{ + auto edge_accessor = db.db.graph.edges.insert(db, from.vlist, to.vlist); + from.update()->data.out.add(edge_accessor.vlist); + to.update()->data.in.add(edge_accessor.vlist); + return edge_accessor; +} + +// LABEL METHODS +const Label &DbAccessor::label_find_or_create(const std::string &name) +{ + return db.db.graph.label_store.find_or_create( + std::forward(name)); +} + +bool DbAccessor::label_contains(const std::string &name) +{ + return db.db.graph.label_store.contains( + std::forward(name)); +} + +VertexIndexRecordCollection &DbAccessor::label_find_index(const Label &label) +{ + return db.db.graph.vertices.find_label_index(label); +} + +// TYPE METHODS +const EdgeType &DbAccessor::type_find_or_create(const std::string &name) +{ + return db.db.graph.edge_type_store.find_or_create( + std::forward(name)); +} + +bool DbAccessor::type_contains(const std::string &name) +{ + return db.db.graph.edge_type_store.contains( + std::forward(name)); +} + +// TRANSACTION METHODS +void DbAccessor::commit() { db.trans.commit(); } +void DbAccessor::abort() { db.trans.abort(); } + +// // EASE OF USE METHODS +// tx::Transaction &DbAccessor::operator*() { return db.trans; } diff --git a/src/database/db_transaction.cpp b/src/database/db_transaction.cpp new file mode 100644 index 000000000..3760ce479 --- /dev/null +++ b/src/database/db_transaction.cpp @@ -0,0 +1,8 @@ +#include "database/db.hpp" +#include "database/db_transaction.hpp" + +void DbTransaction::update_label_index(const Label &label, + VertexIndexRecord &&index_record) +{ + db.graph.vertices.update_label_index(label, std::move(index_record)); +} diff --git a/src/storage/edge_accessor.cpp b/src/storage/edge_accessor.cpp new file mode 100644 index 000000000..72f7e0582 --- /dev/null +++ b/src/storage/edge_accessor.cpp @@ -0,0 +1,22 @@ +#include "storage/edge_accessor.hpp" + +void Edge::Accessor::edge_type(edge_type_ref_t edge_type) +{ + this->record->data.edge_type = &edge_type.get(); +} + +edge_type_ref_t Edge::Accessor::edge_type() const +{ + runtime_assert(this->record->data.edge_type != nullptr, "EdgeType is null"); + return edge_type_ref_t(*this->record->data.edge_type); +} + +Vertex::Accessor Edge::Accessor::from() const +{ + return Vertex::Accessor(this->vlist->from(), this->db); +} + +Vertex::Accessor Edge::Accessor::to() const +{ + return Vertex::Accessor(this->vlist->to(), this->db); +} diff --git a/src/storage/edges.cpp b/src/storage/edges.cpp index 22a3d4810..5c142e9a8 100644 --- a/src/storage/edges.cpp +++ b/src/storage/edges.cpp @@ -1,21 +1,17 @@ #include "storage/edges.hpp" -Edge::Accessor Edges::find(tx::Transaction &t, const Id &id) +Option Edges::find(DbTransaction &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 make_option(); - // find edge - auto edge = edges_iterator->second.find(t); - - if (edge == nullptr) return Edge::Accessor(); - - return Edge::Accessor(edge, &edges_iterator->second, this); + return make_option_const(Edge::Accessor(&edges_iterator->second, t)); } -Edge::Accessor Edges::insert(tx::Transaction &t, VertexRecord *from, +Edge::Accessor Edges::insert(DbTransaction &t, VertexRecord *from, VertexRecord *to) { // get next vertex id @@ -30,7 +26,7 @@ Edge::Accessor Edges::insert(tx::Transaction &t, VertexRecord *from, // create new vertex auto inserted_edge_record = result.first; - auto edge = inserted_edge_record->second.insert(t); + auto edge = inserted_edge_record->second.insert(t.trans); - return Edge::Accessor(edge, &inserted_edge_record->second, this); + return Edge::Accessor(edge, &inserted_edge_record->second, t); } diff --git a/src/storage/vertex_accessor.cpp b/src/storage/vertex_accessor.cpp index 380f30495..250910689 100644 --- a/src/storage/vertex_accessor.cpp +++ b/src/storage/vertex_accessor.cpp @@ -1,6 +1,7 @@ +#include "database/db.hpp" #include "storage/vertex_accessor.hpp" - #include "storage/vertices.hpp" +#include "utils/iterator/iterator.hpp" size_t Vertex::Accessor::out_degree() const { @@ -12,10 +13,7 @@ size_t Vertex::Accessor::in_degree() const return this->record->data.in.degree(); } -size_t Vertex::Accessor::degree() const -{ - return in_degree() + out_degree(); -} +size_t Vertex::Accessor::degree() const { return in_degree() + out_degree(); } void Vertex::Accessor::add_label(const Label &label) { @@ -23,8 +21,8 @@ void Vertex::Accessor::add_label(const Label &label) this->record->data.labels.add(label); // update index - this->store->update_label_index( - label, VertexIndexRecord(this->record, this->vlist)); + this->db.update_label_index(label, + VertexIndexRecord(this->record, this->vlist)); } bool Vertex::Accessor::has_label(const Label &label) const @@ -32,7 +30,30 @@ bool Vertex::Accessor::has_label(const Label &label) const return this->record->data.labels.has(label); } -const std::set& Vertex::Accessor::labels() const +const std::set &Vertex::Accessor::labels() const { return this->record->data.labels(); } + +// Returns unfilled accessors +auto Vertex::Accessor::out() const +{ + DbTransaction &t = this->db; + return iter::make_map( + iter::make_iter_ref(record->data.out), + [&](auto e) -> auto { return Edge::Accessor(*e, t); }); +} + +// Returns unfilled accessors +auto Vertex::Accessor::in() const +{ + DbTransaction &t = this->db; + return iter::make_one_time_accessor( + iter::make_map(iter::make_iter_ref(record->data.in), + [&](auto e) -> auto { return Edge::Accessor(e, t); })); +} + +bool Vertex::Accessor::in_contains(Vertex::Accessor const &other) const +{ + return record->data.in.contains(other.vlist); +} diff --git a/src/storage/vertices.cpp b/src/storage/vertices.cpp index ff94cb7dc..a6cf69c9a 100644 --- a/src/storage/vertices.cpp +++ b/src/storage/vertices.cpp @@ -1,41 +1,19 @@ #include "storage/vertices.hpp" -Vertices::vertices_t::Accessor Vertices::access() -{ - return vertices.access(); -} +Vertices::vertices_t::Accessor Vertices::access() { return vertices.access(); } -const Vertex::Accessor Vertices::find(tx::Transaction &t, const Id &id) +Option Vertices::find(DbTransaction &t, const Id &id) { auto vertices_accessor = vertices.access(); auto vertices_iterator = vertices_accessor.find(id); - if (vertices_iterator == vertices_accessor.end()) return Vertex::Accessor(); + if (vertices_iterator == vertices_accessor.end()) + return make_option(); - // find vertex - auto vertex = vertices_iterator->second.find(t); - - if (vertex == nullptr) return Vertex::Accessor(); - - return Vertex::Accessor(vertex, &vertices_iterator->second, this); + return make_option_const(Vertex::Accessor(&vertices_iterator->second, t)); } -// TODO -const Vertex::Accessor Vertices::first(tx::Transaction &t) -{ - auto vertices_accessor = vertices.access(); - auto vertices_iterator = vertices_accessor.begin(); - - if (vertices_iterator == vertices_accessor.end()) return Vertex::Accessor(); - - auto vertex = vertices_iterator->second.find(t); - - if (vertex == nullptr) return Vertex::Accessor(); - - return Vertex::Accessor(vertex, &vertices_iterator->second, this); -} - -Vertex::Accessor Vertices::insert(tx::Transaction &t) +Vertex::Accessor Vertices::insert(DbTransaction &t) { // get next vertex id auto next = counter.next(); @@ -50,9 +28,9 @@ Vertex::Accessor Vertices::insert(tx::Transaction &t) // create new vertex auto inserted_vertex_record = result.first; - auto vertex = inserted_vertex_record->second.insert(t); + auto vertex = inserted_vertex_record->second.insert(t.trans); - return Vertex::Accessor(vertex, &inserted_vertex_record->second, this); + return Vertex::Accessor(vertex, &inserted_vertex_record->second, t); } void Vertices::update_label_index(const Label &label, diff --git a/tests/concurrent/common.h b/tests/concurrent/common.h index 2a729b9ce..934c29a87 100644 --- a/tests/concurrent/common.h +++ b/tests/concurrent/common.h @@ -14,6 +14,8 @@ #include "data_structures/concurrent/skiplist.hpp" #include "data_structures/static_array.hpp" #include "utils/assert.hpp" +#include "logging/default.hpp" +#include "logging/streams/stdout.hpp" #include "utils/sysinfo/memory.hpp" using std::cout; @@ -231,3 +233,9 @@ void memory_check(size_t no_threads, std::function f) std::cout << "leaked: " << leaked << "\n"; permanent_assert(leaked <= 0, "Memory leak check"); } + +//Initializes loging faccilityes +void init_log(){ + logging::init_async(); + logging::log->pipe(std::make_unique()); +} diff --git a/tests/concurrent/linkedlist.cpp b/tests/concurrent/linkedlist.cpp index a05d29647..2539a2503 100644 --- a/tests/concurrent/linkedlist.cpp +++ b/tests/concurrent/linkedlist.cpp @@ -2,6 +2,7 @@ #include #include +#include "common.h" #include "data_structures/linked_list.hpp" using std::cout; @@ -10,51 +11,52 @@ using std::endl; template void test_concurrent_list_access(list_type &list, std::size_t size) { - // test concurrent access - for (int i = 0; i < 1000000; ++i) { + // test concurrent access + for (int i = 0; i < 1000000; ++i) { - std::thread t1([&list] { - list.push_front(1); - list.pop_front(); - }); + std::thread t1([&list] { + list.push_front(1); + list.pop_front(); + }); - std::thread t2([&list] { - list.push_front(2); - list.pop_front(); - }); + std::thread t2([&list] { + list.push_front(2); + list.pop_front(); + }); - t1.join(); - t2.join(); + t1.join(); + t2.join(); - assert(list.size() == size); - } + assert(list.size() == size); + } } int main() { - LinkedList list; + init_log(); + LinkedList list; - // push & pop operations - list.push_front(10); - list.push_front(20); - auto a = list.front(); - assert(a == 20); - list.pop_front(); - a = list.front(); - assert(a == 10); - list.pop_front(); - assert(list.size() == 0); + // push & pop operations + list.push_front(10); + list.push_front(20); + auto a = list.front(); + assert(a == 20); + list.pop_front(); + a = list.front(); + assert(a == 10); + list.pop_front(); + assert(list.size() == 0); - // concurrent test - LinkedList concurrent_list; - concurrent_list.push_front(1); - concurrent_list.push_front(1); - std::list no_concurrent_list; - no_concurrent_list.push_front(1); - no_concurrent_list.push_front(1); + // concurrent test + LinkedList concurrent_list; + concurrent_list.push_front(1); + concurrent_list.push_front(1); + std::list no_concurrent_list; + no_concurrent_list.push_front(1); + no_concurrent_list.push_front(1); - test_concurrent_list_access(concurrent_list, 2); - // test_concurrent_list_access(no_concurrent_list, 2); + test_concurrent_list_access(concurrent_list, 2); + // test_concurrent_list_access(no_concurrent_list, 2); - return 0; + return 0; } diff --git a/tests/concurrent/sl_insert.cpp b/tests/concurrent/sl_insert.cpp index e1d53f8eb..a0b83e18f 100644 --- a/tests/concurrent/sl_insert.cpp +++ b/tests/concurrent/sl_insert.cpp @@ -9,6 +9,7 @@ constexpr size_t key_range = elems_per_thread * THREADS_NO * 2; // Test checks for missing data and changed/overwriten data. int main() { + init_log(); memory_check(THREADS_NO, [] { map_t skiplist; diff --git a/tests/concurrent/sl_insert_competetive.cpp b/tests/concurrent/sl_insert_competetive.cpp index 2c78b073a..8050a377c 100644 --- a/tests/concurrent/sl_insert_competetive.cpp +++ b/tests/concurrent/sl_insert_competetive.cpp @@ -10,6 +10,7 @@ constexpr size_t key_range = elems_per_thread * THREADS_NO * 2; // Test checks for missing data and changed/overwriten data. int main() { + init_log(); memory_check(THREADS_NO, [] { map_t skiplist; diff --git a/tests/concurrent/sl_map.cpp b/tests/concurrent/sl_map.cpp index 094deb274..8b7684073 100644 --- a/tests/concurrent/sl_map.cpp +++ b/tests/concurrent/sl_map.cpp @@ -5,6 +5,7 @@ constexpr size_t elems_per_thread = 1e5; int main() { + init_log(); memory_check(THREADS_NO, [&] { ds::static_array threads; map_t skiplist; diff --git a/tests/concurrent/sl_memory.cpp b/tests/concurrent/sl_memory.cpp index 486385711..cc7522a3b 100644 --- a/tests/concurrent/sl_memory.cpp +++ b/tests/concurrent/sl_memory.cpp @@ -7,18 +7,20 @@ constexpr size_t elements = 2e6; // Test for simple memory leaks int main() { - memory_check(THREADS_NO, [] { - map_t skiplist; + init_log(); + memory_check(THREADS_NO, [] { + map_t skiplist; - auto futures = run(THREADS_NO, skiplist, [](auto acc, auto index) { - for (size_t i = 0; i < elements; i++) { - acc.insert(i, index); - } - return index; + auto futures = + run(THREADS_NO, skiplist, [](auto acc, auto index) { + for (size_t i = 0; i < elements; i++) { + acc.insert(i, index); + } + return index; + }); + collect(futures); + + auto accessor = skiplist.access(); + check_size(accessor, elements); }); - collect(futures); - - auto accessor = skiplist.access(); - check_size(accessor, elements); - }); } diff --git a/tests/concurrent/sl_memory_leak.cpp b/tests/concurrent/sl_memory_leak.cpp index dca1e9a8d..c5e384ee5 100644 --- a/tests/concurrent/sl_memory_leak.cpp +++ b/tests/concurrent/sl_memory_leak.cpp @@ -6,6 +6,7 @@ constexpr size_t elems_per_thread = 16e5; // Known memory leak at 1,600,000 elements. int main() { + init_log(); memory_check(THREADS_NO, [&] { ds::static_array threads; map_t skiplist; diff --git a/tests/concurrent/sl_multiiterator.cpp b/tests/concurrent/sl_multiiterator.cpp index 187bea1ca..ebff8c0ca 100644 --- a/tests/concurrent/sl_multiiterator.cpp +++ b/tests/concurrent/sl_multiiterator.cpp @@ -13,6 +13,7 @@ constexpr size_t no_insert_for_one_delete = 1; // succeed. int main() { + init_log(); memory_check(THREADS_NO, [] { multimap_t skiplist; diff --git a/tests/concurrent/sl_multiiterator_remove.cpp b/tests/concurrent/sl_multiiterator_remove.cpp index 99d9127ea..e8b8e3d07 100644 --- a/tests/concurrent/sl_multiiterator_remove.cpp +++ b/tests/concurrent/sl_multiiterator_remove.cpp @@ -14,6 +14,7 @@ constexpr size_t no_insert_for_one_delete = 1; // succeed. int main() { + init_log(); memory_check(THREADS_NO, [] { multimap_t skiplist; diff --git a/tests/concurrent/sl_multiiterator_remove_duplicates.cpp b/tests/concurrent/sl_multiiterator_remove_duplicates.cpp index cd6de40f8..da2215ec0 100644 --- a/tests/concurrent/sl_multiiterator_remove_duplicates.cpp +++ b/tests/concurrent/sl_multiiterator_remove_duplicates.cpp @@ -15,6 +15,7 @@ constexpr size_t no_insert_for_one_delete = 2; // succeed. int main() { + init_log(); memory_check(THREADS_NO, [] { multimap_t skiplist; diff --git a/tests/concurrent/sl_multimap.cpp b/tests/concurrent/sl_multimap.cpp index 2fb838275..5953a4ca5 100644 --- a/tests/concurrent/sl_multimap.cpp +++ b/tests/concurrent/sl_multimap.cpp @@ -13,6 +13,7 @@ constexpr size_t no_insert_for_one_delete = 1; // succeed. int main() { + init_log(); memory_check(THREADS_NO, [] { multimap_t skiplist; std::atomic size(0); diff --git a/tests/concurrent/sl_multiset.cpp b/tests/concurrent/sl_multiset.cpp index e8cc159bf..eaca13ca0 100644 --- a/tests/concurrent/sl_multiset.cpp +++ b/tests/concurrent/sl_multiset.cpp @@ -11,6 +11,7 @@ constexpr size_t no_insert_for_one_delete = 1; // succeed. int main() { + init_log(); memory_check(THREADS_NO, [] { multiset_t skiplist; diff --git a/tests/concurrent/sl_remove_competetive.cpp b/tests/concurrent/sl_remove_competetive.cpp index 4a21276d0..614d00d46 100644 --- a/tests/concurrent/sl_remove_competetive.cpp +++ b/tests/concurrent/sl_remove_competetive.cpp @@ -12,6 +12,7 @@ constexpr size_t no_insert_for_one_delete = 2; // Calls of remove method are interleaved with insert calls. int main() { + init_log(); memory_check(THREADS_NO, [] { map_t skiplist; diff --git a/tests/concurrent/sl_remove_disjoint.cpp b/tests/concurrent/sl_remove_disjoint.cpp index 6830f69ba..031d5106e 100644 --- a/tests/concurrent/sl_remove_disjoint.cpp +++ b/tests/concurrent/sl_remove_disjoint.cpp @@ -10,6 +10,7 @@ constexpr size_t no_insert_for_one_delete = 1; // Calls of remove method are interleaved with insert calls. int main() { + init_log(); memory_check(THREADS_NO, [] { map_t skiplist; diff --git a/tests/concurrent/sl_remove_joint.cpp b/tests/concurrent/sl_remove_joint.cpp index 76ba53ae4..b32bae485 100644 --- a/tests/concurrent/sl_remove_joint.cpp +++ b/tests/concurrent/sl_remove_joint.cpp @@ -12,6 +12,7 @@ constexpr size_t no_insert_for_one_delete = 2; // Calls of remove method are interleaved with insert calls. int main() { + init_log(); memory_check(THREADS_NO, [] { map_t skiplist; diff --git a/tests/concurrent/sl_set.cpp b/tests/concurrent/sl_set.cpp index 673c9750b..e86d0a6ae 100644 --- a/tests/concurrent/sl_set.cpp +++ b/tests/concurrent/sl_set.cpp @@ -10,6 +10,7 @@ constexpr size_t no_insert_for_one_delete = 2; // Calls of remove method are interleaved with insert calls. int main() { + init_log(); memory_check(THREADS_NO, [] { set_t skiplist; diff --git a/tests/concurrent/sl_simulation.cpp b/tests/concurrent/sl_simulation.cpp index 705ba416b..564d3d1eb 100644 --- a/tests/concurrent/sl_simulation.cpp +++ b/tests/concurrent/sl_simulation.cpp @@ -14,6 +14,7 @@ constexpr size_t no_insert_for_one_delete = 1; // no_find_per_change and no_insert_for_one_delete. int main() { + init_log(); memory_check(THREADS_NO, [] { map_t skiplist; diff --git a/tests/unit/chunked_encoder.cpp b/tests/unit/chunked_encoder.cpp index 0cbee4143..3cb9898b3 100644 --- a/tests/unit/chunked_encoder.cpp +++ b/tests/unit/chunked_encoder.cpp @@ -1,21 +1,20 @@ -#include -#include #include +#include +#include #include #include "communication/bolt/v1/transport/chunked_encoder.hpp" +#include "logging/default.hpp" +#include "logging/streams/stdout.hpp" using byte = unsigned char; -void print_hex(byte x) -{ - printf("%02X ", static_cast(x)); -} +void print_hex(byte x) { printf("%02X ", static_cast(x)); } class DummyStream { public: - void write(const byte* values, size_t n) + void write(const byte *values, size_t n) { num_calls++; data.insert(data.end(), values, values + n); @@ -28,36 +27,33 @@ public: return c; } - size_t pop_size() - { - return ((size_t)pop() << 8) | pop(); - } + size_t pop_size() { return ((size_t)pop() << 8) | pop(); } void print() { - for(size_t i = 0; i < data.size(); ++i) + for (size_t i = 0; i < data.size(); ++i) print_hex(data[i]); } std::deque data; - size_t num_calls {0}; + size_t num_calls{0}; }; using Encoder = bolt::ChunkedEncoder; -void write_ff(Encoder& encoder, size_t n) +void write_ff(Encoder &encoder, size_t n) { std::vector v; - for(size_t i = 0; i < n; ++i) + for (size_t i = 0; i < n; ++i) v.push_back('\xFF'); encoder.write(v.data(), v.size()); } -void check_ff(DummyStream& stream, size_t n) +void check_ff(DummyStream &stream, size_t n) { - for(size_t i = 0; i < n; ++i) + for (size_t i = 0; i < n; ++i) assert(stream.pop() == byte('\xFF')); (void)stream; @@ -65,6 +61,8 @@ void check_ff(DummyStream& stream, size_t n) int main(void) { + logging::init_async(); + logging::log->pipe(std::make_unique()); DummyStream stream; bolt::ChunkedEncoder encoder(stream); @@ -80,7 +78,7 @@ int main(void) write_ff(encoder, 67000); encoder.flush(); - for(int i = 0; i < 10000; ++i) + for (int i = 0; i < 10000; ++i) write_ff(encoder, 1500); encoder.flush(); @@ -100,8 +98,7 @@ int main(void) size_t k = 10000 * 1500; - while(k > 0) - { + while (k > 0) { auto size = k > encoder.chunk_size ? encoder.chunk_size : k; assert(stream.pop_size() == size); check_ff(stream, size); diff --git a/tests/unit/concurrent_map.cpp b/tests/unit/concurrent_map.cpp index b9e008332..4051e238b 100644 --- a/tests/unit/concurrent_map.cpp +++ b/tests/unit/concurrent_map.cpp @@ -1,6 +1,8 @@ #include #include "data_structures/concurrent/concurrent_map.hpp" +#include "logging/default.hpp" +#include "logging/streams/stdout.hpp" #include "utils/assert.hpp" using std::cout; @@ -8,59 +10,64 @@ using std::endl; using skiplist_t = ConcurrentMap; -void print_skiplist(const skiplist_t::Accessor &skiplist) { - cout << "---- skiplist now has: "; +void print_skiplist(const skiplist_t::Accessor &skiplist) +{ + cout << "---- skiplist now has: "; - for (auto &kv : skiplist) - cout << "(" << kv.first << ", " << kv.second << ") "; + for (auto &kv : skiplist) + cout << "(" << kv.first << ", " << kv.second << ") "; - cout << "----" << endl; + cout << "----" << endl; } -int main(void) { - skiplist_t skiplist; - auto accessor = skiplist.access(); +int main(void) +{ + logging::init_async(); + logging::log->pipe(std::make_unique()); + skiplist_t skiplist; + auto accessor = skiplist.access(); - // insert 10 - permanent_assert(accessor.insert(1, 10).second == true, "add first element"); + // insert 10 + permanent_assert(accessor.insert(1, 10).second == true, + "add first element"); - // try insert 10 again (should fail) - permanent_assert(accessor.insert(1, 10).second == false, - "add the same element, should fail"); + // try insert 10 again (should fail) + permanent_assert(accessor.insert(1, 10).second == false, + "add the same element, should fail"); - // insert 20 - permanent_assert(accessor.insert(2, 20).second == true, - "insert new unique element"); + // insert 20 + permanent_assert(accessor.insert(2, 20).second == true, + "insert new unique element"); - print_skiplist(accessor); + print_skiplist(accessor); - // value at key 3 shouldn't exist - permanent_assert((accessor.find(3) == accessor.end()) == true, - "try to find element which doesn't exist"); + // value at key 3 shouldn't exist + permanent_assert((accessor.find(3) == accessor.end()) == true, + "try to find element which doesn't exist"); - // value at key 2 should exist - permanent_assert((accessor.find(2) != accessor.end()) == true, - "find iterator"); + // value at key 2 should exist + permanent_assert((accessor.find(2) != accessor.end()) == true, + "find iterator"); - // at key 2 is 20 (true) - permanent_assert(accessor.find(2)->second == 20, "find element"); + // at key 2 is 20 (true) + permanent_assert(accessor.find(2)->second == 20, "find element"); - // removed existing (1) - permanent_assert(accessor.remove(1) == true, "try to remove element"); + // removed existing (1) + permanent_assert(accessor.remove(1) == true, "try to remove element"); - // removed non-existing (3) - permanent_assert(accessor.remove(3) == false, - "try to remove element which doesn't exist"); + // removed non-existing (3) + permanent_assert(accessor.remove(3) == false, + "try to remove element which doesn't exist"); - // insert (1, 10) - permanent_assert(accessor.insert(1, 10).second == true, - "insert unique element"); + // insert (1, 10) + permanent_assert(accessor.insert(1, 10).second == true, + "insert unique element"); - // insert (4, 40) - permanent_assert(accessor.insert(4, 40).second == true, - "insert unique element"); + // insert (4, 40) + permanent_assert(accessor.insert(4, 40).second == true, + "insert unique element"); - print_skiplist(accessor); + print_skiplist(accessor); - return 0; + return 0; } diff --git a/tests/unit/concurrent_set.cpp b/tests/unit/concurrent_set.cpp index cd0601b21..684a85cd4 100644 --- a/tests/unit/concurrent_set.cpp +++ b/tests/unit/concurrent_set.cpp @@ -1,6 +1,8 @@ #include #include "data_structures/concurrent/concurrent_set.hpp" +#include "logging/default.hpp" +#include "logging/streams/stdout.hpp" #include "utils/assert.hpp" using std::cout; @@ -18,6 +20,8 @@ void print_skiplist(const ConcurrentSet::Accessor &skiplist) int main(void) { + logging::init_async(); + logging::log->pipe(std::make_unique()); ConcurrentSet set; auto accessor = set.access();