internal void HandleMessage(SubscriptionState state, RedisValue[] multiBytes)
        {
            try
            {
                for (var i = 0; i < multiBytes.Length; i += 3)
                {
                    var messageType = multiBytes[i];
                    var channel = (string)multiBytes[i + 1];

                    if (MessageWord.IsEqualTo(messageType))
                    {
                        if (OnMessage != null)
                            OnMessage(channel, multiBytes[i + 2]);
                    }
                    else if (SubscribeWord.IsEqualTo(messageType))
                    {
                        var count = (int)multiBytes[i + 2];

                        state.DoLock(() =>
                        {
                            int delta = (count - state.SubscriptionCount);
                            Interlocked.Add(ref _subscriptionCount, delta);
                            state.Channels.Add(channel);
                            // if (count != state.Channels.Count) { throw }
                        });

                        if (OnSubscribe != null)
                            OnSubscribe(channel);

                        if (HasSubscriptions)
                            _noSubscriptions.Reset();

                    }
                    else if (UnSubscribeWord.IsEqualTo(messageType))
                    {
                        var count = (int)multiBytes[i + 2];

                        state.DoLock(() =>
                        {
                            int delta = (count - state.SubscriptionCount);
                            Interlocked.Add(ref _subscriptionCount, delta);
                            state.Channels.Remove(channel);
                            // if (state.Channels.Count != count) -- error
                        });

                        if (OnUnSubscribe != null)
                            OnUnSubscribe(channel);

                        if (!HasSubscriptions)
                            _noSubscriptions.Set();

                    }
                    else
                    {
                        throw new RedisException(
                            "Invalid state. Expected [subscribe|unsubscribe|message] got: " + messageType);
                    }
                }
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
        }
        static void BeginSend(SubscriptionState state)
        {
            var buffer = state.CommandBuffer.Data;
            var buflen = state.CommandBuffer.Size;

            var client = state.RawSocket;

            client.BeginSend(buffer, 0, buflen, SocketFlags.None, new AsyncCallback(EndSend), state);
            state.SendDone.WaitOne();
            state.SendDone.Reset();
        }
        static void BeginReadMessages(SubscriptionState state)
        {
            var self = state.Subscription;
            
            if (self.IsShutDown)
                return;

            var client = state.RawSocket;

            int buflen = RedisSubscription.ReadBufferSize;
            var buffer = state.ReadBuffer.Array;
            client.BeginReceive(buffer, 0, buflen, SocketFlags.None, 
                new AsyncCallback(EndReadMessages), state);
        }
 public SubscriptionState GetSubscriptionState(IRedisNode node)
 {
     lock(_lockObject)
     {
         SubscriptionState result;
         if (!_states.TryGetValue(node, out result))
         {
             result = new SubscriptionState(node) {Subscription = this};
             _states.Add(node, result);
         }
         return result;
     }    
 }