示例#1
0
    void ConnectTwoPoint(LockItem pre, LockItem now)
    {
        if (pre == now)
        {
            return;
        }
        Vector3 pos   = (pre.transform.position + now.transform.position) / 2;
        Vector3 engel = Vector3.zero;
        float   dis   = Loc.Distance(pre.loc, now.loc);

        if (dis != 1)
        {
            if (pre.loc.y < now.loc.y && pre.loc.x < now.loc.x || pre.loc.y > now.loc.y && pre.loc.x > now.loc.x)
            {
                engel = new Vector3(0, 0, -45);
            }
            else
            {
                engel = new Vector3(0, 0, 45);
            }
        }
        else
        {
            if (pre.loc.y != now.loc.y)
            {
                engel = new Vector3(0, 0, 90);
            }
        }
        Image mag = GameObject.Instantiate <GameObject>(line).GetComponent <Image>();

        mag.transform.SetParent(lineTrans);
        mag.transform.localScale       = Vector3.one;
        mag.transform.position         = pos;
        mag.transform.localEulerAngles = engel;
    }
示例#2
0
 void DrawSelection(LockItem trans)
 {
     ConnectTwoPoint(prePoint, trans);
     recordList.Add(trans.transform);
     trans.GetComponent <Image>().sprite = selectSprite;
     prePoint = trans;
 }
        /// <summary>
        /// 释放指定名称的锁
        /// </summary>
        /// <param name="itemname"></param>
        public void Free(string itemname)
        {
            LockItem lockitem = null;

            lock (lockobj)
            {
                Dictionary <string, LockItem> dicitems = null;
                if (_dicobj.ContainsKey(CurrentWorkArea))
                {
                    dicitems = _dicobj[CurrentWorkArea];
                }
                else
                {
                    dicitems = new Dictionary <string, LockItem>();
                    _dicobj.Add(CurrentWorkArea, dicitems);
                }

                if (dicitems.ContainsKey(itemname))
                {
                    lockitem = dicitems[itemname];
                }
                else
                {
                    lockitem = new LockItem(itemname);
                    dicitems.Add(lockitem.Name, lockitem);
                }
            }
            if (System.Threading.Monitor.IsEntered(lockitem))
            {
                System.Threading.Monitor.Exit(lockitem);
                lockitem.State = LockState.Free;
            }
        }
示例#4
0
        /// <summary>
        /// ToLockMsg
        /// </summary>
        /// <param name="lockItem">thisLockItem</param>
        /// <returns>string</returns>
        public static string ToLockMsg(this LockItem lockItem)
        {
            if (null == lockItem)
            {
                GlobalDefinition.LoggerWrapper.LogDevError("[ToLockMsg][lockItem == null]");
                return(string.Empty);
            }

            GlobalDefinition.LoggerWrapper.LogDevWarning("[ToLockMsg][Comment:" + lockItem.Comment + "]");

            var lockTip = GlobalDefinition.ToLocalLanguge("UID_PA_Item_LockedInfo");

            if (string.IsNullOrEmpty(lockTip))
            {
                GlobalDefinition.LoggerWrapper.LogDevWarning("[ToLockMsg][lockTip is empty]");
                return(string.Empty);
            }

            if (string.IsNullOrEmpty(lockItem.Comment))
            {
                GlobalDefinition.LoggerWrapper.LogDevWarning("[ToLockMsg][lockItem.Comment is empty]");
                return(lockTip);
            }

            var c = GlobalDefinition.ToLocalLanguge(lockItem.Comment);

            if (string.IsNullOrEmpty(c))
            {
                GlobalDefinition.LoggerWrapper.LogDevWarning("[ToLockMsg][not find resource:" + lockItem.Comment + "]");
                return(lockTip);
            }

            return(string.Format("{0} ({1}...)", lockTip, c));
        }
 public WaitResult(MultiLock <TKey> multiLock, LockItem lockItem, TKey key,
                   bool acquired)
 {
     MultiLock    = multiLock;
     LockItem     = lockItem;
     Key          = key;
     LockAcquired = acquired;
 }
示例#6
0
 void OnItemPressed(LockItem trans)
 {
     if (!isBegin)
     {
         isBegin  = true;
         prePoint = trans;
         DrawSelection(trans);
         Debug.Log("begin draw");
     }
 }
