/// <summary>
        /// Check the thread with the current turn for the lock and grant a secondary lock if applicable.
        /// </summary>
        /// <param name="candidateLock">An unexpired lock request on the current thread, or null to just check the turn thread.</param>
        /// <returns>The activity Id with the current turn for the lock, or null if there are none holding or waiting.</returns>
        internal Guid?CheckCurrentTurnThread(DistributedLock candidateLock)
        {
            var currentLockId = DistributedLockManager.CurrentLockId;

            if (candidateLock != null && candidateLock.OwningLockId != currentLockId)
            {
                throw new InvalidOperationException("A lock request may only be waited on by the thread which created it.");
            }

            lock (_currentLockLock)
            {
                if (_currentLockTurn != null)
                {
                    var currentOwningLockId = _currentLockTurn.OwningLockId;
                    if (candidateLock != null && currentLockId == currentOwningLockId)
                    {
                        candidateLock.GrantTheLock(_currentLockTurn);     // Set it as a secondary lock on that holder (same thread).
                        if (candidateLock.ActualLock == _currentLockTurn) // Sanity-check that it was successful.
                        {
                            candidateLock.OurLockProxy = this;            // So its dispose-on-close setting pass-through can function.
                        }
                    }

                    return(currentOwningLockId); // Whether it's a match or some other thread.
                }

                return(null); // No thread owns the lock.
            }
        }
        public void DistributedLockIsAcquiredSuccessfully()
        {
            async Task ExclusiveLockTask(int node)
            {
                _testOutputHelper.WriteLine($"Executing a long running task on Node {node}");
                // Add 5 second delay
                await Task.Delay(5000);
            }

            const long lockId = 50000;

            // Simulate with 5 nodes
            var nodes = Enumerable.Range(1, 5).ToList();

            Parallel.ForEach(nodes, async node =>
            {
                // Act and Arrange
                _testOutputHelper.WriteLine($"Trying to acquire session lock and run task for Node {node}");
                using var distributedLock = new DistributedLock(_connectionString, NullLogger <DistributedLock> .Instance);
                if (!await distributedLock.TryExecuteInDistributedLock(lockId, () => ExclusiveLockTask(node)))
                {
                    _testOutputHelper.WriteLine($"Node {node} could not acquire lock");
                }
            });
        }
Exemplo n.º 3
0
        public async Task AcquireOneBaseClassAfterLossAsync()
        {
            var lockBase = new LockBase();
            await _col.InsertOneAsync(lockBase);

            var dataStore = new SharpLockMongoDataStore <LockBase>(_col, _logger, TimeSpan.FromSeconds(5));
            var lck       = new DistributedLock <LockBase, ObjectId>(dataStore, 2);

            // Acquire the lock
            Assert.IsTrue(await lck.AcquireLockAsync(lockBase) != null, "Failed to acquire lock.");
            Assert.IsTrue(lockBase.Id == lck.LockedObjectId, "Locked Object is not the expected object.");
            Assert.IsTrue(lck.LockAcquired, "Lock should be acquired but it doesn't appear to be.");
            Assert.IsTrue(await lck.RefreshLockAsync(), "Failed to refresh lock.");
            await Task.Delay(5000);

            // Don't bother releasing it, attempt to re-acquire.
            lck = new DistributedLock <LockBase, ObjectId>(dataStore, 2);
            Assert.IsTrue(await lck.AcquireLockAsync(lockBase) != null, "Failed to acquire lock.");
            Assert.IsTrue(lockBase.Id == lck.LockedObjectId, "Locked Object is not the expected object.");
            Assert.IsTrue(lck.LockAcquired, "Lock should be acquired but it doesn't appear to be.");
            Assert.IsTrue(await lck.RefreshLockAsync(), "Failed to refresh lock.");
            Assert.IsTrue(await lck.ReleaseLockAsync(), "Failed to release lock.");

            await lck.DisposeAsync().ConfigureAwait(false);

            Assert.IsTrue(lck.Disposed, "Failed to mark object as disposed");
        }
