mirror of https://gitee.com/bigwinds/arangodb
transaction interface
This commit is contained in:
parent
eb7a94a861
commit
c29cf874b5
|
@ -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--\\|/// @\\}"
|
||||
|
|
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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" },
|
||||
|
|
|
@ -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" },
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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
|
||||
///
|
||||
|
|
Loading…
Reference in New Issue