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; }
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); }