Example #1
0
        public async Task ReleaseLock(string Id)
        {
            lock (_lockRegistry)
            {
                var localLocks = _lockRegistry.Where(x => x.ResourceId == Id && x.NodeId == _nodeId).ToList();
                foreach (var local in localLocks)
                {
                    _lockRegistry.Remove(local);
                }
            }

            var peerList        = _peerLastContact.Select(x => x.Key).ToList();
            var activePeerCount = _peerLastContact.Where(x => x.Value >= (DateTime.Now.Subtract(_peerTTL))).Count();
            int peerQuorum      = (activePeerCount / 2) + 1;

            if (activePeerCount == 0)
            {
                peerQuorum = 0;
            }

            PendingLock pendingRelease = new PendingLock();

            pendingRelease.ResourceId = Id;
            lock (_pendingReleases)
                _pendingReleases.Add(pendingRelease);

            lock (_server)
            {
                foreach (var peerId in peerList)
                {
                    _server
                    .SendMoreFrame(peerId.ToByteArray())
                    .SendMoreFrame(_nodeId.ToByteArray())
                    .SendMoreFrame(ConvertOp(MessageOp.Release))
                    .SendFrame(Id);
                }
            }

            Task task = new Task(() =>
            {
                DateTime expiry = DateTime.Now.Add(_lockTimeout);
                while ((pendingRelease.Responses.Count() < peerQuorum) && (DateTime.Now < expiry))
                {
                    System.Threading.Thread.Sleep(10);
                }
                _pendingReleases.Remove(pendingRelease);
            });

            task.Start();
            await task;
        }
Example #2
0
        public async Task <bool> AcquireLock(string Id)
        {
            if (_lockRegistry.Any(x => x.ResourceId == Id))
            {
                return(false);
            }

            PendingLock pendingLock = new PendingLock();

            pendingLock.ResourceId = Id;
            lock (_pendingLocks)
                _pendingLocks.Add(pendingLock);

            var peerList     = _peerLastContact.Where(x => x.Value >= (DateTime.Now.Subtract(_peerTTL))).Select(x => x.Key).ToList();
            int requestCount = peerList.Count();
            int peerQuorum   = (requestCount / 2) + 1;

            if (requestCount == 0)
            {
                peerQuorum = 0;
            }

            lock (_server)
            {
                foreach (var peerId in peerList)
                {
                    _server
                    .SendMoreFrame(peerId.ToByteArray())
                    .SendMoreFrame(_nodeId.ToByteArray())
                    .SendMoreFrame(ConvertOp(MessageOp.Acquire))
                    .SendFrame(Id);
                }
            }

            Task <bool> task = new Task <bool>(() =>
            {
                DateTime expiry = DateTime.Now.Add(_lockTimeout);
                _logger.LogDebug("({0}) Waiting for quorum of {1} on {2}, expires at {3}", _nodeId, peerQuorum, Id, expiry);
                while ((pendingLock.Responses.Count() < peerQuorum) && (!pendingLock.Responses.Any(x => !x.Value)) && (DateTime.Now < expiry))
                {
                    System.Threading.Thread.Sleep(10);
                }
                _logger.LogDebug("({0}) Remote responses on {1}, count {2} of {3}", _nodeId, Id, pendingLock.Responses.Count(), peerQuorum);
                var result = (pendingLock.Responses.Count(x => x.Value) >= peerQuorum) && (pendingLock.Responses.Count(x => !x.Value) == 0);
                if (!result)
                {
                    lock (_server)
                    {
                        foreach (var rollbackPeer in pendingLock.Responses.Where(x => x.Value).Select(x => x.Key).ToList())
                        {
                            _server
                            .SendMoreFrame(rollbackPeer.ToByteArray())
                            .SendMoreFrame(_nodeId.ToByteArray())
                            .SendMoreFrame(ConvertOp(MessageOp.Release))
                            .SendFrame(Id);
                        }
                    }
                }
                else
                {
                    DistributedLock distLock = new DistributedLock();
                    distLock.NodeId          = _nodeId;
                    distLock.ResourceId      = Id;
                    distLock.Expiry          = DateTime.Now.Add(_lockTTL);
                    lock (_lockRegistry)
                        _lockRegistry.Add(distLock);
                }
                lock (_pendingLocks)
                    _pendingLocks.Remove(pendingLock);
                return(result);
            });

            task.Start();
            return(await task);
        }