//always call this from a readlock void CleanupMeshEntry(MeshEntry meshEntry) { List <Guid> remove = new List <Guid>(); if (!opened) { return; } LiteLock ll = null; try { LiteLock.Acquire(out ll, meshEntry.Gate, true); foreach (KeyValuePair <Guid, RegistrationEntry> item in meshEntry.EntryTable) { if ((item.Value.Expires <= DateTime.UtcNow) || (item.Value.State == RegistrationState.Deleted)) { remove.Add(item.Key); meshEntry.EntryList.Remove(item.Value); meshEntry.Service2EntryTable.Remove(item.Value.Address.ServicePath); } } foreach (Guid id in remove) { meshEntry.EntryTable.Remove(id); } } finally { LiteLock.Release(ll); } }
private void CleanupMeshEntry(MeshEntry meshEntry) { List <Guid> list = new List <Guid>(); if (this.opened) { LiteLock liteLock = null; try { LiteLock.Acquire(out liteLock, meshEntry.Gate, true); foreach (KeyValuePair <Guid, RegistrationEntry> pair in meshEntry.EntryTable) { if ((pair.Value.Expires <= DateTime.UtcNow) || (pair.Value.State == RegistrationState.Deleted)) { list.Add(pair.Key); meshEntry.EntryList.Remove(pair.Value); meshEntry.Service2EntryTable.Remove(pair.Value.Address.ServicePath); } } foreach (Guid guid in list) { meshEntry.EntryTable.Remove(guid); } } finally { LiteLock.Release(liteLock); } } }
MeshEntry GetMeshEntry(string meshId, bool createIfNotExists) { MeshEntry meshEntry = null; LiteLock ll = null; try { LiteLock.Acquire(out ll, gate); if (!this.meshId2Entry.TryGetValue(meshId, out meshEntry) && createIfNotExists) { meshEntry = new MeshEntry(); try { ll.UpgradeToWriterLock(); meshId2Entry.Add(meshId, meshEntry); } finally { ll.DowngradeFromWriterLock(); } } } finally { LiteLock.Release(ll); } Fx.Assert(meshEntry != null || !createIfNotExists, "GetMeshEntry failed to get an entry!"); return(meshEntry); }
public virtual void Unregister(UnregisterInfo unregisterInfo) { if (unregisterInfo == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("unregisterinfo", System.ServiceModel.SR.GetString("PeerNullRegistrationInfo")); } this.ThrowIfClosed("Unregister"); if ((!unregisterInfo.HasBody() || string.IsNullOrEmpty(unregisterInfo.MeshId)) || (unregisterInfo.RegistrationId == Guid.Empty)) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("unregisterInfo", System.ServiceModel.SR.GetString("PeerInvalidMessageBody", new object[] { unregisterInfo })); } RegistrationEntry entry = null; MeshEntry meshEntry = this.GetMeshEntry(unregisterInfo.MeshId, false); LiteLock liteLock = null; try { LiteLock.Acquire(out liteLock, meshEntry.Gate, true); if (!meshEntry.EntryTable.TryGetValue(unregisterInfo.RegistrationId, out entry)) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("unregisterInfo", System.ServiceModel.SR.GetString("PeerInvalidMessageBody", new object[] { unregisterInfo })); } meshEntry.EntryTable.Remove(unregisterInfo.RegistrationId); meshEntry.EntryList.Remove(entry); meshEntry.Service2EntryTable.Remove(entry.Address.ServicePath); entry.State = RegistrationState.Deleted; } finally { LiteLock.Release(liteLock); } }
public virtual RegisterResponseInfo Register(Guid clientId, string meshId, PeerNodeAddress address) { Guid registrationId = Guid.NewGuid(); DateTime expires = DateTime.UtcNow + this.RefreshInterval; RegistrationEntry entry = null; MeshEntry meshEntry = null; lock (this.ThisLock) { entry = new RegistrationEntry(clientId, registrationId, meshId, expires, address); meshEntry = this.GetMeshEntry(meshId); if (meshEntry.Service2EntryTable.ContainsKey(address.ServicePath)) { PeerExceptionHelper.ThrowInvalidOperation_DuplicatePeerRegistration(address.ServicePath); } LiteLock liteLock = null; try { LiteLock.Acquire(out liteLock, meshEntry.Gate, true); meshEntry.EntryTable.Add(registrationId, entry); meshEntry.EntryList.Add(entry); meshEntry.Service2EntryTable.Add(address.ServicePath, entry); } finally { LiteLock.Release(liteLock); } } return(new RegisterResponseInfo(registrationId, this.RefreshInterval)); }
private MeshEntry GetMeshEntry(string meshId, bool createIfNotExists) { MeshEntry entry = null; LiteLock liteLock = null; try { LiteLock.Acquire(out liteLock, this.gate); if (this.meshId2Entry.TryGetValue(meshId, out entry) || !createIfNotExists) { return(entry); } entry = new MeshEntry(); try { liteLock.UpgradeToWriterLock(); this.meshId2Entry.Add(meshId, entry); } finally { liteLock.DowngradeFromWriterLock(); } } finally { LiteLock.Release(liteLock); } return(entry); }
public virtual RegisterResponseInfo Update(UpdateInfo updateInfo) { if (updateInfo == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("updateInfo", SR.GetString(SR.PeerNullRegistrationInfo)); } ThrowIfClosed("Update"); if (!updateInfo.HasBody() || String.IsNullOrEmpty(updateInfo.MeshId) || updateInfo.NodeAddress == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("updateInfo", SR.GetString(SR.PeerInvalidMessageBody, updateInfo)); } Guid registrationId = updateInfo.RegistrationId; RegistrationEntry entry; MeshEntry meshEntry = GetMeshEntry(updateInfo.MeshId); LiteLock ll = null; //handle cases when Update ----s with Register. if (updateInfo.RegistrationId == Guid.Empty || meshEntry == null) { return(Register(updateInfo.ClientId, updateInfo.MeshId, updateInfo.NodeAddress)); } // // preserve locking order between ThisLock and the LiteLock. lock (ThisLock) { try { LiteLock.Acquire(out ll, meshEntry.Gate); if (!meshEntry.EntryTable.TryGetValue(updateInfo.RegistrationId, out entry)) { try { // upgrade to writer lock ll.UpgradeToWriterLock(); return(Register(updateInfo.ClientId, updateInfo.MeshId, updateInfo.NodeAddress)); } finally { ll.DowngradeFromWriterLock(); } } lock (entry) { entry.Address = updateInfo.NodeAddress; entry.Expires = DateTime.UtcNow + this.RefreshInterval; } } finally { LiteLock.Release(ll); } } return(new RegisterResponseInfo(registrationId, RefreshInterval)); }
public virtual ResolveResponseInfo Resolve(ResolveInfo resolveInfo) { if (resolveInfo == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("resolveInfo", System.ServiceModel.SR.GetString("PeerNullResolveInfo")); } this.ThrowIfClosed("Resolve"); if (!resolveInfo.HasBody()) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("resolveInfo", System.ServiceModel.SR.GetString("PeerInvalidMessageBody", new object[] { resolveInfo })); } int num = 0; int num2 = 0; int maxAddresses = resolveInfo.MaxAddresses; ResolveResponseInfo info = new ResolveResponseInfo(); List <PeerNodeAddress> list = new List <PeerNodeAddress>(); List <RegistrationEntry> entryList = null; MeshEntry meshEntry = this.GetMeshEntry(resolveInfo.MeshId, false); if (meshEntry != null) { LiteLock liteLock = null; try { LiteLock.Acquire(out liteLock, meshEntry.Gate); entryList = meshEntry.EntryList; if (entryList.Count <= maxAddresses) { foreach (RegistrationEntry entry3 in entryList) { list.Add(entry3.Address); } } else { Random random = new Random(); while (num < maxAddresses) { num2 = random.Next(entryList.Count); RegistrationEntry entry = entryList[num2]; PeerNodeAddress item = entry.Address; if (!list.Contains(item)) { list.Add(item); } num++; } } } finally { LiteLock.Release(liteLock); } } info.Addresses = list.ToArray(); return(info); }
internal virtual void CleanupActivity(object state) { if (!opened) { return; } if (!isCleaning) { lock (ThisLock) { if (!isCleaning) { isCleaning = true; try { MeshEntry meshEntry = null; //acquire a write lock. from the reader/writer lock can we postpone until no contention? ICollection <string> keys = null; LiteLock ll = null; try { LiteLock.Acquire(out ll, gate); keys = meshId2Entry.Keys; } finally { LiteLock.Release(ll); } foreach (string meshId in keys) { meshEntry = GetMeshEntry(meshId); CleanupMeshEntry(meshEntry); } } finally { isCleaning = false; if (opened) { timer.Set(this.CleanupInterval); } } } } } }
public virtual RefreshResponseInfo Refresh(RefreshInfo refreshInfo) { if (refreshInfo == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("refreshInfo", SR.GetString(SR.PeerNullRefreshInfo)); } ThrowIfClosed("Refresh"); if (!refreshInfo.HasBody() || String.IsNullOrEmpty(refreshInfo.MeshId) || refreshInfo.RegistrationId == Guid.Empty) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("refreshInfo", SR.GetString(SR.PeerInvalidMessageBody, refreshInfo)); } RefreshResult result = RefreshResult.RegistrationNotFound; RegistrationEntry entry = null; MeshEntry meshEntry = GetMeshEntry(refreshInfo.MeshId, false); LiteLock ll = null; if (meshEntry != null) { try { LiteLock.Acquire(out ll, meshEntry.Gate); if (!meshEntry.EntryTable.TryGetValue(refreshInfo.RegistrationId, out entry)) { return(new RefreshResponseInfo(RefreshInterval, result)); } lock (entry) { if (entry.State == RegistrationState.OK) { entry.Expires = DateTime.UtcNow + RefreshInterval; result = RefreshResult.Success; } } } finally { LiteLock.Release(ll); } } return(new RefreshResponseInfo(RefreshInterval, result)); }
internal virtual void CleanupActivity(object state) { if (this.opened && !this.isCleaning) { lock (this.ThisLock) { if (!this.isCleaning) { this.isCleaning = true; try { MeshEntry meshEntry = null; ICollection <string> keys = null; LiteLock liteLock = null; try { LiteLock.Acquire(out liteLock, this.gate); keys = this.meshId2Entry.Keys; } finally { LiteLock.Release(liteLock); } foreach (string str in keys) { meshEntry = this.GetMeshEntry(str); this.CleanupMeshEntry(meshEntry); } } finally { this.isCleaning = false; if (this.opened) { this.timer.Set(this.CleanupInterval); } } } } } }
public virtual RefreshResponseInfo Refresh(RefreshInfo refreshInfo) { if (refreshInfo == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("refreshInfo", System.ServiceModel.SR.GetString("PeerNullRefreshInfo")); } this.ThrowIfClosed("Refresh"); if ((!refreshInfo.HasBody() || string.IsNullOrEmpty(refreshInfo.MeshId)) || (refreshInfo.RegistrationId == Guid.Empty)) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("refreshInfo", System.ServiceModel.SR.GetString("PeerInvalidMessageBody", new object[] { refreshInfo })); } RefreshResult registrationNotFound = RefreshResult.RegistrationNotFound; RegistrationEntry entry = null; MeshEntry meshEntry = this.GetMeshEntry(refreshInfo.MeshId, false); LiteLock liteLock = null; if (meshEntry != null) { try { LiteLock.Acquire(out liteLock, meshEntry.Gate); if (!meshEntry.EntryTable.TryGetValue(refreshInfo.RegistrationId, out entry)) { return(new RefreshResponseInfo(this.RefreshInterval, registrationNotFound)); } lock (entry) { if (entry.State == RegistrationState.OK) { entry.Expires = DateTime.UtcNow + this.RefreshInterval; registrationNotFound = RefreshResult.Success; } } } finally { LiteLock.Release(liteLock); } } return(new RefreshResponseInfo(this.RefreshInterval, registrationNotFound)); }
public virtual RegisterResponseInfo Register(Guid clientId, string meshId, PeerNodeAddress address) { Guid registrationId = Guid.NewGuid(); DateTime expiry = DateTime.UtcNow + RefreshInterval; RegistrationEntry entry = null; MeshEntry meshEntry = null; lock (ThisLock) { entry = new RegistrationEntry(clientId, registrationId, meshId, expiry, address); meshEntry = GetMeshEntry(meshId); if (meshEntry.Service2EntryTable.ContainsKey(address.ServicePath)) { PeerExceptionHelper.ThrowInvalidOperation_DuplicatePeerRegistration(address.ServicePath); } LiteLock ll = null; try { // meshEntry.gate can be held by this thread for write if this is coming from update // else MUST not be held at all. if (!meshEntry.Gate.IsWriterLockHeld) { LiteLock.Acquire(out ll, meshEntry.Gate, true); } meshEntry.EntryTable.Add(registrationId, entry); meshEntry.EntryList.Add(entry); meshEntry.Service2EntryTable.Add(address.ServicePath, entry); } finally { if (ll != null) { LiteLock.Release(ll); } } } return(new RegisterResponseInfo(registrationId, RefreshInterval)); }
public virtual RegisterResponseInfo Update(UpdateInfo updateInfo) { if (updateInfo == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("updateInfo", System.ServiceModel.SR.GetString("PeerNullRegistrationInfo")); } this.ThrowIfClosed("Update"); if ((!updateInfo.HasBody() || string.IsNullOrEmpty(updateInfo.MeshId)) || (updateInfo.NodeAddress == null)) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("updateInfo", System.ServiceModel.SR.GetString("PeerInvalidMessageBody", new object[] { updateInfo })); } Guid registrationId = updateInfo.RegistrationId; MeshEntry meshEntry = this.GetMeshEntry(updateInfo.MeshId); LiteLock liteLock = null; if ((updateInfo.RegistrationId == Guid.Empty) || (meshEntry == null)) { return(this.Register(updateInfo.ClientId, updateInfo.MeshId, updateInfo.NodeAddress)); } try { RegistrationEntry entry; LiteLock.Acquire(out liteLock, meshEntry.Gate); if (!meshEntry.EntryTable.TryGetValue(updateInfo.RegistrationId, out entry)) { return(this.Register(updateInfo.ClientId, updateInfo.MeshId, updateInfo.NodeAddress)); } lock (entry) { entry.Address = updateInfo.NodeAddress; entry.Expires = DateTime.UtcNow + this.RefreshInterval; } } finally { LiteLock.Release(liteLock); } return(new RegisterResponseInfo(registrationId, this.RefreshInterval)); }
public virtual void Unregister(UnregisterInfo unregisterInfo) { if (unregisterInfo == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("unregisterinfo", SR.GetString(SR.PeerNullRegistrationInfo)); } ThrowIfClosed("Unregister"); if (!unregisterInfo.HasBody() || String.IsNullOrEmpty(unregisterInfo.MeshId) || unregisterInfo.RegistrationId == Guid.Empty) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("unregisterInfo", SR.GetString(SR.PeerInvalidMessageBody, unregisterInfo)); } RegistrationEntry registration = null; MeshEntry meshEntry = GetMeshEntry(unregisterInfo.MeshId, false); //there could be a ---- that two different threads could be working on the same entry //we wont optimize for that case. LiteLock ll = null; try { LiteLock.Acquire(out ll, meshEntry.Gate, true); if (!meshEntry.EntryTable.TryGetValue(unregisterInfo.RegistrationId, out registration)) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("unregisterInfo", SR.GetString(SR.PeerInvalidMessageBody, unregisterInfo)); } meshEntry.EntryTable.Remove(unregisterInfo.RegistrationId); meshEntry.EntryList.Remove(registration); meshEntry.Service2EntryTable.Remove(registration.Address.ServicePath); registration.State = RegistrationState.Deleted; } finally { LiteLock.Release(ll); } }
public virtual ResolveResponseInfo Resolve(ResolveInfo resolveInfo) { if (resolveInfo == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("resolveInfo", SR.GetString(SR.PeerNullResolveInfo)); } ThrowIfClosed("Resolve"); if (!resolveInfo.HasBody()) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("resolveInfo", SR.GetString(SR.PeerInvalidMessageBody, resolveInfo)); } int currentCount = 0; int index = 0; int maxEntries = resolveInfo.MaxAddresses; ResolveResponseInfo response = new ResolveResponseInfo(); List <PeerNodeAddress> results = new List <PeerNodeAddress>(); List <RegistrationEntry> entries = null; PeerNodeAddress address; RegistrationEntry entry; MeshEntry meshEntry = GetMeshEntry(resolveInfo.MeshId, false); if (meshEntry != null) { LiteLock ll = null; try { LiteLock.Acquire(out ll, meshEntry.Gate); entries = meshEntry.EntryList; if (entries.Count <= maxEntries) { foreach (RegistrationEntry e in entries) { results.Add(e.Address); } } else { Random random = new Random(); while (currentCount < maxEntries) { index = random.Next(entries.Count); entry = entries[index]; Fx.Assert(entry.State == RegistrationState.OK, "A deleted registration is still around!"); address = entry.Address; if (!results.Contains(address)) { results.Add(address); } currentCount++; } } } finally { LiteLock.Release(ll); } } response.Addresses = results.ToArray(); return(response); }