2015-11-22 02:16:19 +08:00
|
|
|
#pragma once
|
2015-07-04 17:51:33 +08:00
|
|
|
|
2018-02-15 17:47:50 +08:00
|
|
|
#include <algorithm>
|
|
|
|
#include <mutex>
|
|
|
|
#include <vector>
|
|
|
|
|
2017-11-29 23:03:42 +08:00
|
|
|
#include "data_structures/concurrent/concurrent_map.hpp"
|
2018-02-15 17:47:50 +08:00
|
|
|
#include "threading/sync/spinlock.hpp"
|
2016-08-10 16:39:02 +08:00
|
|
|
#include "transactions/commit_log.hpp"
|
2016-07-05 11:01:22 +08:00
|
|
|
#include "transactions/transaction.hpp"
|
2017-11-29 23:03:42 +08:00
|
|
|
#include "transactions/type.hpp"
|
2015-07-04 17:51:33 +08:00
|
|
|
|
2017-02-18 18:54:37 +08:00
|
|
|
namespace tx {
|
2018-02-15 17:47:50 +08:00
|
|
|
class TxEndListener;
|
2017-11-29 23:03:42 +08:00
|
|
|
/**
|
|
|
|
* Database transaction engine. Used for managing transactions and the related
|
|
|
|
* information such as transaction snapshots and the transaction state info.
|
|
|
|
*
|
|
|
|
* This is an abstract base class for implementing a single-node transactional
|
|
|
|
* engine (MasterEngine), an engine for the master in a distributed system (also
|
|
|
|
* MasterEngine), and for the worker in a distributed system (WorkerEngine).
|
2017-06-12 16:21:19 +08:00
|
|
|
*
|
2017-11-29 23:03:42 +08:00
|
|
|
* Methods in this class are often prefixed with "Global" or "Local", depending
|
|
|
|
* on the guarantees that they need to satisfy. These guarantee requirements are
|
|
|
|
* determined by the users of a particular method.
|
2017-06-12 16:21:19 +08:00
|
|
|
*/
|
2017-11-24 21:46:42 +08:00
|
|
|
class Engine {
|
2018-02-15 17:47:50 +08:00
|
|
|
friend class TxEndListener;
|
|
|
|
|
2017-07-14 19:58:25 +08:00
|
|
|
public:
|
2017-11-29 23:03:42 +08:00
|
|
|
virtual ~Engine() = default;
|
2015-10-04 15:47:15 +08:00
|
|
|
|
2018-02-01 17:58:56 +08:00
|
|
|
/// Begins a transaction and returns a pointer to it's object.
|
|
|
|
virtual Transaction *Begin() = 0;
|
|
|
|
|
|
|
|
/// Advances the command on the transaction with the given id.
|
|
|
|
virtual command_id_t Advance(transaction_id_t id) = 0;
|
|
|
|
|
2018-02-14 16:44:48 +08:00
|
|
|
/// Updates the command on the workers to the master's value.
|
|
|
|
virtual command_id_t UpdateCommand(transaction_id_t id) = 0;
|
|
|
|
|
2018-02-01 17:58:56 +08:00
|
|
|
/// Comits the given transaction. Deletes the transaction object, it's not
|
|
|
|
/// valid after this function executes.
|
|
|
|
virtual void Commit(const Transaction &t) = 0;
|
|
|
|
|
|
|
|
/// Aborts the given transaction. Deletes the transaction object, it's not
|
|
|
|
/// valid after this function executes.
|
|
|
|
virtual void Abort(const Transaction &t) = 0;
|
|
|
|
|
2017-11-29 23:03:42 +08:00
|
|
|
/** Returns the commit log Info about the given transaction. */
|
|
|
|
virtual CommitLog::Info Info(transaction_id_t tx) const = 0;
|
2015-07-04 17:51:33 +08:00
|
|
|
|
2017-07-14 19:58:25 +08:00
|
|
|
/** Returns the snapshot relevant to garbage collection of database records.
|
2017-06-12 16:21:19 +08:00
|
|
|
*
|
2017-07-14 19:58:25 +08:00
|
|
|
* If there are no active transactions that means a snapshot containing only
|
|
|
|
* the next transaction ID. If there are active transactions, that means the
|
|
|
|
* oldest active transaction's snapshot, with that transaction's ID appened as
|
|
|
|
* last.
|
2017-06-12 16:21:19 +08:00
|
|
|
*
|
2017-07-14 19:58:25 +08:00
|
|
|
* The idea is that data records can only be deleted if they were expired (and
|
|
|
|
* that was committed) by a transaction older then the older currently active.
|
|
|
|
* We need the full snapshot to prevent overlaps (see general GC
|
|
|
|
* documentation).
|
2017-11-29 23:03:42 +08:00
|
|
|
*
|
|
|
|
* The returned snapshot must be for the globally oldest active transaction.
|
|
|
|
* If we only looked at locally known transactions, it would be possible to
|
|
|
|
* delete something that and older active transaction can still see.
|
2017-06-12 16:21:19 +08:00
|
|
|
*/
|
2017-11-29 23:03:42 +08:00
|
|
|
virtual Snapshot GlobalGcSnapshot() = 0;
|
2017-11-27 21:57:45 +08:00
|
|
|
|
2017-11-29 23:03:42 +08:00
|
|
|
/** Returns active transactions. */
|
|
|
|
virtual Snapshot GlobalActiveTransactions() = 0;
|
2017-10-06 03:19:32 +08:00
|
|
|
|
2017-11-24 21:46:42 +08:00
|
|
|
/** Returns true if the transaction with the given ID is currently active. */
|
2017-11-29 23:03:42 +08:00
|
|
|
virtual bool GlobalIsActive(transaction_id_t tx) const = 0;
|
2015-07-04 17:51:33 +08:00
|
|
|
|
2017-11-29 23:03:42 +08:00
|
|
|
/** Returns the ID of last locally known transaction. */
|
|
|
|
virtual tx::transaction_id_t LocalLast() const = 0;
|
2017-07-14 19:58:25 +08:00
|
|
|
|
2017-11-29 23:03:42 +08:00
|
|
|
/** Calls function f on each locally active transaction. */
|
|
|
|
virtual void LocalForEachActiveTransaction(
|
|
|
|
std::function<void(Transaction &)> f) = 0;
|
2017-09-27 20:02:24 +08:00
|
|
|
|
2018-01-19 18:18:13 +08:00
|
|
|
/** Gets a transaction object for a running transaction. */
|
2018-02-15 17:47:50 +08:00
|
|
|
virtual tx::Transaction *RunningTransaction(transaction_id_t tx_id) = 0;
|
2018-01-19 18:18:13 +08:00
|
|
|
|
2017-11-29 23:03:42 +08:00
|
|
|
auto &local_lock_graph() { return local_lock_graph_; }
|
|
|
|
const auto &local_lock_graph() const { return local_lock_graph_; }
|
2016-03-12 19:26:56 +08:00
|
|
|
|
2017-02-18 18:54:37 +08:00
|
|
|
private:
|
2017-11-29 23:03:42 +08:00
|
|
|
// Map lock dependencies. Each entry maps (tx_that_wants_lock,
|
|
|
|
// tx_that_holds_lock). Used for local deadlock resolution.
|
|
|
|
// TODO consider global deadlock resolution.
|
|
|
|
ConcurrentMap<transaction_id_t, transaction_id_t> local_lock_graph_;
|
2018-02-15 17:47:50 +08:00
|
|
|
|
|
|
|
// Transaction end listeners and the lock for protecting that datastructure.
|
|
|
|
std::vector<TxEndListener *> end_listeners_;
|
|
|
|
mutable SpinLock end_listeners_lock_;
|
|
|
|
|
|
|
|
/** Register a transaction end listener with this engine. */
|
|
|
|
void Register(TxEndListener *listener);
|
|
|
|
|
|
|
|
/** Unregister a transaction end listener with this engine. */
|
|
|
|
void Unregister(TxEndListener *listener);
|
|
|
|
|
|
|
|
protected:
|
|
|
|
/** Notifies all registered listeners that a transaction has ended. */
|
|
|
|
void NotifyListeners(transaction_id_t tx_id) const;
|
2015-07-04 17:51:33 +08:00
|
|
|
};
|
2017-10-11 19:19:10 +08:00
|
|
|
} // namespace tx
|