/*
***************************************************************************************
* Copyright (C) 2006 EsperTech, Inc. All rights reserved. *
* http://www.espertech.com/esper *
* 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.core.context.factory;
import com.espertech.esper.client.EventBean;
import com.espertech.esper.collection.Pair;
import com.espertech.esper.core.context.activator.ViewableActivationResult;
import com.espertech.esper.core.context.activator.ViewableActivator;
import com.espertech.esper.core.context.activator.ViewableActivatorStreamReuseView;
import com.espertech.esper.core.context.subselect.SubSelectStrategyCollection;
import com.espertech.esper.core.context.subselect.SubSelectStrategyHolder;
import com.espertech.esper.core.context.util.AgentInstanceContext;
import com.espertech.esper.core.context.util.AgentInstanceViewFactoryChainContext;
import com.espertech.esper.core.context.util.EPStatementAgentInstanceHandle;
import com.espertech.esper.core.context.util.StatementAgentInstanceUtil;
import com.espertech.esper.core.service.EPServicesContext;
import com.espertech.esper.core.service.EPStatementDispatch;
import com.espertech.esper.core.service.StatementContext;
import com.espertech.esper.core.service.StreamJoinAnalysisResult;
import com.espertech.esper.core.start.*;
import com.espertech.esper.epl.agg.service.AggregationService;
import com.espertech.esper.epl.core.*;
import com.espertech.esper.epl.expression.core.ExprEvaluatorContext;
import com.espertech.esper.epl.expression.core.ExprNode;
import com.espertech.esper.epl.expression.core.ExprNodeUtility;
import com.espertech.esper.epl.expression.prev.ExprPreviousEvalStrategy;
import com.espertech.esper.epl.expression.prev.ExprPreviousMatchRecognizeNode;
import com.espertech.esper.epl.expression.prev.ExprPreviousNode;
import com.espertech.esper.epl.expression.prior.ExprPriorEvalStrategy;
import com.espertech.esper.epl.expression.prior.ExprPriorNode;
import com.espertech.esper.epl.expression.subquery.ExprSubselectNode;
import com.espertech.esper.epl.expression.table.ExprTableAccessEvalStrategy;
import com.espertech.esper.epl.expression.table.ExprTableAccessNode;
import com.espertech.esper.epl.join.base.*;
import com.espertech.esper.epl.join.plan.QueryGraph;
import com.espertech.esper.epl.named.NamedWindowConsumerView;
import com.espertech.esper.epl.named.NamedWindowProcessor;
import com.espertech.esper.epl.named.NamedWindowProcessorInstance;
import com.espertech.esper.epl.named.NamedWindowTailViewInstance;
import com.espertech.esper.epl.spec.NamedWindowConsumerStreamSpec;
import com.espertech.esper.epl.spec.StatementSpecCompiled;
import com.espertech.esper.epl.spec.StreamSpecCompiled;
import com.espertech.esper.epl.view.FilterExprView;
import com.espertech.esper.epl.view.OutputProcessViewBase;
import com.espertech.esper.epl.view.OutputProcessViewFactory;
import com.espertech.esper.metrics.instrumentation.InstrumentationHelper;
import com.espertech.esper.pattern.EvalRootMatchRemover;
import com.espertech.esper.pattern.EvalRootState;
import com.espertech.esper.rowregex.EventRowRegexHelper;
import com.espertech.esper.rowregex.EventRowRegexNFAViewService;
import com.espertech.esper.rowregex.RegexExprPreviousEvalStrategy;
import com.espertech.esper.util.StopCallback;
import com.espertech.esper.view.*;
import com.espertech.esper.view.internal.BufferView;
import com.espertech.esper.view.internal.PatternRemoveDispatchView;
import com.espertech.esper.view.internal.PriorEventViewFactory;
import com.espertech.esper.view.internal.SingleStreamDispatchView;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
public class StatementAgentInstanceFactorySelect extends StatementAgentInstanceFactoryBase {
private static final Logger log = LoggerFactory.getLogger(StatementAgentInstanceFactorySelect.class);
protected final int numStreams;
protected final ViewableActivator[] eventStreamParentViewableActivators;
protected final StatementContext statementContext;
protected final StatementSpecCompiled statementSpec;
protected final EPServicesContext services;
protected final StreamTypeService typeService;
protected final ViewFactoryChain[] unmaterializedViewChain;
protected final ResultSetProcessorFactoryDesc resultSetProcessorFactoryDesc;
protected final StreamJoinAnalysisResult joinAnalysisResult;
protected final JoinSetComposerPrototype joinSetComposerPrototype;
protected final SubSelectStrategyCollection subSelectStrategyCollection;
protected final ViewResourceDelegateVerified viewResourceDelegate;
protected final OutputProcessViewFactory outputProcessViewFactory;
public StatementAgentInstanceFactorySelect(int numStreams, ViewableActivator[] eventStreamParentViewableActivators, StatementContext statementContext, StatementSpecCompiled statementSpec, EPServicesContext services, StreamTypeService typeService, ViewFactoryChain[] unmaterializedViewChain, ResultSetProcessorFactoryDesc resultSetProcessorFactoryDesc, StreamJoinAnalysisResult joinAnalysisResult, boolean recoveringResilient, JoinSetComposerPrototype joinSetComposerPrototype, SubSelectStrategyCollection subSelectStrategyCollection, ViewResourceDelegateVerified viewResourceDelegate, OutputProcessViewFactory outputProcessViewFactory) {
super(statementSpec.getAnnotations());
this.numStreams = numStreams;
this.eventStreamParentViewableActivators = eventStreamParentViewableActivators;
this.statementContext = statementContext;
this.statementSpec = statementSpec;
this.services = services;
this.typeService = typeService;
this.unmaterializedViewChain = unmaterializedViewChain;
this.resultSetProcessorFactoryDesc = resultSetProcessorFactoryDesc;
this.joinAnalysisResult = joinAnalysisResult;
this.joinSetComposerPrototype = joinSetComposerPrototype;
this.subSelectStrategyCollection = subSelectStrategyCollection;
this.viewResourceDelegate = viewResourceDelegate;
this.outputProcessViewFactory = outputProcessViewFactory;
}
public ViewResourceDelegateVerified getViewResourceDelegate() {
return viewResourceDelegate;
}
public StatementAgentInstanceFactorySelectResult newContextInternal(final AgentInstanceContext agentInstanceContext, boolean isRecoveringResilient) {
final List<StopCallback> stopCallbacks = new ArrayList<StopCallback>(2);
Viewable finalView;
ViewableActivationResult[] viewableActivationResult = new ViewableActivationResult[eventStreamParentViewableActivators.length];
Map<ExprSubselectNode, SubSelectStrategyHolder> subselectStrategies;
AggregationService aggregationService;
Viewable[] streamViews;
Viewable[] eventStreamParentViewable;
Viewable[] topViews;
Map<ExprPriorNode, ExprPriorEvalStrategy> priorNodeStrategies;
Map<ExprPreviousNode, ExprPreviousEvalStrategy> previousNodeStrategies;
Map<ExprTableAccessNode, ExprTableAccessEvalStrategy> tableAccessStrategies;
RegexExprPreviousEvalStrategy regexExprPreviousEvalStrategy = null;
List<StatementAgentInstancePreload> preloadList = new ArrayList<StatementAgentInstancePreload>();
EvalRootState[] patternRoots;
StatementAgentInstancePostLoad postLoadJoin = null;
boolean suppressSameEventMatches = false;
boolean discardPartialsOnMatch = false;
EvalRootMatchRemover evalRootMatchRemover = null;
try {
// create root viewables
eventStreamParentViewable = new Viewable[numStreams];
patternRoots = new EvalRootState[numStreams];
for (int stream = 0; stream < eventStreamParentViewableActivators.length; stream++) {
ViewableActivationResult activationResult = eventStreamParentViewableActivators[stream].activate(agentInstanceContext, false, isRecoveringResilient);
viewableActivationResult[stream] = activationResult;
stopCallbacks.add(activationResult.getStopCallback());
suppressSameEventMatches = activationResult.isSuppressSameEventMatches();
discardPartialsOnMatch = activationResult.isDiscardPartialsOnMatch();
// add stop callback for any stream-level viewable when applicable
if (activationResult.getViewable() instanceof StopCallback) {
stopCallbacks.add((StopCallback) activationResult.getViewable());
}
eventStreamParentViewable[stream] = activationResult.getViewable();
patternRoots[stream] = activationResult.getOptionalPatternRoot();
if (stream == 0) {
evalRootMatchRemover = activationResult.getOptEvalRootMatchRemover();
}
if (activationResult.getOptionalLock() != null) {
agentInstanceContext.getEpStatementAgentInstanceHandle().setStatementAgentInstanceLock(activationResult.getOptionalLock());
statementContext.setDefaultAgentInstanceLock(activationResult.getOptionalLock());
}
}
// compile view factories adding "prior" as necessary
List<ViewFactory>[] viewFactoryChains = new List[numStreams];
for (int i = 0; i < numStreams; i++) {
List<ViewFactory> viewFactoryChain = unmaterializedViewChain[i].getViewFactoryChain();
// add "prior" view factory
boolean hasPrior = viewResourceDelegate.getPerStream()[i].getPriorRequests() != null && !viewResourceDelegate.getPerStream()[i].getPriorRequests().isEmpty();
if (hasPrior) {
PriorEventViewFactory priorEventViewFactory = EPStatementStartMethodHelperPrior.getPriorEventViewFactory(agentInstanceContext.getStatementContext(), i, viewFactoryChain.isEmpty(), false, -1);
viewFactoryChain = new ArrayList<ViewFactory>(viewFactoryChain);
viewFactoryChain.add(priorEventViewFactory);
}
viewFactoryChains[i] = viewFactoryChain;
}
// create view factory chain context: holds stream-specific services
AgentInstanceViewFactoryChainContext[] viewFactoryChainContexts = new AgentInstanceViewFactoryChainContext[numStreams];
for (int i = 0; i < numStreams; i++) {
viewFactoryChainContexts[i] = AgentInstanceViewFactoryChainContext.create(viewFactoryChains[i], agentInstanceContext, viewResourceDelegate.getPerStream()[i]);
}
// handle "prior" nodes and their strategies
priorNodeStrategies = EPStatementStartMethodHelperPrior.compilePriorNodeStrategies(viewResourceDelegate, viewFactoryChainContexts);
// handle "previous" nodes and their strategies
previousNodeStrategies = EPStatementStartMethodHelperPrevious.compilePreviousNodeStrategies(viewResourceDelegate, viewFactoryChainContexts);
// materialize views
streamViews = new Viewable[numStreams];
topViews = new Viewable[numStreams];
for (int i = 0; i < numStreams; i++) {
boolean hasPreviousNode = viewResourceDelegate.getPerStream()[i].getPreviousRequests() != null && !viewResourceDelegate.getPerStream()[i].getPreviousRequests().isEmpty();
ViewServiceCreateResult createResult = services.getViewService().createViews(eventStreamParentViewable[i], viewFactoryChains[i], viewFactoryChainContexts[i], hasPreviousNode);
topViews[i] = createResult.getTopViewable();
streamViews[i] = createResult.getFinalViewable();
boolean isReuseableView = eventStreamParentViewableActivators[i] instanceof ViewableActivatorStreamReuseView;
if (isReuseableView) {
final List<View> viewsCreated = createResult.getNewViews();
StopCallback stopCallback = new StopCallback() {
public void stop() {
ViewServiceHelper.removeFirstUnsharedView(viewsCreated);
}
};
stopCallbacks.add(stopCallback);
}
// add views to stop callback if applicable
addViewStopCallback(stopCallbacks, createResult.getNewViews());
}
// determine match-recognize "previous"-node strategy (none if not present, or one handling and number of nodes)
EventRowRegexNFAViewService matchRecognize = EventRowRegexHelper.recursiveFindRegexService(topViews[0]);
if (matchRecognize != null) {
regexExprPreviousEvalStrategy = matchRecognize.getPreviousEvaluationStrategy();
stopCallbacks.add(matchRecognize);
}
// start subselects
subselectStrategies = EPStatementStartMethodHelperSubselect.startSubselects(services, subSelectStrategyCollection, agentInstanceContext, stopCallbacks, isRecoveringResilient);
// plan table access
tableAccessStrategies = EPStatementStartMethodHelperTableAccess.attachTableAccess(services, agentInstanceContext, statementSpec.getTableNodes());
// obtain result set processor and aggregation services
Pair<ResultSetProcessor, AggregationService> processorPair = EPStatementStartMethodHelperUtil.startResultSetAndAggregation(resultSetProcessorFactoryDesc, agentInstanceContext, false, null);
final ResultSetProcessor resultSetProcessor = processorPair.getFirst();
aggregationService = processorPair.getSecond();
stopCallbacks.add(aggregationService);
stopCallbacks.add(resultSetProcessor);
// for just 1 event stream without joins, handle the one-table process separately.
final JoinPreloadMethod joinPreloadMethod;
JoinSetComposerDesc joinSetComposer = null;
if (streamViews.length == 1) {
finalView = handleSimpleSelect(streamViews[0], resultSetProcessor, agentInstanceContext, evalRootMatchRemover, suppressSameEventMatches, discardPartialsOnMatch);
joinPreloadMethod = null;
} else {
JoinPlanResult joinPlanResult = handleJoin(typeService.getStreamNames(), streamViews, resultSetProcessor,
agentInstanceContext, stopCallbacks, joinAnalysisResult, isRecoveringResilient);
finalView = joinPlanResult.getViewable();
joinPreloadMethod = joinPlanResult.getPreloadMethod();
joinSetComposer = joinPlanResult.getJoinSetComposerDesc();
}
// for stoppable final views, add callback
if (finalView instanceof StopCallback) {
stopCallbacks.add((StopCallback) finalView);
}
// Replay any named window data, for later consumers of named data windows
if (services.getEventTableIndexService().allowInitIndex(isRecoveringResilient)) {
boolean hasNamedWindow = false;
QueryGraph[] namedWindowPostloadFilters = new QueryGraph[statementSpec.getStreamSpecs().length];
NamedWindowTailViewInstance[] namedWindowTailViews = new NamedWindowTailViewInstance[statementSpec.getStreamSpecs().length];
List<ExprNode>[] namedWindowFilters = new List[statementSpec.getStreamSpecs().length];
for (int i = 0; i < statementSpec.getStreamSpecs().length; i++) {
final int streamNum = i;
StreamSpecCompiled streamSpec = statementSpec.getStreamSpecs()[i];
if (streamSpec instanceof NamedWindowConsumerStreamSpec) {
hasNamedWindow = true;
final NamedWindowConsumerStreamSpec namedSpec = (NamedWindowConsumerStreamSpec) streamSpec;
NamedWindowProcessor processor = services.getNamedWindowMgmtService().getProcessor(namedSpec.getWindowName());
NamedWindowProcessorInstance processorInstance = processor.getProcessorInstance(agentInstanceContext);
if (processorInstance != null) {
final NamedWindowTailViewInstance consumerView = processorInstance.getTailViewInstance();
namedWindowTailViews[i] = consumerView;
final NamedWindowConsumerView view = (NamedWindowConsumerView) viewableActivationResult[i].getViewable();
// determine preload/postload filter for index access
if (!namedSpec.getFilterExpressions().isEmpty()) {
namedWindowFilters[streamNum] = namedSpec.getFilterExpressions();
String streamName = streamSpec.getOptionalStreamName() != null ? streamSpec.getOptionalStreamName() : consumerView.getEventType().getName();
StreamTypeServiceImpl types = new StreamTypeServiceImpl(consumerView.getEventType(), streamName, false, services.getEngineURI());
namedWindowPostloadFilters[i] = ExprNodeUtility.validateFilterGetQueryGraphSafe(ExprNodeUtility.connectExpressionsByLogicalAndWhenNeeded(namedSpec.getFilterExpressions()), statementContext, types);
}
// preload view for stream unless the expiry policy is batch window
Iterator<EventBean> consumerViewIterator = consumerView.iterator();
boolean preload = !consumerView.getTailView().isParentBatchWindow() && consumerViewIterator.hasNext();
if (preload) {
if (isRecoveringResilient && numStreams < 2) {
preload = false;
}
}
if (preload) {
final boolean yesRecoveringResilient = isRecoveringResilient;
final QueryGraph preloadFilterSpec = namedWindowPostloadFilters[i];
preloadList.add(new StatementAgentInstancePreload() {
public void executePreload(ExprEvaluatorContext exprEvaluatorContext) {
Collection<EventBean> snapshot = consumerView.snapshot(preloadFilterSpec, statementContext.getAnnotations());
List<EventBean> eventsInWindow = new ArrayList<EventBean>(snapshot.size());
ExprNodeUtility.applyFilterExpressionsIterable(snapshot, namedSpec.getFilterExpressions(), agentInstanceContext, eventsInWindow);
EventBean[] newEvents = eventsInWindow.toArray(new EventBean[eventsInWindow.size()]);
view.update(newEvents, null);
if (!yesRecoveringResilient && joinPreloadMethod != null && !joinPreloadMethod.isPreloading() && agentInstanceContext.getEpStatementAgentInstanceHandle().getOptionalDispatchable() != null) {
agentInstanceContext.getEpStatementAgentInstanceHandle().getOptionalDispatchable().execute();
}
}
});
}
} else {
log.info("Named window access is out-of-context, the named window '" + namedSpec.getWindowName() + "' has been declared for a different context then the current statement, the aggregation and join state will not be initialized for statement expression [" + statementContext.getExpression() + "]");
}
preloadList.add(new StatementAgentInstancePreload() {
public void executePreload(ExprEvaluatorContext exprEvaluatorContext) {
// in a join, preload indexes, if any
if (joinPreloadMethod != null) {
joinPreloadMethod.preloadFromBuffer(streamNum, exprEvaluatorContext);
} else {
if (agentInstanceContext.getEpStatementAgentInstanceHandle().getOptionalDispatchable() != null) {
agentInstanceContext.getEpStatementAgentInstanceHandle().getOptionalDispatchable().execute();
}
}
}
});
}
}
// last, for aggregation we need to send the current join results to the result set processor
if (hasNamedWindow && (joinPreloadMethod != null) && (!isRecoveringResilient) && resultSetProcessorFactoryDesc.getResultSetProcessorFactory().hasAggregation()) {
preloadList.add(new StatementAgentInstancePreload() {
public void executePreload(ExprEvaluatorContext exprEvaluatorContext) {
joinPreloadMethod.preloadAggregation(resultSetProcessor);
}
});
}
if (isRecoveringResilient) {
postLoadJoin = new StatementAgentInstancePostLoadSelect(streamViews, joinSetComposer, namedWindowTailViews, namedWindowPostloadFilters, namedWindowFilters, statementContext.getAnnotations(), agentInstanceContext);
} else if (joinSetComposer != null) {
postLoadJoin = new StatementAgentInstancePostLoadIndexVisiting(joinSetComposer.getJoinSetComposer());
}
}
} catch (RuntimeException ex) {
StopCallback stopCallback = StatementAgentInstanceUtil.getStopCallback(stopCallbacks, agentInstanceContext);
StatementAgentInstanceUtil.stopSafe(stopCallback, statementContext);
if (InstrumentationHelper.ENABLED) {
InstrumentationHelper.get().aContextPartitionAllocate();
}
throw ex;
}
StatementAgentInstanceFactorySelectResult selectResult = new StatementAgentInstanceFactorySelectResult(finalView, null, agentInstanceContext, aggregationService, subselectStrategies, priorNodeStrategies, previousNodeStrategies, regexExprPreviousEvalStrategy, tableAccessStrategies, preloadList, patternRoots, postLoadJoin, topViews, eventStreamParentViewable, viewableActivationResult);
if (statementContext.getStatementExtensionServicesContext() != null) {
statementContext.getStatementExtensionServicesContext().contributeStopCallback(selectResult, stopCallbacks);
}
StopCallback stopCallback = StatementAgentInstanceUtil.getStopCallback(stopCallbacks, agentInstanceContext);
selectResult.setStopCallback(stopCallback);
return selectResult;
}
protected static void addViewStopCallback(List<StopCallback> stopCallbacks, List<View> topViews) {
for (View view : topViews) {
if (view instanceof StoppableView) {
stopCallbacks.add((StoppableView) view);
}
}
}
public void assignExpressions(StatementAgentInstanceFactoryResult result) {
StatementAgentInstanceFactorySelectResult selectResult = (StatementAgentInstanceFactorySelectResult) result;
EPStatementStartMethodHelperAssignExpr.assignAggregations(selectResult.getOptionalAggegationService(), resultSetProcessorFactoryDesc.getAggregationServiceFactoryDesc().getExpressions());
EPStatementStartMethodHelperAssignExpr.assignSubqueryStrategies(subSelectStrategyCollection, result.getSubselectStrategies());
EPStatementStartMethodHelperAssignExpr.assignPriorStrategies(result.getPriorNodeStrategies());
EPStatementStartMethodHelperAssignExpr.assignPreviousStrategies(result.getPreviousNodeStrategies());
Set<ExprPreviousMatchRecognizeNode> matchRecognizeNodes = viewResourceDelegate.getPerStream()[0].getMatchRecognizePreviousRequests();
EPStatementStartMethodHelperAssignExpr.assignMatchRecognizePreviousStrategies(matchRecognizeNodes, result.getRegexExprPreviousEvalStrategy());
}
public void unassignExpressions() {
EPStatementStartMethodHelperAssignExpr.unassignAggregations(resultSetProcessorFactoryDesc.getAggregationServiceFactoryDesc().getExpressions());
EPStatementStartMethodHelperAssignExpr.unassignSubqueryStrategies(subSelectStrategyCollection.getSubqueries().keySet());
for (int streamNum = 0; streamNum < viewResourceDelegate.getPerStream().length; streamNum++) {
ViewResourceDelegateVerifiedStream viewResourceStream = viewResourceDelegate.getPerStream()[streamNum];
SortedMap<Integer, List<ExprPriorNode>> callbacksPerIndex = viewResourceStream.getPriorRequests();
for (Map.Entry<Integer, List<ExprPriorNode>> priorItem : callbacksPerIndex.entrySet()) {
EPStatementStartMethodHelperAssignExpr.unassignPriorStrategies(priorItem.getValue());
}
EPStatementStartMethodHelperAssignExpr.unassignPreviousStrategies(viewResourceStream.getPreviousRequests());
}
Set<ExprPreviousMatchRecognizeNode> matchRecognizeNodes = viewResourceDelegate.getPerStream()[0].getMatchRecognizePreviousRequests();
EPStatementStartMethodHelperAssignExpr.unassignMatchRecognizePreviousStrategies(matchRecognizeNodes);
}
public ViewableActivator[] getEventStreamParentViewableActivators() {
return eventStreamParentViewableActivators;
}
public ViewFactoryChain[] getUnmaterializedViewChain() {
return unmaterializedViewChain;
}
public int getNumStreams() {
return numStreams;
}
public StatementContext getStatementContext() {
return statementContext;
}
public StatementSpecCompiled getStatementSpec() {
return statementSpec;
}
public EPServicesContext getServices() {
return services;
}
public StreamTypeService getTypeService() {
return typeService;
}
public ResultSetProcessorFactoryDesc getResultSetProcessorFactoryDesc() {
return resultSetProcessorFactoryDesc;
}
public StreamJoinAnalysisResult getJoinAnalysisResult() {
return joinAnalysisResult;
}
public JoinSetComposerPrototype getJoinSetComposerPrototype() {
return joinSetComposerPrototype;
}
public SubSelectStrategyCollection getSubSelectStrategyCollection() {
return subSelectStrategyCollection;
}
public OutputProcessViewFactory getOutputProcessViewFactory() {
return outputProcessViewFactory;
}
private Viewable handleSimpleSelect(Viewable view,
ResultSetProcessor resultSetProcessor,
AgentInstanceContext agentInstanceContext,
EvalRootMatchRemover evalRootMatchRemover,
boolean suppressSameEventMatches,
boolean discardPartialsOnMatch) {
Viewable finalView = view;
// Add filter view that evaluates the filter expression
if (statementSpec.getFilterRootNode() != null) {
FilterExprView filterView = new FilterExprView(statementSpec.getFilterRootNode(), statementSpec.getFilterRootNode().getExprEvaluator(), agentInstanceContext);
finalView.addView(filterView);
finalView = filterView;
}
Deque<EPStatementDispatch> dispatches = null;
if (evalRootMatchRemover != null && (suppressSameEventMatches || discardPartialsOnMatch)) {
PatternRemoveDispatchView v = new PatternRemoveDispatchView(evalRootMatchRemover, suppressSameEventMatches, discardPartialsOnMatch);
dispatches = new ArrayDeque<EPStatementDispatch>(2);
dispatches.add(v);
finalView.addView(v);
finalView = v;
}
// for ordered deliver without output limit/buffer
if (statementSpec.getOrderByList().length > 0 && (statementSpec.getOutputLimitSpec() == null)) {
SingleStreamDispatchView bf = new SingleStreamDispatchView();
if (dispatches == null) {
dispatches = new ArrayDeque<EPStatementDispatch>(1);
}
dispatches.add(bf);
finalView.addView(bf);
finalView = bf;
}
if (dispatches != null) {
EPStatementAgentInstanceHandle handle = agentInstanceContext.getEpStatementAgentInstanceHandle();
if (dispatches.size() == 1) {
handle.setOptionalDispatchable(dispatches.getFirst());
} else {
final EPStatementDispatch[] dispatchArray = dispatches.toArray(new EPStatementDispatch[dispatches.size()]);
handle.setOptionalDispatchable(new EPStatementDispatch() {
public void execute() {
for (EPStatementDispatch dispatch : dispatchArray) {
dispatch.execute();
}
}
});
}
}
com.espertech.esper.view.View selectView = outputProcessViewFactory.makeView(resultSetProcessor, agentInstanceContext);
finalView.addView(selectView);
finalView = selectView;
return finalView;
}
private JoinPlanResult handleJoin(String[] streamNames,
Viewable[] streamViews,
ResultSetProcessor resultSetProcessor,
AgentInstanceContext agentInstanceContext,
List<StopCallback> stopCallbacks,
StreamJoinAnalysisResult joinAnalysisResult,
boolean isRecoveringResilient) {
final JoinSetComposerDesc joinSetComposerDesc = joinSetComposerPrototype.create(streamViews, false, agentInstanceContext, isRecoveringResilient);
stopCallbacks.add(new StopCallback() {
public void stop() {
joinSetComposerDesc.getJoinSetComposer().destroy();
}
});
JoinSetFilter filter = new JoinSetFilter(joinSetComposerDesc.getPostJoinFilterEvaluator());
OutputProcessViewBase indicatorView = outputProcessViewFactory.makeView(resultSetProcessor, agentInstanceContext);
// Create strategy for join execution
JoinExecutionStrategy execution = new JoinExecutionStrategyImpl(joinSetComposerDesc.getJoinSetComposer(), filter, indicatorView, agentInstanceContext);
// The view needs a reference to the join execution to pull iterator values
indicatorView.setJoinExecutionStrategy(execution);
// Hook up dispatchable with buffer and execution strategy
JoinExecStrategyDispatchable joinStatementDispatch = new JoinExecStrategyDispatchable(execution, statementSpec.getStreamSpecs().length);
agentInstanceContext.getEpStatementAgentInstanceHandle().setOptionalDispatchable(joinStatementDispatch);
JoinPreloadMethod preloadMethod;
if (joinAnalysisResult.isUnidirectional()) {
preloadMethod = new JoinPreloadMethodNull();
} else {
if (!joinSetComposerDesc.getJoinSetComposer().allowsInit()) {
preloadMethod = new JoinPreloadMethodNull();
} else {
preloadMethod = new JoinPreloadMethodImpl(streamNames.length, joinSetComposerDesc.getJoinSetComposer());
}
}
// Create buffer for each view. Point buffer to dispatchable for join.
for (int i = 0; i < statementSpec.getStreamSpecs().length; i++) {
BufferView buffer = new BufferView(i);
streamViews[i].addView(buffer);
buffer.setObserver(joinStatementDispatch);
preloadMethod.setBuffer(buffer, i);
}
return new JoinPlanResult(indicatorView, preloadMethod, joinSetComposerDesc);
}
private static class JoinPlanResult {
private final Viewable viewable;
private final JoinPreloadMethod preloadMethod;
private final JoinSetComposerDesc joinSetComposerDesc;
private JoinPlanResult(Viewable viewable, JoinPreloadMethod preloadMethod, JoinSetComposerDesc joinSetComposerDesc) {
this.viewable = viewable;
this.preloadMethod = preloadMethod;
this.joinSetComposerDesc = joinSetComposerDesc;
}
public Viewable getViewable() {
return viewable;
}
public JoinPreloadMethod getPreloadMethod() {
return preloadMethod;
}
public JoinSetComposerDesc getJoinSetComposerDesc() {
return joinSetComposerDesc;
}
}
}