/// <summary> /// Determine among the passed in filter parameters any parameter that matches the given index on property name and /// filter operator type. Returns null if none of the parameters matches the index. /// </summary> /// <param name="parameters">is the filter parameter list</param> /// <param name="index">is a filter parameter constant value index</param> /// <returns>filter parameter, or null if no matching parameter found.</returns> public static FilterValueSetParam FindParameter( ArrayDeque<FilterValueSetParam> parameters, FilterParamIndexBase index) { if (index is FilterParamIndexLookupableBase) { var propBasedIndex = (FilterParamIndexLookupableBase) index; var indexLookupable = propBasedIndex.Lookupable; var indexOperator = propBasedIndex.FilterOperator; foreach (var parameter in parameters) { var lookupable = parameter.Lookupable; var paramOperator = parameter.FilterOperator; if (lookupable.Equals(indexLookupable) && paramOperator.Equals(indexOperator)) { return parameter; } } } else { foreach (var parameter in parameters) { var paramOperator = parameter.FilterOperator; if (paramOperator.Equals(index.FilterOperator)) { return parameter; } } } return null; }
private void Verify(FilterParamIndexBase index, long?testValue, bool[] expected) { testBean.LongBoxed = testValue; index.MatchEvent(testEventBean, matchesList, null); for (int i = 0; i < expected.Length; i++) { Assert.AreEqual(expected[i], testEvaluators[i].GetAndResetCountInvoked() == 1); } }
private void VerifyDoubleBoxed( FilterParamIndexBase index, double testValue, int numExpected) { testBean.DoubleBoxed = testValue; index.MatchEvent(testEventBean, matchesList, null); Assert.AreEqual(numExpected, testEvaluator.GetAndResetCountInvoked()); }
private void VerifyLongPrimitive( FilterParamIndexBase index, long testValue, int numExpected) { testBean.LongPrimitive = testValue; index.MatchEvent(testEventBean, matchesList, null); Assert.AreEqual(numExpected, testEvaluator.GetAndResetCountInvoked()); }
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); }
/// <summary> /// Remove an index, returning true if it was found and removed or false if not in collection. /// NOTE: the client to this method must use the read-write lock of this object to lock, if /// required by the client code. /// </summary> /// <param name="index">is the index to remove</param> /// <returns>true if found, false if not existing</returns> public bool Remove(FilterParamIndexBase index) { CheckIndizesIsModifiable(); return(_indizes.Remove(index)); }
/// <summary> /// Add an index. The same index can be added twice - there is no checking done. /// NOTE: the client to this method must use the read-write lock of this object /// to lock, if required by the client code. /// </summary> /// <param name="index">index to add</param> public void Add(FilterParamIndexBase index) { CheckIndizesIsModifiable(); _indizes.Add(index); }
private string GetPropName(FilterParamIndexBase index) { FilterParamIndexLookupableBase propIndex = (FilterParamIndexLookupableBase)index; return(propIndex.Lookupable.Expression); }
private static bool RemoveFromNode( FilterHandle filterCallback, FilterHandleSetNode currentNode, FilterValueSetParam[] @params, int currentLevel) { // No remaining filter parameters if (currentLevel == @params.Length) { using (currentNode.NodeRWLock.WriteLock.Acquire()) { return currentNode.Remove(filterCallback); } } if (currentLevel > @params.Length) { Log.Warn( ".removeFromNode (" + Thread.CurrentThread.ManagedThreadId + ") Current level exceed parameter length, node=" + currentNode + " filterCallback=" + filterCallback); return false; } // Remove from index using (currentNode.NodeRWLock.WriteLock.Acquire()) { FilterParamIndexBase indexFound = null; // find matching index foreach (var index in currentNode.Indizes) { for (var i = 0; i < @params.Length; i++) { var param = @params[i]; var indexMatch = false; if (index is FilterParamIndexLookupableBase) { var baseIndex = (FilterParamIndexLookupableBase) index; if (param.Lookupable.Expression.Equals(baseIndex.Lookupable.Expression) && param.FilterOperator.Equals(baseIndex.FilterOperator)) { indexMatch = true; } } else if (index is FilterParamIndexBooleanExpr && param.FilterOperator == FilterOperator.BOOLEAN_EXPRESSION) { indexMatch = true; } if (indexMatch) { bool found = RemoveFromIndex(filterCallback, index, @params, currentLevel + 1, param.FilterForValue); if (found) { indexFound = index; break; } } } if (indexFound != null) { break; } } if (indexFound == null) { return false; } // Remove the index if the index is now empty if (indexFound.IsEmpty) { var isRemoved = currentNode.Remove(indexFound); if (!isRemoved) { Log.Warn( ".removeFromNode (" + Thread.CurrentThread.ManagedThreadId + ") Could not find the index in index list for removal, index=" + indexFound + " filterCallback=" + filterCallback); return true; } } return true; } }
private static bool RemoveFromIndex( FilterHandle filterCallback, FilterParamIndexBase index, FilterValueSetParam[] @params, int currentLevel, object filterForValue) { using (index.ReadWriteLock.WriteLock.Acquire()) { EventEvaluator eventEvaluator = index.Get(filterForValue); if (eventEvaluator == null) { // This is possible as there can be another path return false; } if (eventEvaluator is FilterHandleSetNode) { var node = (FilterHandleSetNode) eventEvaluator; var found = RemoveFromNode(filterCallback, node, @params, currentLevel); if (!found) { return false; } var isEmpty = node.IsEmpty(); 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); } return true; } var nextIndex = (FilterParamIndexBase) eventEvaluator; FilterParamIndexBase indexFound = null; if (nextIndex is FilterParamIndexLookupableBase) { var baseIndex = (FilterParamIndexLookupableBase) nextIndex; for (var i = 0; i < @params.Length; i++) { var param = @params[i]; if (param.Lookupable.Expression.Equals(baseIndex.Lookupable.Expression) && param.FilterOperator.Equals(baseIndex.FilterOperator)) { var found = RemoveFromIndex(filterCallback, baseIndex, @params, currentLevel + 1, param.FilterForValue); if (found) { indexFound = baseIndex; break; } } } } else { var booleanIndex = (FilterParamIndexBooleanExpr) nextIndex; for (var i = 0; i < @params.Length; i++) { var param = @params[i]; // if boolean-expression then match only if this is the last parameter, // all others considered are higher order and sort ahead if (param.FilterOperator.Equals(FilterOperator.BOOLEAN_EXPRESSION)) { bool found = booleanIndex.RemoveMayNotExist(param.FilterForValue); if (found) { indexFound = booleanIndex; break; } } } } if (indexFound == null) { return false; } var indexIsEmpty = nextIndex.IsEmpty; if (indexIsEmpty) { // 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 true; } }
/// <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); } }