* 'master' of https://phabricator.tomicevic.com/diffusion/MG/memgraph:
  Initial code on crashes and exceptions logging. Related to T31.
  uint64_t was replaced with the Id object. Fixes T28.
  TotalOrdering and Id implementations, related to T28
This commit is contained in:
Dominik Tomičević 2015-11-21 22:49:42 +01:00
commit 039df559de
15 changed files with 181 additions and 61 deletions

View File

@ -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);
},

View File

@ -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

1
examples/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*.out

41
examples/id.cpp Normal file
View File

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

View File

@ -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>();

View File

@ -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

36
mvcc/id.hpp Normal file
View File

@ -0,0 +1,36 @@
#pragma once
#include <ostream>
#include <stdint.h>
#include "utils/total_ordering.hpp"
class Id : public TotalOrdering<Id>
{
public:
Id() = default;
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;
}
operator uint64_t() const
{
return id;
}
private:
uint64_t id {0};
};

View File

@ -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

View File

@ -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

View File

@ -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

View File

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

View File

@ -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

View File

@ -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

View File

@ -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

View File

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