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