Exemplo n.º 4
0
        public void Can_create_distributed_lock()
        {
            var key         = "lockkey";
            var lockTimeout = 2;

            var distributedLock = new DistributedLock();

            Assert.AreEqual(distributedLock.Lock(key, lockTimeout, lockTimeout, out var lockExpire, this.Redis),
                            DistributedLock.LockAcquired);

            // can't re-lock
            distributedLock = new DistributedLock();
            Assert.AreEqual(distributedLock.Lock(key, lockTimeout, lockTimeout, out lockExpire, this.Redis),
                            DistributedLock.LockNotAcquired);

            // re-acquire lock after timeout
            Thread.Sleep(lockTimeout * 1000 + 1000);
            distributedLock = new DistributedLock();
            Assert.AreEqual(distributedLock.Lock(key, lockTimeout, lockTimeout, out lockExpire, this.Redis),
                            DistributedLock.LockRecovered);


            Assert.IsTrue(distributedLock.Unlock(key, lockExpire, this.Redis));

            // can now lock
            distributedLock = new DistributedLock();
            Assert.AreEqual(distributedLock.Lock(key, lockTimeout, lockTimeout, out lockExpire, this.Redis), DistributedLock.LockAcquired);


            // cleanup
            Assert.IsTrue(distributedLock.Unlock(key, lockExpire, this.Redis));
        }
        private int DequeueNextRequest()
        {
            lock (_currentLockLock)
            {
                var dequeueCount = 0;
                RuntimeHelpers.PrepareConstrainedRegions(); // Make sure we don't thread-abort in the middle of this logic.
                try
                {
                }
                finally
                {
                    while (_currentLockTurn == null && _waitQueue.TryDequeue(out _currentLockTurn) == true)
                    {
                        dequeueCount++;

                        if (_currentLockTurn.IsExpired)
                        {
                            _currentLockTurn.Dispose(); // There's no one waiting on that request, so just discard it.
                            _currentLockTurn = null;    // Get the next one (if any) on next loop.
                        }
                        else
                        {
                            _currentLockTurn.Disposed += Lock_Disposed; // Subscribe to their Disposed event.  Now we care.
                        }
                    }
                }

                return(dequeueCount);
            }
        }
        public void AcquireWait()
        {
            var lockName = "AcquireWait" + DateTime.Now.Ticks;

            var collection = GetCollection();

            collection.Should().NotBeNull();

            var locker = new DistributedLock(collection);

            locker.Should().NotBeNull();

            var result = locker.Acquire(lockName, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2));

            result.Should().BeTrue();

            var status = locker.Status(lockName);

            status.Should().NotBeNull();
            status.IsLocked.Should().BeTrue();

            var waited = locker.Acquire(lockName, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2));

            waited.Should().BeTrue();
        }
        private void Release()
        {
            lock (_lock) {
                if (_distributedLock != null)
                {
                    // Non blocking session!
                    try {
                        using (var session = _storage.Repository.OpenSession()) {
                            session.Delete(_distributedLock.Id);
                            session.SaveChanges();
                        }
                    } catch {
                        Console.WriteLine("Unable to delete lock: {0}", _resource);
                    }

                    _distributedLock = null;
                }

                // Stop timer
                if (_heartbeatTimer != null)
                {
                    _heartbeatTimer.Dispose();
                    _heartbeatTimer = null;
                }
            }
        }
        public void AcquireExpire()
        {
            var lockName = "AcquireExpire" + DateTime.Now.Ticks;

            var collection = GetCollection();

            collection.Should().NotBeNull();

            var locker = new DistributedLock(collection);

            locker.Should().NotBeNull();

            var result = locker.Acquire(lockName, TimeSpan.FromMilliseconds(5));

            result.Should().BeTrue();

            var status = locker.Status(lockName);

            status.Should().NotBeNull();
            status.IsLocked.Should().BeTrue();

            // wait for expire
            Thread.Sleep(5);

            var blocked = locker.Acquire(lockName, TimeSpan.FromMilliseconds(5));

            blocked.Should().BeTrue();
        }
