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