Пример #1
0
        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);
        }
Пример #2
0
        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());
        }