示例#7
0
            public override bool Equals(Object obj)
            {
                LockItem <T> p = obj as LockItem <T>;

                if ((object)p == null)
                {
                    return(false);
                }

                return(this == p);
            }
示例#8
0
        private LockItem CreateLockFromDbAttribute(Dictionary <string, AttributeValue> item, DateTime lookUpTime)
        {
            if (!item.ContainsKey(OwnerName) || !item.ContainsKey(LeaseDuration) ||
                !item.ContainsKey(_partitionKeyName) ||
                !item.ContainsKey(RecordVersionNumber))
            {
                throw new InvalidOperationException("cannot create LockItem from dbItem");
            }

            string ownerName           = null;
            long   leaseDuration       = 0;
            string recordVersionNumber = null;
            string partitionKey        = null;
            bool   isReleased;

            //bool deleteOnRelease = true;


            if (item.TryGetValue(OwnerName, out var ownerNameAttributeValue))
            {
                ownerName = ownerNameAttributeValue.S;
            }

            if (item.TryGetValue(_partitionKeyName, out var partitionKeyAttributeValue))
            {
                partitionKey = partitionKeyAttributeValue.S;
            }

            if (item.TryGetValue(LeaseDuration, out var leaseDurationAttributeValue))
            {
                var leaseDurationValue = leaseDurationAttributeValue.S;
                leaseDuration = long.Parse(leaseDurationValue);
            }

            if (item.TryGetValue(RecordVersionNumber, out var recordVersionAttributeValue))
            {
                recordVersionNumber = recordVersionAttributeValue.S;
            }


            if (item.TryGetValue(DeleteOnRelease, out var deleteOnReleaseAttributeValue))
            {
                // deleteOnRelease = deleteOnReleaseAttributeValue.BOOL;
            }


            isReleased = item.ContainsKey(IsReleased);

            var lockItem = new LockItem(partitionKey, ownerName, recordVersionNumber, lookUpTime, leaseDuration,
                                        isReleased);

            return(lockItem);
        }
示例#9
0
        public void Init()
        {
            RepositoryMock = new Mock <IResourceLockRepository>();
            Lock           = LockItem.CreateRead("xxx", null);

            //add both read and write locks as secondary ones
            SecondaryLocks = new List <LockItem>();
            for (int i = 0; i < 10; i++)
            {
                var item = i % 2 == 0 ? LockItem.CreateRead(i.ToString(), null) : LockItem.CreateWrite(i.ToString(), null);
                SecondaryLocks.Add(item);
            }
        }
示例#10
0
        public LockItem TryAcquireLockItem(string partitionKey, long?millisecondsToWait,
                                           long?refreshPeriodInMilliseconds, bool retryOnFirstFail = true)
        {
            LockItem lockItem = null;

            var acquireAction = new Func <LockItem>(() =>
            {
                try
                {
                    LockItem item = null;

                    Task.Run(async() =>
                    {
                        item = await AcquireLockItemAsync(partitionKey, millisecondsToWait, refreshPeriodInMilliseconds);
                    }).Wait();

                    return(item);
                }
                catch (AggregateException ae)
                {
                    foreach (var e in ae.Flatten().InnerExceptions)
                    {
                        ExceptionDispatchInfo.Capture(e).Throw();
                    }
                }

                return(null);
            });

            try
            {
                lockItem = acquireAction();
            }
            catch (Exception e)
            {
                if (retryOnFirstFail)
                {
                    retryOnFirstFail = false;
                    lockItem         = acquireAction();
                }
                else
                {
                    ExceptionDispatchInfo.Capture(e).Throw();
                }
            }


            return(lockItem);
        }
示例#11
0
 void OnItemEnter(LockItem trans)
 {
     if (!isBegin || _isEnd)
     {
         return;
     }
     if (recordList.Contains(trans.transform))
     {
         return;
     }
     if (Loc.Distance(prePoint.loc, trans.loc) >= 2)
     {
         return;
     }
     DrawSelection(trans);
     prePoint = trans;
 }
