private FilterValueSetParam[][] ComputePathsWithNegate(EventBean[] eventsPerStream,
            FilterSpecPlan plan,
            MatchedEventMap matchedEvents,
            ExprEvaluatorContext exprEvaluatorContext,
            StatementContextFilterEvalEnv filterEvalEnv)
        {
            var paths = plan.Paths;
            IList<FilterValueSetParam[]> pathList = new List<FilterValueSetParam[]>(paths.Length);
            foreach (var path in paths) {
                var controlResult = path.PathNegate?.Evaluate(eventsPerStream, true, exprEvaluatorContext);
                if (controlResult != null && false.Equals(controlResult)) {
                    continue;
                }

                var triplets = path.Triplets;
                var valueList = new FilterValueSetParam[triplets.Length];
                PopulateValueSet(valueList, matchedEvents, path.Triplets, exprEvaluatorContext, filterEvalEnv);
                pathList.Add(valueList);
            }

            if (pathList.IsEmpty()) {
                return null; // all path negated
            }

            return pathList.ToArray();
        }
Beispiel #2
0
        public static FilterValueSetParam[][] MultiplyAddendum(
            FilterValueSetParam[][] filtersFirst,
            FilterValueSetParam[][] filtersSecond)
        {
            if (filtersFirst == null || filtersFirst.Length == 0) {
                return filtersSecond;
            }

            if (filtersSecond == null || filtersSecond.Length == 0) {
                return filtersFirst;
            }

            var size = filtersFirst.Length * filtersSecond.Length;
            var result = new FilterValueSetParam[size][];

            var count = 0;
            foreach (var lineFirst in filtersFirst) {
                foreach (var lineSecond in filtersSecond) {
                    result[count] = Append(lineFirst, lineSecond);
                    count++;
                }
            }

            return result;
        }
Beispiel #3
0
        private static void AddAddendums(
            IDictionary <FilterSpecCompiled, FilterValueSetParam[][]> addendums,
            IList <FilterValueSetParam> addendumFilters,
            FilterSpecCompiled filtersSpec,
            FilterValueSetParam[][] optionalPartitionFilters)
        {
            FilterValueSetParam[][] params2Dim = new FilterValueSetParam[1][];
            params2Dim[0] = addendumFilters.ToArray();

            FilterValueSetParam[][] addendum;
            FilterValueSetParam[][] existing = addendums.Get(filtersSpec);
            if (existing != null)
            {
                addendum = ContextControllerAddendumUtil.MultiplyAddendum(existing, params2Dim);
            }
            else
            {
                addendum = params2Dim;
            }

            if (optionalPartitionFilters != null)
            {
                addendum = ContextControllerAddendumUtil.MultiplyAddendum(addendum, optionalPartitionFilters);
            }

            addendums[filtersSpec] = addendum;
        }
Beispiel #4
0
        private static FilterValueSetParam[][] ComputeAddendum(
            object[] parentPartitionKeys,
            FilterSpecActivatable filterCallback,
            bool forStatement,
            ContextControllerStatementDesc optionalStatementDesc,
            ContextControllerFactory[] controllerFactories,
            IDictionary<int, ContextControllerStatementDesc> statements,
            AgentInstanceContext agentInstanceContextCreate)
        {
            var result = new FilterValueSetParam[0][];
            for (var i = 0; i < parentPartitionKeys.Length; i++) {
                var addendumForController = controllerFactories[i]
                    .PopulateFilterAddendum(
                        filterCallback,
                        forStatement,
                        i + 1,
                        parentPartitionKeys[i],
                        optionalStatementDesc,
                        statements,
                        agentInstanceContextCreate);
                result = FilterAddendumUtil.MultiplyAddendum(result, addendumForController);
            }

            return result;
        }
Beispiel #5
0
        private static FilterValueSetParam[] Append(FilterValueSetParam[] first, FilterValueSetParam[] second)
        {
            var appended = new FilterValueSetParam[first.Length + second.Length];

            Array.Copy(first, 0, appended, 0, first.Length);
            Array.Copy(second, 0, appended, first.Length, second.Length);
            return(appended);
        }
