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