Example #1
0
        /// <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);
        }