コード例 #1
0
        private async Task <LockInfo> WaitForLockImpl(Guid resource, TimeSpan?lockTimeout, CancellationToken cancellationToken)
        {
            LockInfo acquiredLock = LockInfo.Empty(resource);

            while (!cancellationToken.IsCancellationRequested)
            {
                acquiredLock = await TryLockAsync(resource, lockTimeout);

                if (acquiredLock.AsImmutable().HasLock())
                {
                    break;
                }

                try
                {
                    await Task.Delay(1000, cancellationToken);
                }
                catch (OperationCanceledException ex)
                {
                    break;
                }
            }

            return(acquiredLock);
        }
コード例 #2
0
        private async Task <bool> releaseAsync(IDbConnectionAsync conn, LockInfo lockInfo)
        {
            var state = lockInfo.AsImmutable();

            if (!state.HasLock())
            {
                return(true); //released already
            }
            var newLockRef = Math.Max(1, state.LockReference + 1);

            using (var command = await DbAccessHelperAsync.CreateDbCommand(conn, RELEASE_LOCK))
            {
                command.Parameters.Add(new SqlParameter("newLockRef", newLockRef));
                command.Parameters.Add(new SqlParameter("resource", state.Resource));
                command.Parameters.Add(new SqlParameter("lockReference", state.LockReference));
                command.Parameters.Add(new SqlParameter("lockedByPID", _PID));

                try
                {
                    await command.ExecuteNonQueryAsync();

                    lockInfo.Update(null, TimeSpan.Zero, 0, FrozenTimeClock.Instance);

                    return(true);
                }
                catch (Exception ex)
                {
                    return(false);
                }
            }
        }
コード例 #3
0
        private async Task <bool> renewLockAsync(IDbConnectionAsync conn, TimeSpan renewTimeout, LockInfo lockInfo)
        {
            var state = lockInfo.AsImmutable();

            if (!state.HasLock())
            {
                return(false);
            }

            var newLockRef = Math.Max(1, state.LockReference + 1);

            using (var command = await DbAccessHelperAsync.CreateDbCommand(conn, RENEW_LOCK_COMMANDS))
            {
                command.Parameters.Add(new SqlParameter("newLockRef", newLockRef));
                command.Parameters.Add(new SqlParameter("resource", state.Resource));
                command.Parameters.Add(new SqlParameter("lockReference", state.LockReference));
                command.Parameters.Add(new SqlParameter("timeout", Convert.ToInt64(renewTimeout.TotalMilliseconds)));
                command.Parameters.Add(new SqlParameter("lockedByPID", _PID));

                try
                {
                    var dbLockedTill = (DateTime?)await command.ExecuteScalarAsync();

                    if (dbLockedTill != null)
                    {
                        var clock = _clockProvider.GetClock();

                        lockInfo.Update(dbLockedTill, renewTimeout, newLockRef, clock);
                        return(lockInfo.AsImmutable().HasLock());
                    }

                    return(false);
                }
                catch (Exception ex)
                {
                    return(false);
                }
            }
        }
コード例 #4
0
        private async Task AwaitLockAndAwaitTaskEnd(Guid resource, TimeSpan lockTimeout, TimeSpan waitTime, TaskCompletionSource <ILockContextAsync> acquiredLockEvent, TaskCompletionSource <object> taskEndEvent)
        {
            try
            {
                using (var cancellationTS = new CancellationTokenSource(waitTime))
                {
                    await _serialExecutionManager.RunAsync(resource, async() =>
                    {
                        LockInfo lockInfo = null;
                        try
                        {
                            lockInfo = await this.WaitForLockImpl(resource, lockTimeout, cancellationTS.Token);
                            if (lockInfo.AsImmutable().HasLock())
                            {
                                var lockContext = new LockContext(this, lockInfo);
                                acquiredLockEvent.SetResult(lockContext);

                                await taskEndEvent.Task;
                            }
                            else
                            {
                                throw new OperationCanceledException();
                            }
                        }
                        finally
                        {
                            this.Release(lockInfo);
                        }
                    }, cancellationTS.Token);
                }
            }
            catch (Exception ex)
            {
                if (acquiredLockEvent.Task.Status != System.Threading.Tasks.TaskStatus.RanToCompletion)
                {
                    if (ex is OperationCanceledException)
                    {
                        acquiredLockEvent.SetException(new TimeoutException($"Couldn't get lock on resource [{resource}]. Operation timed out."));
                    }
                    else
                    {
                        acquiredLockEvent.SetException(ex);
                    }
                }
                else
                {
                    ex.LogException();
                }
            }
        }
コード例 #5
0
        public async Task <bool> TryRenewLockAsync(LockInfo lockInfo, TimeSpan?renewTimeout = null, bool retryLock = false)
        {
            EnsureNotDisposed();
            if (lockInfo == null)
            {
                throw new ArgumentNullException("LockInfo is null");
            }

            //Allows only one task to run TryRenewLock on this lockInfo object
            using (await lockInfo.Mutex.LockAsync())
            {
                renewTimeout = renewTimeout ?? lockInfo.AsImmutable().Timeout;
                verifyTimeoutLimits(renewTimeout.Value);

                using (var tr = new TransactionScope(TransactionScopeOption.Suppress, TransactionScopeAsyncFlowOption.Enabled))
                    using (var conn = CreateConnection())
                    {
                        if (await renewLockAsync(conn, renewTimeout.Value, lockInfo))
                        {
                            return(true);
                        }
                    }
            }

            if (retryLock)
            {
                LockInfo newLock = await this.TryLockAsync(lockInfo.Resource, renewTimeout.Value);

                var newState = newLock.AsImmutable();
                if (newState.HasLock())
                {
                    var clock = _clockProvider.GetClock();
                    lockInfo.Update(newState.LockedUntil, newState.Timeout, newState.LockReference, clock);
                    return(true);
                }
            }

            return(false);
        }
コード例 #6
0
 public bool TryLock(Guid resource, TimeSpan?lockTimeout, out LockInfo lockInfo)
 {
     EnsureNotDisposed();
     lockInfo = TaskHelper.GetResultSafeSync(() => TryLockAsync(resource, lockTimeout));
     return(lockInfo.AsImmutable().HasLock());
 }
コード例 #7
0
 public bool WaitForLock(Guid resource, TimeSpan?lockTimeout, TimeSpan waitTime, out LockInfo lockInfo)
 {
     EnsureNotDisposed();
     lockInfo = TaskHelper.GetResultSafeSync(() => this.WaitForLockAsync(resource, lockTimeout, waitTime));
     return(lockInfo.AsImmutable().HasLock());
 }