/************************************************************************************** * Copyright (C) 2008 EsperTech, Inc. All rights reserved. * * http://esper.codehaus.org * * http://www.espertech.com * * ---------------------------------------------------------------------------------- * * The software in this package is published under the terms of the GPL license * * a copy of which has been included with this distribution in the license.txt file. * **************************************************************************************/ package com.espertech.esper.filter; import com.espertech.esper.client.EventBean; import com.espertech.esper.client.EventType; import com.espertech.esper.util.AuditPath; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.util.ArrayDeque; import java.util.Collection; import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.atomic.AtomicLong; /** * Implementation of the filter service interface. * Does not allow the same filter callback to be added more then once. */ public final class FilterServiceImpl implements FilterServiceSPI { private static final Log log = LogFactory.getLog(FilterServiceImpl.class); private final EventTypeIndexBuilder indexBuilder; private final EventTypeIndex eventTypeIndex; private final AtomicLong numEventsEvaluated = new AtomicLong(); private volatile long filtersVersion = 1; private final CopyOnWriteArraySet<FilterServiceListener> filterServiceListeners; /** * Constructor. */ protected FilterServiceImpl() { eventTypeIndex = new EventTypeIndex(); indexBuilder = new EventTypeIndexBuilder(eventTypeIndex); filterServiceListeners = new CopyOnWriteArraySet<FilterServiceListener>(); } public long getFiltersVersion() { return filtersVersion; } public void destroy() { log.debug("Destroying filter service"); eventTypeIndex.destroy(); indexBuilder.destroy(); } public final void add(FilterValueSet filterValueSet, FilterHandle filterCallback) { indexBuilder.add(filterValueSet, filterCallback); filtersVersion++; } public final void remove(FilterHandle filterCallback) { indexBuilder.remove(filterCallback); filtersVersion++; } public final long evaluate(EventBean theEvent, Collection<FilterHandle> matches) { long version = filtersVersion; numEventsEvaluated.incrementAndGet(); // Finds all matching filters and return their callbacks eventTypeIndex.matchEvent(theEvent, matches); if ((AuditPath.isAuditEnabled) && (!filterServiceListeners.isEmpty())) { for (FilterServiceListener listener : filterServiceListeners) { listener.filtering(theEvent, matches, null); } } return version; } public final long evaluate(EventBean theEvent, Collection<FilterHandle> matches, String statementId) { long version = filtersVersion; numEventsEvaluated.incrementAndGet(); ArrayDeque<FilterHandle> allMatches = new ArrayDeque<FilterHandle>(); // Finds all matching filters eventTypeIndex.matchEvent(theEvent, allMatches); // Add statement matches to collection passed for (FilterHandle match : allMatches) { if (match.getStatementId().equals(statementId)) { matches.add(match); } } if ((AuditPath.isAuditEnabled) && (!filterServiceListeners.isEmpty())) { for (FilterServiceListener listener : filterServiceListeners) { listener.filtering(theEvent, matches, statementId); } } return version; } public final long getNumEventsEvaluated() { return numEventsEvaluated.get(); } public void resetStats() { numEventsEvaluated.set(0); } public void addFilterServiceListener(FilterServiceListener filterServiceListener) { filterServiceListeners.add(filterServiceListener); } public void removeFilterServiceListener(FilterServiceListener filterServiceListener) { filterServiceListeners.remove(filterServiceListener); } public FilterSet take(Set<String> statementIds) { filtersVersion++; return indexBuilder.take(statementIds); } public void apply(FilterSet filterSet) { filtersVersion++; indexBuilder.apply(filterSet); } public int getFilterCountApprox() { return eventTypeIndex.getFilterCountApprox(); } public int getCountTypes() { return eventTypeIndex.size(); } public void removeType(EventType type) { eventTypeIndex.removeType(type); } }