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); }
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); } } }
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); } } }
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(); } } }
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); }
public bool TryLock(Guid resource, TimeSpan?lockTimeout, out LockInfo lockInfo) { EnsureNotDisposed(); lockInfo = TaskHelper.GetResultSafeSync(() => TryLockAsync(resource, lockTimeout)); return(lockInfo.AsImmutable().HasLock()); }
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()); }