1
0
Fork 0

protect all properties of TransactionState

This commit is contained in:
jsteemann 2017-02-15 11:37:35 +01:00
parent f68a793174
commit 112d07f6c2
7 changed files with 33 additions and 34 deletions

View File

@ -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);

View File

@ -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

View File

@ -106,6 +106,7 @@ class MMFilesTransactionState final : public TransactionState {
private: private:
rocksdb::Transaction* _rocksTransaction; rocksdb::Transaction* _rocksTransaction;
bool _beginWritten;
bool _hasOperations; bool _hasOperations;
}; };

View File

@ -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;

View File

@ -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() {

View File

@ -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
}; };
} }

View File

@ -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