1
0
Fork 0

added explicit locking

This commit is contained in:
Jan Steemann 2013-02-04 15:35:26 +01:00
parent 8a6225865f
commit 44f2d05b4c
5 changed files with 136 additions and 49 deletions

View File

@ -66,7 +66,7 @@ namespace triagens {
TRI_aql_context_t* const context) :
Transaction<T>(vocbase, resolver) {
this->addHint(TRI_TRANSACTION_HINT_MANAGE_LOCKS);
this->addHint(TRI_TRANSACTION_HINT_IMPLICIT_LOCK);
TRI_vector_pointer_t* collections = &context->_collections;

View File

@ -349,10 +349,7 @@ namespace triagens {
return TRI_ERROR_INTERNAL;
}
if ((this->status() == TRI_TRANSACTION_RUNNING && ! this->isEmbedded()) ||
this->status() == TRI_TRANSACTION_COMMITTED ||
this->status() == TRI_TRANSACTION_ABORTED ||
this->status() == TRI_TRANSACTION_FINISHED) {
if (this->status() != TRI_TRANSACTION_RUNNING) {
return TRI_ERROR_TRANSACTION_INVALID_STATE;
}
@ -361,14 +358,7 @@ namespace triagens {
return TRI_ERROR_NO_ERROR;
}
if (type == TRI_TRANSACTION_READ) {
primary->beginRead(primary);
}
else {
primary->beginWrite(primary);
}
return TRI_ERROR_NO_ERROR;
return TRI_LockCollectionTransaction(this->_trx, (TRI_transaction_cid_t) primary->base._info._cid, type);
}
////////////////////////////////////////////////////////////////////////////////
@ -381,10 +371,7 @@ namespace triagens {
return TRI_ERROR_INTERNAL;
}
if ((this->status() == TRI_TRANSACTION_RUNNING && ! this->isEmbedded()) ||
this->status() == TRI_TRANSACTION_COMMITTED ||
this->status() == TRI_TRANSACTION_ABORTED ||
this->status() == TRI_TRANSACTION_FINISHED) {
if (this->status() != TRI_TRANSACTION_RUNNING) {
return TRI_ERROR_TRANSACTION_INVALID_STATE;
}
@ -392,15 +379,8 @@ namespace triagens {
// locking is a no-op in embedded transactions
return TRI_ERROR_NO_ERROR;
}
if (type == TRI_TRANSACTION_READ) {
primary->endRead(primary);
}
else {
primary->endWrite(primary);
}
return TRI_ERROR_NO_ERROR;
return TRI_UnlockCollectionTransaction(this->_trx, (TRI_transaction_cid_t) primary->base._info._cid, type);
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -65,7 +65,7 @@ namespace triagens {
const vector<string>& writeCollections) :
Transaction<T>(vocbase, resolver) {
this->addHint(TRI_TRANSACTION_HINT_MANAGE_LOCKS);
this->addHint(TRI_TRANSACTION_HINT_IMPLICIT_LOCK);
for (size_t i = 0; i < readCollections.size(); ++i) {
this->addCollection(readCollections[i], TRI_TRANSACTION_READ);

View File

@ -533,6 +533,60 @@ static void FreeCollection (TRI_transaction_collection_t* collection) {
TRI_Free(TRI_UNKNOWN_MEM_ZONE, collection);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief lock a collection
////////////////////////////////////////////////////////////////////////////////
static int LockCollection (TRI_transaction_collection_t* collection,
const TRI_transaction_type_e type) {
TRI_primary_collection_t* primary;
assert(collection != NULL);
assert(collection->_collection != NULL);
assert(collection->_collection->_collection != NULL);
assert(collection->_locked == false);
primary = collection->_collection->_collection;
if (type == TRI_TRANSACTION_READ) {
primary->beginRead(primary);
}
else {
primary->beginWrite(primary);
}
collection->_locked = true;
return TRI_ERROR_NO_ERROR;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief unlock a collection
////////////////////////////////////////////////////////////////////////////////
static int UnlockCollection (TRI_transaction_collection_t* collection,
const TRI_transaction_type_e type) {
TRI_primary_collection_t* primary;
assert(collection != NULL);
assert(collection->_collection != NULL);
assert(collection->_collection->_collection != NULL);
assert(collection->_locked == true);
primary = collection->_collection->_collection;
if (type == TRI_TRANSACTION_READ) {
primary->endRead(primary);
}
else {
primary->endWrite(primary);
}
collection->_locked = false;
return TRI_ERROR_NO_ERROR;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return a global instance for the collection
/// this function will create a global instance if it does not yet exist
@ -599,17 +653,12 @@ static int UseCollections (TRI_transaction_t* const trx) {
collection->_globalLock = true;
}
if ((trx->_hints & (TRI_transaction_hint_t) TRI_TRANSACTION_HINT_MANAGE_LOCKS) != 0) {
TRI_primary_collection_t* primary = (TRI_primary_collection_t*) collection->_collection->_collection;
if ((trx->_hints & (TRI_transaction_hint_t) TRI_TRANSACTION_HINT_IMPLICIT_LOCK) != 0) {
int res = LockCollection(collection, collection->_type);
if (collection->_type == TRI_TRANSACTION_WRITE) {
primary->beginWrite(primary);
if (res != TRI_ERROR_NO_ERROR) {
return res;
}
else if (collection->_type == TRI_TRANSACTION_READ) {
primary->beginRead(primary);
}
collection->_locked = true;
}
}
@ -639,18 +688,8 @@ static int ReleaseCollections (TRI_transaction_t* const trx) {
continue;
}
if (collection->_locked &&
(trx->_hints & (TRI_transaction_hint_t) TRI_TRANSACTION_HINT_MANAGE_LOCKS) != 0) {
TRI_primary_collection_t* primary = (TRI_primary_collection_t*) collection->_collection->_collection;
if (collection->_type == TRI_TRANSACTION_WRITE) {
primary->endWrite(primary);
}
else if (collection->_type == TRI_TRANSACTION_READ) {
primary->endRead(primary);
}
collection->_locked = false;
if (collection->_locked) {
UnlockCollection(collection, collection->_type);
}
if (collection->_type == TRI_TRANSACTION_WRITE && collection->_globalLock) {
@ -971,6 +1010,58 @@ void TRI_FreeTransaction (TRI_transaction_t* const trx) {
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief request a lock for a collection
////////////////////////////////////////////////////////////////////////////////
int TRI_LockCollectionTransaction (TRI_transaction_t* const trx,
const TRI_transaction_cid_t cid,
const TRI_transaction_type_e type) {
size_t i, n;
n = trx->_collections._length;
for (i = 0; i < n; ++i) {
TRI_transaction_collection_t* collection = TRI_AtVectorPointer(&trx->_collections, i);
if (collection->_collection == NULL) {
continue;
}
if (collection->_cid == cid) {
return LockCollection(collection, type);
}
}
return TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief request an unlock for a collection
////////////////////////////////////////////////////////////////////////////////
int TRI_UnlockCollectionTransaction (TRI_transaction_t* const trx,
const TRI_transaction_cid_t cid,
const TRI_transaction_type_e type) {
size_t i, n;
n = trx->_collections._length;
for (i = 0; i < n; ++i) {
TRI_transaction_collection_t* collection = TRI_AtVectorPointer(&trx->_collections, i);
if (collection->_collection == NULL) {
continue;
}
if (collection->_cid == cid) {
return UnlockCollection(collection, type);
}
}
return TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return whether the transaction consists only of a single operation
////////////////////////////////////////////////////////////////////////////////

View File

@ -303,7 +303,7 @@ typedef uint32_t TRI_transaction_hint_t;
typedef enum {
TRI_TRANSACTION_HINT_NONE = 0,
TRI_TRANSACTION_HINT_SINGLE_OPERATION = 1,
TRI_TRANSACTION_HINT_MANAGE_LOCKS = 2
TRI_TRANSACTION_HINT_IMPLICIT_LOCK = 2
}
TRI_transaction_hint_e;
@ -401,6 +401,22 @@ int TRI_AddCollectionTransaction (TRI_transaction_t* const,
const TRI_transaction_cid_t,
const TRI_transaction_type_e);
////////////////////////////////////////////////////////////////////////////////
/// @brief request a lock for a collection
////////////////////////////////////////////////////////////////////////////////
int TRI_LockCollectionTransaction (TRI_transaction_t* const,
const TRI_transaction_cid_t,
const TRI_transaction_type_e);
////////////////////////////////////////////////////////////////////////////////
/// @brief request an unlock for a collection
////////////////////////////////////////////////////////////////////////////////
int TRI_UnlockCollectionTransaction (TRI_transaction_t* const,
const TRI_transaction_cid_t,
const TRI_transaction_type_e);
////////////////////////////////////////////////////////////////////////////////
/// @brief start a transaction
////////////////////////////////////////////////////////////////////////////////