/// <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"); } }); }
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"); }
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(); }
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(); }
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"); }
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); }
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)); }
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; } } }
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); } }
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); } }
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); } }
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; }
public void TestGetLock() { var key = Guid.NewGuid().ToString(); using (var l = DistributedLock.TryGetLock(key)) { Assert.IsTrue(l.HasLock); } }
public void TestLockOwner() { var key = Guid.NewGuid().ToString(); using (var l = DistributedLock.TryGetLock(key)) { Assert.AreEqual(DistributedLock.Owner, l.CurrentLockOwner); } }
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); }
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); }
public GenerateIDTool(string applyType) { this._applyType = applyType; _disLock = new DistributedLock(_lockKey + applyType); if (!_isMotinor) { GetTimerStart(); _isMotinor = true; } }
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); }
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); } } }
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) { } } } }