private RemovedKeys UnsubscribeInternal(IRedisChannel channel, IEnumerable <String> keys)
        {
            var removed = new RemovedKeys();
            HashSet <IRedisChannel> subscribed;

            foreach (var key in keys)
            {
                if (_subscribed.TryGetValue(key, out subscribed))
                {
                    subscribed.Remove(channel);
                    if (subscribed.Count == 0)
                    {
                        removed.Add(key);
                        _subscribed.Remove(key);
                    }
                }
            }

            HashSet <String> channelSubscriptions;

            if (_subscriptions.TryGetValue(channel, out channelSubscriptions))
            {
                channelSubscriptions.RemoveWhere(s => keys.Contains(s));
                if (channelSubscriptions.Count == 0)
                {
                    _subscriptions.Remove(channel);
                }
            }

            return(removed);
        }
        public void ApplyLeave(
            EventBean[] eventsPerStream,
            object groupByKeyProvided,
            ExprEvaluatorContext exprEvaluatorContext)
        {
            if (InstrumentationHelper.ENABLED)
            {
                InstrumentationHelper.Get().QAggregationGroupedApplyEnterLeave(false, LocalGroupByPlan.NumMethods, LocalGroupByPlan.NumAccess, groupByKeyProvided);
            }

            if (LocalGroupByPlan.OptionalLevelTop != null)
            {
                if (AggregatorsTopLevel == null)
                {
                    AggregatorsTopLevel = AggSvcGroupByUtil.NewAggregators(LocalGroupByPlan.OptionalLevelTop.MethodFactories);
                    StatesTopLevel      = AggSvcGroupByUtil.NewAccesses(exprEvaluatorContext.AgentInstanceId, IsJoin, LocalGroupByPlan.OptionalLevelTop.StateFactories, null, null);
                }
                AggregateIntoLeave(
                    LocalGroupByPlan.OptionalLevelTop, AggregatorsTopLevel, StatesTopLevel, eventsPerStream,
                    exprEvaluatorContext);
                InternalHandleUpdatedTop();
            }

            for (var levelNum = 0; levelNum < LocalGroupByPlan.AllLevels.Length; levelNum++)
            {
                var level         = LocalGroupByPlan.AllLevels[levelNum];
                var partitionEval = level.PartitionEvaluators;
                var groupByKey    = ComputeGroupKey(
                    level, groupByKeyProvided, partitionEval, eventsPerStream, true, exprEvaluatorContext);
                var row = AggregatorsPerLevelAndGroup[levelNum].Get(groupByKey);
                if (row == null)
                {
                    var rowAggregators           = AggSvcGroupByUtil.NewAggregators(level.MethodFactories);
                    AggregationState[] rowStates = AggSvcGroupByUtil.NewAccesses(exprEvaluatorContext.AgentInstanceId, IsJoin, level.StateFactories, groupByKey, null);
                    row = new AggregationMethodPairRow(1, rowAggregators, rowStates);
                    AggregatorsPerLevelAndGroup[levelNum].Put(groupByKey, row);
                }
                else
                {
                    row.DecreaseRefcount();
                    if (row.Refcount <= 0)
                    {
                        RemovedKeys.Add(new Pair <int, object>(levelNum, groupByKey));
                    }
                }
                AggregateIntoLeave(level, row.Methods, row.States, eventsPerStream, exprEvaluatorContext);
                InternalHandleUpdatedGroup(levelNum, groupByKey, row);
            }
            if (InstrumentationHelper.ENABLED)
            {
                InstrumentationHelper.Get().AAggregationGroupedApplyEnterLeave(false);
            }
        }