示例#12
0
        public static bool GetLock(string id)
        {
            if (string.IsNullOrEmpty(id))
            {
                return(false);
            }

            id = id.ToLower().Trim();

            int wait     = 0;
            int threadId = Thread.CurrentThread.ManagedThreadId;

Next:
            lock (LockObj)
            {
                if (Locks.ContainsKey(id))
                {
                    if (Locks[id].ThreadId == threadId)
                    {
                        Locks[id].ReLock();
                        return(true);
                    }

                    if (Locks[id].IsOverdue())
                    {//已经过期
                        Locks[id] = new LockItem(threadId);
                        return(true);
                    }
                }
                else
                {
                    Locks.Add(id, new LockItem(threadId));
                    return(true);
                }
            }

            if (wait < TRYCOUNT)
            {
                wait++;
                Thread.Sleep(TRYINTERVAL);
                goto Next;
            }

            return(false);
        }
示例#13
0
        private LockItem AddLockItemToDynamo(string partitionKey, string recordVersionNumber,
                                             PutItemRequest putItemRequest)
        {
            long lastUpdatedTime = LockClientUtils.TimeStamp();


            PutItemResponse response = _client.PutItemAsync(putItemRequest).Result;

            if (response.HttpStatusCode == HttpStatusCode.OK)
            {
                //todo: do something with this
            }

            LockItem lockItem =
                new LockItem(partitionKey, _ownerName, recordVersionNumber, DateTime.Now, null);

            _locks.TryAdd(lockItem.UniqueIdentifier, lockItem);

            return(lockItem);
        }
 private void ReleaseLockItem(LockItem lockItem, TKey key)
 {
     lock (Locker)
     {
         lockItem.UsedCount -= 1;
         if (lockItem.UsedCount == 0)
         {
             if (Dictionary.TryGetValue(key, out var stored))
             {
                 if (stored == lockItem)     // Sanity check
                 {
                     Dictionary.Remove(key);
                     if (Pool.Count < PoolSize)
                     {
                         Pool.Enqueue(lockItem);
                     }
                 }
             }
         }
     }
 }
示例#15
0
        public LockItem AddAndWatchNewOrReleasedLock(string partitionKey, string recordVersionNumber,
                                                     Dictionary <string, AttributeValue> item)
        {
            Dictionary <string, string> expressionAttributeNames = new Dictionary <string, string>
            {
                { PkPathExpressionVariable, _partitionKeyName },
                { IsReleasedPathExpressionVariable, IsReleased }
            };

            Dictionary <string, AttributeValue> expressionAttributeValues =
                new Dictionary <string, AttributeValue> {
                { IsReleasedValueExpressionVariable, IsReleasedAttributeValue }
            };


            PutItemRequest putItemRequest = new PutItemRequest(_tableName, item)
            {
                ConditionExpression       = AcquireLockThatDoesntExistOrIsReleasedCondition,
                ExpressionAttributeNames  = expressionAttributeNames,
                ExpressionAttributeValues = expressionAttributeValues
            };


            long lastUpdatedTime = LockClientUtils.TimeStamp();


            PutItemResponse response = _client.PutItemAsync(putItemRequest).Result;

            if (response.HttpStatusCode != HttpStatusCode.OK)
            {
                //todo: do something with this
            }

            LockItem lockItem =
                new LockItem(partitionKey, _ownerName, recordVersionNumber, DateTime.Now, null);

            _locks.TryAdd(lockItem.UniqueIdentifier, lockItem);

            return(lockItem);
        }
    private LockItem GetLockItem(TKey key)
    {
        LockItem lockItem;

        lock (Locker)
        {
            if (!Dictionary.TryGetValue(key, out lockItem))
            {
                if (Pool.Count > 0)
                {
                    lockItem = Pool.Dequeue();
                }
                else
                {
                    lockItem = new LockItem();
                }
                Dictionary.Add(key, lockItem);
            }
            lockItem.UsedCount += 1;
        }
        return(lockItem);
    }
示例#17
0
        /// <summary>
        /// Waits for and acquires a lock on the specified key. Dispose the returned value to release the lock.
        /// </summary>
        /// <param name="key"></param>
        public Task <IDisposable> GetLock(T key)
        {
            // ReSharper disable once InconsistentlySynchronizedField - by design
            var nextLi = new LockItem(locks, key);

            try
            {
                var continueImmediately = false;
                lock (locks)
                {
                    if (!locks.TryGetValue(key, out var li))
                    {
                        locks.Add(key, nextLi);
                        continueImmediately = true;
                    }
                    else
                    {
                        while (li.Next != null)
                        {
                            li = li.Next;
                        }

                        li.Next = nextLi;
                    }
                }
                if (continueImmediately)
                {
                    nextLi.Continue();
                }
            }
            catch (Exception e)
            {
                nextLi.Error(e);
            }
            return(nextLi.GetTask());
        }