Exemplo n.º 9
0
        private async void Handle()
        {
            var cancellationToken = CancellationTokenSource.Token;

            while (!CancellationTokenSource.IsCancellationRequested)
            {
                Thread.Sleep(Options.BlockThreadMS);
                if (NextExecutionDateTime != null && DateTime.UtcNow <= NextExecutionDateTime.Value)
                {
                    continue;
                }

                if (!await DistributedLock.TryAcquireLock(LockName, cancellationToken))
                {
                    continue;
                }

                try
                {
                    await Execute(cancellationToken);
                }
                catch (Exception ex)
                {
                    Logger.LogError(ex.ToString());
                }
                finally
                {
                    await DistributedLock.ReleaseLock(LockName, cancellationToken);

                    NextExecutionDateTime = DateTime.UtcNow.AddMilliseconds(Options.BlockThreadMS);
                }
            }
        }
        public void AcquireBlock()
        {
            var lockName = "AcquireBlock" + DateTime.Now.Ticks;

            var collection = GetCollection();

            collection.Should().NotBeNull();

            var locker = new DistributedLock(collection, TimeSpan.FromMinutes(5));

            locker.Should().NotBeNull();

            var result = locker.Acquire(lockName);

            result.Should().BeTrue();

            var status = locker.Status(lockName);

            status.Should().NotBeNull();
            status.IsLocked.Should().BeTrue();

            var blocked = locker.Acquire(lockName);

            blocked.Should().BeFalse();
        }
Exemplo n.º 11
0
        public async Task GetObjectSubClassAsync()
        {
            var lockBase = new LockBase();
            await _col.InsertOneAsync(lockBase);

            var dataStore = new SharpLockMongoDataStore <LockBase, InnerLock>(_col, _logger, TimeSpan.FromSeconds(30));
            var lck       = new DistributedLock <LockBase, InnerLock, ObjectId>(dataStore, x => x.SingularInnerLock);

            Assert.IsTrue(await lck.GetObjectAsync() == null, "await lck.GetObjectAsync() == null");

            await Assert.ThrowsExceptionAsync <DistributedLockException>(() => lck.GetObjectAsync(true), "() => lck.GetObjectAsync(true)");

            Assert.IsNotNull(await lck.AcquireLockAsync(lockBase, lockBase.SingularInnerLock), "await lck.AcquireLockAsync(lockBase, lockBase.SingularInnerLock)");

            Assert.IsTrue(lck.LockAcquired, "Lock should be acquired but it doesn't appear to be.");

            Assert.AreEqual(lck.ToString(), $"LockId: {lck.LockedObjectLockId}, Locked ObjectId: {lck.LockedObjectId}.");

            Assert.IsTrue(await lck.ReleaseLockAsync(), "await lck.ReleaseLockAsync()");

            Assert.AreEqual(lck.ToString(), "No lock acquired.");

            await lck.DisposeAsync().ConfigureAwait(false);

            Assert.IsTrue(lck.Disposed, "Failed to mark object as disposed");
        }
Exemplo n.º 12
0
        public static void LockAndUnlock(bool isActive)
        {
            if (!isActive)
            {
                return;
            }

            DistributedLock _lock = new DistributedLock();

            string value1 = Guid.NewGuid().ToString();
            var    result = _lock.TryLockTransaction("test", value1);

            Console.WriteLine("Thread {0} output: {1}.", value1, result);
            Thread.Sleep(1000);

            string value2 = Guid.NewGuid().ToString();

            result = _lock.TryLockTransaction("test", value2);
            Console.WriteLine("Thread {0} output: {1}.", value2, result);

            _lock.UnLock("test");

            string value3 = Guid.NewGuid().ToString();

            result = _lock.TryLockTransaction("test", value3);
            Console.WriteLine("Thread {0} output: {1}.", value3, result);
        }
