/// <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); }