Beispiel #6
0
        public void SetUp()
        {
            _eventType  = SupportEventTypeFactory.CreateBeanType(typeof(SupportBean));
            _parameters = new LinkedList <FilterValueSetParam>();

            // Create parameter test list
            _parameterOne = new FilterValueSetParamImpl(MakeLookupable("IntPrimitive"), FilterOperator.GREATER, 10);
            _parameters.AddLast(_parameterOne);
            _parameterTwo = new FilterValueSetParamImpl(MakeLookupable("DoubleBoxed"), FilterOperator.GREATER, 20d);
            _parameters.AddLast(_parameterTwo);
            _parameterThree = new FilterValueSetParamImpl(MakeLookupable("TheString"), FilterOperator.EQUAL, "sometext");
            _parameters.AddLast(_parameterThree);
        }
 internal static void PopulateValueSet(
     FilterValueSetParam[] valueList,
     MatchedEventMap matchedEvents,
     FilterSpecPlanPathTriplet[] triplets,
     ExprEvaluatorContext exprEvaluatorContext,
     StatementContextFilterEvalEnv filterEvalEnv)
 {
     var count = 0;
     foreach (var specParam in triplets) {
         FilterValueSetParam valueParam = specParam.Param.GetFilterValue(matchedEvents, exprEvaluatorContext, filterEvalEnv);
         valueList[count] = valueParam;
         count++;
     }
 }
Beispiel #8
0
        public static FilterValueSetParam[][] GetAddendumFilters(
            FilterSpecCompiled filterSpecCompiled,
            int hashCode,
            ContextDetailHash hashSpec,
            ContextControllerStatementDesc statementDesc)
        {
            // determine whether create-named-window
            var isCreateWindow = statementDesc != null && statementDesc.Statement.StatementSpec.CreateWindowDesc != null;
            ContextDetailHashItem foundPartition = null;

            if (!isCreateWindow)
            {
                foundPartition = FindHashItemSpec(hashSpec, filterSpecCompiled);
            }
            else
            {
                string declaredAsName = statementDesc.Statement.StatementSpec.CreateWindowDesc.AsEventTypeName;
                foreach (var partitionItem in hashSpec.Items)
                {
                    if (partitionItem.FilterSpecCompiled.FilterForEventType.Name.Equals(declaredAsName))
                    {
                        foundPartition = partitionItem;
                        break;
                    }
                }
            }

            if (foundPartition == null)
            {
                return(null);
            }

            var filter = new FilterValueSetParamImpl(foundPartition.Lookupable, FilterOperator.EQUAL, hashCode);

            var addendum = new FilterValueSetParam[1][];

            addendum[0] = new FilterValueSetParam[]
            {
                filter
            };

            var partitionFilters = foundPartition.ParametersCompiled;

            if (partitionFilters != null)
            {
                addendum = ContextControllerAddendumUtil.AddAddendum(partitionFilters, filter);
            }
            return(addendum);
        }
        public static FilterValueSetParam[][] ComputeFixedLength(
            FilterSpecPlanPath[] paths,
            MatchedEventMap matchedEvents,
            ExprEvaluatorContext exprEvaluatorContext,
            StatementContextFilterEvalEnv filterEvalEnv)
        {
            var valueList = new FilterValueSetParam[paths.Length][];
            for (var i = 0; i < paths.Length; i++) {
                var path = paths[i];
                valueList[i] = new FilterValueSetParam[path.Triplets.Length];
                PopulateValueSet(valueList[i], matchedEvents, path.Triplets, exprEvaluatorContext, filterEvalEnv);
            }

            return valueList;
        }
Beispiel #10
0
        public static FilterValueSetParam[][] AddAddendum(
            FilterValueSetParam[][] filters,
            FilterValueSetParam[] toAdd)
        {
            if (filters.Length == 0) {
                filters = new FilterValueSetParam[1][];
                filters[0] = new FilterValueSetParam[0];
            }

            var @params = new FilterValueSetParam[filters.Length][];
            for (var i = 0; i < @params.Length; i++) {
                @params[i] = Append(filters[i], toAdd);
            }

            return @params;
        }
