1
0
Fork 0

transaction interface

This commit is contained in:
Jan Steemann 2014-04-08 14:40:09 +02:00
parent eb7a94a861
commit c29cf874b5
9 changed files with 207 additions and 71 deletions

View File

@ -98,30 +98,88 @@ void Manager::shutdown () {
/// @brief create a transaction object
////////////////////////////////////////////////////////////////////////////////
Transaction* Manager::createTransaction (TRI_vocbase_t* vocbase) {
Transaction* Manager::createTransaction (TRI_vocbase_t* vocbase,
bool singleOperation) {
Transaction::IdType id = _generator.next();
Transaction* transaction = new Transaction(this, id, vocbase);
Transaction* transaction = new Transaction(this, id, vocbase, singleOperation);
WRITE_LOCKER(_lock);
auto it = _transactions.insert(make_pair(id, transaction));
if (it.first == _transactions.end()) {
// couldn't insert transaction
delete transaction;
return nullptr;
}
return transaction;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return the status of a transaction
////////////////////////////////////////////////////////////////////////////////
Transaction::StateType Manager::statusTransaction (Transaction::IdType id) {
READ_LOCKER(_lock);
auto it = _transactions.find(id);
if (it != _transactions.end()) {
return (*it).second->state();
}
// unknown transaction. probably already committed
return Transaction::StateType::STATE_COMMITTED;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief get oldest still running transaction
////////////////////////////////////////////////////////////////////////////////
TransactionInfo Manager::getOldestRunning () {
READ_LOCKER(_lock);
for (auto it = _transactions.begin(); it != _transactions.end(); ++it) {
Transaction* transaction = (*it).second;
if (transaction->state() == Transaction::StateType::STATE_BEGUN) {
return TransactionInfo(transaction->id(), transaction->elapsedTime());
}
}
return TransactionInfo();
}
////////////////////////////////////////////////////////////////////////////////
/// @brief remove failed transactions from the failed list
////////////////////////////////////////////////////////////////////////////////
int Manager::removeFailed (vector<Transaction::IdType> const& ids) {
WRITE_LOCKER(_lock);
for (auto it = ids.begin(); it != ids.end(); ++it) {
_transactions.erase(*it);
}
return TRI_ERROR_NO_ERROR;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief begin a transaction
////////////////////////////////////////////////////////////////////////////////
int Manager::beginTransaction (Transaction* transaction) {
double startTime = TRI_microtime();
Transaction::IdType id = transaction->id();
WRITE_LOCKER(_lock);
auto it = _transactions.insert(make_pair(id, Transaction::StateType::STATE_BEGUN));
if (it.first == _transactions.end()) {
return TRI_ERROR_INTERNAL;
// check the transaction state first
if (transaction->state() != Transaction::StateType::STATE_UNINITIALISED) {
transaction->setAborted();
return TRI_ERROR_TRANSACTION_INTERNAL;
}
transaction->setStartTime(startTime);
// sets status and start time stamp
transaction->setBegun();
return TRI_ERROR_NO_ERROR;
}
@ -134,13 +192,25 @@ int Manager::commitTransaction (Transaction* transaction) {
Transaction::IdType id = transaction->id();
WRITE_LOCKER(_lock);
if (transaction->state() != Transaction::StateType::STATE_BEGUN) {
// set it to aborted
transaction->setAborted();
return TRI_ERROR_TRANSACTION_INTERNAL;
}
transaction->setCommitted();
auto it = _transactions.find(id);
if (it == _transactions.end()) {
return TRI_ERROR_INTERNAL;
// not found
return TRI_ERROR_TRANSACTION_INTERNAL;
}
// erase it in the list of transactions
_transactions.erase(id);
return TRI_ERROR_NO_ERROR;
}
@ -149,33 +219,19 @@ int Manager::commitTransaction (Transaction* transaction) {
////////////////////////////////////////////////////////////////////////////////
int Manager::abortTransaction (Transaction* transaction) {
Transaction::IdType id = transaction->id();
WRITE_LOCKER(_lock);
auto it = _transactions.find(id);
if (it == _transactions.end()) {
return TRI_ERROR_INTERNAL;
if (transaction->state() != Transaction::StateType::STATE_BEGUN) {
// TODO: set it to aborted
return TRI_ERROR_TRANSACTION_INTERNAL;
}
(*it).second = Transaction::StateType::STATE_ABORTED;
transaction->setAborted();
// leave it in the list of transactions
return TRI_ERROR_NO_ERROR;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return the status of a transaction
////////////////////////////////////////////////////////////////////////////////
Transaction::StateType Manager::statusTransaction (Transaction::IdType id) {
READ_LOCKER(_lock);
auto it = _transactions.find(id);
if (it == _transactions.end()) {
return Transaction::StateType::STATE_COMMITTED;
}
return (*it).second;
}
// mode: outline-minor
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}"

View File

@ -84,7 +84,26 @@ namespace triagens {
/// @brief create a transaction object
////////////////////////////////////////////////////////////////////////////////
Transaction* createTransaction (struct TRI_vocbase_s*);
Transaction* createTransaction (struct TRI_vocbase_s*,
bool);
////////////////////////////////////////////////////////////////////////////////
/// @brief abort a transaction
////////////////////////////////////////////////////////////////////////////////
Transaction::StateType statusTransaction (Transaction::IdType);
////////////////////////////////////////////////////////////////////////////////
/// @brief get oldest still running transaction
////////////////////////////////////////////////////////////////////////////////
TransactionInfo getOldestRunning ();
////////////////////////////////////////////////////////////////////////////////
/// @brief remove failed transactions from the failed list
////////////////////////////////////////////////////////////////////////////////
int removeFailed (std::vector<Transaction::IdType> const&);
////////////////////////////////////////////////////////////////////////////////
/// @brief begin a transaction
@ -104,12 +123,6 @@ namespace triagens {
int abortTransaction (Transaction*);
////////////////////////////////////////////////////////////////////////////////
/// @brief abort a transaction
////////////////////////////////////////////////////////////////////////////////
Transaction::StateType statusTransaction (Transaction::IdType);
// -----------------------------------------------------------------------------
// --SECTION-- private variables
// -----------------------------------------------------------------------------
@ -132,7 +145,7 @@ namespace triagens {
/// @brief all running or aborted transactions
////////////////////////////////////////////////////////////////////////////////
map<Transaction::IdType, Transaction::StateType> _transactions;
map<Transaction::IdType, Transaction*> _transactions;
};

View File

@ -41,11 +41,13 @@ using namespace triagens::transaction;
Transaction::Transaction (Manager* manager,
IdType id,
TRI_vocbase_t* vocbase)
TRI_vocbase_t* vocbase,
bool singleOperation)
: _manager(manager),
_id(id),
_state(StateType::STATE_UNINITIALISED),
_vocbase(vocbase),
_singleOperation(singleOperation),
_operations(),
_startTime() {
}
@ -70,15 +72,7 @@ Transaction::~Transaction () {
////////////////////////////////////////////////////////////////////////////////
int Transaction::begin () {
if (state() == StateType::STATE_UNINITIALISED &&
_manager->beginTransaction(this)) {
_state = StateType::STATE_BEGUN;
return TRI_ERROR_NO_ERROR;
}
this->abort();
return TRI_ERROR_TRANSACTION_INTERNAL;
return _manager->beginTransaction(this);
}
////////////////////////////////////////////////////////////////////////////////
@ -86,15 +80,7 @@ int Transaction::begin () {
////////////////////////////////////////////////////////////////////////////////
int Transaction::commit () {
if (state() == StateType::STATE_BEGUN &&
_manager->commitTransaction(this)) {
_state = StateType::STATE_COMMITTED;
return TRI_ERROR_NO_ERROR;
}
this->abort();
return TRI_ERROR_TRANSACTION_INTERNAL;
return _manager->commitTransaction(this);
}
////////////////////////////////////////////////////////////////////////////////
@ -102,15 +88,7 @@ int Transaction::commit () {
////////////////////////////////////////////////////////////////////////////////
int Transaction::abort () {
if (state() == StateType::STATE_BEGUN &&
_manager->abortTransaction(this)) {
_state = StateType::STATE_ABORTED;
return TRI_ERROR_NO_ERROR;
}
_state = StateType::STATE_ABORTED;
return TRI_ERROR_TRANSACTION_INTERNAL;
return _manager->abortTransaction(this);
}
// Local Variables:

View File

@ -44,6 +44,8 @@ namespace triagens {
class Transaction {
friend class Manager;
// -----------------------------------------------------------------------------
// --SECTION-- typedefs
// -----------------------------------------------------------------------------
@ -87,7 +89,8 @@ namespace triagens {
Transaction (Manager*,
IdType,
struct TRI_vocbase_s*);
struct TRI_vocbase_s*,
bool);
////////////////////////////////////////////////////////////////////////////////
/// @brief destroy a transaction
@ -118,11 +121,30 @@ namespace triagens {
}
////////////////////////////////////////////////////////////////////////////////
/// @brief set the transaction start time stamp
/// @brief is single operation?
////////////////////////////////////////////////////////////////////////////////
inline void setStartTime (double s) {
_startTime = s;
inline bool singleOperation () const {
return _singleOperation;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief get the transaction start time stamp
////////////////////////////////////////////////////////////////////////////////
inline double startTime () const {
return _startTime;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief get the time since transaction start
////////////////////////////////////////////////////////////////////////////////
inline double elapsedTime () const {
if (state() == Transaction::StateType::STATE_BEGUN) {
return TRI_microtime() - _startTime;
}
return 0.0;
}
////////////////////////////////////////////////////////////////////////////////
@ -149,6 +171,31 @@ namespace triagens {
private:
////////////////////////////////////////////////////////////////////////////////
/// @brief set a transaction to committed
////////////////////////////////////////////////////////////////////////////////
void setBegun () {
_startTime = TRI_microtime();
_state = StateType::STATE_BEGUN;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief set a transaction to committed
////////////////////////////////////////////////////////////////////////////////
void setCommitted () {
_state = StateType::STATE_COMMITTED;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief set a transaction to aborted
////////////////////////////////////////////////////////////////////////////////
void setAborted () {
_state = StateType::STATE_ABORTED;
}
// -----------------------------------------------------------------------------
// --SECTION-- private variables
// -----------------------------------------------------------------------------
@ -179,6 +226,12 @@ namespace triagens {
struct TRI_vocbase_s* _vocbase;
////////////////////////////////////////////////////////////////////////////////
/// @brief whether or not the transaction consists of a single operation
////////////////////////////////////////////////////////////////////////////////
bool const _singleOperation;
////////////////////////////////////////////////////////////////////////////////
/// @brief transaction operations, per collection
////////////////////////////////////////////////////////////////////////////////
@ -193,6 +246,26 @@ namespace triagens {
};
// -----------------------------------------------------------------------------
// --SECTION-- TransactionInfo
// -----------------------------------------------------------------------------
struct TransactionInfo {
TransactionInfo (Transaction::IdType id,
double elapsedTime)
: _id(id),
_elapsedTime(elapsedTime) {
}
TransactionInfo ()
: _id(0),
_elapsedTime(0.0) {
}
Transaction::IdType const _id;
double const _elapsedTime;
};
}
}

View File

@ -169,6 +169,7 @@
"ERROR_TRANSACTION_NESTED" : { "code" : 1651, "message" : "nested transactions detected" },
"ERROR_TRANSACTION_UNREGISTERED_COLLECTION" : { "code" : 1652, "message" : "unregistered collection used in transaction" },
"ERROR_TRANSACTION_DISALLOWED_OPERATION" : { "code" : 1653, "message" : "disallowed operation inside transaction" },
"ERROR_TRANSACTION_ABORTED" : { "code" : 1654, "message" : "transaction aborted" },
"ERROR_USER_INVALID_NAME" : { "code" : 1700, "message" : "invalid user name" },
"ERROR_USER_INVALID_PASSWORD" : { "code" : 1701, "message" : "invalid password" },
"ERROR_USER_DUPLICATE" : { "code" : 1702, "message" : "duplicate user" },

View File

@ -169,6 +169,7 @@
"ERROR_TRANSACTION_NESTED" : { "code" : 1651, "message" : "nested transactions detected" },
"ERROR_TRANSACTION_UNREGISTERED_COLLECTION" : { "code" : 1652, "message" : "unregistered collection used in transaction" },
"ERROR_TRANSACTION_DISALLOWED_OPERATION" : { "code" : 1653, "message" : "disallowed operation inside transaction" },
"ERROR_TRANSACTION_ABORTED" : { "code" : 1654, "message" : "transaction aborted" },
"ERROR_USER_INVALID_NAME" : { "code" : 1700, "message" : "invalid user name" },
"ERROR_USER_INVALID_PASSWORD" : { "code" : 1701, "message" : "invalid password" },
"ERROR_USER_DUPLICATE" : { "code" : 1702, "message" : "duplicate user" },

View File

@ -224,6 +224,7 @@ ERROR_TRANSACTION_INTERNAL,1650,"internal transaction error","Will be raised whe
ERROR_TRANSACTION_NESTED,1651,"nested transactions detected","Will be raised when transactions are nested."
ERROR_TRANSACTION_UNREGISTERED_COLLECTION,1652,"unregistered collection used in transaction","Will be raised when a collection is used in the middle of a transaction but was not registered at transaction start."
ERROR_TRANSACTION_DISALLOWED_OPERATION,1653,"disallowed operation inside transaction","Will be raised when a disallowed operation is carried out in a transaction."
ERROR_TRANSACTION_ABORTED,1654,"transaction aborted","Will be raised when a transaction was aborted."
################################################################################
## User management

View File

@ -165,6 +165,7 @@ void TRI_InitialiseErrorMessages (void) {
REG_ERROR(ERROR_TRANSACTION_NESTED, "nested transactions detected");
REG_ERROR(ERROR_TRANSACTION_UNREGISTERED_COLLECTION, "unregistered collection used in transaction");
REG_ERROR(ERROR_TRANSACTION_DISALLOWED_OPERATION, "disallowed operation inside transaction");
REG_ERROR(ERROR_TRANSACTION_ABORTED, "transaction aborted");
REG_ERROR(ERROR_USER_INVALID_NAME, "invalid user name");
REG_ERROR(ERROR_USER_INVALID_PASSWORD, "invalid password");
REG_ERROR(ERROR_USER_DUPLICATE, "duplicate user");

View File

@ -394,6 +394,8 @@ extern "C" {
/// - 1653: @LIT{disallowed operation inside transaction}
/// Will be raised when a disallowed operation is carried out in a
/// transaction.
/// - 1654: @LIT{transaction aborted}
/// Will be raised when a transaction was aborted.
/// - 1700: @LIT{invalid user name}
/// Will be raised when an invalid user name is used.
/// - 1701: @LIT{invalid password}
@ -2111,6 +2113,16 @@ void TRI_InitialiseErrorMessages (void);
#define TRI_ERROR_TRANSACTION_DISALLOWED_OPERATION (1653)
////////////////////////////////////////////////////////////////////////////////
/// @brief 1654: ERROR_TRANSACTION_ABORTED
///
/// transaction aborted
///
/// Will be raised when a transaction was aborted.
////////////////////////////////////////////////////////////////////////////////
#define TRI_ERROR_TRANSACTION_ABORTED (1654)
////////////////////////////////////////////////////////////////////////////////
/// @brief 1700: ERROR_USER_INVALID_NAME
///