All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.espertech.esper.view.stream.StreamFactorySvcImpl Maven / Gradle / Ivy

Go to download

Complex event processing and event series analysis component

There is a newer version: 7.1.0
Show newest version
/**************************************************************************************
 * 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.view.stream;

import com.espertech.esper.client.EventBean;
import com.espertech.esper.client.EventType;
import com.espertech.esper.client.annotation.Audit;
import com.espertech.esper.client.annotation.AuditEnum;
import com.espertech.esper.collection.Pair;
import com.espertech.esper.collection.RefCountedMap;
import com.espertech.esper.core.EPStatementHandle;
import com.espertech.esper.core.EPStatementHandleCallback;
import com.espertech.esper.core.StatementLock;
import com.espertech.esper.epl.expression.ExprEvaluatorContext;
import com.espertech.esper.filter.*;
import com.espertech.esper.view.EventStream;
import com.espertech.esper.view.ZeroDepthStream;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.io.StringWriter;
import java.lang.annotation.Annotation;
import java.util.IdentityHashMap;


/**
 * Service implementation to reuse or not reuse event streams and existing filters depending on
 * the type of statement.
 * 

* For non-join statements, the class manages the reuse of event streams when filters match, and thus * when an event stream is reused such can be the views under the stream. For joins however, this can lead to * problems in multithread-safety since the statement resource lock would then have to be multiple locks, * i.e. the reused statement's resource lock and the join statement's own lock, at a minimum. *

* For join statements, always creating a new event stream and * therefore not reusing view resources, for use with joins. *

* This can be very effective in that if a client applications creates a large number of very similar * statements in terms of filters and views used then these resources are all re-used * across statements. *

* The re-use is multithread-safe in that * (A) statement start/stop is locked against other engine processing * (B) the first statement supplies the lock for shared filters and views, protecting multiple threads * from entering into the same view. * (C) joins statements do not participate in filter and view reuse */ public class StreamFactorySvcImpl implements StreamFactoryService { private static Log log = LogFactory.getLog(StreamFactorySvcImpl.class); // Using identify hash map - ignoring the equals semantics on filter specs // Thus two filter specs objects are always separate entries in the map private final IdentityHashMap> eventStreamsIdentity; // Using a reference-counted map for non-join statements private final RefCountedMap> eventStreamsRefCounted; private boolean isReuseViews; /** * Ctor. * @param isReuseViews indicator on whether stream and view resources are to be reused between statements */ public StreamFactorySvcImpl(boolean isReuseViews) { this.eventStreamsRefCounted = new RefCountedMap>(); this.eventStreamsIdentity = new IdentityHashMap>(); this.isReuseViews = isReuseViews; } public void destroy() { eventStreamsRefCounted.clear(); eventStreamsIdentity.clear(); } /** * See the method of the same name in {@link com.espertech.esper.view.stream.StreamFactoryService}. Always attempts to reuse an existing event stream. * May thus return a new event stream or an existing event stream depending on whether filter criteria match. * @param filterSpec is the filter definition * @param epStatementHandle is the statement resource lock * @return newly createdStatement event stream, not reusing existing instances */ public Pair createStream(final String statementId, final FilterSpecCompiled filterSpec, FilterService filterService, EPStatementHandle epStatementHandle, boolean isJoin, final boolean isSubSelect, final ExprEvaluatorContext exprEvaluatorContext, boolean isNamedWindowTrigger, boolean filterWithSameTypeSubselect, Annotation[] annotations) { if (log.isDebugEnabled()) { log.debug(".createStream hashCode=" + filterSpec.hashCode() + " filter=" + filterSpec); } // Check if a stream for this filter already exists Pair pair; boolean forceNewStream = isJoin || (!isReuseViews) || isSubSelect || isNamedWindowTrigger || filterWithSameTypeSubselect; if (forceNewStream) { pair = eventStreamsIdentity.get(filterSpec); } else { pair = eventStreamsRefCounted.get(filterSpec); } // If pair exists, either reference count or illegal state if (pair != null) { if (forceNewStream) { throw new IllegalStateException("Filter spec object already found in collection"); } else { log.debug(".createStream filter already found"); eventStreamsRefCounted.reference(filterSpec); // audit proxy EventStream eventStream = getAuditProxy(epStatementHandle.getStatementName(), annotations, filterSpec, pair.getFirst()); // We return the lock of the statement first establishing the stream to use that as the new statement's lock return new Pair(eventStream, pair.getSecond().getEpStatementHandle().getStatementLock()); } } // New event stream EventType resultEventType = filterSpec.getResultEventType(); EventStream zeroDepthStream = new ZeroDepthStream(resultEventType); // audit proxy EventStream inputStream = getAuditProxy(epStatementHandle.getStatementName(), annotations, filterSpec, zeroDepthStream); final EventStream eventStream = inputStream; FilterHandleCallback filterCallback; if (filterSpec.getOptionalPropertyEvaluator() != null) { filterCallback = new FilterHandleCallback() { public String getStatementId() { return statementId; } public void matchFound(EventBean event) { EventBean[] result = filterSpec.getOptionalPropertyEvaluator().getProperty(event, exprEvaluatorContext); if (result == null) { return; } eventStream.insert(result); } public boolean isSubSelect() { return isSubSelect; } }; } else { filterCallback = new FilterHandleCallback() { public String getStatementId() { return statementId; } public void matchFound(EventBean event) { eventStream.insert(event); } public boolean isSubSelect() { return isSubSelect; } }; } EPStatementHandleCallback handle = new EPStatementHandleCallback(epStatementHandle, filterCallback); // Store stream for reuse pair = new Pair(eventStream, handle); if (forceNewStream) { eventStreamsIdentity.put(filterSpec, pair); } else { eventStreamsRefCounted.put(filterSpec, pair); } // Activate filter FilterValueSet filterValues = filterSpec.getValueSet(null); filterService.add(filterValues, handle); return new Pair(inputStream, null); } private EventStream getAuditProxy(String statementName, Annotation[] annotations, FilterSpecCompiled filterSpec, EventStream designated) { Audit audit = AuditEnum.STREAM.getAudit(annotations); if (audit == null) { return designated; } StringWriter filterAndParams = new StringWriter(); filterAndParams.write(filterSpec.getFilterForEventType().getName()); if (filterSpec.getParameters() != null && !filterSpec.getParameters().isEmpty()) { filterAndParams.write('('); String delimiter = ""; for (FilterSpecParam param : filterSpec.getParameters()) { filterAndParams.write(delimiter); filterAndParams.write(param.getPropertyName()); filterAndParams.write(param.getFilterOperator().getTextualOp()); filterAndParams.write("..."); delimiter = ","; } filterAndParams.write(')'); } return (EventStream) EventStreamProxy.newInstance(statementName, filterAndParams.toString(), designated); } /** * See the method of the same name in {@link com.espertech.esper.view.stream.StreamFactoryService}. * @param filterSpec is the filter definition */ public void dropStream(FilterSpecCompiled filterSpec, FilterService filterService, boolean isJoin, boolean isSubSelect, boolean isNamedWindowTrigger, boolean filterWithSameTypeSubselect) { Pair pair; boolean forceNewStream = isJoin || (!isReuseViews) || isSubSelect || isNamedWindowTrigger || filterWithSameTypeSubselect; if (forceNewStream) { pair = eventStreamsIdentity.get(filterSpec); if (pair == null) { throw new IllegalStateException("Filter spec object not in collection"); } eventStreamsIdentity.remove(filterSpec); filterService.remove(pair.getSecond()); } else { pair = eventStreamsRefCounted.get(filterSpec); boolean isLast = eventStreamsRefCounted.dereference(filterSpec); if (isLast) { filterService.remove(pair.getSecond()); } } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy