private ConnectionLock DetermineHigherLock(ConnectionLock exstLock, ConnectionLock newLock) { ConnectionLock txnLock = newLock; // is existing lock restricting access? if (newLock.IsRestrictedBy(exstLock)) { // does restricting lock belong to this connection? // if yes and it is a higher-level lock, use that if (exstLock.BelongsTo(this) && exstLock.LockType <= newLock.LockType) { logger.Debug("Existing lock {0} is higher than new {1}", exstLock, newLock); txnLock = exstLock; } // does the lock not belong to this connection in which case reject // or is trying to acquire a higher level lock that active lock else { logger.Debug("New lock {0} is restricted by {1}", newLock, exstLock); throw new AccessRestrictedException(newLock, exstLock); } } // if not restricting, does this connection already have a txn block lock of equal level // reject again since the connection need to close its block lock first and then // work on another entry else { if (exstLock.BelongsTo(this)) { logger.Debug("New lock {0} not on the same path as existing {1}", newLock, exstLock); throw new AccessRestrictedByExistingLockException(newLock, exstLock); } } return(txnLock); }
private void AcquireLocks(ConnectionLock newLock) { logger.Debug("RECORD LOCK"); // open datastore for exclusive access using (var dstore = new DataStore(ActiveDataStoreType, exclusive: true)) { // get all existing locks // check access, find the highest-level compatible lock ConnectionLock txnLock = newLock; foreach (ConnectionLock activeLock in ReadActiveLocks(dstore)) { logger.Debug("Lock Found: {0}", activeLock); // is existing lock restricting access? if (newLock.IsRestrictedBy(activeLock)) { // does restricting lock belong to this connection? // if yes and it is a higher-level lock, use that if (activeLock.BelongsTo(this) && activeLock.LockType <= newLock.LockType) { logger.Debug("Existing lock {0} is higher than new {1}", activeLock, newLock); txnLock = activeLock; } // does the lock not belong to this connection in which case reject // or is trying to acquire a higher level lock that active lock else { logger.Debug("New lock {0} is restricted by {1}", newLock, activeLock); throw new AccessRestrictedException(newLock, activeLock); } } // if not restricting, does this connection already have a txn block lock of equal level // reject again since the connection need to close its block lock first and then // work on another entry else { if (activeLock.BelongsTo(this)) { logger.Debug("New lock {0} not on the same path as existing {1}", newLock, activeLock); throw new AccessRestrictedByExistingLockException(newLock, activeLock); } } } logger.Debug("Using lock: {0}", txnLock); // at this point, the are no locks that restrict access // but we might be re-using an active compatible lock // so only write the lock if is not existing compatible if (txnLock == newLock) { try { // register the new lock: if target is not locked, lock it DataFunctions.InsertRecord( dstore, connDbName, connDbLocksTableName, newLock.LockId, new Dictionary <string, object>() { { connDbLockSourceField, newLock.LockSource }, { connDbLockRequesterField, newLock.LockRequester }, { connDbLockConnUUIDField, newLock.LockConnId }, { connDbLockDBField, newLock.LockTargetDB }, { connDbLockTableField, newLock.LockTargetTable }, { connDbLockRecordKeyField, newLock.LockTargetRecordKey }, }); } catch (Exception lockEx) { // finally statement closes the dstore and release the exclusivity if throwing an exception throw new Exception( string.Format("Error creating lock: {0} | {1}", newLock, lockEx.Message) ); } finally { try { // write changes dstore.Commit(); } catch (Exception commitEx) { // finally statement closes the dstore and release the exclusivity if throwing an exception throw new Exception( string.Format("Exception occured when commiting new locks. | {0}", commitEx.Message) ); } } } } }