/*
***************************************************************************************
* 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.EPException;
import com.espertech.esper.client.EventType;
import com.espertech.esper.core.context.factory.StatementAgentInstanceFactoryCreateIndex;
import com.espertech.esper.core.context.factory.StatementAgentInstanceFactoryCreateIndexResult;
import com.espertech.esper.core.context.mgr.ContextManagedStatementCreateIndexDesc;
import com.espertech.esper.core.context.mgr.ContextManagementService;
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.expression.core.ExprValidationException;
import com.espertech.esper.epl.join.plan.QueryPlanIndexItem;
import com.espertech.esper.epl.lookup.AdvancedIndexDesc;
import com.espertech.esper.epl.lookup.EventTableIndexUtil;
import com.espertech.esper.epl.lookup.IndexMultiKey;
import com.espertech.esper.epl.named.NamedWindowProcessor;
import com.espertech.esper.epl.spec.CreateIndexDesc;
import com.espertech.esper.epl.spec.StatementSpecCompiled;
import com.espertech.esper.epl.table.mgmt.TableMetadata;
import com.espertech.esper.epl.table.mgmt.TableService;
import com.espertech.esper.epl.util.EPLValidationUtil;
import com.espertech.esper.util.DestroyCallback;
import com.espertech.esper.util.StopCallback;
import com.espertech.esper.view.ViewProcessingException;
import com.espertech.esper.view.Viewable;
import com.espertech.esper.view.ViewableDefaultImpl;
/**
* Starts and provides the stop method for EPL statements.
*/
public class EPStatementStartMethodCreateIndex extends EPStatementStartMethodBase {
public EPStatementStartMethodCreateIndex(StatementSpecCompiled statementSpec) {
super(statementSpec);
}
public EPStatementStartResult startInternal(EPServicesContext services, final StatementContext statementContext, boolean isNewStatement, boolean isRecoveringStatement, boolean isRecoveringResilient) throws ExprValidationException, ViewProcessingException {
CreateIndexDesc spec = statementSpec.getCreateIndexDesc();
final NamedWindowProcessor namedWindowProcessor = services.getNamedWindowMgmtService().getProcessor(spec.getWindowName());
final TableMetadata tableMetadata = services.getTableService().getTableMetadata(spec.getWindowName());
if (namedWindowProcessor == null && tableMetadata == null) {
throw new ExprValidationException("A named window or table by name '" + spec.getWindowName() + "' does not exist");
}
EventType indexedEventType = namedWindowProcessor != null ? namedWindowProcessor.getNamedWindowType() : tableMetadata.getInternalEventType();
String infraContextName = namedWindowProcessor != null ? namedWindowProcessor.getContextName() : tableMetadata.getContextName();
EPLValidationUtil.validateContextName(namedWindowProcessor == null, spec.getWindowName(), infraContextName, statementSpec.getOptionalContextName(), true);
// validate index
QueryPlanIndexItem explicitIndexDesc = EventTableIndexUtil.validateCompileExplicitIndex(spec.getIndexName(), spec.isUnique(), spec.getColumns(), indexedEventType, statementContext);
AdvancedIndexDesc advancedIndexDesc = explicitIndexDesc.getAdvancedIndexProvisionDesc() == null ? null : explicitIndexDesc.getAdvancedIndexProvisionDesc().getIndexDesc();
final IndexMultiKey imk = new IndexMultiKey(spec.isUnique(), explicitIndexDesc.getHashPropsAsList(), explicitIndexDesc.getBtreePropsAsList(), advancedIndexDesc);
// for tables we add the index to metadata
if (tableMetadata != null) {
services.getTableService().validateAddIndex(statementContext.getStatementName(), tableMetadata, spec.getIndexName(), explicitIndexDesc, imk);
} else {
namedWindowProcessor.validateAddIndex(statementContext.getStatementName(), spec.getIndexName(), explicitIndexDesc, imk);
}
// allocate context factory
Viewable viewable = new ViewableDefaultImpl(indexedEventType);
StatementAgentInstanceFactoryCreateIndex contextFactory = new StatementAgentInstanceFactoryCreateIndex(services, spec, viewable, namedWindowProcessor, tableMetadata == null ? null : tableMetadata.getTableName(), statementSpec.getOptionalContextName(), explicitIndexDesc);
statementContext.setStatementAgentInstanceFactory(contextFactory);
// provide destroy method which de-registers interest in this index
final TableService finalTableService = services.getTableService();
final String finalStatementName = statementContext.getStatementName();
EPStatementDestroyCallbackList destroyMethod = new EPStatementDestroyCallbackList();
if (tableMetadata != null) {
destroyMethod.addCallback(new DestroyCallback() {
public void destroy() {
finalTableService.removeIndexReferencesStmtMayRemoveIndex(finalStatementName, tableMetadata);
}
});
} else {
destroyMethod.addCallback(new DestroyCallback() {
public void destroy() {
namedWindowProcessor.removeIndexReferencesStmtMayRemoveIndex(imk, finalStatementName);
}
});
}
EPStatementStopMethod stopMethod;
if (statementSpec.getOptionalContextName() != null) {
ContextMergeView mergeView = new ContextMergeView(indexedEventType);
ContextManagedStatementCreateIndexDesc statement = new ContextManagedStatementCreateIndexDesc(statementSpec, statementContext, mergeView, contextFactory);
services.getContextManagementService().addStatement(statementSpec.getOptionalContextName(), statement, isRecoveringResilient);
stopMethod = new EPStatementStopMethod() {
public void stop() {
}
};
final ContextManagementService contextManagementService = services.getContextManagementService();
destroyMethod.addCallback(new DestroyCallback() {
public void destroy() {
contextManagementService.destroyedStatement(statementSpec.getOptionalContextName(), statementContext.getStatementName(), statementContext.getStatementId());
}
});
} else {
AgentInstanceContext defaultAgentInstanceContext = getDefaultAgentInstanceContext(statementContext);
StatementAgentInstanceFactoryCreateIndexResult result;
try {
result = contextFactory.newContext(defaultAgentInstanceContext, isRecoveringResilient);
} catch (EPException ex) {
if (ex.getCause() instanceof ExprValidationException) {
throw (ExprValidationException) ex.getCause();
}
destroyMethod.destroy();
throw ex;
} catch (Throwable t) {
destroyMethod.destroy();
throw t;
}
final StopCallback stopCallback = services.getEpStatementFactory().makeStopMethod(result);
stopMethod = new EPStatementStopMethod() {
public void stop() {
stopCallback.stop();
}
};
if (statementContext.getStatementExtensionServicesContext() != null && statementContext.getStatementExtensionServicesContext().getStmtResources() != null) {
StatementResourceHolder holder = statementContext.getStatementExtensionServicesContext().extractStatementResourceHolder(result);
statementContext.getStatementExtensionServicesContext().getStmtResources().setUnpartitioned(holder);
statementContext.getStatementExtensionServicesContext().postProcessStart(result, isRecoveringResilient);
}
}
if (tableMetadata != null) {
services.getStatementVariableRefService().addReferences(statementContext.getStatementName(), tableMetadata.getTableName());
} else {
services.getStatementVariableRefService().addReferences(statementContext.getStatementName(), namedWindowProcessor.getNamedWindowType().getName());
}
return new EPStatementStartResult(viewable, stopMethod, destroyMethod);
}
}