1
0
Fork 0

changed interface for locking

Conflicts:
	arangod/VocBase/transaction.cpp
This commit is contained in:
Jan Steemann 2014-09-19 12:45:29 +02:00
parent c91b78da15
commit 067f253dd5
3 changed files with 89 additions and 35 deletions

View File

@ -237,7 +237,8 @@ int Syncer::applyCollectionDumpMarker (TRI_transaction_collection_t* trxCollecti
try { try {
TRI_doc_mptr_copy_t mptr; TRI_doc_mptr_copy_t mptr;
int res = TRI_ReadShapedJsonDocumentCollection(trxCollection, key, &mptr, ! trxCollection->_locked); bool const isLocked = TRI_IsLockedCollectionTransaction(trxCollection);
int res = TRI_ReadShapedJsonDocumentCollection(trxCollection, key, &mptr, ! isLocked);
if (res == TRI_ERROR_ARANGO_DOCUMENT_NOT_FOUND) { if (res == TRI_ERROR_ARANGO_DOCUMENT_NOT_FOUND) {
// insert // insert
@ -268,7 +269,7 @@ int Syncer::applyCollectionDumpMarker (TRI_transaction_collection_t* trxCollecti
} }
if (res == TRI_ERROR_NO_ERROR) { if (res == TRI_ERROR_NO_ERROR) {
res = TRI_InsertShapedJsonDocumentCollection(trxCollection, key, rid, nullptr, &mptr, shaped, &edge, ! trxCollection->_locked, false, true); res = TRI_InsertShapedJsonDocumentCollection(trxCollection, key, rid, nullptr, &mptr, shaped, &edge, ! isLocked, false, true);
} }
} }
else { else {
@ -277,13 +278,13 @@ int Syncer::applyCollectionDumpMarker (TRI_transaction_collection_t* trxCollecti
res = TRI_ERROR_ARANGO_COLLECTION_TYPE_INVALID; res = TRI_ERROR_ARANGO_COLLECTION_TYPE_INVALID;
} }
else { else {
res = TRI_InsertShapedJsonDocumentCollection(trxCollection, key, rid, nullptr, &mptr, shaped, nullptr, ! trxCollection->_locked, false, true); res = TRI_InsertShapedJsonDocumentCollection(trxCollection, key, rid, nullptr, &mptr, shaped, nullptr, ! isLocked, false, true);
} }
} }
} }
else { else {
// update // update
res = TRI_UpdateShapedJsonDocumentCollection(trxCollection, key, rid, nullptr, &mptr, shaped, &_policy, ! trxCollection->_locked, false); res = TRI_UpdateShapedJsonDocumentCollection(trxCollection, key, rid, nullptr, &mptr, shaped, &_policy, ! isLocked, false);
} }
TRI_FreeShapedJson(zone, shaped); TRI_FreeShapedJson(zone, shaped);
@ -302,9 +303,10 @@ int Syncer::applyCollectionDumpMarker (TRI_transaction_collection_t* trxCollecti
// {"type":2402,"key":"592063"} // {"type":2402,"key":"592063"}
int res = TRI_ERROR_INTERNAL; int res = TRI_ERROR_INTERNAL;
bool const isLocked = TRI_IsLockedCollectionTransaction(trxCollection);
try { try {
res = TRI_RemoveShapedJsonDocumentCollection(trxCollection, key, rid, nullptr, &_policy, ! trxCollection->_locked, false); res = TRI_RemoveShapedJsonDocumentCollection(trxCollection, key, rid, nullptr, &_policy, ! isLocked, false);
if (res != TRI_ERROR_NO_ERROR && res == TRI_ERROR_ARANGO_DOCUMENT_NOT_FOUND) { if (res != TRI_ERROR_NO_ERROR && res == TRI_ERROR_ARANGO_DOCUMENT_NOT_FOUND) {
// ignore this error // ignore this error

View File

@ -61,10 +61,18 @@
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief whether or not a transaction consists of a single operation /// @brief returns whether the collection is currently locked
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
static triagens::wal::LogfileManager* GetLogfileManager () { static inline bool IsLocked (TRI_transaction_collection_t const* trxCollection) {
return (trxCollection->_lockType != TRI_TRANSACTION_NONE);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return the logfile manager
////////////////////////////////////////////////////////////////////////////////
static inline triagens::wal::LogfileManager* GetLogfileManager () {
return triagens::wal::LogfileManager::instance(); return triagens::wal::LogfileManager::instance();
} }
@ -268,7 +276,7 @@ static TRI_transaction_collection_t* CreateCollection (TRI_transaction_t* trx,
trxCollection->_barrier = nullptr; trxCollection->_barrier = nullptr;
trxCollection->_operations = nullptr; trxCollection->_operations = nullptr;
trxCollection->_originalRevision = 0; trxCollection->_originalRevision = 0;
trxCollection->_locked = false; trxCollection->_lockType = TRI_TRANSACTION_NONE;
trxCollection->_compactionLocked = false; trxCollection->_compactionLocked = false;
trxCollection->_waitForSync = false; trxCollection->_waitForSync = false;
@ -325,7 +333,7 @@ static int LockCollection (TRI_transaction_collection_t* trxCollection,
TRI_ASSERT(trxCollection->_collection != nullptr); TRI_ASSERT(trxCollection->_collection != nullptr);
TRI_ASSERT(trxCollection->_collection->_collection != nullptr); TRI_ASSERT(trxCollection->_collection->_collection != nullptr);
TRI_ASSERT(trxCollection->_locked == false); TRI_ASSERT(! IsLocked(trxCollection));
TRI_document_collection_t* document = trxCollection->_collection->_collection; TRI_document_collection_t* document = trxCollection->_collection->_collection;
@ -355,7 +363,7 @@ static int LockCollection (TRI_transaction_collection_t* trxCollection,
} }
if (res == TRI_ERROR_NO_ERROR) { if (res == TRI_ERROR_NO_ERROR) {
trxCollection->_locked = true; trxCollection->_lockType = type;
} }
return res; return res;
@ -378,7 +386,7 @@ static int UnlockCollection (TRI_transaction_collection_t* trxCollection,
TRI_ASSERT(trxCollection->_collection != nullptr); TRI_ASSERT(trxCollection->_collection != nullptr);
TRI_ASSERT(trxCollection->_collection->_collection != nullptr); TRI_ASSERT(trxCollection->_collection->_collection != nullptr);
TRI_ASSERT(trxCollection->_locked == true); TRI_ASSERT(IsLocked(trxCollection));
TRI_document_collection_t* document = trxCollection->_collection->_collection; TRI_document_collection_t* document = trxCollection->_collection->_collection;
@ -387,7 +395,20 @@ static int UnlockCollection (TRI_transaction_collection_t* trxCollection,
return TRI_ERROR_NO_ERROR; return TRI_ERROR_NO_ERROR;
} }
if (type == TRI_TRANSACTION_READ) { if (type == TRI_TRANSACTION_READ &&
trxCollection->_lockType == TRI_TRANSACTION_WRITE) {
// do not remove a write-lock if a read-unlock was requested!
return TRI_ERROR_NO_ERROR;
}
else if (type == TRI_TRANSACTION_WRITE &&
trxCollection->_lockType == TRI_TRANSACTION_READ) {
// we should never try to write-unlock a collection that we have only read-locked
LOG_ERROR("logic error in UnlockCollection");
TRI_ASSERT(false);
return TRI_ERROR_INTERNAL;
}
if (trxCollection->_lockType == TRI_TRANSACTION_READ) {
LOG_TRX(trxCollection->_transaction, LOG_TRX(trxCollection->_transaction,
nestingLevel, nestingLevel,
"read-unlocking collection %llu", "read-unlocking collection %llu",
@ -402,7 +423,7 @@ static int UnlockCollection (TRI_transaction_collection_t* trxCollection,
document->endWrite(document); document->endWrite(document);
} }
trxCollection->_locked = false; trxCollection->_lockType = TRI_TRANSACTION_NONE;
return TRI_ERROR_NO_ERROR; return TRI_ERROR_NO_ERROR;
} }
@ -475,7 +496,7 @@ static int UseCollections (TRI_transaction_t* trx,
shouldLock = (trxCollection->_accessType == TRI_TRANSACTION_WRITE) && (! IsSingleOperationTransaction(trx)); shouldLock = (trxCollection->_accessType == TRI_TRANSACTION_WRITE) && (! IsSingleOperationTransaction(trx));
} }
if (shouldLock && ! trxCollection->_locked) { if (shouldLock && ! IsLocked(trxCollection)) {
// r/w lock the collection // r/w lock the collection
int res = LockCollection(trxCollection, trxCollection->_accessType, nestingLevel); int res = LockCollection(trxCollection, trxCollection->_accessType, nestingLevel);
@ -502,7 +523,7 @@ static int UnuseCollections (TRI_transaction_t* trx,
while (i-- > 0) { while (i-- > 0) {
TRI_transaction_collection_t* trxCollection = static_cast<TRI_transaction_collection_t*>(TRI_AtVectorPointer(&trx->_collections, i)); TRI_transaction_collection_t* trxCollection = static_cast<TRI_transaction_collection_t*>(TRI_AtVectorPointer(&trx->_collections, i));
if (trxCollection->_locked && if (IsLocked(trxCollection) &&
(nestingLevel == 0 || trxCollection->_nestingLevel == nestingLevel)) { (nestingLevel == 0 || trxCollection->_nestingLevel == nestingLevel)) {
// unlock our own r/w locks // unlock our own r/w locks
UnlockCollection(trxCollection, trxCollection->_accessType, nestingLevel); UnlockCollection(trxCollection, trxCollection->_accessType, nestingLevel);
@ -518,7 +539,7 @@ static int UnuseCollections (TRI_transaction_t* trx,
trxCollection->_compactionLocked = false; trxCollection->_compactionLocked = false;
} }
trxCollection->_locked = false; trxCollection->_lockType = TRI_TRANSACTION_NONE;
} }
} }
@ -939,7 +960,7 @@ int TRI_LockCollectionTransaction (TRI_transaction_collection_t* trxCollection,
return TRI_ERROR_INTERNAL; return TRI_ERROR_INTERNAL;
} }
if (trxCollection->_locked) { if (IsLocked(trxCollection)) {
// already locked // already locked
return TRI_ERROR_NO_ERROR; return TRI_ERROR_NO_ERROR;
} }
@ -955,12 +976,13 @@ int TRI_UnlockCollectionTransaction (TRI_transaction_collection_t* trxCollection
TRI_transaction_type_e accessType, TRI_transaction_type_e accessType,
int nestingLevel) { int nestingLevel) {
if (accessType == TRI_TRANSACTION_WRITE && trxCollection->_accessType != TRI_TRANSACTION_WRITE) { if (accessType == TRI_TRANSACTION_WRITE &&
// wrong lock type trxCollection->_accessType != TRI_TRANSACTION_WRITE) {
// wrong lock type: write-unlock requested but collection is read-only
return TRI_ERROR_INTERNAL; return TRI_ERROR_INTERNAL;
} }
if (! trxCollection->_locked) { if (! IsLocked(trxCollection)) {
// already unlocked // already unlocked
return TRI_ERROR_NO_ERROR; return TRI_ERROR_NO_ERROR;
} }
@ -972,7 +994,7 @@ int TRI_UnlockCollectionTransaction (TRI_transaction_collection_t* trxCollection
/// @brief check if a collection is locked in a transaction /// @brief check if a collection is locked in a transaction
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool TRI_IsLockedCollectionTransaction (TRI_transaction_collection_t* trxCollection, bool TRI_IsLockedCollectionTransaction (TRI_transaction_collection_t const* trxCollection,
TRI_transaction_type_e accessType, TRI_transaction_type_e accessType,
int nestingLevel) { int nestingLevel) {
@ -983,7 +1005,15 @@ bool TRI_IsLockedCollectionTransaction (TRI_transaction_collection_t* trxCollect
return false; return false;
} }
return trxCollection->_locked; return IsLocked(trxCollection);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief check if a collection is locked in a transaction
////////////////////////////////////////////////////////////////////////////////
bool TRI_IsLockedCollectionTransaction (TRI_transaction_collection_t const* trxCollection) {
return IsLocked(trxCollection);
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -1171,7 +1201,7 @@ int TRI_AddOperationTransaction (triagens::wal::DocumentOperation& operation,
int TRI_BeginTransaction (TRI_transaction_t* trx, int TRI_BeginTransaction (TRI_transaction_t* trx,
TRI_transaction_hint_t hints, TRI_transaction_hint_t hints,
int nestingLevel) { int nestingLevel) {
LOG_TRX(trx, nestingLevel, "%s transaction", "beginning"); LOG_TRX(trx, nestingLevel, "%s %s transaction", "beginning", (trx->_type == TRI_TRANSACTION_READ ? "read" : "write"));
if (nestingLevel == 0) { if (nestingLevel == 0) {
TRI_ASSERT(trx->_status == TRI_TRANSACTION_CREATED); TRI_ASSERT(trx->_status == TRI_TRANSACTION_CREATED);
@ -1237,7 +1267,7 @@ int TRI_BeginTransaction (TRI_transaction_t* trx,
int TRI_CommitTransaction (TRI_transaction_t* trx, int TRI_CommitTransaction (TRI_transaction_t* trx,
int nestingLevel) { int nestingLevel) {
LOG_TRX(trx, nestingLevel, "%s transaction", "committing"); LOG_TRX(trx, nestingLevel, "%s %s transaction", "committing", (trx->_type == TRI_TRANSACTION_READ ? "read" : "write"));
TRI_ASSERT(trx->_status == TRI_TRANSACTION_RUNNING); TRI_ASSERT(trx->_status == TRI_TRANSACTION_RUNNING);
@ -1269,7 +1299,7 @@ int TRI_CommitTransaction (TRI_transaction_t* trx,
int TRI_AbortTransaction (TRI_transaction_t* trx, int TRI_AbortTransaction (TRI_transaction_t* trx,
int nestingLevel) { int nestingLevel) {
LOG_TRX(trx, nestingLevel, "%s transaction", "aborting"); LOG_TRX(trx, nestingLevel, "%s %s transaction", "aborting", (trx->_type == TRI_TRANSACTION_READ ? "read" : "write"));
TRI_ASSERT(trx->_status == TRI_TRANSACTION_RUNNING); TRI_ASSERT(trx->_status == TRI_TRANSACTION_RUNNING);

View File

@ -89,6 +89,7 @@ struct TRI_vocbase_col_s;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
typedef enum { typedef enum {
TRI_TRANSACTION_NONE = 0,
TRI_TRANSACTION_READ = 1, TRI_TRANSACTION_READ = 1,
TRI_TRANSACTION_WRITE = 2 TRI_TRANSACTION_WRITE = 2
} }
@ -168,7 +169,7 @@ typedef struct TRI_transaction_collection_s {
struct TRI_barrier_s* _barrier; struct TRI_barrier_s* _barrier;
std::vector<triagens::wal::DocumentOperation*>* _operations; std::vector<triagens::wal::DocumentOperation*>* _operations;
TRI_voc_rid_t _originalRevision; // collection revision at trx start TRI_voc_rid_t _originalRevision; // collection revision at trx start
bool _locked; // collection lock flag TRI_transaction_type_e _lockType; // collection lock type
bool _compactionLocked; // was the compaction lock grabbed for the collection? bool _compactionLocked; // was the compaction lock grabbed for the collection?
bool _waitForSync; // whether or not the collection has waitForSync bool _waitForSync; // whether or not the collection has waitForSync
} }
@ -197,6 +198,28 @@ void TRI_FreeTransaction (TRI_transaction_t*);
// --SECTION-- public functions // --SECTION-- public functions
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief return the type of the transaction as a string
////////////////////////////////////////////////////////////////////////////////
inline char const* TRI_TransactionTypeGetStr (TRI_transaction_type_e t) {
switch (t) {
case TRI_TRANSACTION_READ:
return "read";
case TRI_TRANSACTION_WRITE:
return "write";
case TRI_TRANSACTION_NONE: {
}
}
return "";
}
////////////////////////////////////////////////////////////////////////////////
/// @brief get the transaction type from a string
////////////////////////////////////////////////////////////////////////////////
TRI_transaction_type_e TRI_GetTransactionTypeFromStr (char const*);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief get the transaction id for usage in a marker /// @brief get the transaction id for usage in a marker
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -209,13 +232,6 @@ static inline TRI_voc_tid_t TRI_MarkerIdTransaction (TRI_transaction_t const* tr
return trx->_id; return trx->_id;
} }
////////////////////////////////////////////////////////////////////////////////
/// @brief increase the number of writes done for a collection
////////////////////////////////////////////////////////////////////////////////
void TRI_IncreaseWritesCollectionTransaction (TRI_transaction_collection_t*,
bool);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief return the collection from a transaction /// @brief return the collection from a transaction
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -267,10 +283,16 @@ int TRI_UnlockCollectionTransaction (TRI_transaction_collection_t*,
/// @brief check whether a collection is locked in a transaction /// @brief check whether a collection is locked in a transaction
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool TRI_IsLockedCollectionTransaction (TRI_transaction_collection_t*, bool TRI_IsLockedCollectionTransaction (TRI_transaction_collection_t const*,
TRI_transaction_type_e, TRI_transaction_type_e,
int); int);
////////////////////////////////////////////////////////////////////////////////
/// @brief check whether a collection is locked in a transaction
////////////////////////////////////////////////////////////////////////////////
bool TRI_IsLockedCollectionTransaction (TRI_transaction_collection_t const*);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief begin a transaction /// @brief begin a transaction
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////