Beispiel #11
0
        public void SetUp()
        {
            _container = SupportContainer.Reset();

            _lockFactory = new FilterServiceGranularLockFactoryReentrant(_container.RWLockManager());
            _eventType   = SupportEventTypeFactory.CreateBeanType(typeof(SupportBean));
            _parameters  = new LinkedList <FilterValueSetParam>();

            // Create parameter test list
            _parameterOne = new FilterValueSetParamImpl(MakeLookupable("IntPrimitive"), FilterOperator.GREATER, 10);
            _parameters.AddLast(_parameterOne);
            _parameterTwo = new FilterValueSetParamImpl(MakeLookupable("DoubleBoxed"), FilterOperator.GREATER, 20d);
            _parameters.AddLast(_parameterTwo);
            _parameterThree = new FilterValueSetParamImpl(MakeLookupable("TheString"), FilterOperator.EQUAL, "sometext");
            _parameters.AddLast(_parameterThree);
        }
Beispiel #12
0
        /// <summary>
        /// Returns the values for the filter, using the supplied result events to ask filter parameters for the value to filter for.
        /// </summary>
        /// <param name="matchedEvents">contains the result events to use for determining filter values</param>
        /// <param name="evaluatorContext">The evaluator context.</param>
        /// <param name="addendum">The addendum.</param>
        /// <returns>filter values</returns>
        public FilterValueSet GetValueSet(MatchedEventMap matchedEvents, ExprEvaluatorContext evaluatorContext, FilterValueSetParam[][] addendum)
        {
            var valueList = new FilterValueSetParam[Parameters.Length][];

            for (int i = 0; i < Parameters.Length; i++)
            {
                valueList[i] = new FilterValueSetParam[Parameters[i].Length];
                PopulateValueSet(valueList[i], matchedEvents, evaluatorContext, Parameters[i]);
            }

            if (addendum != null)
            {
                valueList = ContextControllerAddendumUtil.MultiplyAddendum(addendum, valueList);
            }

            return(new FilterValueSetImpl(_filterForEventType, valueList));
        }
Beispiel #13
0
        public ContextInternalFilterAddendum DeepCopy()
        {
            var copy = new ContextInternalFilterAddendum();

            foreach (var entry in _filterAddendum)
            {
                var copy2Dim = new FilterValueSetParam[entry.Value.Length][];
                copy.FilterAddendum[entry.Key] = copy2Dim;
                for (int ii = 0; ii < entry.Value.Length; ii++)
                {
                    var copyList = new FilterValueSetParam[entry.Value[ii].Length];
                    copy2Dim[ii] = copyList;
                    Array.Copy(entry.Value[ii], 0, copyList, 0, copyList.Length);
                }
                copy.FilterAddendum[entry.Key] = copy2Dim;
            }
            return(copy);
        }
        private FilterValueSetParam[] ComputeTriplets(
            IList<FilterValueSetParam[]> pathList,
            FilterSpecPlanPath path,
            EventBean[] eventsPerStream,
            MatchedEventMap matchedEvents,
            ExprEvaluatorContext exprEvaluatorContext,
            StatementContextFilterEvalEnv filterEvalEnv)
        {
            var triplets = path.Triplets;
            var valueList = new List<FilterValueSetParam>(triplets.Length);
            var count = 0;
            foreach (var triplet in triplets) {
                var controlResult = triplet.TripletConfirm?.Evaluate(eventsPerStream, true, exprEvaluatorContext);
                if (controlResult != null && true.Equals(controlResult)) {
                    continue;
                }

                FilterValueSetParam valueParam = triplet.Param.GetFilterValue(matchedEvents, exprEvaluatorContext, filterEvalEnv);
                valueList.Add(valueParam);
                count++;
            }

            return valueList.ToArray();
        }
