mirror of https://gitee.com/bigwinds/arangodb
protect all properties of TransactionState
This commit is contained in:
parent
f68a793174
commit
112d07f6c2
|
@ -117,7 +117,7 @@ void MMFilesTransactionCollection::freeOperations(transaction::Methods* activeTr
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool const isSingleOperationTransaction = _transaction->_hints.has(transaction::Hints::Hint::SINGLE_OPERATION);
|
bool const isSingleOperationTransaction = _transaction->hasHint(transaction::Hints::Hint::SINGLE_OPERATION);
|
||||||
|
|
||||||
if (mustRollback) {
|
if (mustRollback) {
|
||||||
// revert all operations
|
// revert all operations
|
||||||
|
@ -151,8 +151,8 @@ void MMFilesTransactionCollection::freeOperations(transaction::Methods* activeTr
|
||||||
|
|
||||||
bool MMFilesTransactionCollection::canAccess(AccessMode::Type accessType) const {
|
bool MMFilesTransactionCollection::canAccess(AccessMode::Type accessType) const {
|
||||||
if (_collection == nullptr) {
|
if (_collection == nullptr) {
|
||||||
if (!_transaction->_hints.has(transaction::Hints::Hint::LOCK_NEVER) ||
|
if (!_transaction->hasHint(transaction::Hints::Hint::LOCK_NEVER) ||
|
||||||
!_transaction->_hints.has(transaction::Hints::Hint::NO_USAGE_LOCK)) {
|
!_transaction->hasHint(transaction::Hints::Hint::NO_USAGE_LOCK)) {
|
||||||
// not opened. probably a mistake made by the caller
|
// not opened. probably a mistake made by the caller
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -200,8 +200,8 @@ int MMFilesTransactionCollection::use(int nestingLevel) {
|
||||||
|
|
||||||
if (_collection == nullptr) {
|
if (_collection == nullptr) {
|
||||||
// open the collection
|
// open the collection
|
||||||
if (!_transaction->_hints.has(transaction::Hints::Hint::LOCK_NEVER) &&
|
if (!_transaction->hasHint(transaction::Hints::Hint::LOCK_NEVER) &&
|
||||||
!_transaction->_hints.has(transaction::Hints::Hint::NO_USAGE_LOCK)) {
|
!_transaction->hasHint(transaction::Hints::Hint::NO_USAGE_LOCK)) {
|
||||||
// use and usage-lock
|
// use and usage-lock
|
||||||
TRI_vocbase_col_status_e status;
|
TRI_vocbase_col_status_e status;
|
||||||
LOG_TRX(_transaction, nestingLevel) << "using collection " << _cid;
|
LOG_TRX(_transaction, nestingLevel) << "using collection " << _cid;
|
||||||
|
@ -241,7 +241,7 @@ int MMFilesTransactionCollection::use(int nestingLevel) {
|
||||||
if (nestingLevel == 0 &&
|
if (nestingLevel == 0 &&
|
||||||
AccessMode::isWriteOrExclusive(_accessType)) {
|
AccessMode::isWriteOrExclusive(_accessType)) {
|
||||||
// read-lock the compaction lock
|
// read-lock the compaction lock
|
||||||
if (!_transaction->_hints.has(transaction::Hints::Hint::NO_COMPACTION_LOCK)) {
|
if (!_transaction->hasHint(transaction::Hints::Hint::NO_COMPACTION_LOCK)) {
|
||||||
if (!_compactionLocked) {
|
if (!_compactionLocked) {
|
||||||
logicalToMMFiles(_collection)->preventCompaction();
|
logicalToMMFiles(_collection)->preventCompaction();
|
||||||
_compactionLocked = true;
|
_compactionLocked = true;
|
||||||
|
@ -254,10 +254,10 @@ int MMFilesTransactionCollection::use(int nestingLevel) {
|
||||||
_originalRevision = _collection->revision();
|
_originalRevision = _collection->revision();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool shouldLock = _transaction->_hints.has(transaction::Hints::Hint::LOCK_ENTIRELY);
|
bool shouldLock = _transaction->hasHint(transaction::Hints::Hint::LOCK_ENTIRELY);
|
||||||
|
|
||||||
if (!shouldLock) {
|
if (!shouldLock) {
|
||||||
shouldLock = (AccessMode::isWriteOrExclusive(_accessType) && !_transaction->_hints.has(transaction::Hints::Hint::SINGLE_OPERATION));
|
shouldLock = (AccessMode::isWriteOrExclusive(_accessType) && !_transaction->hasHint(transaction::Hints::Hint::SINGLE_OPERATION));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shouldLock && !isLocked()) {
|
if (shouldLock && !isLocked()) {
|
||||||
|
@ -281,7 +281,7 @@ void MMFilesTransactionCollection::unuse(int nestingLevel) {
|
||||||
|
|
||||||
// the top level transaction releases all collections
|
// the top level transaction releases all collections
|
||||||
if (nestingLevel == 0 && _collection != nullptr) {
|
if (nestingLevel == 0 && _collection != nullptr) {
|
||||||
if (!_transaction->_hints.has(transaction::Hints::Hint::NO_COMPACTION_LOCK)) {
|
if (!_transaction->hasHint(transaction::Hints::Hint::NO_COMPACTION_LOCK)) {
|
||||||
if (AccessMode::isWriteOrExclusive(_accessType) && _compactionLocked) {
|
if (AccessMode::isWriteOrExclusive(_accessType) && _compactionLocked) {
|
||||||
// read-unlock the compaction lock
|
// read-unlock the compaction lock
|
||||||
logicalToMMFiles(_collection)->allowCompaction();
|
logicalToMMFiles(_collection)->allowCompaction();
|
||||||
|
@ -306,7 +306,7 @@ void MMFilesTransactionCollection::release() {
|
||||||
|
|
||||||
/// @brief lock a collection
|
/// @brief lock a collection
|
||||||
int MMFilesTransactionCollection::doLock(AccessMode::Type type, int nestingLevel) {
|
int MMFilesTransactionCollection::doLock(AccessMode::Type type, int nestingLevel) {
|
||||||
if (_transaction->_hints.has(transaction::Hints::Hint::LOCK_NEVER)) {
|
if (_transaction->hasHint(transaction::Hints::Hint::LOCK_NEVER)) {
|
||||||
// never lock
|
// never lock
|
||||||
return TRI_ERROR_NO_ERROR;
|
return TRI_ERROR_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -333,12 +333,12 @@ int MMFilesTransactionCollection::doLock(AccessMode::Type type, int nestingLevel
|
||||||
TRI_ASSERT(physical != nullptr);
|
TRI_ASSERT(physical != nullptr);
|
||||||
|
|
||||||
double timeout = _transaction->timeout();
|
double timeout = _transaction->timeout();
|
||||||
if (_transaction->_hints.has(transaction::Hints::Hint::TRY_LOCK)) {
|
if (_transaction->hasHint(transaction::Hints::Hint::TRY_LOCK)) {
|
||||||
// give up early if we cannot acquire the lock instantly
|
// give up early if we cannot acquire the lock instantly
|
||||||
timeout = 0.00000001;
|
timeout = 0.00000001;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool const useDeadlockDetector = !_transaction->_hints.has(transaction::Hints::Hint::SINGLE_OPERATION);
|
bool const useDeadlockDetector = !_transaction->hasHint(transaction::Hints::Hint::SINGLE_OPERATION);
|
||||||
|
|
||||||
int res;
|
int res;
|
||||||
if (!isWrite(type)) {
|
if (!isWrite(type)) {
|
||||||
|
@ -358,7 +358,7 @@ int MMFilesTransactionCollection::doLock(AccessMode::Type type, int nestingLevel
|
||||||
|
|
||||||
/// @brief unlock a collection
|
/// @brief unlock a collection
|
||||||
int MMFilesTransactionCollection::doUnlock(AccessMode::Type type, int nestingLevel) {
|
int MMFilesTransactionCollection::doUnlock(AccessMode::Type type, int nestingLevel) {
|
||||||
if (_transaction->_hints.has(transaction::Hints::Hint::LOCK_NEVER)) {
|
if (_transaction->hasHint(transaction::Hints::Hint::LOCK_NEVER)) {
|
||||||
// never unlock
|
// never unlock
|
||||||
return TRI_ERROR_NO_ERROR;
|
return TRI_ERROR_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -394,7 +394,7 @@ int MMFilesTransactionCollection::doUnlock(AccessMode::Type type, int nestingLev
|
||||||
return TRI_ERROR_INTERNAL;
|
return TRI_ERROR_INTERNAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool const useDeadlockDetector = !_transaction->_hints.has(transaction::Hints::Hint::SINGLE_OPERATION);
|
bool const useDeadlockDetector = !_transaction->hasHint(transaction::Hints::Hint::SINGLE_OPERATION);
|
||||||
|
|
||||||
LogicalCollection* collection = _collection;
|
LogicalCollection* collection = _collection;
|
||||||
TRI_ASSERT(collection != nullptr);
|
TRI_ASSERT(collection != nullptr);
|
||||||
|
|
|
@ -53,6 +53,7 @@ static inline MMFilesLogfileManager* GetMMFilesLogfileManager() {
|
||||||
MMFilesTransactionState::MMFilesTransactionState(TRI_vocbase_t* vocbase)
|
MMFilesTransactionState::MMFilesTransactionState(TRI_vocbase_t* vocbase)
|
||||||
: TransactionState(vocbase),
|
: TransactionState(vocbase),
|
||||||
_rocksTransaction(nullptr),
|
_rocksTransaction(nullptr),
|
||||||
|
_beginWritten(false),
|
||||||
_hasOperations(false) {}
|
_hasOperations(false) {}
|
||||||
|
|
||||||
/// @brief free a transaction container
|
/// @brief free a transaction container
|
||||||
|
|
|
@ -106,6 +106,7 @@ class MMFilesTransactionState final : public TransactionState {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
rocksdb::Transaction* _rocksTransaction;
|
rocksdb::Transaction* _rocksTransaction;
|
||||||
|
bool _beginWritten;
|
||||||
bool _hasOperations;
|
bool _hasOperations;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -33,13 +33,12 @@ class LogicalCollection;
|
||||||
namespace transaction {
|
namespace transaction {
|
||||||
class Methods;
|
class Methods;
|
||||||
}
|
}
|
||||||
;
|
|
||||||
class TransactionState;
|
class TransactionState;
|
||||||
|
|
||||||
/// @brief collection used in a transaction
|
/// @brief collection used in a transaction
|
||||||
class TransactionCollection {
|
class TransactionCollection {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
TransactionCollection(TransactionCollection const&) = delete;
|
TransactionCollection(TransactionCollection const&) = delete;
|
||||||
TransactionCollection& operator=(TransactionCollection const&) = delete;
|
TransactionCollection& operator=(TransactionCollection const&) = delete;
|
||||||
|
|
||||||
|
|
|
@ -43,11 +43,10 @@ TransactionState::TransactionState(TRI_vocbase_t* vocbase)
|
||||||
_collections{_arena}, // assign arena to vector
|
_collections{_arena}, // assign arena to vector
|
||||||
_serverRole(ServerState::instance()->getRole()),
|
_serverRole(ServerState::instance()->getRole()),
|
||||||
_hints(),
|
_hints(),
|
||||||
|
_timeout(transaction::Methods::DefaultLockTimeout),
|
||||||
_nestingLevel(0),
|
_nestingLevel(0),
|
||||||
_allowImplicitCollections(true),
|
_allowImplicitCollections(true),
|
||||||
_waitForSync(false),
|
_waitForSync(false) {}
|
||||||
_beginWritten(false),
|
|
||||||
_timeout(transaction::Methods::DefaultLockTimeout) {}
|
|
||||||
|
|
||||||
/// @brief free a transaction container
|
/// @brief free a transaction container
|
||||||
TransactionState::~TransactionState() {
|
TransactionState::~TransactionState() {
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
#include "Basics/Common.h"
|
#include "Basics/Common.h"
|
||||||
#include "Basics/SmallVector.h"
|
#include "Basics/SmallVector.h"
|
||||||
#include "Cluster/ServerState.h"
|
#include "Cluster/ServerState.h"
|
||||||
#include "Transaction/Methods.h"
|
|
||||||
#include "Transaction/Hints.h"
|
#include "Transaction/Hints.h"
|
||||||
#include "Transaction/Status.h"
|
#include "Transaction/Status.h"
|
||||||
#include "VocBase/AccessMode.h"
|
#include "VocBase/AccessMode.h"
|
||||||
|
@ -50,7 +49,6 @@ namespace arangodb {
|
||||||
namespace transaction {
|
namespace transaction {
|
||||||
class Methods;
|
class Methods;
|
||||||
}
|
}
|
||||||
;
|
|
||||||
class TransactionCollection;
|
class TransactionCollection;
|
||||||
|
|
||||||
/// @brief transaction type
|
/// @brief transaction type
|
||||||
|
@ -71,6 +69,12 @@ class TransactionState {
|
||||||
TRI_voc_tid_t id() const { return _id; }
|
TRI_voc_tid_t id() const { return _id; }
|
||||||
transaction::Status status() const { return _status; }
|
transaction::Status status() const { return _status; }
|
||||||
|
|
||||||
|
int increaseNesting() { return ++_nestingLevel; }
|
||||||
|
int decreaseNesting() {
|
||||||
|
TRI_ASSERT(_nestingLevel > 0);
|
||||||
|
return --_nestingLevel;
|
||||||
|
}
|
||||||
|
|
||||||
double timeout() const { return _timeout; }
|
double timeout() const { return _timeout; }
|
||||||
void timeout(double value) {
|
void timeout(double value) {
|
||||||
if (value > 0.0) {
|
if (value > 0.0) {
|
||||||
|
@ -112,9 +116,10 @@ class TransactionState {
|
||||||
void updateStatus(transaction::Status status);
|
void updateStatus(transaction::Status status);
|
||||||
|
|
||||||
/// @brief whether or not a specific hint is set for the transaction
|
/// @brief whether or not a specific hint is set for the transaction
|
||||||
bool hasHint(transaction::Hints::Hint hint) const {
|
bool hasHint(transaction::Hints::Hint hint) const { return _hints.has(hint); }
|
||||||
return _hints.has(hint);
|
|
||||||
}
|
/// @brief set a hint for the transaction
|
||||||
|
void setHint(transaction::Hints::Hint hint) { _hints.set(hint); }
|
||||||
|
|
||||||
/// @brief begin a transaction
|
/// @brief begin a transaction
|
||||||
virtual int beginTransaction(transaction::Hints hints, int nestingLevel) = 0;
|
virtual int beginTransaction(transaction::Hints hints, int nestingLevel) = 0;
|
||||||
|
@ -125,7 +130,6 @@ class TransactionState {
|
||||||
/// @brief abort a transaction
|
/// @brief abort a transaction
|
||||||
virtual int abortTransaction(transaction::Methods* trx, int nestingLevel) = 0;
|
virtual int abortTransaction(transaction::Methods* trx, int nestingLevel) = 0;
|
||||||
|
|
||||||
/// TODO: implement this in base class
|
|
||||||
virtual bool hasFailedOperations() const = 0;
|
virtual bool hasFailedOperations() const = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -158,16 +162,11 @@ class TransactionState {
|
||||||
|
|
||||||
ServerState::RoleEnum const _serverRole; // role of the server
|
ServerState::RoleEnum const _serverRole; // role of the server
|
||||||
|
|
||||||
public:
|
|
||||||
transaction::Hints _hints; // hints;
|
transaction::Hints _hints; // hints;
|
||||||
public:
|
double _timeout; // timeout for lock acquisition
|
||||||
int _nestingLevel;
|
int _nestingLevel;
|
||||||
|
|
||||||
protected:
|
|
||||||
bool _allowImplicitCollections;
|
bool _allowImplicitCollections;
|
||||||
bool _waitForSync; // whether or not the transaction had a synchronous op
|
bool _waitForSync; // whether or not the transaction had a synchronous op
|
||||||
bool _beginWritten; // whether or not the begin marker was already written
|
|
||||||
double _timeout; // timeout for lock acquisition
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -167,7 +167,7 @@ void transaction::Methods::addHint(transaction::Hints::Hint hint, bool passthrou
|
||||||
_hints.set(hint);
|
_hints.set(hint);
|
||||||
|
|
||||||
if (passthrough) {
|
if (passthrough) {
|
||||||
_state->_hints.set(hint);
|
_state->setHint(hint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -580,7 +580,7 @@ transaction::Methods::Methods(std::shared_ptr<TransactionContext> transactionCon
|
||||||
/// @brief destroy the transaction
|
/// @brief destroy the transaction
|
||||||
transaction::Methods::~Methods() {
|
transaction::Methods::~Methods() {
|
||||||
if (isEmbeddedTransaction()) {
|
if (isEmbeddedTransaction()) {
|
||||||
_state->_nestingLevel--;
|
_state->decreaseNesting();
|
||||||
} else {
|
} else {
|
||||||
if (getStatus() == transaction::Status::RUNNING) {
|
if (getStatus() == transaction::Status::RUNNING) {
|
||||||
// auto abort a running transaction
|
// auto abort a running transaction
|
||||||
|
@ -2904,7 +2904,7 @@ void transaction::Methods::setupEmbedded(TRI_vocbase_t*) {
|
||||||
_state = _transactionContextPtr->getParentTransaction();
|
_state = _transactionContextPtr->getParentTransaction();
|
||||||
|
|
||||||
TRI_ASSERT(_state != nullptr);
|
TRI_ASSERT(_state != nullptr);
|
||||||
_nestingLevel = ++_state->_nestingLevel;
|
_nestingLevel = _state->increaseNesting();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief set up a top-level transaction
|
/// @brief set up a top-level transaction
|
||||||
|
|
Loading…
Reference in New Issue