Exemplo n.º 13
0
        public void Can_create_distributed_lock()
        {
            var key         = "lockkey";
            int lockTimeout = 2;

            var  distributedLock = new DistributedLock();
            long lockExpire;

            Assert.AreEqual(distributedLock.Lock(key, lockTimeout, lockTimeout, out lockExpire, Redis), DistributedLock.LOCK_ACQUIRED);

            //can't re-lock
            distributedLock = new DistributedLock();
            Assert.AreEqual(distributedLock.Lock(key, lockTimeout, lockTimeout, out lockExpire, Redis), DistributedLock.LOCK_NOT_ACQUIRED);

            // re-acquire lock after timeout
            Thread.Sleep(lockTimeout * 1000 + 1000);
            distributedLock = new DistributedLock();
            Assert.AreEqual(distributedLock.Lock(key, lockTimeout, lockTimeout, out lockExpire, Redis), DistributedLock.LOCK_RECOVERED);


            Assert.IsTrue(distributedLock.Unlock(key, lockExpire, Redis));

            //can now lock
            distributedLock = new DistributedLock();
            Assert.AreEqual(distributedLock.Lock(key, lockTimeout, lockTimeout, out lockExpire, Redis), DistributedLock.LOCK_ACQUIRED);


            //cleanup
            Assert.IsTrue(distributedLock.Unlock(key, lockExpire, Redis));
        }
Exemplo n.º 14
0
        public static void LockTest(bool isActive)
        {
            if (!isActive)
            {
                return;
            }

            DistributedLock _lock        = new DistributedLock();
            int             threads_size = 100;

            Thread[] t_arr = new Thread[threads_size];

            for (int i = 0; i < threads_size; i++)
            {
                t_arr[i] = new Thread(_ =>
                {
                    Stopwatch sw = new Stopwatch();
                    sw.Start();
                    string value = Guid.NewGuid().ToString();
                    var result   = _lock.TryLockScript("test", value);
                    sw.Stop();
                    Console.WriteLine(sw.ElapsedMilliseconds);
                });
            }

            for (int i = 0; i < threads_size; i++)
            {
                t_arr[i].Start();
            }
        }
        private async void Handle()
        {
            var cancellationToken = CancellationTokenSource.Token;

            while (!CancellationTokenSource.IsCancellationRequested)
            {
                Thread.Sleep(Options.BlockThreadMS);
                if (NextExecutionDateTime != null && DateTime.UtcNow <= NextExecutionDateTime.Value)
                {
                    continue;
                }

                if (!await DistributedLock.TryAcquireLock(LockName, cancellationToken))
                {
                    continue;
                }

                try
                {
                    await Execute(cancellationToken);
                }
                catch (Exception ex)
                {
                    Logger.LogError(ex.ToString());
                }
                finally
                {
                    await DistributedLock.ReleaseLock(LockName, cancellationToken);

                    var schedulingResult = await ScheduledJobStore.TryGetNextScheduling(this.GetType().FullName, cancellationToken);

                    NextExecutionDateTime = schedulingResult.NextDateTime;
                }
            }
        }
Exemplo n.º 16
0
 private void Release()
 {
     try
     {
         if (_distributedLock != null)
         {
             // Non blocking session!
             using (var session = _storage.Repository.OpenSession())
             {
                 session.Delete(_distributedLock.Id);
                 session.SaveChanges();
                 _distributedLock = null;
             }
         }
         EventWaitHandle eventWaitHandler;
         if (EventWaitHandle.TryOpenExisting(EventWaitHandleName, out eventWaitHandler))
         {
             eventWaitHandler.Set();
         }
     }
     catch (PlatformNotSupportedException)
     {
     }
     catch (Exception ex)
     {
         _distributedLock = null;
         throw new RavenDistributedLockException($"Could not release a lock on the resource \'{_resource}\': Check inner exception for details.", ex);
     }
 }
Exemplo n.º 17
0
        private void HelperThreadStart()
        {
            DistributedLockManager.LockBarrier();

            lock (m_Lock)
            {
                m_LockManager.TryLock(this, m_Name, m_Timeout, out m_RepositoryLock);

                if (m_RepositoryLock != null)
                {
                    Monitor.PulseAll(m_Lock);

                    while (m_Exiting == false)
                    {
                        Monitor.Wait(m_Lock); // Thread waits until we're told to exit.
                    }

                    m_RepositoryLock.Dispose(); // We're exiting, so it's time to release the lock!
                    m_RepositoryLock = null;
                }
                // Otherwise, we couldn't get the lock.

                m_Exited = true; // Lock is released and thread is exiting.
                Monitor.PulseAll(m_Lock);
            }
        }
