/// <summary> /// Acquires a lock in the context of this store transaction. /// </summary> /// <param name="lockManager">Lock manager that issues the lock.</param> /// <param name="lockResourceNameHash">Lock resource name hash.</param> /// <param name="lockMode">Lock mode requested.</param> /// <param name="lockTimeout">Lock timeout.</param> /// <exception cref="TransactionFaultedException" /> /// <exception cref="InvalidOperationException">Thrown by the replicator (ReplicatorTransactionBase.AddLockContext)</exception> /// <exception cref="TimeoutException" /> /// <returns></returns> public async Task <ILock> LockAsync(LockManager lockManager, ulong lockResourceNameHash, LockMode lockMode, int lockTimeout) { // Check arguments. if (LockMode.Free == lockMode) { throw new ArgumentException(SR.Error_LockMode); } if (0 > lockTimeout && Timeout.Infinite != lockTimeout) { throw new ArgumentException(SR.Error_LockTimeout); } if (this.isReadOnly) { if (!lockManager.IsShared(lockMode)) { throw new ArgumentException(SR.Error_LockMode); } } if (this.enableStrict2PL == true && lockMode == LockMode.Shared) { this.ReplicatorTransactionBase.AddLockContext(this, LockContextMode.Read); } // Call the lock manager to get the lock. var acquiredLock = await lockManager.AcquireLockAsync(this.id, lockResourceNameHash, lockMode, lockTimeout).ConfigureAwait(false); Diagnostics.Assert(null != acquiredLock, this.tracer, "incorrect lock"); // Check is error has occured. if (LockStatus.Invalid == acquiredLock.Status) { throw new TransactionFaultedException(string.Format(CultureInfo.CurrentCulture, SR.Error_ReplicatorTransactionInternallyAborted, this.Id)); } if (LockStatus.Timeout == acquiredLock.Status) { throw new TimeoutException( string.Format( CultureInfo.CurrentCulture, SR.LockTimeout_TStore_KeyLock, lockMode, this.tracer, lockTimeout, this.id, lockResourceNameHash)); } Diagnostics.Assert(LockStatus.Granted == acquiredLock.Status, this.tracer, "incorrect lock status"); Diagnostics.Assert(lockMode == acquiredLock.Mode, this.tracer, "incorrect lock mode"); Diagnostics.Assert(this.id == acquiredLock.Owner, this.tracer, "incorrect lock owner"); Diagnostics.Assert(0 < acquiredLock.Count, this.tracer, "incorrect lock count"); Diagnostics.Assert(null != acquiredLock.LockManager, this.tracer, "incorrect lock manager"); var releaseLastLockAcquired = false; lock (this) { // It's possible that the store transaction has been terminated before this last lock was acquired. releaseLastLockAcquired = (this.isClosed == true); // Add the acquired lock only once to the lock list. if (acquiredLock.Count == 1 && !releaseLastLockAcquired) { this.lockRequests.Add(acquiredLock); } } if (releaseLastLockAcquired) { lockManager.ReleaseLock(acquiredLock); throw new TransactionFaultedException(string.Format(CultureInfo.CurrentCulture, SR.Error_ReplicatorTransactionInternallyAborted, this.Id)); } return(acquiredLock); }