/// <summary>Add to the current node building up the tree path information.</summary> /// <param name="remainingParameters">any remaining parameters</param> /// <param name="filterCallback">the filter callback</param> /// <param name="currentNode">is the node to add to</param> /// <param name="lockFactory">the lock factory</param> private static void AddToNode( ArrayDeque<FilterValueSetParam> remainingParameters, FilterHandle filterCallback, FilterHandleSetNode currentNode, FilterServiceGranularLockFactory lockFactory) { // If no parameters are specified, add to current node, and done if (remainingParameters.IsEmpty()) { using (currentNode.NodeRWLock.WriteLock.Acquire()) { currentNode.Add(filterCallback); } return; } // Need to find an existing index that matches one of the filter parameters Pair<FilterValueSetParam, FilterParamIndexBase> pair; using (currentNode.NodeRWLock.ReadLock.Acquire()) { 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; AddToIndex(remainingParameters, filterCallback, index, filterForValue, lockFactory); return; } } // An index for any of the filter parameters was not found, create one using (currentNode.NodeRWLock.WriteLock.Acquire()) { 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 indexInner = pair.Second; AddToIndex(remainingParameters, filterCallback, indexInner, filterForValue, lockFactory); return; } // No index found that matches any parameters, create a new one // Pick the next parameter for an index var parameterPickedForIndex = remainingParameters.RemoveFirst(); var index = IndexFactory.CreateIndex(parameterPickedForIndex.Lookupable, lockFactory, parameterPickedForIndex.FilterOperator); currentNode.Add(index); AddToIndex(remainingParameters, filterCallback, index, parameterPickedForIndex.FilterForValue, lockFactory); } }
public void TestFindParameter() { var indexOne = IndexFactory.CreateIndex(MakeLookupable("BoolPrimitive"), lockFactory, FilterOperator.EQUAL); Assert.IsNull(IndexHelper.FindParameter(parameters, indexOne)); var indexTwo = IndexFactory.CreateIndex(MakeLookupable("string"), lockFactory, FilterOperator.EQUAL); Assert.AreEqual(parameterThree, IndexHelper.FindParameter(parameters, indexTwo)); var indexThree = IndexFactory.CreateIndex(MakeLookupable("IntPrimitive"), lockFactory, FilterOperator.GREATER); Assert.AreEqual(parameterOne, IndexHelper.FindParameter(parameters, indexThree)); }
public void TestCreateIndex() { // Create a "greater" index FilterParamIndexBase index = IndexFactory.CreateIndex(MakeLookupable("IntPrimitive"), lockFactory, FilterOperator.GREATER); Assert.IsTrue(index != null); Assert.IsTrue(index is FilterParamIndexCompare); Assert.IsTrue(GetPropName(index).Equals("IntPrimitive")); Assert.IsTrue(index.FilterOperator == FilterOperator.GREATER); // Create an "Equals" index index = IndexFactory.CreateIndex(MakeLookupable("string"), lockFactory, FilterOperator.EQUAL); Assert.IsTrue(index != null); Assert.IsTrue(index is FilterParamIndexEquals); Assert.IsTrue(GetPropName(index).Equals("string")); Assert.IsTrue(index.FilterOperator == FilterOperator.EQUAL); // Create an "not equals" index index = IndexFactory.CreateIndex(MakeLookupable("string"), lockFactory, FilterOperator.NOT_EQUAL); Assert.IsTrue(index != null); Assert.IsTrue(index is FilterParamIndexNotEquals); Assert.IsTrue(GetPropName(index).Equals("string")); Assert.IsTrue(index.FilterOperator == FilterOperator.NOT_EQUAL); // Create a range index index = IndexFactory.CreateIndex(MakeLookupable("DoubleBoxed"), lockFactory, FilterOperator.RANGE_CLOSED); Assert.IsTrue(index is FilterParamIndexDoubleRange); index = IndexFactory.CreateIndex(MakeLookupable("DoubleBoxed"), lockFactory, FilterOperator.NOT_RANGE_CLOSED); Assert.IsTrue(index is FilterParamIndexDoubleRangeInverted); // Create a in-index index = IndexFactory.CreateIndex(MakeLookupable("DoubleBoxed"), lockFactory, FilterOperator.IN_LIST_OF_VALUES); Assert.IsTrue(index is FilterParamIndexIn); index = IndexFactory.CreateIndex(MakeLookupable("DoubleBoxed"), lockFactory, FilterOperator.NOT_IN_LIST_OF_VALUES); Assert.IsTrue(index is FilterParamIndexNotIn); // Create a boolean-expression-index index = IndexFactory.CreateIndex(MakeLookupable("boolean"), lockFactory, FilterOperator.BOOLEAN_EXPRESSION); Assert.IsTrue(index is FilterParamIndexBooleanExpr); index = IndexFactory.CreateIndex(MakeLookupable("boolean"), lockFactory, FilterOperator.BOOLEAN_EXPRESSION); Assert.IsTrue(index is FilterParamIndexBooleanExpr); }
public void TestFindIndex() { IList <FilterParamIndexBase> indexes = new List <FilterParamIndexBase>(); // Create index list wity index that doesn't match var indexOne = IndexFactory.CreateIndex(MakeLookupable("BoolPrimitive"), lockFactory, FilterOperator.EQUAL); indexes.Add(indexOne); Assert.IsTrue(IndexHelper.FindIndex(parameters, indexes) == null); // Create index list wity index that doesn't match indexOne = IndexFactory.CreateIndex(MakeLookupable("DoubleBoxed"), lockFactory, FilterOperator.GREATER_OR_EQUAL); indexes.Clear(); indexes.Add(indexOne); Assert.IsTrue(IndexHelper.FindIndex(parameters, indexes) == null); // Add an index that does match a parameter var indexTwo = IndexFactory.CreateIndex(MakeLookupable("DoubleBoxed"), lockFactory, FilterOperator.GREATER); indexes.Add(indexTwo); var pair = IndexHelper.FindIndex(parameters, indexes); Assert.IsTrue(pair != null); Assert.AreEqual(parameterTwo, pair.First); Assert.AreEqual(indexTwo, pair.Second); // Add another index that does match a parameter, should return first match however which is doubleBoxed var indexThree = IndexFactory.CreateIndex(MakeLookupable("IntPrimitive"), lockFactory, FilterOperator.GREATER); indexes.Add(indexThree); pair = IndexHelper.FindIndex(parameters, indexes); Assert.AreEqual(parameterOne, pair.First); Assert.AreEqual(indexThree, pair.Second); // Try again removing one index indexes.Remove(indexTwo); pair = IndexHelper.FindIndex(parameters, indexes); Assert.AreEqual(parameterOne, pair.First); Assert.AreEqual(indexThree, pair.Second); }
/// <summary> /// Add to an index the value to filter for. /// </summary> /// <param name="index">is the index to add to</param> /// <param name="filterForValue">is the filter parameter value to add</param> /// <param name="remainingParameters">any remaining parameters</param> /// <param name="filterCallback">the filter callback</param> /// <param name="lockFactory">the lock factory</param> private static void AddToIndex( ArrayDeque<FilterValueSetParam> remainingParameters, FilterHandle filterCallback, FilterParamIndexBase index, object filterForValue, FilterServiceGranularLockFactory lockFactory) { EventEvaluator eventEvaluator; using (index.ReadWriteLock.ReadLock.Acquire()) { eventEvaluator = index.Get(filterForValue); // The filter parameter value already existed in bean, add and release locks if (eventEvaluator != null) { var added = AddToEvaluator(remainingParameters, filterCallback, eventEvaluator, lockFactory); if (added) { return; } } } // new filter parameter value, need a write lock using (index.ReadWriteLock.WriteLock.Acquire()) { eventEvaluator = index.Get(filterForValue); // It may exist now since another thread could have added the entry if (eventEvaluator != null) { var added = AddToEvaluator(remainingParameters, filterCallback, eventEvaluator, lockFactory); if (added) { return; } // The found eventEvaluator must be converted to a new FilterHandleSetNode var nextIndexInner = (FilterParamIndexBase) eventEvaluator; var newNode = new FilterHandleSetNode(lockFactory.ObtainNew()); newNode.Add(nextIndexInner); index.Remove(filterForValue); index.Put(filterForValue, newNode); AddToNode(remainingParameters, filterCallback, newNode, 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, lockFactory); index.Put(filterForValue, node); return; } // If there are remaining parameters, create a new index for the next parameter var parameterPickedForIndex = remainingParameters.RemoveFirst(); var nextIndex = IndexFactory.CreateIndex(parameterPickedForIndex.Lookupable, lockFactory, parameterPickedForIndex.FilterOperator); index.Put(filterForValue, nextIndex); AddToIndex(remainingParameters, filterCallback, nextIndex, parameterPickedForIndex.FilterForValue, lockFactory); } }