Exemplo n.º 18
0
        private void Acquire(TimeSpan timeout)
        {
            try
            {
                var isLockAcquired  = false;
                var now             = DateTime.Now;
                var lockTimeoutTime = now.Add(timeout);

                while (!isLockAcquired && (lockTimeoutTime >= now))
                {
                    using (var session = _storage.Repository.OpenSession())
                    {
                        _distributedLock = new DistributedLock()
                        {
                            ClientId = _storage.Options.ClientId,
                            Resource = _resource
                        };

                        session.Store(_distributedLock);
                        session.Advanced.AddExpire(_distributedLock, DateTime.UtcNow.Add(_options.DistributedLockLifetime));

                        try
                        {
                            // Blocking session!
                            session.Advanced.UseOptimisticConcurrency = true;
                            session.SaveChanges();
                            isLockAcquired = true;
                        }
                        catch (ConcurrencyException)
                        {
                            _distributedLock = null;
                            try
                            {
                                var eventWaitHandle = new EventWaitHandle(false, EventResetMode.AutoReset, EventWaitHandleName);
                                eventWaitHandle.WaitOne((int)timeout.TotalMilliseconds / 10);
                            }
                            catch (PlatformNotSupportedException)
                            {
                                Thread.Sleep((int)timeout.TotalMilliseconds / 10);
                            }
                            now = DateTime.Now;
                        }
                    }
                }

                if (!isLockAcquired)
                {
                    throw new DistributedLockTimeoutException(_resource);
                }
            }
            catch (DistributedLockTimeoutException)
            {
                throw;
            }
            catch (Exception ex)
            {
                throw new RavenDistributedLockException($"Could not place a lock on the resource \'{_resource}\': Check inner exception for details.", ex);
            }
        }
Exemplo n.º 19
0
 private OtherThreadLockHelper(object requester, DistributedLockManager lockManager, string lockName, int timeout)
 {
     m_RepositoryLock = null;
     m_Requester      = requester;
     m_LockManager    = lockManager;
     m_Name           = lockName;
     m_Timeout        = timeout;
 }
Exemplo n.º 20
0
        public void TestGetLock()
        {
            var key = Guid.NewGuid().ToString();

            using (var l = DistributedLock.TryGetLock(key))
            {
                Assert.IsTrue(l.HasLock);
            }
        }
Exemplo n.º 21
0
        public void TestLockOwner()
        {
            var key = Guid.NewGuid().ToString();

            using (var l = DistributedLock.TryGetLock(key))
            {
                Assert.AreEqual(DistributedLock.Owner, l.CurrentLockOwner);
            }
        }
Exemplo n.º 22
0
        public void IsLockedByAnotherProcess_WhenNotLocked_ReturnsFalse()
        {
            var distributedLock = new DistributedLock()
            {
                DistributedLockId = "TSTTST"
            };

            Assert.False(distributedLock.IsLockedByAnotherProcess());
        }
        public DistributedLockTests()
        {
            var options = Options.Create(new CosmosDataStoreOptions
            {
                DistributedLocksCollection = "test-collection"
            });

            _cosmosDbLockStore = new Mock <ICosmosDistributedLockStore>();
            _distributedLock   = new DistributedLock(_cosmosDbLockStore.Object, options);
        }
Exemplo n.º 24
0
 public DequeueManager(PooledRedisClientManager clientManager, RedisSequentialWorkQueue <T> workQueue, string workItemId, string dequeueLockKey, int numberOfDequeuedItems, int dequeueLockTimeout)
 {
     this.workQueue             = workQueue;
     this.workItemId            = workItemId;
     this.clientManager         = clientManager;
     this.numberOfDequeuedItems = numberOfDequeuedItems;
     myLock = new DistributedLock();
     this.dequeueLockKey     = dequeueLockKey;
     this.dequeueLockTimeout = dequeueLockTimeout;
 }
        private async Task GratuitousWorkAsync(DistributedLock distributedLock)
        {
            Assert.That(distributedLock.IsDisposed == false);

            await Task.Delay(10).ConfigureAwait(false);

            await Task.Delay(10).ConfigureAwait(false);

            await Task.Delay(10).ConfigureAwait(false);
        }
Exemplo n.º 26
0
        public GenerateIDTool(string applyType)
        {
            this._applyType = applyType;
            _disLock        = new DistributedLock(_lockKey + applyType);

            if (!_isMotinor)
            {
                GetTimerStart();
                _isMotinor = true;
            }
        }
