/// <summary> /// Add a filter callback according to the filter specification to the top node returning information to be used to remove the filter callback. /// </summary> /// <param name="filterValueSet">is the filter definition</param> /// <param name="filterCallback">is the callback to be added</param> /// <param name="topNode">node to be added to any subnode beneath it</param> /// <param name="lockFactory">The lock factory.</param> /// <returns> /// an encapsulation of information need to allow for safe removal of the filter tree. /// </returns> public static ArrayDeque <EventTypeIndexBuilderIndexLookupablePair>[] Add( FilterValueSet filterValueSet, FilterHandle filterCallback, FilterHandleSetNode topNode, FilterServiceGranularLockFactory lockFactory) { if ((ExecutionPathDebugLog.IsEnabled) && (Log.IsDebugEnabled)) { Log.Debug(".add (" + Thread.CurrentThread.ManagedThreadId + ") Adding filter callback, " + " topNode=" + topNode + " filterCallback=" + filterCallback); } ArrayDeque <EventTypeIndexBuilderIndexLookupablePair>[] treePathInfo; if (filterValueSet.Parameters.Length == 0) { treePathInfo = AllocateTreePath(1); treePathInfo[0] = new ArrayDeque <EventTypeIndexBuilderIndexLookupablePair>(1); AddToNode(new ArrayDeque <FilterValueSetParam>(1), filterCallback, topNode, treePathInfo[0], lockFactory); } else { treePathInfo = AllocateTreePath(filterValueSet.Parameters.Length); var remainingParameters = new ArrayDeque <FilterValueSetParam>(4); for (int i = 0; i < filterValueSet.Parameters.Length; i++) { treePathInfo[i] = new ArrayDeque <EventTypeIndexBuilderIndexLookupablePair>(filterValueSet.Parameters[i].Length); remainingParameters.Clear(); remainingParameters.AddAll(filterValueSet.Parameters[i]); AddToNode(remainingParameters, filterCallback, topNode, treePathInfo[i], lockFactory); } } return(treePathInfo); }
private void PerformMultithreadedTest(FilterHandleSetNode topNode, int numberOfThreads, int numberOfRunnables, int numberOfSecondsSleep) { Log.Info(".performMultithreadedTest Loading thread pool work queue,numberOfRunnables=" + numberOfRunnables); var pool = new DedicatedExecutorService("test", numberOfThreads, new ImperfectBlockingQueue <Runnable>()); for (var i = 0; i < numberOfRunnables; i++) { var runnable = new IndexTreeBuilderRunnable(_eventType, topNode, _testFilterSpecs, _matchedEvents, _unmatchedEvents); pool.Submit(runnable.Run); } Log.Info(".performMultithreadedTest Starting thread pool, threads=" + numberOfThreads); // Sleep X seconds Sleep(numberOfSecondsSleep); Log.Info(".performMultithreadedTest Completed, numberOfRunnables=" + numberOfRunnables + " numberOfThreads=" + numberOfThreads + " completed=" + pool.NumExecuted); pool.Shutdown(); pool.AwaitTermination(TimeSpan.FromSeconds(1)); Assert.AreEqual(pool.NumExecuted, numberOfRunnables); }
/// <summary>Returns the root node for the given event type, or null if this event type has not been seen before. </summary> /// <param name="eventType">is an event type</param> /// <returns>the subtree's root node</returns> public FilterHandleSetNode Get(EventType eventType) { using (_eventTypesLock.AcquireReadLock()) { FilterHandleSetNode result = _eventTypes.Get(eventType); return(result); } }
public void SetUp() { _container = SupportContainer.Reset(); _lockFactory = new FilterServiceGranularLockFactoryReentrant(_container.RWLockManager()); _eventType = SupportEventTypeFactory.CreateBeanType(typeof(SupportBean)); _topNode = new FilterHandleSetNode(_container.RWLockManager().CreateDefaultLock()); _filterCallbacks = new List <FilterHandle>(); _pathsAddedTo = new List <ArrayDeque <EventTypeIndexBuilderIndexLookupablePair> >(); _testFilterSpecs = new List <FilterSpecCompiled>(); _matchedEvents = new List <EventBean>(); _unmatchedEvents = new List <EventBean>(); // Any int and double value specified here must match only the current filter spec not any other filter spec _testFilterSpecs.Add(MakeSpec(new Object[] { "IntPrimitive", FilterOperator.GREATER_OR_EQUAL, 100000 })); _matchedEvents.Add(MakeEvent(9999999, -1)); _unmatchedEvents.Add(MakeEvent(0, -1)); _testFilterSpecs.Add(MakeSpec(new Object[] { "IntPrimitive", FilterOperator.GREATER_OR_EQUAL, 10, "DoublePrimitive", FilterOperator.EQUAL, 0.5 })); _matchedEvents.Add(MakeEvent(10, 0.5)); _unmatchedEvents.Add(MakeEvent(0, 0.5)); _testFilterSpecs.Add(MakeSpec(new Object[] { "DoublePrimitive", FilterOperator.EQUAL, 0.8 })); _matchedEvents.Add(MakeEvent(-1, 0.8)); _unmatchedEvents.Add(MakeEvent(-1, 0.1)); _testFilterSpecs.Add(MakeSpec(new Object[] { "DoublePrimitive", FilterOperator.EQUAL, 99.99, "IntPrimitive", FilterOperator.LESS, 1 })); _matchedEvents.Add(MakeEvent(0, 99.99)); _unmatchedEvents.Add(MakeEvent(2, 0.5)); _testFilterSpecs.Add(MakeSpec(new Object[] { "DoublePrimitive", FilterOperator.GREATER, .99, "IntPrimitive", FilterOperator.EQUAL, 5001 })); _matchedEvents.Add(MakeEvent(5001, 1.1)); _unmatchedEvents.Add(MakeEvent(5002, 0.98)); _testFilterSpecs.Add(MakeSpec(new Object[] { "IntPrimitive", FilterOperator.LESS, -99000 })); _matchedEvents.Add(MakeEvent(-99001, -1)); _unmatchedEvents.Add(MakeEvent(-98999, -1)); _testFilterSpecs.Add(MakeSpec(new Object[] { "IntPrimitive", FilterOperator.GREATER_OR_EQUAL, 11, "DoublePrimitive", FilterOperator.GREATER, 888.0 })); _matchedEvents.Add(MakeEvent(11, 888.001)); _unmatchedEvents.Add(MakeEvent(10, 888)); _testFilterSpecs.Add(MakeSpec(new Object[] { "IntPrimitive", FilterOperator.EQUAL, 973, "DoublePrimitive", FilterOperator.EQUAL, 709.0 })); _matchedEvents.Add(MakeEvent(973, 709)); _unmatchedEvents.Add(MakeEvent(0, 0.5)); _testFilterSpecs.Add(MakeSpec(new Object[] { "IntPrimitive", FilterOperator.EQUAL, 973, "DoublePrimitive", FilterOperator.EQUAL, 655.0 })); _matchedEvents.Add(MakeEvent(973, 655)); _unmatchedEvents.Add(MakeEvent(33838, 655.5)); }
// Remove an filterCallback from the current node, return true if the node is the node is empty now private static bool RemoveFromNode( FilterHandle filterCallback, FilterHandleSetNode currentNode, EventTypeIndexBuilderIndexLookupablePair[] treePathInfo, int treePathPosition) { var nextPair = treePathPosition < treePathInfo.Length ? treePathInfo[treePathPosition++] : null; // No remaining filter parameters if (nextPair == null) { using (currentNode.NodeRWLock.AcquireWriteLock()) { var isRemoved = currentNode.Remove(filterCallback); var isEmpty = currentNode.IsEmpty(); if (!isRemoved) { Log.Warn(".removeFromNode (" + Thread.CurrentThread.ManagedThreadId + ") Could not find the filterCallback to be removed within the supplied node , node=" + currentNode + " filterCallback=" + filterCallback); } return(isEmpty); } } // Remove from index var nextIndex = nextPair.Index; var filteredForValue = nextPair.Lookupable; using (currentNode.NodeRWLock.AcquireWriteLock()) { var isEmpty = RemoveFromIndex(filterCallback, nextIndex, treePathInfo, treePathPosition, filteredForValue); if (!isEmpty) { return(false); } // Remove the index if the index is now empty if (nextIndex.Count == 0) { var isRemoved = currentNode.Remove(nextIndex); if (!isRemoved) { Log.Warn(".removeFromNode (" + Thread.CurrentThread.ManagedThreadId + ") Could not find the index in index list for removal, index=" + nextIndex + " filterCallback=" + filterCallback); return(false); } } return(currentNode.IsEmpty()); } }
/// <summary> /// Add a new event type to the index and use the specified node for the root node of /// its subtree. If the event type already existed, the method will throw an /// IllegalStateException. /// </summary> /// <param name="eventType">is the event type to be added to the index</param> /// <param name="rootNode">is the root node of the subtree for filter constant indizes and callbacks</param> public void Add(EventType eventType, FilterHandleSetNode rootNode) { using (_eventTypesLock.AcquireWriteLock()) { if (_eventTypes.ContainsKey(eventType)) { throw new IllegalStateException("Event type already in index, add not performed, type=" + eventType); } _eventTypes.Put(eventType, rootNode); } }
public void TestMultithreaded() { var topNode = new FilterHandleSetNode(ReaderWriterLockManager.CreateDefaultLock()); PerformMultithreadedTest(topNode, 2, 1000, 1); PerformMultithreadedTest(topNode, 3, 1000, 1); PerformMultithreadedTest(topNode, 4, 1000, 1); PerformMultithreadedTest(new FilterHandleSetNode(ReaderWriterLockManager.CreateDefaultLock()), 2, 1000, 1); PerformMultithreadedTest(new FilterHandleSetNode(ReaderWriterLockManager.CreateDefaultLock()), 3, 1000, 1); PerformMultithreadedTest(new FilterHandleSetNode(ReaderWriterLockManager.CreateDefaultLock()), 4, 1000, 1); }
public void SetUp() { SupportBean testBean = new SupportBean(); _testEventBean = SupportEventBeanFactory.CreateObject(testBean); _testEventType = _testEventBean.EventType; _handleSetNode = new FilterHandleSetNode(ReaderWriterLockManager.CreateDefaultLock()); _filterCallback = new SupportFilterHandle(); _handleSetNode.Add(_filterCallback); _testIndex = new EventTypeIndex(new FilterServiceGranularLockFactoryReentrant()); _testIndex.Add(_testEventType, _handleSetNode); }
/// <summary> /// Remove an filterCallback from the given top node. The IndexTreePath instance passed in must be the same as obtained when the same filterCallback was added. /// </summary> /// <param name="eventType">Type of the event.</param> /// <param name="filterCallback">filter callback to be removed</param> /// <param name="treePathInfo">encapsulates information need to allow for safe removal of the filterCallback</param> /// <param name="topNode">The top tree node beneath which the filterCallback was added</param> public static void Remove( EventType eventType, FilterHandle filterCallback, EventTypeIndexBuilderIndexLookupablePair[] treePathInfo, FilterHandleSetNode topNode) { if ((ExecutionPathDebugLog.IsEnabled) && (Log.IsDebugEnabled)) { Log.Debug(".remove (" + Thread.CurrentThread.ManagedThreadId + ") Removing filterCallback " + " type " + eventType.Name + " topNode=" + topNode + " filterCallback=" + filterCallback); } RemoveFromNode(filterCallback, topNode, treePathInfo, 0); }
/// <summary> /// Add a filter to the event type index structure, and to the filter subtree. /// Throws an IllegalStateException exception if the callback is already registered. /// </summary> /// <param name="filterValueSet">is the filter information</param> /// <param name="filterCallback">is the callback</param> /// <param name="lockFactory">The lock factory.</param> /// <returns></returns> /// <exception cref="IllegalStateException">Callback for filter specification already exists in collection</exception> public FilterServiceEntry Add(FilterValueSet filterValueSet, FilterHandle filterCallback, FilterServiceGranularLockFactory lockFactory) { using (Instrument.With( i => i.QFilterAdd(filterValueSet, filterCallback), i => i.AFilterAdd())) { var eventType = filterValueSet.EventType; // Check if a filter tree exists for this event type var rootNode = _eventTypeIndex.Get(eventType); // Make sure we have a root node if (rootNode == null) { using (_callbacksLock.Acquire()) { rootNode = _eventTypeIndex.Get(eventType); if (rootNode == null) { rootNode = new FilterHandleSetNode(lockFactory.ObtainNew()); _eventTypeIndex.Add(eventType, rootNode); } } } // GetInstance add to tree var path = IndexTreeBuilder.Add(filterValueSet, filterCallback, rootNode, lockFactory); var pathArray = path.Select(p => p.ToArray()).ToArray(); var pair = new EventTypeIndexBuilderValueIndexesPair(filterValueSet, pathArray); // for non-isolatable callbacks the consumer keeps track of tree location if (_isolatableCallbacks == null) { return(pair); } // for isolatable callbacks this class is keeping track of tree location using (_callbacksLock.Acquire()) { _isolatableCallbacks.Put(filterCallback, pair); } return(null); } }
public void SetUp() { _testEvaluator = new SupportEventEvaluator(); _testNode = new FilterHandleSetNode(ReaderWriterLockManager.CreateDefaultLock()); }
public void TestBuildWithMatch() { var topNode = new FilterHandleSetNode(_container.RWLockManager().CreateDefaultLock()); // Add some parameter-less expression var filterSpec = MakeFilterValues(); IndexTreeBuilder.Add(filterSpec, _testFilterCallback[0], topNode, _lockFactory); Assert.IsTrue(topNode.Contains(_testFilterCallback[0])); // Attempt a match topNode.MatchEvent(_eventBean, _matches); Assert.IsTrue(_matches.Count == 1); _matches.Clear(); // Add a filter that won't match, with a single parameter matching against an int filterSpec = MakeFilterValues("IntPrimitive", FilterOperator.EQUAL, 100); IndexTreeBuilder.Add(filterSpec, _testFilterCallback[1], topNode, _lockFactory); Assert.IsTrue(topNode.Indizes.Count == 1); Assert.IsTrue(topNode.Indizes[0].Count == 1); // Match again topNode.MatchEvent(_eventBean, _matches); Assert.IsTrue(_matches.Count == 1); _matches.Clear(); // Add a filter that will match filterSpec = MakeFilterValues("IntPrimitive", FilterOperator.EQUAL, 50); IndexTreeBuilder.Add(filterSpec, _testFilterCallback[2], topNode, _lockFactory); Assert.IsTrue(topNode.Indizes.Count == 1); Assert.IsTrue(topNode.Indizes[0].Count == 2); // match topNode.MatchEvent(_eventBean, _matches); Assert.IsTrue(_matches.Count == 2); _matches.Clear(); // Add some filter against a double filterSpec = MakeFilterValues("DoublePrimitive", FilterOperator.LESS, 1.1); IndexTreeBuilder.Add(filterSpec, _testFilterCallback[3], topNode, _lockFactory); Assert.IsTrue(topNode.Indizes.Count == 2); Assert.IsTrue(topNode.Indizes[0].Count == 2); Assert.IsTrue(topNode.Indizes[1].Count == 1); topNode.MatchEvent(_eventBean, _matches); Assert.IsTrue(_matches.Count == 3); _matches.Clear(); filterSpec = MakeFilterValues("DoublePrimitive", FilterOperator.LESS_OR_EQUAL, 0.5); IndexTreeBuilder.Add(filterSpec, _testFilterCallback[4], topNode, _lockFactory); Assert.IsTrue(topNode.Indizes.Count == 3); Assert.IsTrue(topNode.Indizes[0].Count == 2); Assert.IsTrue(topNode.Indizes[1].Count == 1); Assert.IsTrue(topNode.Indizes[2].Count == 1); topNode.MatchEvent(_eventBean, _matches); Assert.IsTrue(_matches.Count == 4); _matches.Clear(); // Add an filterSpec against double and string filterSpec = MakeFilterValues("DoublePrimitive", FilterOperator.LESS, 1.1, "TheString", FilterOperator.EQUAL, "jack"); IndexTreeBuilder.Add(filterSpec, _testFilterCallback[5], topNode, _lockFactory); Assert.IsTrue(topNode.Indizes.Count == 3); Assert.IsTrue(topNode.Indizes[0].Count == 2); Assert.IsTrue(topNode.Indizes[1].Count == 1); Assert.IsTrue(topNode.Indizes[2].Count == 1); var nextLevelSetNode = (FilterHandleSetNode)topNode.Indizes[1][1.1d]; Assert.IsTrue(nextLevelSetNode != null); Assert.IsTrue(nextLevelSetNode.Indizes.Count == 1); topNode.MatchEvent(_eventBean, _matches); Assert.IsTrue(_matches.Count == 5); _matches.Clear(); filterSpec = MakeFilterValues("DoublePrimitive", FilterOperator.LESS, 1.1, "TheString", FilterOperator.EQUAL, "beta"); IndexTreeBuilder.Add(filterSpec, _testFilterCallback[6], topNode, _lockFactory); topNode.MatchEvent(_eventBean, _matches); Assert.IsTrue(_matches.Count == 5); _matches.Clear(); filterSpec = MakeFilterValues("DoublePrimitive", FilterOperator.LESS, 1.1, "TheString", FilterOperator.EQUAL, "jack"); IndexTreeBuilder.Add(filterSpec, _testFilterCallback[7], topNode, _lockFactory); Assert.IsTrue(nextLevelSetNode.Indizes.Count == 1); var nodeTwo = (FilterHandleSetNode)nextLevelSetNode.Indizes[0]["jack"]; Assert.IsTrue(nodeTwo.FilterCallbackCount == 2); topNode.MatchEvent(_eventBean, _matches); Assert.IsTrue(_matches.Count == 6); _matches.Clear(); // Try depth first filterSpec = MakeFilterValues("TheString", FilterOperator.EQUAL, "jack", "LongPrimitive", FilterOperator.EQUAL, 10L, "ShortPrimitive", FilterOperator.EQUAL, (short)20); IndexTreeBuilder.Add(filterSpec, _testFilterCallback[8], topNode, _lockFactory); topNode.MatchEvent(_eventBean, _matches); Assert.IsTrue(_matches.Count == 7); _matches.Clear(); // Add an filterSpec in the middle filterSpec = MakeFilterValues("LongPrimitive", FilterOperator.EQUAL, 10L, "TheString", FilterOperator.EQUAL, "jack"); IndexTreeBuilder.Add(filterSpec, _testFilterCallback[9], topNode, _lockFactory); filterSpec = MakeFilterValues("LongPrimitive", FilterOperator.EQUAL, 10L, "TheString", FilterOperator.EQUAL, "jim"); IndexTreeBuilder.Add(filterSpec, _testFilterCallback[10], topNode, _lockFactory); filterSpec = MakeFilterValues("LongPrimitive", FilterOperator.EQUAL, 10L, "TheString", FilterOperator.EQUAL, "joe"); IndexTreeBuilder.Add(filterSpec, _testFilterCallback[11], topNode, _lockFactory); topNode.MatchEvent(_eventBean, _matches); Assert.IsTrue(_matches.Count == 8); _matches.Clear(); }
public void TestBuildMatchRemove() { var top = new FilterHandleSetNode(_container.RWLockManager().CreateDefaultLock()); // Add a parameter-less filter var filterSpecNoParams = MakeFilterValues(); var pathAddedTo = IndexTreeBuilder.Add(filterSpecNoParams, _testFilterCallback[0], top, _lockFactory); // Try a match top.MatchEvent(_eventBean, _matches); Assert.IsTrue(_matches.Count == 1); _matches.Clear(); // Remove filter IndexTreeBuilder.Remove(_eventType, _testFilterCallback[0], ToArrayPath(pathAddedTo[0]), top); // Match should not be found top.MatchEvent(_eventBean, _matches); Assert.IsTrue(_matches.Count == 0); _matches.Clear(); // Add a depth-first filterSpec var filterSpecOne = MakeFilterValues( "TheString", FilterOperator.EQUAL, "jack", "LongPrimitive", FilterOperator.EQUAL, 10L, "ShortPrimitive", FilterOperator.EQUAL, (short)20); var pathAddedToOne = IndexTreeBuilder.Add(filterSpecOne, _testFilterCallback[1], top, _lockFactory); var filterSpecTwo = MakeFilterValues( "TheString", FilterOperator.EQUAL, "jack", "LongPrimitive", FilterOperator.EQUAL, 10L, "ShortPrimitive", FilterOperator.EQUAL, (short)20); var pathAddedToTwo = IndexTreeBuilder.Add(filterSpecTwo, _testFilterCallback[2], top, _lockFactory); var filterSpecThree = MakeFilterValues( "TheString", FilterOperator.EQUAL, "jack", "LongPrimitive", FilterOperator.EQUAL, 10L); var pathAddedToThree = IndexTreeBuilder.Add(filterSpecThree, _testFilterCallback[3], top, _lockFactory); var filterSpecFour = MakeFilterValues( "TheString", FilterOperator.EQUAL, "jack"); var pathAddedToFour = IndexTreeBuilder.Add(filterSpecFour, _testFilterCallback[4], top, _lockFactory); var filterSpecFive = MakeFilterValues( "LongPrimitive", FilterOperator.EQUAL, 10L); var pathAddedToFive = IndexTreeBuilder.Add(filterSpecFive, _testFilterCallback[5], top, _lockFactory); top.MatchEvent(_eventBean, _matches); Assert.IsTrue(_matches.Count == 5); _matches.Clear(); // Remove some of the nodes IndexTreeBuilder.Remove(_eventType, _testFilterCallback[2], ToArrayPath(pathAddedToTwo[0]), top); top.MatchEvent(_eventBean, _matches); Assert.IsTrue(_matches.Count == 4); _matches.Clear(); // Remove some of the nodes IndexTreeBuilder.Remove(_eventType, _testFilterCallback[4], ToArrayPath(pathAddedToFour[0]), top); top.MatchEvent(_eventBean, _matches); Assert.IsTrue(_matches.Count == 3); _matches.Clear(); // Remove some of the nodes IndexTreeBuilder.Remove(_eventType, _testFilterCallback[5], ToArrayPath(pathAddedToFive[0]), top); top.MatchEvent(_eventBean, _matches); Assert.IsTrue(_matches.Count == 2); _matches.Clear(); // Remove some of the nodes IndexTreeBuilder.Remove(_eventType, _testFilterCallback[1], ToArrayPath(pathAddedToOne[0]), top); top.MatchEvent(_eventBean, _matches); Assert.IsTrue(_matches.Count == 1); _matches.Clear(); // Remove some of the nodes IndexTreeBuilder.Remove(_eventType, _testFilterCallback[3], ToArrayPath(pathAddedToThree[0]), top); top.MatchEvent(_eventBean, _matches); Assert.IsTrue(_matches.Count == 0); _matches.Clear(); }
/// <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); } }
/// <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); } }
public void SetUp() { _container = SupportContainer.Reset(); _testEvaluator = new SupportEventEvaluator(); _testNode = new FilterHandleSetNode(_container.RWLockManager().CreateDefaultLock()); }