示例#18
0
        public Task <IDisposable> GetLock(T key)
        {
            LockItem nextLi = new LockItem(locks, key);

            try
            {
                bool continueImmediately = false;
                lock (locks)
                {
                    LockItem li;
                    if (!locks.TryGetValue(key, out li))
                    {
                        locks.Add(key, nextLi);
                        continueImmediately = true;
                    }
                    else
                    {
                        while (li.Next != null)
                        {
                            li = li.Next;
                        }

                        li.Next = nextLi;
                    }
                }
                if (continueImmediately)
                {
                    nextLi.Continue();
                }
            }
            catch (Exception e)
            {
                nextLi.Error(e);
            }
            return(nextLi.GetTask());
        }
示例#19
0
 void OnItemUp(LockItem trans)
 {
     if (!isBegin)
     {
         return;
     }
     if (recordList.Count <= maxPoint && recordList.Count >= minPoint)  //点个数有效
     {
         isEnd = true;
     }
     if (!_isEnd)
     {
         OnDrawIllegal(recordList.Count);
         DisDrawSelection();
     }
     else
     {
         List <int> vl = new List <int>();
         recordList.ForEach((x) => {
             vl.Add(x.GetComponent <LockItem>().getValue());
         });
         OnDrawEnd(vl.ToArray());
     }
 }
示例#20
0
 public void Init()
 {
     Lock           = LockItem.CreateDenied("xxx");
     RepositoryMock = new Mock <IResourceLockRepository>();
     Guard          = new ResourceLockGuard(Lock, Repository);
 }
 public void Init()
 {
     Lock           = LockItem.CreateWrite("xxx", null);
     RepositoryMock = new Mock <IResourceLockRepository>();
     Guard          = new ResourceLockGuard(Lock, Repository);
 }
示例#22
0
 public bool Equals(LockItem <T> p)
 {
     return(this == p);
 }
示例#23
0
        private async Task <LockItem> AcquireLockItemAsync(string partitionKey, long?millisecondsToWait,
                                                           long?refreshPeriodInMilliseconds)
        {
            long timeToWait    = millisecondsToWait ?? DefaultBufferMs;
            long refreshPeriod = refreshPeriodInMilliseconds ?? DefaultBufferMs;

            Stopwatch stopWatch = new Stopwatch();

            stopWatch.Start();

            LockItem lockTryingToBeAcquired            = null;
            bool     alreadySleptOnceForOneLeasePeriod = false;


            while (true)
            {
                try
                {
                    try
                    {
                        var existingLockItem = GetExistingLock(partitionKey);

                        if (existingLockItem == null || existingLockItem.IsReleased)
                        {
                            var recordVersionNumber = GenerateRecordVersionNumber();
                            var item = BuildLockItem(partitionKey, recordVersionNumber);

                            var lockItem = AddAndWatchNewOrReleasedLock(partitionKey, recordVersionNumber, item);

                            var lockAcquiredTime = stopWatch.ElapsedMilliseconds;

                            Console.WriteLine($"lock acquired in {lockAcquiredTime / 1000}");

                            return(lockItem);
                        }

                        if (lockTryingToBeAcquired == null)
                        {
                            //this branch of logic only happens once, in the first iteration of the while loop
                            //lockTryingToBeAcquired only ever gets set to non-null values after this point.
                            //so it is impossible to get in this

                            /*
                             * Someone else has the lock, and they have the lock for LEASE_DURATION time. At this point, we need
                             * to wait at least LEASE_DURATION milliseconds before we can try to acquire the lock.
                             */
                            lockTryingToBeAcquired = existingLockItem;
                            if (!alreadySleptOnceForOneLeasePeriod)
                            {
                                alreadySleptOnceForOneLeasePeriod = true;
                                timeToWait += existingLockItem.LeaseDuration;

                                Console.WriteLine($"will wait {timeToWait / 1000} seconds for lock");
                            }
                        }
                        else
                        {
                            if (lockTryingToBeAcquired.RecordVersionNumber.Equals(existingLockItem.RecordVersionNumber))
                            {
                                /* If the version numbers match, then we can acquire the lock, assuming it has already expired */
                                if (lockTryingToBeAcquired.IsExpired)
                                {
                                    var lockItem = UpsertExpiredLock(partitionKey,
                                                                     lockTryingToBeAcquired.RecordVersionNumber);

                                    var lockAcquiredTime = stopWatch.ElapsedMilliseconds;

                                    Console.WriteLine($"lock acquired in {lockAcquiredTime / 1000}");

                                    return(lockItem);
                                }
                            }
                            else
                            {
                                /*
                                 * If the version number changed since we last queried the lock, then we need to update
                                 * lockTryingToBeAcquired as the lock has been refreshed since we last checked
                                 */
                                lockTryingToBeAcquired = existingLockItem;
                            }
                        }
                    }
                    catch (ConditionalCheckFailedException conditionalCheckFailedException)
                    {
                        /* Someone else acquired the lock while we tried to do so, so we throw an exception */
                        // logger.debug("Someone else acquired the lock", conditionalCheckFailedException);
                        throw new LockNotGrantedException("Could not acquire lock because someone else acquired it: ",
                                                          conditionalCheckFailedException);
                    }
                    catch (AmazonClientException amazonClientException)
                    {
                        /* This indicates that we were unable to successfully connect and make a service call to DDB. Often
                         * indicative of a network failure, such as a socket timeout. We retry if still within the time we
                         * can wait to acquire the lock.
                         */
                        //  logger.warn("Could not acquire lock because of a client side failure in talking to DDB", amazonClientException);
                    }
                }
                catch (LockNotGrantedException lockNotGrantedException)
                {
                    if (stopWatch.ElapsedMilliseconds > timeToWait)
                    {
                        //logger.debug("This client waited more than millisecondsToWait=" + millisecondsToWait
                        //                                                                + " ms since the beginning of this acquire call.", x);
                        //throw x;

                        throw;
                    }
                }


                double timeElapsed = Math.Round((double)stopWatch.ElapsedMilliseconds, MidpointRounding.ToEven);

                Console.WriteLine($"Time elapsed {timeElapsed * 0.001} seconds");

                if (timeElapsed > timeToWait)
                {
                    Console.WriteLine($"item timesince last lookup {lockTryingToBeAcquired.TimeSinceLastLookUp}");
                    Console.WriteLine($"lock not granted after {timeElapsed / 1000} seconds of waiting. ");

                    throw new LockNotGrantedException(
                              "Didn't acquire lock after sleeping for " +
                              (timeElapsed) + " milliseconds", null);
                }

                //logger.trace("Sleeping for a refresh period of " + refreshPeriodInMilliseconds + " ms");

                Console.WriteLine("Sleeping for a refresh period of " + refreshPeriod + " ms");

                //Thread.Sleep((int)refreshPeriod);

                var sleepStartTime = stopWatch.ElapsedMilliseconds;

                await Task.Delay((int)refreshPeriod);

                var sleepEndTime = stopWatch.ElapsedMilliseconds;

                var sleepTime = sleepEndTime - sleepStartTime;

                Console.WriteLine($"slept {sleepTime / 1000} seconds");
            }
        }
示例#24
0
        public bool ReleaseLock(LockItem item)
        {
            if (!item.Owner.Equals(_ownerName))
            {
                return(false);
            }

            lock (_threadLock)
            {
                try
                {
                    _locks.TryRemove(item.UniqueIdentifier, out var removedLockItem);

                    Dictionary <string, AttributeValue> expressionAttributeValues =
                        new Dictionary <string, AttributeValue>
                    {
                        { RvnValueExpressionVariable, new AttributeValue {
                              S = item.RecordVersionNumber
                          } },
                        { OwnerNameValueExpressionVariable, new AttributeValue {
                              S = item.Owner
                          } }
                    };

                    Dictionary <string, string> expressionAttributeNames = new Dictionary <string, string>
                    {
                        { PkPathExpressionVariable, _partitionKeyName },
                        { OwnerNamePathExpressionVariable, OwnerName },
                        { RvnPathExpressionVariable, RecordVersionNumber }
                    };

                    var conditionalExpression = PkExistsAndOwnerNameSameAndRvnSameCondition;

                    Dictionary <string, AttributeValue> key = new Dictionary <string, AttributeValue>
                    {
                        {
                            _partitionKeyName, new AttributeValue
                            {
                                S = item.UniqueIdentifier
                            }
                        }
                    };

                    string updateExpression = null;
                    expressionAttributeNames.Add(IsReleasedPathExpressionVariable, IsReleased);
                    expressionAttributeValues.Add(IsReleasedValueExpressionVariable, IsReleasedAttributeValue);

                    updateExpression = UpdateIsReleased;


                    UpdateItemRequest updateItemRequest =
                        new UpdateItemRequest(_tableName, key, null)
                    {
                        ConditionExpression       = conditionalExpression,
                        UpdateExpression          = updateExpression,
                        ExpressionAttributeNames  = expressionAttributeNames,
                        ExpressionAttributeValues = expressionAttributeValues
                    };


                    UpdateItemResponse response =
                        _client.UpdateItemAsync(updateItemRequest, CancellationToken.None).Result;
                }
                catch (ConditionalCheckFailedException conditionalCheckFailedException)
                {
                    // logger.debug("Someone else acquired the lock before you asked to release it", conditionalCheckFailedException);
                    return(false);
                }
                catch (AmazonClientException amazonClientException)
                {
                    throw;
                }
            }

            return(true);
        }