Exemplo n.º 27
0
        public void IsLocked_WhenNotLocked_ReturnsFalse()
        {
            var distributedLock = new DistributedLock()
            {
                DistributedLockId = "TSTTST",
                ExpiryDate        = DateTime.MinValue,
                LockDate          = DateTime.MinValue
            };

            Assert.False(distributedLock.IsLocked());
        }
        /// <summary>
        /// Try to get the actual file lock on behalf of the current request.
        /// </summary>
        /// <param name="currentRequest"></param>
        /// <returns></returns>
        private bool TryGetLock(DistributedLock currentRequest)
        {
            var waitForLock = currentRequest.WaitForLock;
            var lockTimeout = currentRequest.WaitTimeout;
            var validLock   = false;

            while (waitForLock == false || DateTimeOffset.Now < lockTimeout)
            {
                if (DateTimeOffset.Now >= _minTimeNextTurn) // Make sure we aren't in a back-off delay.
                {
                    var newLock = _provider.GetLock(_name);
                    if (newLock != null)
                    {
                        lock (_currentLockLock)
                        {
                            _lock = newLock;

                            // We have the lock!  Close our lock request if we have one so later we can detect if anyone else does.
                            if (_lockRequest != null)
                            {
                                _lockRequest.Dispose();
                                _lockRequest = null;
                            }
                        }

                        validLock = true; // Report that we have the lock now.
                    }
                }
                // Otherwise, just pretend we couldn't get the lock in this attempt.

                if (validLock == false && waitForLock)
                {
                    // We didn't get the lock and we want to wait for it, so try to open a lock request.
                    lock (_currentLockLock)
                    {
                        if (_lockRequest == null)
                        {
                            _lockRequest = _provider.GetLockRequest(_name); // Tell the other process we'd like a turn.
                        }
                    }

                    // Then we should allow some real time to pass before trying again because external locks aren't very fast.
                    Thread.Sleep(LockPollingDelay);
                }
                else
                {
                    // We either got the lock or the user doesn't want to keep retrying, so exit the loop.
                    break;
                }
            }

            return(validLock);
        }
Exemplo n.º 29
0
        public void TestGetLockTwoTimesWithTry()
        {
            var key = Guid.NewGuid().ToString();

            using (var l1 = DistributedLock.TryGetLock(key))
            {
                using (var l2 = DistributedLock.TryGetLock(key, DistributedLock.DefaultExpiry, TimeSpan.FromSeconds(1)))
                {
                    Assert.IsFalse(l2.HasLock);
                }
            }
        }
Exemplo n.º 30
0
    protected virtual async Task RunAsync()
    {
        if (StoppingToken.IsCancellationRequested)
        {
            return;
        }

        await using (var handle = await DistributedLock.TryAcquireAsync(DistributedLockName, cancellationToken: StoppingToken))
        {
            if (handle != null)
            {
                await DeleteOldEventsAsync();

                while (true)
                {
                    var waitingEvents = await Inbox.GetWaitingEventsAsync(EventBusBoxesOptions.InboxWaitingEventMaxCount, StoppingToken);

                    if (waitingEvents.Count <= 0)
                    {
                        break;
                    }

                    Logger.LogInformation($"Found {waitingEvents.Count} events in the inbox.");

                    foreach (var waitingEvent in waitingEvents)
                    {
                        using (var uow = UnitOfWorkManager.Begin(isTransactional: true, requiresNew: true))
                        {
                            await DistributedEventBus
                            .AsSupportsEventBoxes()
                            .ProcessFromInboxAsync(waitingEvent, InboxConfig);

                            await Inbox.MarkAsProcessedAsync(waitingEvent.Id);

                            await uow.CompleteAsync();
                        }

                        Logger.LogInformation($"Processed the incoming event with id = {waitingEvent.Id:N}");
                    }
                }
            }
            else
            {
                Logger.LogDebug("Could not obtain the distributed lock: " + DistributedLockName);
                try
                {
                    await Task.Delay(EventBusBoxesOptions.DistributedLockWaitDuration, StoppingToken);
                }
                catch (TaskCanceledException) { }
            }
        }
    }