/// <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); } }
// Remove filterCallback from index, returning true if index empty after removal private static bool RemoveFromIndex( FilterHandle filterCallback, FilterParamIndexBase index, EventTypeIndexBuilderIndexLookupablePair[] treePathInfo, int treePathPosition, Object filterForValue) { using (index.ReadWriteLock.AcquireWriteLock()) { EventEvaluator eventEvaluator = index[filterForValue]; if (eventEvaluator == null) { Log.Warn(".removeFromIndex ({0}) Could not find the filterCallback value in index, index={1} value={2} filterCallback={3}", Thread.CurrentThread.ManagedThreadId, index, filterForValue, filterCallback); return(false); } if (eventEvaluator is FilterHandleSetNode) { var node = (FilterHandleSetNode)eventEvaluator; var isEmptyX = RemoveFromNode(filterCallback, node, treePathInfo, treePathPosition); if (isEmptyX) { // Since we are holding a write lock to this index, there should not be a chance that // another thread had been adding anything to this FilterHandleSetNode index.Remove(filterForValue); } return(index.Count == 0); } var nextIndex = (FilterParamIndexBase)eventEvaluator; var nextPair = treePathPosition < treePathInfo.Length ? treePathInfo[treePathPosition++] : null; if (nextPair == null) { Log.Fatal(".removeFromIndex Expected an inner index to this index, this=" + filterCallback); Debug.Assert(false); return(false); } if (nextPair.Index != nextIndex) { Log.Fatal(".removeFromIndex Expected an index for filterCallback that differs from the found index, this=" + filterCallback + " expected=" + nextPair.Index); Debug.Assert(false); return(false); } var nextExpressionValue = nextPair.Lookupable; var isEmpty = RemoveFromIndex(filterCallback, nextPair.Index, treePathInfo, treePathPosition, nextExpressionValue); if (isEmpty) { // Since we are holding a write lock to this index, there should not be a chance that // another thread had been adding anything to this FilterHandleSetNode index.Remove(filterForValue); } var size = index.Count; return(size == 0); } }