Beispiel #15
0
        /// <summary>
        /// Add to the current node building up the tree path information.
        /// </summary>
        /// <param name="remainingParameters">The remaining parameters.</param>
        /// <param name="filterCallback">The filter callback.</param>
        /// <param name="currentNode">is the node to add to</param>
        /// <param name="treePathInfo">is filled with information about which indizes were chosen to add the filter to</param>
        /// <param name="lockFactory">The lock factory.</param>
        private static void AddToNode(
            ArrayDeque <FilterValueSetParam> remainingParameters,
            FilterHandle filterCallback,
            FilterHandleSetNode currentNode,
            ArrayDeque <EventTypeIndexBuilderIndexLookupablePair> treePathInfo,
            FilterServiceGranularLockFactory lockFactory)
        {
            if ((ExecutionPathDebugLog.IsEnabled) && (Log.IsDebugEnabled))
            {
                Log.Debug(".addToNode (" + Thread.CurrentThread.ManagedThreadId + ") Adding filterCallback, node=" + currentNode +
                          "  remainingParameters=" + PrintRemainingParameters(remainingParameters));
            }

            // If no parameters are specified, add to current node, and done
            if (remainingParameters.IsEmpty())
            {
                using (currentNode.NodeRWLock.AcquireWriteLock())
                {
                    currentNode.Add(filterCallback);
                }
                return;
            }

            // Need to find an existing index that matches one of the filter parameters
            Pair <FilterValueSetParam, FilterParamIndexBase> pair;

            using (currentNode.NodeRWLock.AcquireReadLock())
            {
                pair = IndexHelper.FindIndex(remainingParameters, currentNode.Indizes);

                // Found an index matching a filter parameter
                if (pair != null)
                {
                    remainingParameters.Remove(pair.First);
                    var filterForValue = pair.First.FilterForValue;
                    var index          = pair.Second;
                    treePathInfo.Add(new EventTypeIndexBuilderIndexLookupablePair(index, filterForValue));
                    AddToIndex(remainingParameters, filterCallback, index, filterForValue, treePathInfo, lockFactory);
                    return;
                }
            }

            // An index for any of the filter parameters was not found, create one
            using (currentNode.NodeRWLock.AcquireWriteLock())
            {
                pair = IndexHelper.FindIndex(remainingParameters, currentNode.Indizes);

                // Attempt to find an index again this time under a write lock
                if (pair != null)
                {
                    remainingParameters.Remove(pair.First);
                    var filterForValue = pair.First.FilterForValue;
                    var indexX         = pair.Second;
                    treePathInfo.Add(new EventTypeIndexBuilderIndexLookupablePair(indexX, filterForValue));
                    AddToIndex(remainingParameters, filterCallback, indexX, filterForValue, treePathInfo, lockFactory);
                    return;
                }

                // No index found that matches any parameters, create a new one
                // Pick the next parameter for an index
                FilterValueSetParam parameterPickedForIndex = remainingParameters.RemoveFirst();

                var index = IndexFactory.CreateIndex(parameterPickedForIndex.Lookupable, lockFactory, parameterPickedForIndex.FilterOperator);

                currentNode.Indizes.Add(index);
                treePathInfo.Add(new EventTypeIndexBuilderIndexLookupablePair(index, parameterPickedForIndex.FilterForValue));
                AddToIndex(remainingParameters, filterCallback, index, parameterPickedForIndex.FilterForValue, treePathInfo, lockFactory);
            }
        }
