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