Beispiel #1
0
        async static Task<LockingCoordinator> InitCoordinator(
            IEnumerable<LockingNode> lockingNodes,
            Func<long> timeProvider,
            ILogger logger)
        {
            logger.ToInfoLog("Connecting to the locking nodes...");

            return await LockingCoordinator
                .CreateNewForNodes(lockingNodes, timeProvider, logger)
                .ConfigureAwait(false);
        }
Beispiel #2
0
        async static Task StartAttemptingAcquisition(
            LockingCoordinator lockingCoordinator,
            LockId lockId,
            ILogger logger,
            CancellationTokenSource lockingCancellationSource,
            IObserver<object> observer)
        {
            var holdingLock = false;
            var retryInterval = lockId.CalculateRetryInterval();
            var randomGenerator = new Random(Guid.NewGuid().GetHashCode());

            while (!lockingCancellationSource.IsCancellationRequested && !holdingLock)
            {
                try
                {
                    holdingLock = await lockingCoordinator.TryAcquireLock(lockId).ConfigureAwait(false);

                    if(holdingLock)
                    {
                        logger.ToInfoLog(string.Format("DISTRIBUTED LOCK ACQUIRED for {0}", lockId.Resource));
                    }
                    else
                    {
                        logger.ToDebugLog("Unable to acquire the lock, retrying...");

                        await TaskUtils.SilentlyCanceledDelay(
                            randomGenerator.Next(retryInterval.First(), retryInterval.Second()),
                            lockingCancellationSource.Token)
                        .ConfigureAwait(false);
                    }
                }
                catch (Exception ex)
                {
                    observer.OnError(ex);

                    if(lockingCoordinator != null)
                        await lockingCoordinator
                            .TryReleaseTheLock(lockId)
                            .ConfigureAwait(false);

                    holdingLock = false;
                }
            }
        }
Beispiel #3
0
        async Task ReleaseLock(
            LockingCoordinator lockingCoordinator,
            LockId lockId,
            ILogger logger,
            CancellationTokenSource lockingCancellationSource,
            IObserver<object> observer)
        {
            try
            {
                if(!lockingCancellationSource.IsCancellationRequested)
                    lockingCancellationSource.Cancel();

                observer.OnNext(new LockReleaseStarted());

                logger.ToInfoLog(string.Format("Releasing the lock on {0}...", _lockId.Resource));

                if(lockingCoordinator != null)
                    await lockingCoordinator
                        .TryReleaseTheLock(lockId)
                        .ConfigureAwait(false);
                
                logger.ToInfoLog(string.Format("DISTRIBUTED LOCK RELEASED for {0}", _lockId.Resource));

                observer.OnNext(new LockReleased());

                lockingCoordinator.Dispose();
            }
            catch (Exception ex)
            {
                observer.OnError(ex);
            }
        }
Beispiel #4
0
        async Task KeepConfirmingTheLock(
            LockingCoordinator lockingCoordinator,
            ILogger logger,
            CancellationTokenSource lockingCancellationSource,
            IObserver<object> observer)
        {
            if (lockingCoordinator == null)
            {
                observer.OnError(new ApplicationException("Trying to confirm lock on a NULL coordinator. Invalid locking engine state. Aborting..."));

                return;
            }

            var acquisitionSignaled = false;
            var holdingLock = true;
            var confirmationInterval = _lockId.CalculateConfirmationIntervalMillis();

            logger.ToInfoLog(string.Format("Entering lock retaining mode for {0}", _lockId.Resource));

            try
            {
                while(!lockingCancellationSource.IsCancellationRequested && holdingLock)
                {
                    holdingLock = await lockingCoordinator
                        .TryConfirmTheLock(_lockId)
                        .ConfigureAwait(false);
                    
                    await TaskUtils
                        .SilentlyCanceledDelay(
                            (int)confirmationInterval,
                            lockingCancellationSource.Token)
                        .ConfigureAwait(false);

                    //  signaling the acquisition here guarantees that during a partition the former
                    //  lock holder have the time to realizes it's not holding the lock anymore
                    if(!acquisitionSignaled)
                    {
                        observer.OnNext(new LockAcquired());
                        acquisitionSignaled = true;
                    }
                }
            }
            catch (Exception ex)
            {
                observer.OnError(ex);
            }

            if (!lockingCancellationSource.IsCancellationRequested)
            {
                logger.ToInfoLog(string.Format("Lock held for {0} lost", _lockId.Resource));

                observer.OnNext(new LockHeldLost());

                await ReleaseLock(lockingCoordinator, _lockId, _logger, lockingCancellationSource, observer).ConfigureAwait(false);
            }
        }