Package com.espertech.esper.core.context.util

Source Code of com.espertech.esper.core.context.util.StatementAgentInstanceUtil

/*
* *************************************************************************************
*  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.core.context.util;

import com.espertech.esper.client.EventBean;
import com.espertech.esper.core.context.factory.StatementAgentInstanceFactoryResult;
import com.espertech.esper.core.context.factory.StatementAgentInstancePreload;
import com.espertech.esper.core.context.mgr.AgentInstance;
import com.espertech.esper.core.context.mgr.AgentInstanceFilterProxy;
import com.espertech.esper.core.context.mgr.ContextControllerStatementBase;
import com.espertech.esper.core.context.mgr.ContextControllerTreeAgentInstanceList;
import com.espertech.esper.core.context.stmt.AIRegistryAggregation;
import com.espertech.esper.core.context.stmt.AIRegistryExpr;
import com.espertech.esper.core.context.subselect.SubSelectStrategyHolder;
import com.espertech.esper.core.service.*;
import com.espertech.esper.core.start.EPStatementStopMethodImpl;
import com.espertech.esper.epl.expression.*;
import com.espertech.esper.epl.script.AgentInstanceScriptContext;
import com.espertech.esper.epl.view.OutputProcessViewTerminable;
import com.espertech.esper.event.MappedEventBean;
import com.espertech.esper.filter.FilterHandle;
import com.espertech.esper.metrics.instrumentation.InstrumentationHelper;
import com.espertech.esper.rowregex.RegexExprPreviousEvalStrategy;
import com.espertech.esper.util.StopCallback;
import com.espertech.esper.view.Viewable;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.util.*;

public class StatementAgentInstanceUtil {

    private static final Log log = LogFactory.getLog(EPStatementStopMethodImpl.class);

    public static void handleFilterFault(EventBean theEvent, long version, EPServicesContext servicesContext, Map<Integer, ContextControllerTreeAgentInstanceList> agentInstanceListMap) {
        for (Map.Entry<Integer, ContextControllerTreeAgentInstanceList> agentInstanceEntry : agentInstanceListMap.entrySet()) {
            if (agentInstanceEntry.getValue().getFilterVersionAfterAllocation() > version) {
                StatementAgentInstanceUtil.evaluateEventForStatement(servicesContext, theEvent, null, agentInstanceEntry.getValue().getAgentInstances());
            }
        }
    }

    public static void stopAgentInstances(List<AgentInstance> agentInstances, Map<String, Object> terminationProperties, EPServicesContext servicesContext, boolean isStatementStop, boolean leaveLocksAcquired) {
        if (agentInstances == null) {
            return;
        }
        for (AgentInstance instance : agentInstances) {
            stopAgentInstance(instance, terminationProperties, servicesContext, isStatementStop, leaveLocksAcquired);
        }
    }

    public static void stopAgentInstance(AgentInstance agentInstance, Map<String, Object> terminationProperties, EPServicesContext servicesContext, boolean isStatementStop, boolean leaveLocksAcquired) {
        if (terminationProperties != null) {
            agentInstance.getAgentInstanceContext().getContextProperties().getProperties().putAll(terminationProperties);
        }
        StatementAgentInstanceUtil.stop(agentInstance.getStopCallback(), agentInstance.getAgentInstanceContext(), agentInstance.getFinalView(), servicesContext, isStatementStop, leaveLocksAcquired);
    }

    public static void stopSafe(Collection<StopCallback> terminationCallbacks, StopCallback[] stopCallbacks, StatementContext statementContext) {
        StopCallback[] terminationArr = terminationCallbacks.toArray(new StopCallback[terminationCallbacks.size()]);
        stopSafe(terminationArr, statementContext);
        stopSafe(stopCallbacks, statementContext);
    }

    public static void stopSafe(StopCallback[] stopMethods, StatementContext statementContext) {
        for (StopCallback stopCallback : stopMethods) {
            stopSafe(stopCallback, statementContext);
        }
    }

    public static void stopSafe(StopCallback stopMethod, StatementContext statementContext) {
        try {
            stopMethod.stop();
        }
        catch (RuntimeException e) {
            log.warn("Failed to perform statement stop for statement '" + statementContext.getStatementName() +
                    "' expression '" + statementContext.getExpression() + "' : " + e.getMessage(), e);
        }
    }

    public static void stop(StopCallback stopCallback, AgentInstanceContext agentInstanceContext, Viewable finalView, EPServicesContext servicesContext, boolean isStatementStop, boolean leaveLocksAcquired) {

        if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().qContextPartitionDestroy(agentInstanceContext);}
        // obtain statement lock
        StatementAgentInstanceLock lock = agentInstanceContext.getEpStatementAgentInstanceHandle().getStatementAgentInstanceLock();
        lock.acquireWriteLock(null);
        try {
            if (finalView instanceof OutputProcessViewTerminable && !isStatementStop) {
                OutputProcessViewTerminable terminable = (OutputProcessViewTerminable) finalView;
                terminable.terminated();
            }

            stopSafe(stopCallback, agentInstanceContext.getStatementContext());

            if (servicesContext.getSchedulableAgentInstanceDirectory() != null) {
                servicesContext.getSchedulableAgentInstanceDirectory().remove(agentInstanceContext.getStatementContext().getStatementId(), agentInstanceContext.getAgentInstanceId());
            }

            // indicate method resolution
            agentInstanceContext.getStatementContext().getMethodResolutionService().destroyedAgentInstance(agentInstanceContext.getAgentInstanceId());

            // release resource
            agentInstanceContext.getStatementContext().getStatementAgentInstanceRegistry().deassign(agentInstanceContext.getAgentInstanceId());

            // cause any remaining schedules, that may concide with the caller's schedule, to be ignored
            agentInstanceContext.getEpStatementAgentInstanceHandle().setDestroyed(true);

            // cause any filters, that may concide with the caller's filters, to be ignored
            agentInstanceContext.getEpStatementAgentInstanceHandle().getStatementFilterVersion().setStmtFilterVersion(Long.MAX_VALUE);

            if (agentInstanceContext.getStatementContext().getExtensionServicesContext() != null && agentInstanceContext.getStatementContext().getExtensionServicesContext().getStmtResources() != null) {
                agentInstanceContext.getStatementContext().getExtensionServicesContext().getStmtResources().endContextPartition(agentInstanceContext.getAgentInstanceId());
            }
        }
        finally {
            if (!leaveLocksAcquired) {
                lock.releaseWriteLock(null);
            }
            if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().aContextPartitionDestroy();}
        }
    }

    public static StatementAgentInstanceFactoryResult start(EPServicesContext servicesContext,
                                                     ContextControllerStatementBase statement,
                                                     boolean isSingleInstanceContext,
                                                     int agentInstanceId,
                                                     MappedEventBean agentInstanceProperties,
                                                     AgentInstanceFilterProxy agentInstanceFilterProxy,
                                                     boolean isRecoveringResilient)
    {
        StatementContext statementContext = statement.getStatementContext();

        // make a new lock for the agent instance or use the already-allocated default lock
        StatementAgentInstanceLock agentInstanceLock;
        if (isSingleInstanceContext) {
            agentInstanceLock = statementContext.getDefaultAgentInstanceLock();
        }
        else {
            agentInstanceLock = servicesContext.getStatementLockFactory().getStatementLock(statementContext.getStatementName(), statementContext.getExpression(), statementContext.getAnnotations(), statementContext.isStatelessSelect());
        }

        // share the filter version between agent instance handle (callbacks) and agent instance context
        StatementAgentInstanceFilterVersion filterVersion = new StatementAgentInstanceFilterVersion();

        // create handle that comtains lock for use in scheduling and filter callbacks
        EPStatementAgentInstanceHandle agentInstanceHandle = new EPStatementAgentInstanceHandle(statementContext.getEpStatementHandle(), agentInstanceLock, agentInstanceId, filterVersion);

        // create agent instance context
        AgentInstanceScriptContext agentInstanceScriptContext = null;
        if (statementContext.getDefaultAgentInstanceScriptContext() != null) {
            agentInstanceScriptContext = new AgentInstanceScriptContext();
        }
        AgentInstanceContext agentInstanceContext = new AgentInstanceContext(statementContext, agentInstanceHandle, agentInstanceId, agentInstanceFilterProxy, agentInstanceProperties, agentInstanceScriptContext);
        StatementAgentInstanceLock statementAgentInstanceLock = agentInstanceContext.getEpStatementAgentInstanceHandle().getStatementAgentInstanceLock();

        if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().qContextPartitionAllocate(agentInstanceContext);}
        statementAgentInstanceLock.acquireWriteLock(null);

        try {
            // start
            StatementAgentInstanceFactoryResult startResult = statement.getFactory().newContext(agentInstanceContext, isRecoveringResilient);

            // hook up with listeners+subscribers
            startResult.getFinalView().addView(statement.getMergeView()); // hook output to merge view

            // assign agents for expression-node based strategies
            AIRegistryExpr aiExprSvc = statementContext.getStatementAgentInstanceRegistry().getAgentInstanceExprService();
            AIRegistryAggregation aiAggregationSvc = statementContext.getStatementAgentInstanceRegistry().getAgentInstanceAggregationService();

            // allocate aggregation service
            if (startResult.getOptionalAggegationService() != null) {
                aiAggregationSvc.assignService(agentInstanceId, startResult.getOptionalAggegationService());
            }

            // allocate subquery
            for (Map.Entry<ExprSubselectNode, SubSelectStrategyHolder> item : startResult.getSubselectStrategies().entrySet()) {
                ExprSubselectNode node = item.getKey();
                SubSelectStrategyHolder strategyHolder = item.getValue();

                aiExprSvc.getSubselectService(node).assignService(agentInstanceId, strategyHolder.getStategy());
                aiExprSvc.getSubselectAggregationService(node).assignService(agentInstanceId, strategyHolder.getSubselectAggregationService());

                // allocate prior within subquery
                for (Map.Entry<ExprPriorNode, ExprPriorEvalStrategy> priorEntry : strategyHolder.getPriorStrategies().entrySet()) {
                    aiExprSvc.getPriorServices(priorEntry.getKey()).assignService(agentInstanceId, priorEntry.getValue());
                }

                // allocate previous within subquery
                for (Map.Entry<ExprPreviousNode, ExprPreviousEvalStrategy> prevEntry : strategyHolder.getPreviousNodeStrategies().entrySet()) {
                    aiExprSvc.getPreviousServices(prevEntry.getKey()).assignService(agentInstanceId, prevEntry.getValue());
                }
            }

            // allocate prior-expressions
            for (Map.Entry<ExprPriorNode, ExprPriorEvalStrategy> item : startResult.getPriorNodeStrategies().entrySet()) {
                aiExprSvc.getPriorServices(item.getKey()).assignService(agentInstanceId, item.getValue());
            }

            // allocate previous-expressions
            for (Map.Entry<ExprPreviousNode, ExprPreviousEvalStrategy> item : startResult.getPreviousNodeStrategies().entrySet()) {
                aiExprSvc.getPreviousServices(item.getKey()).assignService(agentInstanceId, item.getValue());
            }

            // allocate match-recognize previous expressions
            RegexExprPreviousEvalStrategy regexExprPreviousEvalStrategy = startResult.getRegexExprPreviousEvalStrategy();
            aiExprSvc.getMatchRecognizePrevious().assignService(agentInstanceId, regexExprPreviousEvalStrategy);

            // execute preloads, if any
            for (StatementAgentInstancePreload preload : startResult.getPreloadList()) {
                preload.executePreload();
            }

            if (statementContext.getExtensionServicesContext() != null && statementContext.getExtensionServicesContext().getStmtResources() != null) {
                statementContext.getExtensionServicesContext().getStmtResources().startContextPartition(startResult, agentInstanceId);
            }

            // instantiate
            return startResult;
        }
        finally {
            statementAgentInstanceLock.releaseWriteLock(null);
            if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().aContextPartitionAllocate();}
        }
    }

    public static void evaluateEventForStatement(EPServicesContext servicesContext, EventBean theEvent, Map<String, Object> optionalTriggeringPattern, List<AgentInstance> agentInstances) {
        if (theEvent != null) {
            evaluateEventForStatementInternal(servicesContext, theEvent, agentInstances);
        }
        if (optionalTriggeringPattern != null) {
            // evaluation order definition is up to the originator of the triggering pattern
            for (Map.Entry<String, Object> entry : optionalTriggeringPattern.entrySet()) {
                if (entry.getValue() instanceof EventBean) {
                    evaluateEventForStatementInternal(servicesContext, (EventBean) entry.getValue(), agentInstances);
                }
                else if (entry.getValue() instanceof EventBean[]) {
                    EventBean[] eventsArray = (EventBean[]) entry.getValue();
                    for (EventBean eventElement : eventsArray) {
                        evaluateEventForStatementInternal(servicesContext, eventElement, agentInstances);
                    }
                }
            }
        }
    }

    private static void evaluateEventForStatementInternal(EPServicesContext servicesContext, EventBean theEvent, List<AgentInstance> agentInstances) {
        // context was created - reevaluate for the given event
        ArrayDeque<FilterHandle> callbacks = new ArrayDeque<FilterHandle>(2);
        servicesContext.getFilterService().evaluate(theEvent, callbacks);   // evaluates for ALL statements
        if (callbacks.isEmpty()) {
            return;
        }

        // there is a single callback and a single context, if they match we are done
        if (agentInstances.size() == 1 && callbacks.size() == 1) {
            AgentInstance agentInstance = agentInstances.get(0);
            if (agentInstance.getAgentInstanceContext().getStatementId().equals(callbacks.getFirst().getStatementId())) {
                process(agentInstance, servicesContext, callbacks, theEvent);
            }
            return;
        }

        // use the right sorted/unsorted Map keyed by AgentInstance to sort
        boolean isPrioritized = servicesContext.getConfigSnapshot().getEngineDefaults().getExecution().isPrioritized();
        Map<AgentInstance, Object> stmtCallbacks;
        if (!isPrioritized) {
            stmtCallbacks = new HashMap<AgentInstance, Object>();
        }
        else {
            stmtCallbacks = new TreeMap<AgentInstance, Object>(AgentInstanceComparator.INSTANCE);
        }

        // process all callbacks
        for (FilterHandle filterHandle : callbacks)
        {
            // determine if this filter entry applies to any of the affected agent instances
            String statementId = filterHandle.getStatementId();
            AgentInstance agentInstanceFound = null;
            for (AgentInstance agentInstance : agentInstances) {
                if (agentInstance.getAgentInstanceContext().getStatementId().equals(statementId)) {
                    agentInstanceFound = agentInstance;
                    break;
                }
            }
            if (agentInstanceFound == null) {   // when the callback is for some other stmt
                continue;
            }

            EPStatementHandleCallback handleCallback = (EPStatementHandleCallback) filterHandle;
            EPStatementAgentInstanceHandle handle = handleCallback.getAgentInstanceHandle();

            // Self-joins require that the internal dispatch happens after all streams are evaluated.
            // Priority or preemptive settings also require special ordering.
            if (handle.isCanSelfJoin() || isPrioritized)
            {
                Object stmtCallback = stmtCallbacks.get(agentInstanceFound);
                if (stmtCallback == null) {
                    stmtCallbacks.put(agentInstanceFound, handleCallback);
                }
                else if (stmtCallback instanceof ArrayDeque) {
                    ArrayDeque<EPStatementHandleCallback> q = (ArrayDeque<EPStatementHandleCallback>) stmtCallback;
                    q.add(handleCallback);
                }
                else {
                    ArrayDeque<EPStatementHandleCallback> q = new ArrayDeque<EPStatementHandleCallback>(4);
                    q.add((EPStatementHandleCallback) stmtCallback);
                    q.add(handleCallback);
                    stmtCallbacks.put(agentInstanceFound, q);
                }
                continue;
            }

            // no need to be sorted, process
            process(agentInstanceFound, servicesContext, Collections.<FilterHandle>singletonList(handleCallback), theEvent);
        }

        if (stmtCallbacks.isEmpty()) {
            return;
        }

        // Process self-join or sorted prioritized callbacks
        for (Map.Entry<AgentInstance, Object> entry : stmtCallbacks.entrySet())
        {
            AgentInstance agentInstance = entry.getKey();
            Object callbackList = entry.getValue();
            if (callbackList instanceof ArrayDeque) {
                process(agentInstance, servicesContext, (Collection<FilterHandle>) callbackList, theEvent);
            }
            else {
                process(agentInstance, servicesContext, Collections.<FilterHandle>singletonList((FilterHandle) callbackList), theEvent);
            }
            if (agentInstance.getAgentInstanceContext().getEpStatementAgentInstanceHandle().isPreemptive()) {
                return;
            }
        }
    }

    public static boolean evaluateFilterForStatement(EPServicesContext servicesContext, EventBean theEvent, AgentInstanceContext agentInstanceContext, FilterHandle filterHandle) {
        // context was created - reevaluate for the given event
        ArrayDeque<FilterHandle> callbacks = new ArrayDeque<FilterHandle>();
        servicesContext.getFilterService().evaluate(theEvent, callbacks, agentInstanceContext.getStatementContext().getStatementId());

        try
        {
            servicesContext.getVariableService().setLocalVersion();

            // sub-selects always go first
            for (FilterHandle handle : callbacks)
            {
                if (handle == filterHandle) {
                    return true;
                }
            }

            agentInstanceContext.getEpStatementAgentInstanceHandle().internalDispatch(agentInstanceContext);

        }
        catch (RuntimeException ex) {
            servicesContext.getExceptionHandlingService().handleException(ex, agentInstanceContext.getEpStatementAgentInstanceHandle());
        }

        return false;
    }

    public static StopCallback getStopCallback(List<StopCallback> stopCallbacks, final AgentInstanceContext agentInstanceContext) {
        final StopCallback[] stopCallbackArr = stopCallbacks.toArray(new StopCallback[stopCallbacks.size()]);
        return new StopCallback() {
            public void stop() {
                StatementAgentInstanceUtil.stopSafe(agentInstanceContext.getTerminationCallbackRO(), stopCallbackArr, agentInstanceContext.getStatementContext());
            }
        };
    }

    private static void process(AgentInstance agentInstance,
                                EPServicesContext servicesContext,
                                Collection<FilterHandle> callbacks,
                                EventBean theEvent) {
        AgentInstanceContext agentInstanceContext = agentInstance.getAgentInstanceContext();
        agentInstance.getAgentInstanceContext().getAgentInstanceLock().acquireWriteLock(servicesContext.getStatementLockFactory());
        try {
            servicesContext.getVariableService().setLocalVersion();

            // sub-selects always go first
            for (FilterHandle handle : callbacks)
            {
                EPStatementHandleCallback callback = (EPStatementHandleCallback) handle;
                if (callback.getAgentInstanceHandle() != agentInstanceContext.getEpStatementAgentInstanceHandle()) {
                    continue;
                }
                callback.getFilterCallback().matchFound(theEvent, null);
            }

            agentInstanceContext.getEpStatementAgentInstanceHandle().internalDispatch(agentInstanceContext);
        }
        catch (RuntimeException ex) {
            servicesContext.getExceptionHandlingService().handleException(ex, agentInstanceContext.getEpStatementAgentInstanceHandle());
        }
        finally {
            agentInstanceContext.getAgentInstanceLock().releaseWriteLock(servicesContext.getStatementLockFactory());
        }
    }
}
TOP

Related Classes of com.espertech.esper.core.context.util.StatementAgentInstanceUtil

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.