From e7953fc7e0068e44eef9705d05f40d726bae4ed7 Mon Sep 17 00:00:00 2001 From: Marko Budiselic <mbudiselicbuda@gmail.com> Date: Sat, 21 Nov 2015 16:08:23 +0100 Subject: [PATCH 1/3] TotalOrdering and Id implementations, related to T28 --- examples/.gitignore | 1 + examples/id.cpp | 41 ++++++++++++++++++++++++++++++++++++++++ mvcc/id.hpp | 29 ++++++++++++++++++++++++++++ utils/total_ordering.hpp | 13 +++++++++++-- 4 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 examples/.gitignore create mode 100644 examples/id.cpp create mode 100644 mvcc/id.hpp diff --git a/examples/.gitignore b/examples/.gitignore new file mode 100644 index 000000000..f47cb2045 --- /dev/null +++ b/examples/.gitignore @@ -0,0 +1 @@ +*.out diff --git a/examples/id.cpp b/examples/id.cpp new file mode 100644 index 000000000..9919109e9 --- /dev/null +++ b/examples/id.cpp @@ -0,0 +1,41 @@ +#include <iostream> + +#include "mvcc/id.hpp" + +using std::cout; +using std::endl; + +int main() { + + Id id0(0); + Id id1(1); + Id id2(1); + Id id3(id2); + Id id4 = id3; + Id id5(5); + + cout << id5 << " " << id0 << endl; + + if (id0 < id5) + cout << "id0 < id5" << endl; + + if (id1 == id2) + cout << "are equal" << endl; + + if (id3 == id4) + cout << "id3 == id4" << endl; + + if (id5 > id0) + cout << "id5 > id0" << endl; + + if (id5 != id3) + cout << "id5 != id3" << endl; + + if (id1 >= id2) + cout << "id1 >= id2" << endl; + + if (id3 <= id4) + cout << "id3 <= id4" << endl; + + return 0; +} diff --git a/mvcc/id.hpp b/mvcc/id.hpp new file mode 100644 index 000000000..4d5e6d23a --- /dev/null +++ b/mvcc/id.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include <ostream> +#include <stdint.h> +#include "utils/total_ordering.hpp" + +class Id : public TotalOrdering<Id> +{ +public: + Id(uint64_t id) : id(id) {} + + friend bool operator<(const Id& a, const Id& b) + { + return a.id < b.id; + } + + friend bool operator==(const Id& a, const Id& b) + { + return a.id == b.id; + } + + friend std::ostream& operator<<(std::ostream& stream, const Id& id) + { + return stream << id.id; + } + +private: + uint64_t id; +}; diff --git a/utils/total_ordering.hpp b/utils/total_ordering.hpp index 6272c56a9..09651cf23 100644 --- a/utils/total_ordering.hpp +++ b/utils/total_ordering.hpp @@ -8,9 +8,18 @@ struct TotalOrdering return !(a == b); } - friend bool operator>(const Derived& a, const Derived& b) + friend bool operator<=(const Derived& a, const Derived& b) { - return !(a == b); + return a < b || a == b; } + friend bool operator>(const Derived& a, const Derived& b) + { + return !(a <= b); + } + + friend bool operator>=(const Derived& a, const Derived& b) + { + return !(a < b); + } }; From aeb8586bfd3e4b0a5ca6273edc13c957fcae0429 Mon Sep 17 00:00:00 2001 From: Marko Budiselic <mbudiselicbuda@gmail.com> Date: Sat, 21 Nov 2015 19:16:19 +0100 Subject: [PATCH 2/3] uint64_t was replaced with the Id object. Fixes T28. --- api/resources/node.hpp | 2 +- cypher/lexer.hpp | 5 +---- mvcc/atom.hpp | 11 ++++------- mvcc/id.hpp | 9 ++++++++- mvcc/mvcc.hpp | 15 ++++++--------- storage/graph.hpp | 7 ++----- storage/vertex.hpp | 4 +--- transactions/commit_log.hpp | 13 +++++++------ transactions/engine.hpp | 20 +++++++------------- transactions/snapshot.hpp | 29 +++++++++++++++++++++++++---- transactions/transaction.hpp | 12 +++++------- 11 files changed, 67 insertions(+), 60 deletions(-) diff --git a/api/resources/node.hpp b/api/resources/node.hpp index 3d8fd5034..3f1a1fa69 100644 --- a/api/resources/node.hpp +++ b/api/resources/node.hpp @@ -69,7 +69,7 @@ public: { task->run([this, &req]() -> Vertex* { // read id param - uint64_t id = std::stoull(req.params[0]); + Id id(std::stoull(req.params[0])); // TODO: transaction? return db->graph.find_vertex(id); }, diff --git a/cypher/lexer.hpp b/cypher/lexer.hpp index cec017f5b..82481f470 100644 --- a/cypher/lexer.hpp +++ b/cypher/lexer.hpp @@ -1,5 +1,4 @@ -#ifndef MEMGRAPH_CYPHER_LEXER_HPP -#define MEMGRAPH_CYPHER_LEXER_HPP +#pragma once #include <cstdint> @@ -59,5 +58,3 @@ protected: lexertl::rules rules; lexertl::state_machine sm; }; - -#endif diff --git a/mvcc/atom.hpp b/mvcc/atom.hpp index b19b38b8b..75f20dadc 100644 --- a/mvcc/atom.hpp +++ b/mvcc/atom.hpp @@ -1,8 +1,7 @@ -#ifndef MEMGRAPH_MVCC_ATOM_HPP -#define MEMGRAPH_MVCC_ATOM_HPP +#pragma once +#include "mvcc/id.hpp" #include "threading/sync/lockable.hpp" - #include "transactions/transaction.hpp" #include "version.hpp" @@ -14,7 +13,7 @@ class Atom : public Version<T>, public Lockable<SpinLock> { public: - Atom(uint64_t id, T* first) : Version<T>(first), id(id) + Atom(const Id& id, T* first) : Version<T>(first), id(id) { // it's illegal that the first version is nullptr. there should be at // least one version of a record @@ -36,11 +35,9 @@ public: // every record has a unique id. 2^64 = 1.8 x 10^19. that should be enough // for a looong time :) but keep in mind that some vacuuming would be nice // to reuse indices for deleted nodes. - uint64_t id; + Id id; std::atomic<Atom<T>*> next; }; } - -#endif diff --git a/mvcc/id.hpp b/mvcc/id.hpp index 4d5e6d23a..f0aaaf252 100644 --- a/mvcc/id.hpp +++ b/mvcc/id.hpp @@ -7,6 +7,8 @@ class Id : public TotalOrdering<Id> { public: + Id() = default; + Id(uint64_t id) : id(id) {} friend bool operator<(const Id& a, const Id& b) @@ -23,7 +25,12 @@ public: { return stream << id.id; } + + operator uint64_t() const + { + return id; + } private: - uint64_t id; + uint64_t id {0}; }; diff --git a/mvcc/mvcc.hpp b/mvcc/mvcc.hpp index 5c5ad007f..c35248ad0 100644 --- a/mvcc/mvcc.hpp +++ b/mvcc/mvcc.hpp @@ -1,11 +1,10 @@ -#ifndef MEMGRAPH_STORAGE_MODEL_UTILS_MVCC_HPP -#define MEMGRAPH_STORAGE_MODEL_UTILS_MVCC_HPP +#pragma once #include <atomic> #include "transactions/transaction.hpp" #include "transactions/commit_log.hpp" - +#include "mvcc/id.hpp" #include "minmax.hpp" #include "version.hpp" #include "hints.hpp" @@ -26,7 +25,7 @@ public: // and tx.max is the id of the transaction that deleted the record // these values are used to determine the visibility of the record // to the current transaction - MinMax<uint64_t> tx; + MinMax<Id> tx; // cmd.min is the id of the command in this transaction that created the // record and cmd.max is the id of the command in this transaction that @@ -94,18 +93,18 @@ public: protected: Hints hints; - bool max_committed(uint64_t id, const tx::Transaction& t) + bool max_committed(const Id& id, const tx::Transaction& t) { return committed(hints.max, id, t); } - bool min_committed(uint64_t id, const tx::Transaction& t) + bool min_committed(const Id& id, const tx::Transaction& t) { return committed(hints.min, id, t); } template <class U> - bool committed(U& hints, uint64_t id, const tx::Transaction& t) + bool committed(U& hints, const Id& id, const tx::Transaction& t) { auto hint_bits = hints.load(); @@ -135,5 +134,3 @@ protected: }; } - -#endif diff --git a/storage/graph.hpp b/storage/graph.hpp index a2377fb58..18e81b12b 100644 --- a/storage/graph.hpp +++ b/storage/graph.hpp @@ -1,5 +1,4 @@ -#ifndef MEMGRAPH_STORAGE_GRAPH_HPP -#define MEMGRAPH_STORAGE_GRAPH_HPP +#pragma once #include <list> @@ -39,7 +38,7 @@ public: } // TODO: this should probably return mvcc::Atom<Vertex>* - Vertex* find_vertex(uint64_t id) + Vertex* find_vertex(const Id& id) { // get atom iterator auto atom_it = vertices.begin(); @@ -62,5 +61,3 @@ public: VertexStore vertices; EdgeStore edges; }; - -#endif diff --git a/storage/vertex.hpp b/storage/vertex.hpp index bcf3ad7b3..372c0d1a3 100644 --- a/storage/vertex.hpp +++ b/storage/vertex.hpp @@ -1,5 +1,4 @@ -#ifndef MEMGRAPH_STORAGE_VERTEX_HPP -#define MEMGRAPH_STORAGE_VERTEX_HPP +#pragma once #include <vector> @@ -42,4 +41,3 @@ inline std::string properties_to_string(Vertex* vertex) // respond to the use with the buffer return std::move(buffer.str()); } -#endif diff --git a/transactions/commit_log.hpp b/transactions/commit_log.hpp index b5f6b5373..0f5b08d25 100644 --- a/transactions/commit_log.hpp +++ b/transactions/commit_log.hpp @@ -1,6 +1,7 @@ #ifndef MEMGRAPH_TRANSACTIONS_COMMIT_LOG_HPP #define MEMGRAPH_TRANSACTIONS_COMMIT_LOG_HPP +#include "mvcc/id.hpp" #include "data_structures/bitset/dynamic_bitset.hpp" namespace tx @@ -53,32 +54,32 @@ public: return log; } - Info fetch_info(uint64_t id) + Info fetch_info(const Id& id) { return Info { log.at(2 * id, 2) }; } - bool is_active(uint64_t id) + bool is_active(const Id& id) { return fetch_info(id).is_active(); } - bool is_committed(uint64_t id) + bool is_committed(const Id& id) { return fetch_info(id).is_committed(); } - void set_committed(uint64_t id) + void set_committed(const Id& id) { log.set(2 * id); } - bool is_aborted(uint64_t id) + bool is_aborted(const Id& id) { return fetch_info(id).is_aborted(); } - void set_aborted(uint64_t id) + void set_aborted(const Id& id) { log.set(2 * id + 1); } diff --git a/transactions/engine.hpp b/transactions/engine.hpp index a7929bc29..efe8be1ad 100644 --- a/transactions/engine.hpp +++ b/transactions/engine.hpp @@ -1,5 +1,4 @@ -#ifndef MEMGRAPH_TRANSACTIONS_ENGINE_HPP -#define MEMGRAPH_TRANSACTIONS_ENGINE_HPP +#pragma once #include <atomic> #include <vector> @@ -33,16 +32,16 @@ public: { auto guard = this->acquire_unique(); - auto id = counter.next(); + auto id = Id(counter.next()); auto t = new Transaction(id, active); - active.push_back(id); + active.insert(id); cache.put(id, t); return *t; } - const Transaction& advance(uint64_t id) + const Transaction& advance(const Id& id) { auto guard = this->acquire_unique(); @@ -73,7 +72,7 @@ public: finalize(t); } - uint64_t last_known_active() + Id last_known_active() { auto guard = this->acquire_unique(); return active.front(); @@ -96,20 +95,15 @@ public: private: void finalize(const Transaction& t) { - // remove transaction from the active transactions list - auto last = std::remove(active.begin(), active.end(), t.id); - active.erase(last, active.end()); + active.remove(t.id); // remove transaction from cache cache.del(t.id); } SimpleCounter<uint64_t> counter; - - std::vector<uint64_t> active; + Snapshot<Id> active; TransactionCache<uint64_t> cache; }; } - -#endif diff --git a/transactions/snapshot.hpp b/transactions/snapshot.hpp index 7c72e8882..8c558b3e6 100644 --- a/transactions/snapshot.hpp +++ b/transactions/snapshot.hpp @@ -1,5 +1,4 @@ -#ifndef MEMGRAPH_TRANSACTIONS_SNAPSHOT_HPP -#define MEMGRAPH_TRANSACTIONS_SNAPSHOT_HPP +#pragma once #include <vector> #include <algorithm> @@ -11,6 +10,8 @@ template <class id_t> class Snapshot { public: + Snapshot() = default; + Snapshot(std::vector<id_t> active) : active(std::move(active)) {} Snapshot(const Snapshot& other) @@ -28,10 +29,30 @@ public: return std::binary_search(active.begin(), active.end(), xid); } + void insert(const id_t& id) + { + active.push_back(id); + } + + void remove(const id_t& id) + { + // remove transaction from the active transactions list + auto last = std::remove(active.begin(), active.end(), id); + active.erase(last, active.end()); + } + + const id_t& front() + { + return active.front(); + } + + size_t size() + { + return active.size(); + } + private: std::vector<id_t> active; }; } - -#endif diff --git a/transactions/transaction.hpp b/transactions/transaction.hpp index 5133d0341..1e67efb90 100644 --- a/transactions/transaction.hpp +++ b/transactions/transaction.hpp @@ -1,10 +1,10 @@ -#ifndef MEMGRAPH_MVCC_TRANSACTION_HPP -#define MEMGRAPH_MVCC_TRANSACTION_HPP +#pragma once #include <cstdlib> #include <cstdint> #include <vector> +#include "mvcc/id.hpp" #include "snapshot.hpp" namespace tx @@ -12,19 +12,17 @@ namespace tx struct Transaction { - Transaction(uint64_t id, Snapshot<uint64_t> snapshot) + Transaction(const Id& id, Snapshot<Id> snapshot) : id(id), cid(1), snapshot(std::move(snapshot)) {} // index of this transaction - uint64_t id; + Id id; // index of the current command in the current transaction; uint8_t cid; // a snapshot of currently active transactions - Snapshot<uint64_t> snapshot; + Snapshot<Id> snapshot; }; } - -#endif From 9685ac3cb6fcfc9a8f7cf306c0a18089b4bacb5d Mon Sep 17 00:00:00 2001 From: Marko Budiselic <mbudiselicbuda@gmail.com> Date: Sat, 21 Nov 2015 20:34:10 +0100 Subject: [PATCH 3/3] Initial code on crashes and exceptions logging. Related to T31. --- memgraph.cpp | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/memgraph.cpp b/memgraph.cpp index 2d4255777..036e96cb7 100644 --- a/memgraph.cpp +++ b/memgraph.cpp @@ -12,8 +12,41 @@ #include "threading/pool.hpp" #include "threading/task.hpp" +#include <execinfo.h> + +// TODO: move to separate header or source file +// TODO: log to local file or remote database +void stacktrace() noexcept +{ + void *array[50]; + int size = backtrace(array, 50); + std::cout << __FUNCTION__ << " backtrace returned " << size << " frames\n\n"; + char **messages = backtrace_symbols(array, size); + for (int i = 0; i < size && messages != NULL; ++i) { + std::cout << "[bt]: (" << i << ") " << messages[i] << std::endl; + } + std::cout << std::endl; + free(messages); +} + +// TODO: log to local file or remote database +void on_terminate() noexcept +{ + if (auto exc = std::current_exception()) { + try { + std::rethrow_exception(exc); + } catch (std::exception &ex) { + std::cout << ex.what() << std::endl << std::endl; + stacktrace(); + } + } + std::_Exit(EXIT_FAILURE); +} + int main() { + std::set_terminate(&on_terminate); + ioc::Container container; container.singleton<Db>();