示例#25
0
        public void SendHeartbeat(LockItem item)
        {
            long leaseDurationToEnsureInMilliseconds = _leaseDuration;


            if (item.IsExpired || !item.Owner.Equals(this._ownerName) || item.IsReleased)
            {
                _locks.TryRemove(item.UniqueIdentifier, out var removedLockItem);

                throw new LockNotGrantedException("Cannot send heartbeat because lock is not granted", null);
            }

            lock (_threadLock)
            {
                string recordVersionNumber   = GenerateRecordVersionNumber();
                string conditionalExpression = null;
                string updateExpression      = null;

                Dictionary <string, AttributeValue> expressionAttributeValues = new Dictionary <string, AttributeValue>
                {
                    { RvnValueExpressionVariable, new AttributeValue {
                          S = item.RecordVersionNumber
                      } },
                    { OwnerNameValueExpressionVariable, new AttributeValue {
                          S = item.Owner
                      } }
                };

                Dictionary <string, string> expressionAttributeNames = new Dictionary <string, string>
                {
                    { PkPathExpressionVariable, _partitionKeyName },
                    { LeaseDurationPathValueExpressionVariable, LeaseDuration },
                    { RvnPathExpressionVariable, RecordVersionNumber },
                    { OwnerNamePathExpressionVariable, OwnerName }
                };


                expressionAttributeValues.Add(NewRvnValueExpressionVariable, new AttributeValue {
                    S = recordVersionNumber
                });
                expressionAttributeValues.Add(LeaseDurationValueExpressionVariable, new AttributeValue
                {
                    S = _leaseDuration.ToString()
                });


                conditionalExpression = PkExistsAndOwnerNameSameAndRvnSameCondition;
                updateExpression      = UpdateLeaseDurationAndRvn;

                var key = new Dictionary <string, AttributeValue>
                {
                    { _partitionKeyName, new AttributeValue {
                          S = item.UniqueIdentifier
                      } }
                };

                UpdateItemRequest updateItemRequest =
                    new UpdateItemRequest(_tableName, key, null)
                {
                    ConditionExpression       = conditionalExpression,
                    UpdateExpression          = updateExpression,
                    ExpressionAttributeValues = expressionAttributeValues,
                    ExpressionAttributeNames  = expressionAttributeNames
                };



                try
                {
                    UpdateItemResponse response = _client.UpdateItemAsync(updateItemRequest).Result;

                    if (response.HttpStatusCode != HttpStatusCode.OK)
                    {
                        throw new LockNotGrantedException("failed to updated database", null);
                    }

                    item.UpdatedRecordVersionNumber(recordVersionNumber, DateTime.Now,
                                                    leaseDurationToEnsureInMilliseconds);

                    Console.WriteLine($"updated lock item : {item.UniqueIdentifier} with new RVN: {recordVersionNumber} and lease {_leaseDuration / 1000} seconds");
                }
                catch (ConditionalCheckFailedException conditionalCheckFailedException)
                {
                    //    logger.debug("Someone else acquired the lock, so we will stop heartbeating it", conditionalCheckFailedException);
                    _locks.TryRemove(item.UniqueIdentifier, out var lockToRemove);
                    throw new LockNotGrantedException("Someone else acquired the lock, so we will stop heartbeating it",
                                                      conditionalCheckFailedException);
                }
            }
        }