Beispiel #16
0
        public static FilterValueSetParam[][] GetAddendumFilters(
            object getterKey,
            FilterSpecActivatable filtersSpec,
            ContextControllerDetailKeyed keyedSpec,
            bool includePartition,
            ContextControllerStatementDesc optionalStatementDesc,
            AgentInstanceContext agentInstanceContext)
        {
            // determine whether create-named-window
            var isCreateWindow = optionalStatementDesc != null &&
                                 optionalStatementDesc.Lightweight.StatementContext.StatementInformationals
                                     .StatementType ==
                                 StatementType.CREATE_WINDOW;
            ContextControllerDetailKeyedItem foundPartition = null;

            if (!isCreateWindow) {
                foreach (var partitionItem in keyedSpec.Items) {
                    var typeOrSubtype = EventTypeUtility.IsTypeOrSubTypeOf(
                        filtersSpec.FilterForEventType,
                        partitionItem.FilterSpecActivatable.FilterForEventType);
                    if (typeOrSubtype) {
                        foundPartition = partitionItem;
                        break;
                    }
                }
            }
            else {
                var factory = (StatementAgentInstanceFactoryCreateNW) optionalStatementDesc.Lightweight.StatementContext
                    .StatementAIFactoryProvider
                    .Factory;
                var declaredAsName = factory.AsEventTypeName;
                foreach (var partitionItem in keyedSpec.Items) {
                    if (partitionItem.FilterSpecActivatable.FilterForEventType.Name.Equals(declaredAsName)) {
                        foundPartition = partitionItem;
                        break;
                    }
                }
            }

            if (foundPartition == null) {
                return null;
            }

            var lookupables = foundPartition.Lookupables;
            var addendumFilters = new FilterValueSetParam[lookupables.Length];
            if (lookupables.Length == 1) {
                addendumFilters[0] = GetFilterMayEqualOrNull(lookupables[0], getterKey);
            }
            else {
                var keys = getterKey is HashableMultiKey ? ((HashableMultiKey) getterKey).Keys : (object[]) getterKey;
                for (var i = 0; i < lookupables.Length; i++) {
                    addendumFilters[i] = GetFilterMayEqualOrNull(lookupables[i], keys[i]);
                }
            }

            var addendum = new FilterValueSetParam[1][];
            addendum[0] = addendumFilters;

            var partitionFilters = foundPartition.FilterSpecActivatable.GetValueSet(
                null,
                null,
                agentInstanceContext,
                agentInstanceContext.StatementContextFilterEvalEnv);
            if (partitionFilters != null && includePartition) {
                addendum = FilterAddendumUtil.AddAddendum(partitionFilters, addendum[0]);
            }

            return addendum;
        }
Beispiel #17
0
        // Compare filters in statement with filters in segmented context, addendum filter compilation
        /// <summary>
        /// Gets the addendum filters.
        /// </summary>
        /// <param name="addendums">The addendums.</param>
        /// <param name="agentInstanceId">The agent instance identifier.</param>
        /// <param name="filtersSpecs">The filters specs.</param>
        /// <param name="hashSpec">The hash spec.</param>
        /// <param name="statementDesc">The statement desc.</param>
        private static void GetAddendumFilters(
            IDictionary <FilterSpecCompiled, FilterValueSetParam[][]> addendums,
            int agentInstanceId,
            IList <FilterSpecCompiled> filtersSpecs,
            ContextDetailHash hashSpec,
            ContextControllerStatementDesc statementDesc)
        {
            // determine whether create-named-window
            var isCreateWindow = statementDesc != null && statementDesc.Statement.StatementSpec.CreateWindowDesc != null;

            if (!isCreateWindow)
            {
                foreach (var filtersSpec in filtersSpecs)
                {
                    var foundPartition = FindHashItemSpec(hashSpec, filtersSpec);
                    if (foundPartition == null)
                    {
                        continue;
                    }

                    FilterValueSetParam filter = new FilterValueSetParamImpl(foundPartition.Lookupable, FilterOperator.EQUAL, agentInstanceId);

                    var addendum = new FilterValueSetParam[1][];
                    addendum[0] = new FilterValueSetParam[] { filter };

                    var partitionFilters = foundPartition.ParametersCompiled;
                    if (partitionFilters != null)
                    {
                        addendum = ContextControllerAddendumUtil.AddAddendum(partitionFilters, filter);
                    }

                    FilterValueSetParam[][] existing = addendums.Get(filtersSpec);
                    if (existing != null)
                    {
                        addendum = ContextControllerAddendumUtil.MultiplyAddendum(existing, addendum);
                    }

                    addendums[filtersSpec] = addendum;
                }
            }
            // handle segmented context for create-window
            else
            {
                var declaredAsName = statementDesc.Statement.StatementSpec.CreateWindowDesc.AsEventTypeName;
                if (declaredAsName != null)
                {
                    foreach (var filterSpec in filtersSpecs)
                    {
                        ContextDetailHashItem foundPartition = null;
                        foreach (var partitionItem in hashSpec.Items)
                        {
                            if (partitionItem.FilterSpecCompiled.FilterForEventType.Name.Equals(declaredAsName))
                            {
                                foundPartition = partitionItem;
                                break;
                            }
                        }

                        if (foundPartition == null)
                        {
                            continue;
                        }

                        FilterValueSetParam filter = new FilterValueSetParamImpl(foundPartition.Lookupable, FilterOperator.EQUAL, agentInstanceId);

                        var addendum = new FilterValueSetParam[1][];
                        addendum[0] = new FilterValueSetParam[] { filter };

                        var existing = addendums.Get(filterSpec);
                        if (existing != null)
                        {
                            addendum = ContextControllerAddendumUtil.MultiplyAddendum(existing, addendum);
                        }

                        addendums[filterSpec] = addendum;
                    }
                }
            }
        }
