예제 #1
0
        /// <summary>
        /// Initializes a store transaction.
        /// </summary>
        /// <param name="lockManager">Lock manager that issues the lock.</param>
        /// <param name="lockMode">Lock mode requested.</param>
        /// <param name="lockTimeout">Lock timeout.</param>
        /// <param name="reacquirePrimeLock">Unconditionally acquire the prime lock, even if it's already been acquired by this store transaction.</param>
        /// <returns>Amount of time left after the lock was taken.</returns>
        public async Task <int> AcquirePrimeLocksAsync(LockManager lockManager, LockMode lockMode, int lockTimeout, bool reacquirePrimeLock)
        {
            Diagnostics.Assert(lockMode == LockMode.Shared || lockMode == LockMode.Exclusive, this.tracer, "unexpected lock mode");

            if (reacquirePrimeLock)
            {
                this.isPrimeLockAcquired = false;
            }

            if (this.isPrimeLockAcquired)
            {
                lock (this)
                {
                    // Lock must have been released already so there is no need to release anything here.
                    if (this.isClosed == true)
                    {
                        throw new TransactionFaultedException(string.Format(CultureInfo.CurrentCulture, SR.Error_ReplicatorTransactionInternallyAborted, this.Id));
                    }
                }

                // Initialization was already performed.
                return(lockTimeout);
            }

            var timeoutLeftOver = lockTimeout;
            var start           = DateTime.UtcNow;

            FabricEvents.Events.PrimeLocksAsync(this.tracer, (byte)lockMode, this.id, lockTimeout);

            await lockManager.AcquirePrimeLockAsync(lockMode, lockTimeout, CancellationToken.None).ConfigureAwait(false);

            var releaseAcquiredPrimeLock = false;

            lock (this)
            {
                if (this.isClosed == true)
                {
                    releaseAcquiredPrimeLock = true;
                }
                else
                {
                    this.primeLockRequests.Add(new PrimeLockRequest(lockManager, lockMode));
                }
            }

            if (releaseAcquiredPrimeLock)
            {
                lockManager.ReleasePrimeLock(lockMode);

                throw new TransactionFaultedException(string.Format(CultureInfo.CurrentCulture, SR.Error_ReplicatorTransactionInternallyAborted, this.Id));
            }

            // Reset initializer.
            this.isPrimeLockAcquired = true;

            // Compute left-over timeout, if needed.
            if (Timeout.Infinite != lockTimeout && 0 != lockTimeout)
            {
                var end      = DateTime.UtcNow;
                var duration = end.Subtract(start);

                if (duration.TotalMilliseconds <= 0)
                {
                    timeoutLeftOver = lockTimeout;
                }
                else if (lockTimeout < duration.TotalMilliseconds)
                {
                    // Inform the caller that locks could not be acquired in the given timeout.
                    timeoutLeftOver = 0;
                }
                else
                {
                    // Next use left-over timeout.
                    timeoutLeftOver = lockTimeout - (int)duration.TotalMilliseconds;
                }
            }

            // Initialization is now done.
            return(timeoutLeftOver);
        }