예제 #1
0
        /// <summary>
        /// Invalidates the MessageClient.
        /// </summary>
        /// <param name="notifyClient">Push a subscription invalidation message to the client.</param>
        public void Invalidate(bool notifyClient)
        {
            lock (this.SyncRoot)
            {
                if (!IsValid || IsInvalidating)
                    return; // Already shutting down.

                SetIsInvalidating(true);
                _messageDestination.SubscriptionManager.CancelTimeout(this);
            }

            // Build a subscription invalidation message and push to the client if it is still valid.
            if (notifyClient && _client != null && _client.IsValid)
            {
                CommandMessage commandMessage = new CommandMessage();
                commandMessage.destination= _messageDestination.Id;
                commandMessage.clientId = _clientId;
                commandMessage.operation = CommandMessage.SessionInvalidateOperation;

                MessageService messageService = _messageDestination.Service as MessageService;
                object[] subscribers = new object[] { commandMessage.clientId };
                try
                {
                    messageService.PushMessageToClients(subscribers, commandMessage);
                }
                catch (MessageException) 
                { }
            }

            // Notify listeners that we're being invalidated.
            if (_messageClientDestroyedListeners != null && _messageClientDestroyedListeners.Count != 0)
            {
                foreach (IMessageClientListener listener in _messageClientDestroyedListeners.Keys )
                {
                    listener.MessageClientDestroyed(this);
                }
                _messageClientDestroyedListeners.Clear();
            }

            // Generate unsubscribe messages for all of the MessageClient's subscriptions and 
            // route them to the destination this MessageClient is subscribed to.
            // Some adapters manage their own subscription state.
            ArrayList unsubscribeMessages = new ArrayList();
            lock (this.SyncRoot)
            {
                foreach(SubscriptionInfo subscription in _subscriptions)
                {
                    CommandMessage unsubscribeMessage = new CommandMessage();
                    unsubscribeMessage.destination = _messageDestination.Id;
                    unsubscribeMessage.clientId = _clientId;
                    unsubscribeMessage.operation = CommandMessage.UnsubscribeOperation;
                    unsubscribeMessage.SetHeader(CommandMessage.SessionInvalidatedHeader, true);
                    unsubscribeMessage.SetHeader(CommandMessage.SelectorHeader, subscription.Selector);
                    unsubscribeMessage.SetHeader(AsyncMessage.SubtopicHeader, subscription.Subtopic);
                    unsubscribeMessages.Add(unsubscribeMessage);
                }
            }
            // Release the lock and send the unsub messages.
            foreach (CommandMessage commandMessage in unsubscribeMessages)
            {
                try
                {
                    _messageDestination.Service.ServiceMessage(commandMessage);
                }
                catch (MessageException me)
                {
                    if (log.IsDebugEnabled)
                        log.Debug("MessageClient: " + _clientId + " issued an unsubscribe message during invalidation that was not processed but will continue with invalidation.", me);
                }
            }

            //TODO
            RemoveSubscription(this.Selector, this.Subtopic);

            lock (this.SyncRoot)
            {
                // If we didn't clean up all subscriptions log an error and continue with shutdown.
                int remainingSubscriptionCount = _subscriptions.Count;
                if (remainingSubscriptionCount > 0 && log.IsErrorEnabled)
                    log.Error("MessageClient: " + _clientId + " failed to remove " + remainingSubscriptionCount + " subscription(s) during invalidation");
            }

            _messageDestination.SubscriptionManager.RemoveSubscriber(this);

            lock (this.SyncRoot)
            {
                SetIsValid(false);
                SetIsInvalidating(false);
            }
        }