From 49dc08b9b38664b918946620d10445f415bbabae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Tomic=CC=8Cevic=CC=81?= <dominik.tomicevic@gmail.com> Date: Sun, 4 Oct 2015 09:47:15 +0200 Subject: [PATCH] moved transactions back to threading --- mvcc/commit_log.hpp | 44 ------------------- threading/sync/lockable.hpp | 7 ++- {mvcc => transactions}/transaction.hpp | 7 ++- transactions/transaction_cache.hpp | 39 ++++++++++++++++ {mvcc => transactions}/transaction_engine.hpp | 44 ++++++++++++++++--- 5 files changed, 87 insertions(+), 54 deletions(-) delete mode 100644 mvcc/commit_log.hpp rename {mvcc => transactions}/transaction.hpp (95%) create mode 100644 transactions/transaction_cache.hpp rename {mvcc => transactions}/transaction_engine.hpp (67%) diff --git a/mvcc/commit_log.hpp b/mvcc/commit_log.hpp deleted file mode 100644 index 1a6a2bc11..000000000 --- a/mvcc/commit_log.hpp +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef MEMGRAPH_TRANSACTION_COMMIT_LOG_HPP -#define MEMGRAPH_TRANSACTION_COMMIT_LOG_HPP - -#include <cstdint> - -#include <boost/dynamic_bitset/dynamic_bitset.hpp> - -#include "threading/sync/spinlock.hpp" -#include "threading/sync/lockable.hpp" - -// optimize allocation performance by preallocating chunks in like 2MB or so -// optimize memory by purging old transactions after vacuuming or something -// this is not sustainable in the long run - -class CommitLog : Lockable<SpinLock> -{ - void begin() - { - auto guard = this->acquire(); - log.push_back(0); - } - - void mark_aborted(uint64_t) - { - // this would be useful in a different implementation - } - - void mark_committed(uint64_t id) - { - auto guard = this->acquire(); - log.set(id, true); - } - - bool is_committed(uint64_t id) - { - auto guard = this->acquire(); - return log[id]; - } - -private: - boost::dynamic_bitset<uint64_t> log; -}; - -#endif diff --git a/threading/sync/lockable.hpp b/threading/sync/lockable.hpp index d669523ca..d0f78ee7a 100644 --- a/threading/sync/lockable.hpp +++ b/threading/sync/lockable.hpp @@ -8,7 +8,12 @@ template <class lock_t = SpinLock> class Lockable { protected: - std::unique_lock<lock_t> acquire() + std::lock_guard<lock_t> acquire_guard() + { + return std::lock_guard<lock_t>(lock); + } + + std::unique_lock<lock_t> acquire_unique() { return std::unique_lock<lock_t>(lock); } diff --git a/mvcc/transaction.hpp b/transactions/transaction.hpp similarity index 95% rename from mvcc/transaction.hpp rename to transactions/transaction.hpp index 80a38748c..6b01cc5e2 100644 --- a/mvcc/transaction.hpp +++ b/transactions/transaction.hpp @@ -5,7 +5,8 @@ #include <cstdint> #include <vector> -#include "commit_log.hpp" +namespace tx +{ struct Transaction { @@ -26,7 +27,7 @@ struct Transaction // check weather the transaction with the xid looks committed from the // database snapshot given to this transaction - bool committed(uint64_t xid) const + bool looks_committed(uint64_t xid) const { // transaction xid is newer than id and therefore not visible at all if (xid > id) @@ -44,4 +45,6 @@ struct Transaction } }; +} + #endif diff --git a/transactions/transaction_cache.hpp b/transactions/transaction_cache.hpp new file mode 100644 index 000000000..0fb933a26 --- /dev/null +++ b/transactions/transaction_cache.hpp @@ -0,0 +1,39 @@ +#ifndef MEMGRAPH_TRANSACTIONS_TRANSACTION_CACHE_HPP +#define MEMGRAPH_TRANSACTIONS_TRANSACTION_CACHE_HPP + +#include <map> +#include <memory> + +#include "transaction.hpp" + +namespace tx +{ + +template <class id_t> +class TransactionCache +{ +public: + + Transaction* get(id_t id) const + { + auto it = cache.find(id); + return it != cache.end() ? it->second : nullptr; + } + + void put(id_t id, Transaction* transaction) + { + cache.emplace(std::make_pair(id, transaction)); + } + + void del(id_t id) + { + cache.erase(id); + } + +private: + std::map<id_t, std::unique_ptr<Transaction>> cache; +}; + +} + +#endif diff --git a/mvcc/transaction_engine.hpp b/transactions/transaction_engine.hpp similarity index 67% rename from mvcc/transaction_engine.hpp rename to transactions/transaction_engine.hpp index d6ce74a91..e63949013 100644 --- a/mvcc/transaction_engine.hpp +++ b/transactions/transaction_engine.hpp @@ -10,26 +10,53 @@ #include <algorithm> #include "transaction.hpp" +#include "transaction_cache.hpp" + #include "utils/counters/simple_counter.hpp" #include "threading/sync/spinlock.hpp" #include "threading/sync/lockable.hpp" +namespace tx +{ + +class TransactionError : std::runtime_error +{ +public: + using std::runtime_error::runtime_error; +}; + class TransactionEngine : Lockable<SpinLock> { public: TransactionEngine(uint64_t n) : counter(n) {} - Transaction begin() + const Transaction& begin() { auto guard = this->acquire(); auto id = counter.next(); - auto t = Transaction(id, active); + auto t = new Transaction(id, active); active.push_back(id); + cache.put(id, t); - return t; + return *t; + } + + const Transaction& advance(uint64_t id) + { + auto guard = this->acquire(); + + auto* t = cache.get(id); + + if(t == nullptr) + throw TransactionError("transaction does not exist"); + + // this is a new command + t->cid++; + + return *t; } void commit(const Transaction& t) @@ -42,7 +69,6 @@ public: void rollback(const Transaction& t) { auto guard = this->acquire(); - // what to do here? finalize(t); } @@ -70,16 +96,20 @@ public: private: void finalize(const Transaction& t) { - auto x = t.id; - // remove transaction from the active transactions list - auto last = std::remove(active.begin(), active.end(), x); + auto last = std::remove(active.begin(), active.end(), t.id); active.erase(last, active.end()); + + // remove transaction from cache + cache.del(t.id); } SimpleCounter<uint64_t> counter; std::vector<uint64_t> active; + TransactionCache<uint64_t> cache; }; +} + #endif