/* *************************************************************************************** * 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.agg.service; import com.espertech.esper.client.EventBean; import com.espertech.esper.epl.agg.access.AggregationAccessorSlotPair; import com.espertech.esper.epl.agg.access.AggregationAgent; import com.espertech.esper.epl.agg.access.AggregationState; import com.espertech.esper.epl.agg.aggregator.AggregationMethod; import com.espertech.esper.epl.expression.core.ExprEvaluatorContext; import com.espertech.esper.epl.expression.core.ExprNode; import com.espertech.esper.epl.table.mgmt.TableColumnMethodPair; import com.espertech.esper.epl.table.mgmt.TableMetadata; import com.espertech.esper.epl.table.mgmt.TableStateInstanceGrouped; import com.espertech.esper.epl.table.strategy.ExprTableEvalLockUtil; import com.espertech.esper.event.ObjectArrayBackedEventBean; import com.espertech.esper.metrics.instrumentation.InstrumentationHelper; import java.util.Collection; /** * Implementation for handling aggregation with grouping by group-keys. */ public abstract class AggSvcGroupByWTableBase implements AggregationService { protected final TableMetadata tableMetadata; protected final TableColumnMethodPair[] methodPairs; protected final AggregationAccessorSlotPair[] accessors; protected final boolean isJoin; protected final TableStateInstanceGrouped tableStateInstance; protected final int[] targetStates; protected final ExprNode[] accessStateExpr; private final AggregationAgent[] agents; // maintain a current row for random access into the aggregator state table // (row=groups, columns=expression nodes that have aggregation functions) protected AggregationMethod[] currentAggregatorMethods; protected AggregationState[] currentAggregatorStates; protected Object currentGroupKey; public AggSvcGroupByWTableBase(TableMetadata tableMetadata, TableColumnMethodPair[] methodPairs, AggregationAccessorSlotPair[] accessors, boolean join, TableStateInstanceGrouped tableStateInstance, int[] targetStates, ExprNode[] accessStateExpr, AggregationAgent[] agents) { this.tableMetadata = tableMetadata; this.methodPairs = methodPairs; this.accessors = accessors; isJoin = join; this.tableStateInstance = tableStateInstance; this.targetStates = targetStates; this.accessStateExpr = accessStateExpr; this.agents = agents; } public abstract void applyEnterInternal(EventBean[] eventsPerStream, Object groupByKey, ExprEvaluatorContext exprEvaluatorContext); public abstract void applyLeaveInternal(EventBean[] eventsPerStream, Object groupByKey, ExprEvaluatorContext exprEvaluatorContext); public void applyEnter(EventBean[] eventsPerStream, Object groupByKey, ExprEvaluatorContext exprEvaluatorContext) { // acquire table-level write lock ExprTableEvalLockUtil.obtainLockUnless(tableStateInstance.getTableLevelRWLock().writeLock(), exprEvaluatorContext); applyEnterInternal(eventsPerStream, groupByKey, exprEvaluatorContext); } public void applyLeave(EventBean[] eventsPerStream, Object groupByKey, ExprEvaluatorContext exprEvaluatorContext) { // acquire table-level write lock ExprTableEvalLockUtil.obtainLockUnless(tableStateInstance.getTableLevelRWLock().writeLock(), exprEvaluatorContext); applyLeaveInternal(eventsPerStream, groupByKey, exprEvaluatorContext); } protected void applyEnterGroupKey(EventBean[] eventsPerStream, Object groupByKey, ExprEvaluatorContext exprEvaluatorContext) { ObjectArrayBackedEventBean bean = tableStateInstance.getCreateRowIntoTable(groupByKey, exprEvaluatorContext); AggregationRowPair row = (AggregationRowPair) bean.getProperties()[0]; currentAggregatorMethods = row.getMethods(); currentAggregatorStates = row.getStates(); if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().qAggregationGroupedApplyEnterLeave(true, methodPairs.length, targetStates.length, groupByKey); } for (int j = 0; j < methodPairs.length; j++) { TableColumnMethodPair methodPair = methodPairs[j]; AggregationMethod method = currentAggregatorMethods[methodPair.getTargetIndex()]; if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().qAggNoAccessEnterLeave(true, j, method, methodPair.getAggregationNode()); } Object columnResult = methodPair.getEvaluator().evaluate(eventsPerStream, true, exprEvaluatorContext); method.enter(columnResult); if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().aAggNoAccessEnterLeave(true, j, method); } } for (int i = 0; i < targetStates.length; i++) { AggregationState state = currentAggregatorStates[targetStates[i]]; if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().qAggAccessEnterLeave(true, i, state, accessStateExpr[i]); } agents[i].applyEnter(eventsPerStream, exprEvaluatorContext, state); if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().aAggAccessEnterLeave(true, i, state); } } tableStateInstance.handleRowUpdated(bean); if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().aAggregationGroupedApplyEnterLeave(true); } } protected void applyLeaveGroupKey(EventBean[] eventsPerStream, Object groupByKey, ExprEvaluatorContext exprEvaluatorContext) { ObjectArrayBackedEventBean bean = tableStateInstance.getCreateRowIntoTable(groupByKey, exprEvaluatorContext); AggregationRowPair row = (AggregationRowPair) bean.getProperties()[0]; currentAggregatorMethods = row.getMethods(); currentAggregatorStates = row.getStates(); if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().qAggregationGroupedApplyEnterLeave(false, methodPairs.length, targetStates.length, groupByKey); } for (int j = 0; j < methodPairs.length; j++) { TableColumnMethodPair methodPair = methodPairs[j]; AggregationMethod method = currentAggregatorMethods[methodPair.getTargetIndex()]; if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().qAggNoAccessEnterLeave(false, j, method, methodPair.getAggregationNode()); } Object columnResult = methodPair.getEvaluator().evaluate(eventsPerStream, false, exprEvaluatorContext); method.leave(columnResult); if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().aAggNoAccessEnterLeave(false, j, method); } } for (int i = 0; i < targetStates.length; i++) { AggregationState state = currentAggregatorStates[targetStates[i]]; if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().qAggAccessEnterLeave(false, i, state, accessStateExpr[i]); } agents[i].applyLeave(eventsPerStream, exprEvaluatorContext, state); if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().aAggAccessEnterLeave(false, i, state); } } tableStateInstance.handleRowUpdated(bean); if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().aAggregationGroupedApplyEnterLeave(false); } } public void setCurrentAccess(Object groupByKey, int agentInstanceId, AggregationGroupByRollupLevel rollupLevel) { ObjectArrayBackedEventBean bean = tableStateInstance.getRowForGroupKey(groupByKey); if (bean != null) { AggregationRowPair row = (AggregationRowPair) bean.getProperties()[0]; currentAggregatorMethods = row.getMethods(); currentAggregatorStates = row.getStates(); } else { currentAggregatorMethods = null; } this.currentGroupKey = groupByKey; } public Object getValue(int column, int agentInstanceId, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { if (column < currentAggregatorMethods.length) { return currentAggregatorMethods[column].getValue(); } else { AggregationAccessorSlotPair pair = accessors[column - currentAggregatorMethods.length]; return pair.getAccessor().getValue(currentAggregatorStates[pair.getSlot()], eventsPerStream, isNewData, exprEvaluatorContext); } } public Collection<EventBean> getCollectionOfEvents(int column, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext context) { if (column < currentAggregatorMethods.length) { return null; } else { AggregationAccessorSlotPair pair = accessors[column - currentAggregatorMethods.length]; return pair.getAccessor().getEnumerableEvents(currentAggregatorStates[pair.getSlot()], eventsPerStream, isNewData, context); } } public Collection<Object> getCollectionScalar(int column, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext context) { if (column < currentAggregatorMethods.length) { return null; } else { AggregationAccessorSlotPair pair = accessors[column - currentAggregatorMethods.length]; return pair.getAccessor().getEnumerableScalar(currentAggregatorStates[pair.getSlot()], eventsPerStream, isNewData, context); } } public EventBean getEventBean(int column, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext context) { if (column < currentAggregatorMethods.length) { return null; } else { AggregationAccessorSlotPair pair = accessors[column - currentAggregatorMethods.length]; return pair.getAccessor().getEnumerableEvent(currentAggregatorStates[pair.getSlot()], eventsPerStream, isNewData, context); } } public void setRemovedCallback(AggregationRowRemovedCallback callback) { // not applicable } public void accept(AggregationServiceVisitor visitor) { // not applicable } public void acceptGroupDetail(AggregationServiceVisitorWGroupDetail visitor) { // not applicable } public boolean isGrouped() { return true; } public Object getGroupKey(int agentInstanceId) { return currentGroupKey; } public Collection<Object> getGroupKeys(ExprEvaluatorContext exprEvaluatorContext) { return tableStateInstance.getGroupKeys(); } public void clearResults(ExprEvaluatorContext exprEvaluatorContext) { tableStateInstance.clear(); } public void stop() { } public AggregationService getContextPartitionAggregationService(int agentInstanceId) { return this; } }