/*
***************************************************************************************
* 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.start;
import com.espertech.esper.client.EventType;
import com.espertech.esper.client.annotation.HintEnum;
import com.espertech.esper.core.context.activator.ViewableActivator;
import com.espertech.esper.core.context.factory.StatementAgentInstanceFactoryCreateWindow;
import com.espertech.esper.core.context.factory.StatementAgentInstanceFactoryCreateWindowResult;
import com.espertech.esper.core.context.mgr.ContextManagedStatementCreateWindowDesc;
import com.espertech.esper.core.context.util.AgentInstanceContext;
import com.espertech.esper.core.context.util.ContextMergeView;
import com.espertech.esper.core.service.EPServicesContext;
import com.espertech.esper.core.service.StatementContext;
import com.espertech.esper.core.service.resource.StatementResourceHolder;
import com.espertech.esper.epl.core.ResultSetProcessorFactoryDesc;
import com.espertech.esper.epl.core.ResultSetProcessorFactoryFactory;
import com.espertech.esper.epl.core.StreamTypeService;
import com.espertech.esper.epl.core.StreamTypeServiceImpl;
import com.espertech.esper.epl.expression.core.ExprValidationException;
import com.espertech.esper.epl.named.NamedWindowMgmtService;
import com.espertech.esper.epl.named.NamedWindowProcessor;
import com.espertech.esper.epl.spec.FilterStreamSpecCompiled;
import com.espertech.esper.epl.spec.SelectClauseElementWildcard;
import com.espertech.esper.epl.spec.SelectClauseStreamSelectorEnum;
import com.espertech.esper.epl.spec.StatementSpecCompiled;
import com.espertech.esper.epl.view.OutputProcessViewFactory;
import com.espertech.esper.epl.view.OutputProcessViewFactoryFactory;
import com.espertech.esper.epl.virtualdw.VirtualDWViewFactory;
import com.espertech.esper.event.vaevent.ValueAddEventProcessor;
import com.espertech.esper.metrics.instrumentation.InstrumentationAgent;
import com.espertech.esper.metrics.instrumentation.InstrumentationHelper;
import com.espertech.esper.util.StopCallback;
import com.espertech.esper.view.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
* Starts and provides the stop method for EPL statements.
*/
public class EPStatementStartMethodCreateWindow extends EPStatementStartMethodBase {
public EPStatementStartMethodCreateWindow(StatementSpecCompiled statementSpec) {
super(statementSpec);
}
public EPStatementStartResult startInternal(final EPServicesContext services, final StatementContext statementContext, boolean isNewStatement, boolean isRecoveringStatement, boolean isRecoveringResilient) throws ExprValidationException, ViewProcessingException {
// define stop
final List<StopCallback> stopCallbacks = new ArrayList<StopCallback>();
// determine context
final String contextName = statementSpec.getOptionalContextName();
// Create view factories and parent view based on a filter specification
// Since only for non-joins we get the existing stream's lock and try to reuse it's views
final FilterStreamSpecCompiled filterStreamSpec = (FilterStreamSpecCompiled) statementSpec.getStreamSpecs()[0];
InstrumentationAgent instrumentationAgentCreateWindowInsert = null;
if (InstrumentationHelper.ENABLED) {
final String eventTypeName = filterStreamSpec.getFilterSpec().getFilterForEventType().getName();
instrumentationAgentCreateWindowInsert = new InstrumentationAgent() {
public void indicateQ() {
InstrumentationHelper.get().qFilterActivationNamedWindowInsert(eventTypeName);
}
public void indicateA() {
InstrumentationHelper.get().aFilterActivationNamedWindowInsert();
}
};
}
ViewableActivator activator = services.getViewableActivatorFactory().createFilterProxy(services, filterStreamSpec.getFilterSpec(), statementContext.getAnnotations(), false, instrumentationAgentCreateWindowInsert, false, 0);
// create data window view factories
ViewFactoryChain unmaterializedViewChain = services.getViewService().createFactories(0, filterStreamSpec.getFilterSpec().getResultEventType(), filterStreamSpec.getViewSpecs(), filterStreamSpec.getOptions(), statementContext, false, -1);
// verify data window
verifyDataWindowViewFactoryChain(unmaterializedViewChain.getViewFactoryChain());
// get processor for variant-streams and versioned typed
final String windowName = statementSpec.getCreateWindowDesc().getWindowName();
ValueAddEventProcessor optionalRevisionProcessor = statementContext.getValueAddEventService().getValueAddProcessor(windowName);
// add named window processor (one per named window for all agent instances)
boolean isPrioritized = services.getEngineSettingsService().getEngineSettings().getExecution().isPrioritized();
boolean isEnableSubqueryIndexShare = HintEnum.ENABLE_WINDOW_SUBQUERY_INDEXSHARE.getHint(statementSpec.getAnnotations()) != null;
if (!isEnableSubqueryIndexShare && unmaterializedViewChain.getViewFactoryChain().get(0) instanceof VirtualDWViewFactory) {
isEnableSubqueryIndexShare = true; // index share is always enabled for virtual data window (otherwise it wouldn't make sense)
}
boolean isBatchingDataWindow = determineBatchingDataWindow(unmaterializedViewChain.getViewFactoryChain());
final VirtualDWViewFactory virtualDataWindowFactory = determineVirtualDataWindow(unmaterializedViewChain.getViewFactoryChain());
Set<String> optionalUniqueKeyProps = ViewServiceHelper.getUniqueCandidateProperties(unmaterializedViewChain.getViewFactoryChain(), statementSpec.getAnnotations());
NamedWindowProcessor processor = services.getNamedWindowMgmtService().addProcessor(windowName, contextName, filterStreamSpec.getFilterSpec().getResultEventType(), statementContext.getStatementResultService(), optionalRevisionProcessor, statementContext.getExpression(), statementContext.getStatementName(), isPrioritized, isEnableSubqueryIndexShare, isBatchingDataWindow, virtualDataWindowFactory != null, optionalUniqueKeyProps,
statementSpec.getCreateWindowDesc().getAsEventTypeName(),
statementContext, services.getNamedWindowDispatchService());
Viewable finalViewable;
EPStatementStopMethod stopStatementMethod;
EPStatementDestroyMethod destroyStatementMethod;
try {
// add stop callback
stopCallbacks.add(new StopCallback() {
public void stop() {
services.getNamedWindowMgmtService().removeProcessor(windowName);
if (virtualDataWindowFactory != null) {
virtualDataWindowFactory.destroyNamedWindow();
}
}
});
// Add a wildcard to the select clause as subscribers received the window contents
statementSpec.getSelectClauseSpec().setSelectExprList(new SelectClauseElementWildcard());
statementSpec.setSelectStreamDirEnum(SelectClauseStreamSelectorEnum.RSTREAM_ISTREAM_BOTH);
// obtain result set processor factory
StreamTypeService typeService = new StreamTypeServiceImpl(new EventType[]{processor.getNamedWindowType()}, new String[]{windowName}, new boolean[]{true}, services.getEngineURI(), false);
ResultSetProcessorFactoryDesc resultSetProcessorPrototype = ResultSetProcessorFactoryFactory.getProcessorPrototype(
statementSpec, statementContext, typeService, null, new boolean[0], true, null, null, services.getConfigSnapshot(), services.getResultSetProcessorHelperFactory(), false, false);
// obtain factory for output limiting
OutputProcessViewFactory outputViewFactory = OutputProcessViewFactoryFactory.make(statementSpec, services.getInternalEventRouter(), statementContext, resultSetProcessorPrototype.getResultSetProcessorFactory().getResultEventType(), null, services.getTableService(), resultSetProcessorPrototype.getResultSetProcessorFactory().getResultSetProcessorType(), services.getResultSetProcessorHelperFactory(), services.getStatementVariableRefService());
// create context factory
// Factory for statement-context instances
StatementAgentInstanceFactoryCreateWindow contextFactory = new StatementAgentInstanceFactoryCreateWindow(statementContext, statementSpec, services, activator, unmaterializedViewChain, resultSetProcessorPrototype, outputViewFactory, isRecoveringStatement);
statementContext.setStatementAgentInstanceFactory(contextFactory);
// With context - delegate instantiation to context
final EPStatementStopMethod stopMethod = new EPStatementStopMethodImpl(statementContext, stopCallbacks);
if (statementSpec.getOptionalContextName() != null) {
ContextMergeView mergeView = new ContextMergeView(processor.getNamedWindowType());
finalViewable = mergeView;
final ContextManagedStatementCreateWindowDesc statement = new ContextManagedStatementCreateWindowDesc(statementSpec, statementContext, mergeView, contextFactory);
services.getContextManagementService().addStatement(contextName, statement, isRecoveringResilient);
stopStatementMethod = new EPStatementStopMethod() {
public void stop() {
services.getContextManagementService().stoppedStatement(contextName, statementContext.getStatementName(), statementContext.getStatementId(), statementContext.getExpression(), statementContext.getExceptionHandlingService());
stopMethod.stop();
}
};
destroyStatementMethod = new EPStatementDestroyMethod() {
public void destroy() {
services.getContextManagementService().destroyedStatement(contextName, statementContext.getStatementName(), statementContext.getStatementId());
}
};
} else {
// Without context - start here
AgentInstanceContext agentInstanceContext = getDefaultAgentInstanceContext(statementContext);
final StatementAgentInstanceFactoryCreateWindowResult resultOfStart;
try {
resultOfStart = (StatementAgentInstanceFactoryCreateWindowResult) contextFactory.newContext(agentInstanceContext, isRecoveringResilient);
} catch (RuntimeException ex) {
services.getNamedWindowMgmtService().removeProcessor(windowName);
throw ex;
}
finalViewable = resultOfStart.getFinalView();
final StopCallback stopCallback = services.getEpStatementFactory().makeStopMethod(resultOfStart);
stopStatementMethod = new EPStatementStopMethod() {
public void stop() {
stopCallback.stop();
stopMethod.stop();
}
};
destroyStatementMethod = null;
if (statementContext.getStatementExtensionServicesContext() != null && statementContext.getStatementExtensionServicesContext().getStmtResources() != null) {
StatementResourceHolder holder = statementContext.getStatementExtensionServicesContext().extractStatementResourceHolder(resultOfStart);
statementContext.getStatementExtensionServicesContext().getStmtResources().setUnpartitioned(holder);
statementContext.getStatementExtensionServicesContext().postProcessStart(resultOfStart, isRecoveringResilient);
}
}
} catch (ExprValidationException ex) {
services.getNamedWindowMgmtService().removeProcessor(windowName);
throw ex;
} catch (RuntimeException ex) {
services.getNamedWindowMgmtService().removeProcessor(windowName);
throw ex;
}
services.getStatementVariableRefService().addReferences(statementContext.getStatementName(), windowName);
return new EPStatementStartResult(finalViewable, stopStatementMethod, destroyStatementMethod);
}
private static VirtualDWViewFactory determineVirtualDataWindow(List<ViewFactory> viewFactoryChain) {
for (ViewFactory viewFactory : viewFactoryChain) {
if (viewFactory instanceof VirtualDWViewFactory) {
return (VirtualDWViewFactory) viewFactory;
}
}
return null;
}
private static boolean determineBatchingDataWindow(List<ViewFactory> viewFactoryChain) {
for (ViewFactory viewFactory : viewFactoryChain) {
if (viewFactory instanceof DataWindowBatchingViewFactory) {
return true;
}
}
return false;
}
private void verifyDataWindowViewFactoryChain(List<ViewFactory> viewFactories) throws ExprValidationException {
for (ViewFactory viewFactory : viewFactories) {
if (viewFactory instanceof DataWindowViewFactory) {
return;
}
}
throw new ExprValidationException(NamedWindowMgmtService.ERROR_MSG_DATAWINDOWS);
}
}