public LockAttemptResult TryLock([NotNull] string lockId, [NotNull] string threadId) { var lockMetadata = baseOperationsPerformer.TryGetLockMetadata(lockId) ?? new LockMetadata(lockId, lockId, 0, null, null, 0L); var newThreshold = NewThreshold(lockMetadata.PreviousThreshold ?? (Timestamp.Now - TimeSpan.FromHours(1)).Ticks); LockAttemptResult result; var probableOwnerThreadId = lockMetadata.ProbableOwnerThreadId; if (!string.IsNullOrEmpty(probableOwnerThreadId) && baseOperationsPerformer.ThreadAlive(lockMetadata.LockRowId, lockMetadata.PreviousThreshold, probableOwnerThreadId)) { if (probableOwnerThreadId == threadId) { throw new InvalidOperationException($"TryLock(lockId = {lockId}, threadId = {threadId}): probableOwnerThreadId == threadId, though it seemed to be impossible!"); } result = LockAttemptResult.AnotherOwner(probableOwnerThreadId); } else { result = RunBattle(lockMetadata, threadId, newThreshold); } if (result.Status == LockAttemptStatus.Success) { lockMetadata = baseOperationsPerformer.TryGetLockMetadata(lockId) ?? new LockMetadata(lockId, lockId, 0, null, null, 0L); if (lockMetadata.LockCount <= changeLockRowThreshold) { var newLockMetadata = new NewLockMetadata(lockId, lockMetadata.LockRowId, lockMetadata.LockCount + 1, newThreshold, threadId); baseOperationsPerformer.WriteLockMetadata(newLockMetadata, lockMetadata.Timestamp); } else { var newLockMetadata = new NewLockMetadata(lockId, Guid.NewGuid().ToString(), 1, newThreshold, threadId); baseOperationsPerformer.WriteThread(newLockMetadata.MainRowKey(), newThreshold, threadId, LockTtl); baseOperationsPerformer.WriteLockMetadata(newLockMetadata, lockMetadata.Timestamp); baseOperationsPerformer.WriteThread(lockMetadata.MainRowKey(), newThreshold, threadId, LockTtl.Multiply(10)); } } return(result); }
private LockAttemptResult RunBattle([NotNull] LockMetadata lockMetadata, [NotNull] string threadId, long newThreshold) { var items = baseOperationsPerformer.SearchThreads(lockMetadata.MainRowKey(), lockMetadata.PreviousThreshold); if (items.Length == 1) { return(items[0] == threadId?LockAttemptResult.Success() : LockAttemptResult.AnotherOwner(items[0])); } if (items.Length > 1) { if (items.Any(s => s == threadId)) { throw new Exception("Lock unknown exception"); } return(LockAttemptResult.AnotherOwner(items[0])); } var beforeOurWriteShades = baseOperationsPerformer.SearchThreads(lockMetadata.ShadowRowKey(), lockMetadata.PreviousThreshold); if (beforeOurWriteShades.Length > 0) { return(LockAttemptResult.ConcurrentAttempt()); } baseOperationsPerformer.WriteThread(lockMetadata.ShadowRowKey(), newThreshold, threadId, LockTtl); var shades = baseOperationsPerformer.SearchThreads(lockMetadata.ShadowRowKey(), lockMetadata.PreviousThreshold); if (shades.Length == 1) { items = baseOperationsPerformer.SearchThreads(lockMetadata.MainRowKey(), lockMetadata.PreviousThreshold); if (items.Length == 0) { baseOperationsPerformer.WriteThread(lockMetadata.MainRowKey(), newThreshold, threadId, LockTtl); baseOperationsPerformer.DeleteThread(lockMetadata.ShadowRowKey(), newThreshold, threadId); return(LockAttemptResult.Success()); } } baseOperationsPerformer.DeleteThread(lockMetadata.ShadowRowKey(), newThreshold, threadId); return(LockAttemptResult.ConcurrentAttempt()); }