Beispiel #18
0
 public static FilterValueSetParam[][] AddAddendum(
     FilterValueSetParam[][] filters,
     FilterValueSetParam toAdd)
 {
     return AddAddendum(filters, new[] {toAdd});
 }
Beispiel #19
0
        public static FilterValueSetParam[][] GetAddendumFilters(
            object keyValue,
            FilterSpecCompiled filtersSpec,
            ContextDetailPartitioned segmentedSpec,
            StatementSpecCompiled optionalStatementSpecCompiled)
        {
            // determine whether create-named-window
            var isCreateWindow = optionalStatementSpecCompiled != null &&
                                 optionalStatementSpecCompiled.CreateWindowDesc != null;
            ContextDetailPartitionItem foundPartition = null;

            if (!isCreateWindow)
            {
                foreach (var partitionItem in segmentedSpec.Items)
                {
                    var typeOrSubtype = EventTypeUtility.IsTypeOrSubTypeOf(
                        filtersSpec.FilterForEventType, partitionItem.FilterSpecCompiled.FilterForEventType);
                    if (typeOrSubtype)
                    {
                        foundPartition = partitionItem;
                    }
                }
            }
            else
            {
                var declaredAsName = optionalStatementSpecCompiled.CreateWindowDesc.AsEventTypeName;
                if (declaredAsName == null)
                {
                    return(null);
                }
                foreach (var partitionItem in segmentedSpec.Items)
                {
                    if (partitionItem.FilterSpecCompiled.FilterForEventType.Name.Equals(declaredAsName))
                    {
                        foundPartition = partitionItem;
                        break;
                    }
                }
            }

            if (foundPartition == null)
            {
                return(null);
            }

            var addendumFilters = new List <FilterValueSetParam>(foundPartition.PropertyNames.Count);

            if (foundPartition.PropertyNames.Count == 1)
            {
                var propertyName           = foundPartition.PropertyNames[0];
                var getter                 = foundPartition.FilterSpecCompiled.FilterForEventType.GetGetter(propertyName);
                var resultType             = foundPartition.FilterSpecCompiled.FilterForEventType.GetPropertyType(propertyName);
                var lookupable             = new FilterSpecLookupable(propertyName, getter, resultType, false);
                FilterValueSetParam filter = new FilterValueSetParamImpl(lookupable, FilterOperator.EQUAL, keyValue);
                addendumFilters.Add(filter);
            }
            else
            {
                var keys = ((MultiKeyUntyped)keyValue).Keys;
                for (var i = 0; i < foundPartition.PropertyNames.Count; i++)
                {
                    var partitionPropertyName = foundPartition.PropertyNames[i];
                    var getter                 = foundPartition.FilterSpecCompiled.FilterForEventType.GetGetter(partitionPropertyName);
                    var resultType             = foundPartition.FilterSpecCompiled.FilterForEventType.GetPropertyType(partitionPropertyName);
                    var lookupable             = new FilterSpecLookupable(partitionPropertyName, getter, resultType, false);
                    FilterValueSetParam filter = new FilterValueSetParamImpl(lookupable, FilterOperator.EQUAL, keys[i]);
                    addendumFilters.Add(filter);
                }
            }

            var addendum = new FilterValueSetParam[1][];

            addendum[0] = addendumFilters.ToArray();

            var partitionFilters = foundPartition.ParametersCompiled;

            if (partitionFilters != null)
            {
                addendum = ContextControllerAddendumUtil.AddAddendum(partitionFilters, addendum[0]);
            }

            return(addendum);
        }
