com.espertech.esper.epl.db.DatabasePollingViewable Maven / Gradle / Ivy
/*
***************************************************************************************
* 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.epl.db;
import com.espertech.esper.client.ConfigurationInformation;
import com.espertech.esper.client.EPException;
import com.espertech.esper.client.EventBean;
import com.espertech.esper.client.EventType;
import com.espertech.esper.collection.IterablesArrayIterator;
import com.espertech.esper.core.service.StatementContext;
import com.espertech.esper.epl.core.EngineImportService;
import com.espertech.esper.epl.core.StreamTypeService;
import com.espertech.esper.epl.expression.core.*;
import com.espertech.esper.epl.expression.visitor.ExprNodeIdentifierCollectVisitor;
import com.espertech.esper.epl.join.pollindex.PollResultIndexingStrategy;
import com.espertech.esper.epl.join.table.EventTable;
import com.espertech.esper.epl.join.table.UnindexedEventTableList;
import com.espertech.esper.epl.table.mgmt.TableService;
import com.espertech.esper.epl.variable.VariableService;
import com.espertech.esper.event.EventAdapterService;
import com.espertech.esper.schedule.SchedulingService;
import com.espertech.esper.schedule.TimeProvider;
import com.espertech.esper.view.HistoricalEventViewable;
import com.espertech.esper.view.View;
import com.espertech.esper.view.ViewSupport;
import java.util.*;
/**
* Implements a poller viewable that uses a polling strategy, a cache and
* some input parameters extracted from event streams to perform the polling.
*/
public class DatabasePollingViewable implements HistoricalEventViewable {
private final int myStreamNumber;
private final PollExecStrategy pollExecStrategy;
private final List inputParameters;
private final DataCache dataCache;
private final EventType eventType;
private final ThreadLocal dataCacheThreadLocal = new ThreadLocal();
private ExprEvaluator[] evaluators;
private SortedSet subordinateStreams;
private ExprEvaluatorContext exprEvaluatorContext;
private StatementContext statementContext;
private static final EventBean[][] NULL_ROWS;
static {
NULL_ROWS = new EventBean[1][];
NULL_ROWS[0] = new EventBean[1];
}
private static final PollResultIndexingStrategy ITERATOR_INDEXING_STRATEGY = new PollResultIndexingStrategy() {
public EventTable[] index(List pollResult, boolean isActiveCache, StatementContext statementContext) {
return new EventTable[]{new UnindexedEventTableList(pollResult, -1)};
}
public String toQueryPlan() {
return this.getClass().getSimpleName() + " unindexed";
}
};
/**
* Ctor.
*
* @param myStreamNumber is the stream number of the view
* @param inputParameters are the event property names providing input parameter keys
* @param pollExecStrategy is the strategy to use for retrieving results
* @param dataCache is looked up before using the strategy
* @param eventType is the type of events generated by the view
*/
public DatabasePollingViewable(int myStreamNumber,
List inputParameters,
PollExecStrategy pollExecStrategy,
DataCache dataCache,
EventType eventType) {
this.myStreamNumber = myStreamNumber;
this.inputParameters = inputParameters;
this.pollExecStrategy = pollExecStrategy;
this.dataCache = dataCache;
this.eventType = eventType;
}
public void stop() {
pollExecStrategy.destroy();
dataCache.destroy();
}
public DataCache getOptionalDataCache() {
return dataCache;
}
public void validate(EngineImportService engineImportService,
StreamTypeService streamTypeService,
TimeProvider timeProvider,
VariableService variableService,
TableService tableService,
ExprEvaluatorContext exprEvaluatorContext,
ConfigurationInformation configSnapshot,
SchedulingService schedulingService,
String engineURI,
Map> sqlParameters,
EventAdapterService eventAdapterService,
StatementContext statementContext) throws ExprValidationException {
this.statementContext = statementContext;
evaluators = new ExprEvaluator[inputParameters.size()];
subordinateStreams = new TreeSet();
this.exprEvaluatorContext = exprEvaluatorContext;
int count = 0;
ExprValidationContext validationContext = new ExprValidationContext(streamTypeService, engineImportService, statementContext.getStatementExtensionServicesContext(), null, timeProvider, variableService, tableService, exprEvaluatorContext, eventAdapterService, statementContext.getStatementName(), statementContext.getStatementId(), statementContext.getAnnotations(), null, false, false, true, false, null, false);
for (String inputParam : inputParameters) {
ExprNode raw = findSQLExpressionNode(myStreamNumber, count, sqlParameters);
if (raw == null) {
throw new ExprValidationException("Internal error find expression for historical stream parameter " + count + " stream " + myStreamNumber);
}
ExprNode evaluator = ExprNodeUtility.getValidatedSubtree(ExprNodeOrigin.DATABASEPOLL, raw, validationContext);
evaluators[count++] = evaluator.getExprEvaluator();
ExprNodeIdentifierCollectVisitor visitor = new ExprNodeIdentifierCollectVisitor();
visitor.visit(evaluator);
for (ExprIdentNode identNode : visitor.getExprProperties()) {
if (identNode.getStreamId() == myStreamNumber) {
throw new ExprValidationException("Invalid expression '" + inputParam + "' resolves to the historical data itself");
}
subordinateStreams.add(identNode.getStreamId());
}
}
}
public EventTable[][] poll(EventBean[][] lookupEventsPerStream, PollResultIndexingStrategy indexingStrategy, ExprEvaluatorContext exprEvaluatorContext) {
DataCache localDataCache = dataCacheThreadLocal.get();
boolean strategyStarted = false;
EventTable[][] resultPerInputRow = new EventTable[lookupEventsPerStream.length][];
// Get input parameters for each row
EventBean[] eventsPerStream;
for (int row = 0; row < lookupEventsPerStream.length; row++) {
Object[] lookupValues = new Object[inputParameters.size()];
// Build lookup keys
for (int valueNum = 0; valueNum < inputParameters.size(); valueNum++) {
eventsPerStream = lookupEventsPerStream[row];
Object lookupValue = evaluators[valueNum].evaluate(eventsPerStream, true, exprEvaluatorContext);
lookupValues[valueNum] = lookupValue;
}
EventTable[] result = null;
// try the threadlocal iteration cache, if set
if (localDataCache != null) {
EventTable[] tables = localDataCache.getCached(lookupValues, lookupValues.length);
result = tables;
}
// try the connection cache
if (result == null) {
EventTable[] multi = dataCache.getCached(lookupValues, lookupValues.length);
if (multi != null) {
result = multi;
if (localDataCache != null) {
localDataCache.put(lookupValues, lookupValues.length, multi);
}
}
}
// use the result from cache
if (result != null) {
// found in cache
resultPerInputRow[row] = result;
} else {
// not found in cache, get from actual polling (db query)
try {
if (!strategyStarted) {
pollExecStrategy.start();
strategyStarted = true;
}
// Poll using the polling execution strategy and lookup values
List pollResult = pollExecStrategy.poll(lookupValues, exprEvaluatorContext);
// index the result, if required, using an indexing strategy
EventTable[] indexTable = indexingStrategy.index(pollResult, dataCache.isActive(), statementContext);
// assign to row
resultPerInputRow[row] = indexTable;
// save in cache
dataCache.put(lookupValues, lookupValues.length, indexTable);
if (localDataCache != null) {
localDataCache.put(lookupValues, lookupValues.length, indexTable);
}
} catch (EPException ex) {
if (strategyStarted) {
pollExecStrategy.done();
}
throw ex;
}
}
}
if (strategyStarted) {
pollExecStrategy.done();
}
return resultPerInputRow;
}
public View addView(View view) {
view.setParent(this);
return view;
}
public View[] getViews() {
return ViewSupport.EMPTY_VIEW_ARRAY;
}
public boolean removeView(View view) {
throw new UnsupportedOperationException("Subviews not supported");
}
public boolean hasViews() {
return false;
}
public EventType getEventType() {
return eventType;
}
public Iterator iterator() {
EventTable[][] tablesPerRow = poll(NULL_ROWS, ITERATOR_INDEXING_STRATEGY, exprEvaluatorContext);
return new IterablesArrayIterator(tablesPerRow);
}
public SortedSet getRequiredStreams() {
return subordinateStreams;
}
public boolean hasRequiredStreams() {
return !subordinateStreams.isEmpty();
}
public ThreadLocal getDataCacheThreadLocal() {
return dataCacheThreadLocal;
}
public void removeAllViews() {
throw new UnsupportedOperationException("Subviews not supported");
}
private static ExprNode findSQLExpressionNode(int myStreamNumber, int count, Map> sqlParameters) {
if ((sqlParameters == null) || (sqlParameters.isEmpty())) {
return null;
}
List parameters = sqlParameters.get(myStreamNumber);
if ((parameters == null) || (parameters.isEmpty()) || (parameters.size() < (count + 1))) {
return null;
}
return parameters.get(count);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy