public IDisposable TryAcquire <TLockCookie>(
            string connectionString,
            string lockName,
            int timeoutMillis,
            ISqlSynchronizationStrategy <TLockCookie> strategy)
            where TLockCookie : class
        {
            // opportunistic phase: see if we can use a connection that is already holding a lock
            // to acquire the current lock
            var existingLock = this.GetExistingLockOrDefault(connectionString);

            if (existingLock != null)
            {
                try
                {
                    var opportunisticResult = existingLock.TryAcquire(lockName, timeoutMillis, strategy, opportunistic: true);
                    if (opportunisticResult.Handle != null)
                    {
                        return(opportunisticResult.Handle);
                    }

                    switch (opportunisticResult.Retry)
                    {
                    case MultiplexedConnectionLockRetry.NoRetry:
                        return(null);

                    case MultiplexedConnectionLockRetry.RetryOnThisLock:
                        var result = existingLock.TryAcquire(lockName, timeoutMillis, strategy, opportunistic: false);
                        return(result.Handle);

                    case MultiplexedConnectionLockRetry.Retry:
                        break;

                    default:
                        throw new InvalidOperationException("unexpected retry");
                    }
                }
                finally
                {
                    // since we took this lock from the pool, always return it to the pool
                    this.AddLockToPool(connectionString, existingLock);
                }
            }

            // normal phase: if we were not able to be opportunistic, ensure that we have a lock
            var         @lock  = new MultiplexedConnectionLock(connectionString);
            IDisposable handle = null;

            try
            {
                handle = @lock.TryAcquire(lockName, timeoutMillis, strategy, opportunistic: false).Handle;
            }
            finally
            {
                // only store the lock on success; otherwise there's no reason to keep it around
                if (handle != null)
                {
                    this.AddLockToPool(connectionString, @lock);
                }
                else
                {
                    @lock.Dispose();
                }
            }
            return(handle);
        }
Ejemplo n.º 2
0
        public async Task <IDisposable> TryAcquireAsync(
            string connectionString,
            string lockName,
            int timeoutMillis,
            SqlApplicationLock.Mode mode,
            CancellationToken cancellationToken)
        {
            // opportunistic phase: see if we can use a connection that is already holding a lock
            // to acquire the current lock
            var existingLock = this.GetExistingLockOrDefault(connectionString);

            if (existingLock != null)
            {
                try
                {
                    var opportunisticResult = await existingLock.TryAcquireAsync(lockName, timeoutMillis, mode, cancellationToken, opportunistic : true).ConfigureAwait(false);

                    if (opportunisticResult.Handle != null)
                    {
                        return(opportunisticResult.Handle);
                    }

                    switch (opportunisticResult.Retry)
                    {
                    case MultiplexedConnectionLockRetry.NoRetry:
                        return(null);

                    case MultiplexedConnectionLockRetry.RetryOnThisLock:
                        var result = await existingLock.TryAcquireAsync(lockName, timeoutMillis, mode, cancellationToken, opportunistic : false).ConfigureAwait(false);

                        return(result.Handle);

                    case MultiplexedConnectionLockRetry.Retry:
                        break;

                    default:
                        throw new InvalidOperationException("unexpected retry");
                    }
                }
                finally
                {
                    // since we took this lock from the pool, always return it to the pool
                    this.AddLockToPool(connectionString, existingLock);
                }
            }

            // normal phase: if we were not able to be opportunistic, ensure that we have a lock
            var         @lock  = new MultiplexedConnectionLock(connectionString);
            IDisposable handle = null;

            try
            {
                handle = (await @lock.TryAcquireAsync(lockName, timeoutMillis, mode, cancellationToken, opportunistic: false).ConfigureAwait(false)).Handle;
            }
            finally
            {
                // only store the lock on success; otherwise there's no reason to keep it around
                if (handle != null)
                {
                    this.AddLockToPool(connectionString, @lock);
                }
                else
                {
                    @lock.Dispose();
                }
            }
            return(handle);
        }