Beispiel #20
0
        /// <summary>
        /// Add to an index the value to filter for.
        /// </summary>
        /// <param name="remainingParameters">The remaining parameters.</param>
        /// <param name="filterCallback">The filter callback.</param>
        /// <param name="index">is the index to add to</param>
        /// <param name="filterForValue">is the filter parameter value to add</param>
        /// <param name="treePathInfo">is the specification to fill on where is was added</param>
        /// <param name="lockFactory">The lock factory.</param>
        private static void AddToIndex(
            ArrayDeque <FilterValueSetParam> remainingParameters,
            FilterHandle filterCallback,
            FilterParamIndexBase index,
            Object filterForValue,
            ArrayDeque <EventTypeIndexBuilderIndexLookupablePair> treePathInfo,
            FilterServiceGranularLockFactory lockFactory)
        {
            if ((ExecutionPathDebugLog.IsEnabled) && (Log.IsDebugEnabled))
            {
                Log.Debug(".addToIndex ({0}) Adding to index {1}  expressionValue={2}",
                          Thread.CurrentThread.ManagedThreadId, index, filterForValue);
            }

            EventEvaluator eventEvaluator;

            using (index.ReadWriteLock.AcquireReadLock())
            {
                eventEvaluator = index[filterForValue];

                // The filter parameter value already existed in bean, add and release locks
                if (eventEvaluator != null)
                {
                    var added = AddToEvaluator(remainingParameters, filterCallback, eventEvaluator, treePathInfo, lockFactory);
                    if (added)
                    {
                        return;
                    }
                }
            }

            // new filter parameter value, need a write lock
            using (index.ReadWriteLock.AcquireWriteLock())
            {
                eventEvaluator = index[filterForValue];

                // It may exist now since another thread could have added the entry
                if (eventEvaluator != null)
                {
                    var added = AddToEvaluator(remainingParameters, filterCallback, eventEvaluator, treePathInfo, lockFactory);
                    if (added)
                    {
                        return;
                    }

                    // The found eventEvaluator must be converted to a new FilterHandleSetNode
                    var nextIndexX = (FilterParamIndexBase)eventEvaluator;
                    var newNode    = new FilterHandleSetNode(lockFactory.ObtainNew());
                    newNode.Add(nextIndexX);
                    index.Remove(filterForValue);
                    index[filterForValue] = newNode;
                    AddToNode(remainingParameters, filterCallback, newNode, treePathInfo, lockFactory);

                    return;
                }

                // The index does not currently have this filterCallback value,
                // if there are no remaining parameters, create a node
                if (remainingParameters.IsEmpty())
                {
                    var node = new FilterHandleSetNode(lockFactory.ObtainNew());
                    AddToNode(remainingParameters, filterCallback, node, treePathInfo, lockFactory);
                    index[filterForValue] = node;
                    return;
                }

                // If there are remaining parameters, create a new index for the next parameter
                FilterValueSetParam parameterPickedForIndex = remainingParameters.RemoveFirst();

                var nextIndex = IndexFactory.CreateIndex(parameterPickedForIndex.Lookupable, lockFactory, parameterPickedForIndex.FilterOperator);

                index[filterForValue] = nextIndex;
                treePathInfo.Add(new EventTypeIndexBuilderIndexLookupablePair(nextIndex, parameterPickedForIndex.FilterForValue));
                AddToIndex(remainingParameters, filterCallback, nextIndex, parameterPickedForIndex.FilterForValue, treePathInfo, lockFactory);
            }
        }