/* *************************************************************************************** * 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.core; import com.espertech.esper.client.EventBean; import com.espertech.esper.client.EventType; import com.espertech.esper.collection.ArrayEventIterator; import com.espertech.esper.collection.MultiKey; import com.espertech.esper.collection.MultiKeyUntyped; import com.espertech.esper.collection.UniformPair; import com.espertech.esper.core.context.util.AgentInstanceContext; import com.espertech.esper.epl.agg.service.AggregationRowRemovedCallback; import com.espertech.esper.epl.agg.service.AggregationService; import com.espertech.esper.epl.expression.core.ExprEvaluator; import com.espertech.esper.epl.spec.OutputLimitLimitType; import com.espertech.esper.epl.view.OutputConditionPolled; import com.espertech.esper.metrics.instrumentation.InstrumentationHelper; import com.espertech.esper.view.Viewable; import java.util.*; /** * Result set processor for the fully-grouped case: * there is a group-by and all non-aggregation event properties in the select clause are listed in the group by, * and there are aggregation functions. * <p> * Produces one row for each group that changed (and not one row per event). Computes MultiKey group-by keys for * each event and uses a set of the group-by keys to generate the result rows, using the first (old or new, anyone) event * for each distinct group-by key. */ public class ResultSetProcessorRowPerGroup implements ResultSetProcessor, AggregationRowRemovedCallback { protected final ResultSetProcessorRowPerGroupFactory prototype; protected final SelectExprProcessor selectExprProcessor; protected final OrderByProcessor orderByProcessor; protected final AggregationService aggregationService; protected AgentInstanceContext agentInstanceContext; // For output rate limiting, keep a representative event for each group for // representing each group in an output limit clause protected ResultSetProcessorGroupedOutputAllGroupReps outputAllGroupReps; private ResultSetProcessorGroupedOutputFirstHelper outputFirstHelper; private ResultSetProcessorRowPerGroupOutputLastHelper outputLastHelper; private ResultSetProcessorRowPerGroupOutputAllHelper outputAllHelper; public ResultSetProcessorRowPerGroup(ResultSetProcessorRowPerGroupFactory prototype, SelectExprProcessor selectExprProcessor, OrderByProcessor orderByProcessor, AggregationService aggregationService, AgentInstanceContext agentInstanceContext) { this.prototype = prototype; this.selectExprProcessor = selectExprProcessor; this.orderByProcessor = orderByProcessor; this.aggregationService = aggregationService; this.agentInstanceContext = agentInstanceContext; aggregationService.setRemovedCallback(this); if (prototype.isOutputLast()) { outputLastHelper = prototype.getResultSetProcessorHelperFactory().makeRSRowPerGroupOutputLastOpt(agentInstanceContext, this, prototype); } else if (prototype.isOutputAll()) { if (!prototype.isEnableOutputLimitOpt()) { outputAllGroupReps = prototype.getResultSetProcessorHelperFactory().makeRSGroupedOutputAllNoOpt(agentInstanceContext, prototype.getGroupKeyNodes(), prototype.getNumStreams()); } else { outputAllHelper = prototype.getResultSetProcessorHelperFactory().makeRSRowPerGroupOutputAllOpt(agentInstanceContext, this, prototype); } } else if (prototype.isOutputFirst()) { outputFirstHelper = prototype.getResultSetProcessorHelperFactory().makeRSGroupedOutputFirst(agentInstanceContext, prototype.getGroupKeyNodes(), prototype.getOptionalOutputFirstConditionFactory(), null, -1); } } public void setAgentInstanceContext(AgentInstanceContext agentInstanceContext) { this.agentInstanceContext = agentInstanceContext; } public EventType getResultEventType() { return prototype.getResultEventType(); } public void applyViewResult(EventBean[] newData, EventBean[] oldData) { EventBean[] eventsPerStream = new EventBean[1]; if (newData != null) { // apply new data to aggregates for (EventBean aNewData : newData) { eventsPerStream[0] = aNewData; Object mk = generateGroupKey(eventsPerStream, true); aggregationService.applyEnter(eventsPerStream, mk, agentInstanceContext); } } if (oldData != null) { // apply old data to aggregates for (EventBean anOldData : oldData) { eventsPerStream[0] = anOldData; Object mk = generateGroupKey(eventsPerStream, false); aggregationService.applyLeave(eventsPerStream, mk, agentInstanceContext); } } } public void applyJoinResult(Set<MultiKey<EventBean>> newEvents, Set<MultiKey<EventBean>> oldEvents) { if (!newEvents.isEmpty()) { // apply old data to aggregates for (MultiKey<EventBean> eventsPerStream : newEvents) { Object mk = generateGroupKey(eventsPerStream.getArray(), true); aggregationService.applyEnter(eventsPerStream.getArray(), mk, agentInstanceContext); } } if (oldEvents != null && !oldEvents.isEmpty()) { // apply old data to aggregates for (MultiKey<EventBean> eventsPerStream : oldEvents) { Object mk = generateGroupKey(eventsPerStream.getArray(), false); aggregationService.applyLeave(eventsPerStream.getArray(), mk, agentInstanceContext); } } } public UniformPair<EventBean[]> processJoinResult(Set<MultiKey<EventBean>> newEvents, Set<MultiKey<EventBean>> oldEvents, boolean isSynthesize) { if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().qResultSetProcessGroupedRowPerGroup(); } // Generate group-by keys for all events, collect all keys in a set for later event generation Map<Object, EventBean[]> keysAndEvents = new HashMap<Object, EventBean[]>(); Object[] newDataMultiKey = generateGroupKeys(newEvents, keysAndEvents, true); Object[] oldDataMultiKey = generateGroupKeys(oldEvents, keysAndEvents, false); if (prototype.isUnidirectional()) { this.clear(); } // generate old events EventBean[] selectOldEvents = null; if (prototype.isSelectRStream()) { selectOldEvents = generateOutputEventsJoin(keysAndEvents, false, isSynthesize); } // update aggregates if (!newEvents.isEmpty()) { // apply old data to aggregates int count = 0; for (MultiKey<EventBean> eventsPerStream : newEvents) { aggregationService.applyEnter(eventsPerStream.getArray(), newDataMultiKey[count], agentInstanceContext); count++; } } if (oldEvents != null && !oldEvents.isEmpty()) { // apply old data to aggregates int count = 0; for (MultiKey<EventBean> eventsPerStream : oldEvents) { aggregationService.applyLeave(eventsPerStream.getArray(), oldDataMultiKey[count], agentInstanceContext); count++; } } // generate new events using select expressions EventBean[] selectNewEvents = generateOutputEventsJoin(keysAndEvents, true, isSynthesize); if ((selectNewEvents != null) || (selectOldEvents != null)) { if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().aResultSetProcessGroupedRowPerGroup(selectNewEvents, selectOldEvents); } return new UniformPair<EventBean[]>(selectNewEvents, selectOldEvents); } if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().aResultSetProcessGroupedRowPerGroup(null, null); } return null; } public UniformPair<EventBean[]> processViewResult(EventBean[] newData, EventBean[] oldData, boolean isSynthesize) { if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().qResultSetProcessGroupedRowPerGroup(); } // Generate group-by keys for all events, collect all keys in a set for later event generation Map<Object, EventBean> keysAndEvents = new HashMap<Object, EventBean>(); Object[] newDataMultiKey = generateGroupKeys(newData, keysAndEvents, true); Object[] oldDataMultiKey = generateGroupKeys(oldData, keysAndEvents, false); EventBean[] selectOldEvents = null; if (prototype.isSelectRStream()) { selectOldEvents = generateOutputEventsView(keysAndEvents, false, isSynthesize); } // update aggregates EventBean[] eventsPerStream = new EventBean[1]; if (newData != null) { // apply new data to aggregates for (int i = 0; i < newData.length; i++) { eventsPerStream[0] = newData[i]; aggregationService.applyEnter(eventsPerStream, newDataMultiKey[i], agentInstanceContext); } } if (oldData != null) { // apply old data to aggregates for (int i = 0; i < oldData.length; i++) { eventsPerStream[0] = oldData[i]; aggregationService.applyLeave(eventsPerStream, oldDataMultiKey[i], agentInstanceContext); } } // generate new events using select expressions EventBean[] selectNewEvents = generateOutputEventsView(keysAndEvents, true, isSynthesize); if ((selectNewEvents != null) || (selectOldEvents != null)) { if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().aResultSetProcessGroupedRowPerGroup(selectNewEvents, selectOldEvents); } return new UniformPair<EventBean[]>(selectNewEvents, selectOldEvents); } if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().aResultSetProcessGroupedRowPerGroup(null, null); } return null; } protected EventBean[] generateOutputEventsView(Map<Object, EventBean> keysAndEvents, boolean isNewData, boolean isSynthesize) { EventBean[] eventsPerStream = new EventBean[1]; EventBean[] events = new EventBean[keysAndEvents.size()]; Object[] keys = new Object[keysAndEvents.size()]; EventBean[][] currentGenerators = null; if (prototype.isSorting()) { currentGenerators = new EventBean[keysAndEvents.size()][]; } int count = 0; for (Map.Entry<Object, EventBean> entry : keysAndEvents.entrySet()) { // Set the current row of aggregation states aggregationService.setCurrentAccess(entry.getKey(), agentInstanceContext.getAgentInstanceId(), null); eventsPerStream[0] = entry.getValue(); // Filter the having clause if (prototype.getOptionalHavingNode() != null) { if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().qHavingClauseNonJoin(entry.getValue()); } Boolean result = (Boolean) prototype.getOptionalHavingNode().evaluate(eventsPerStream, isNewData, agentInstanceContext); if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().aHavingClauseNonJoin(result); } if ((result == null) || (!result)) { continue; } } events[count] = selectExprProcessor.process(eventsPerStream, isNewData, isSynthesize, agentInstanceContext); keys[count] = entry.getKey(); if (prototype.isSorting()) { EventBean[] currentEventsPerStream = new EventBean[]{entry.getValue()}; currentGenerators[count] = currentEventsPerStream; } count++; } // Resize if some rows were filtered out if (count != events.length) { if (count == 0) { return null; } EventBean[] outEvents = new EventBean[count]; System.arraycopy(events, 0, outEvents, 0, count); events = outEvents; if (prototype.isSorting()) { Object[] outKeys = new Object[count]; System.arraycopy(keys, 0, outKeys, 0, count); keys = outKeys; EventBean[][] outGens = new EventBean[count][]; System.arraycopy(currentGenerators, 0, outGens, 0, count); currentGenerators = outGens; } } if (prototype.isSorting()) { events = orderByProcessor.sort(events, currentGenerators, keys, isNewData, agentInstanceContext); } return events; } private void generateOutputBatchedRow(Map<Object, EventBean> keysAndEvents, boolean isNewData, boolean isSynthesize, List<EventBean> resultEvents, List<Object> optSortKeys, AgentInstanceContext agentInstanceContext) { EventBean[] eventsPerStream = new EventBean[1]; for (Map.Entry<Object, EventBean> entry : keysAndEvents.entrySet()) { // Set the current row of aggregation states aggregationService.setCurrentAccess(entry.getKey(), agentInstanceContext.getAgentInstanceId(), null); eventsPerStream[0] = entry.getValue(); // Filter the having clause if (prototype.getOptionalHavingNode() != null) { if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().qHavingClauseNonJoin(entry.getValue()); } Boolean result = (Boolean) prototype.getOptionalHavingNode().evaluate(eventsPerStream, isNewData, agentInstanceContext); if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().aHavingClauseNonJoin(result); } if ((result == null) || (!result)) { continue; } } resultEvents.add(selectExprProcessor.process(eventsPerStream, isNewData, isSynthesize, agentInstanceContext)); if (prototype.isSorting()) { optSortKeys.add(orderByProcessor.getSortKey(eventsPerStream, isNewData, agentInstanceContext)); } } } public void generateOutputBatchedArr(boolean join, Iterator<Map.Entry<Object, EventBean[]>> keysAndEvents, boolean isNewData, boolean isSynthesize, List<EventBean> resultEvents, List<Object> optSortKeys) { while (keysAndEvents.hasNext()) { Map.Entry<Object, EventBean[]> entry = keysAndEvents.next(); generateOutputBatchedRow(join, entry.getKey(), entry.getValue(), isNewData, isSynthesize, resultEvents, optSortKeys); } } private void generateOutputBatchedRow(boolean join, Object mk, EventBean[] eventsPerStream, boolean isNewData, boolean isSynthesize, List<EventBean> resultEvents, List<Object> optSortKeys) { // Set the current row of aggregation states aggregationService.setCurrentAccess(mk, agentInstanceContext.getAgentInstanceId(), null); // Filter the having clause if (prototype.getOptionalHavingNode() != null) { if (InstrumentationHelper.ENABLED) { if (!join) InstrumentationHelper.get().qHavingClauseNonJoin(eventsPerStream[0]); else InstrumentationHelper.get().qHavingClauseJoin(eventsPerStream); } Boolean result = (Boolean) prototype.getOptionalHavingNode().evaluate(eventsPerStream, isNewData, agentInstanceContext); if (InstrumentationHelper.ENABLED) { if (!join) InstrumentationHelper.get().aHavingClauseNonJoin(result); else InstrumentationHelper.get().aHavingClauseJoin(result); } if ((result == null) || (!result)) { return; } } resultEvents.add(selectExprProcessor.process(eventsPerStream, isNewData, isSynthesize, agentInstanceContext)); if (prototype.isSorting()) { optSortKeys.add(orderByProcessor.getSortKey(eventsPerStream, isNewData, agentInstanceContext)); } } public EventBean generateOutputBatchedNoSortWMap(boolean join, Object mk, EventBean[] eventsPerStream, boolean isNewData, boolean isSynthesize) { // Set the current row of aggregation states aggregationService.setCurrentAccess(mk, agentInstanceContext.getAgentInstanceId(), null); // Filter the having clause if (prototype.getOptionalHavingNode() != null) { if (InstrumentationHelper.ENABLED) { if (!join) InstrumentationHelper.get().qHavingClauseNonJoin(eventsPerStream[0]); else InstrumentationHelper.get().qHavingClauseJoin(eventsPerStream); } Boolean result = (Boolean) prototype.getOptionalHavingNode().evaluate(eventsPerStream, isNewData, agentInstanceContext); if (InstrumentationHelper.ENABLED) { if (!join) InstrumentationHelper.get().aHavingClauseNonJoin(result); else InstrumentationHelper.get().aHavingClauseJoin(result); } if ((result == null) || (!result)) { return null; } } return selectExprProcessor.process(eventsPerStream, isNewData, isSynthesize, agentInstanceContext); } private EventBean[] generateOutputEventsJoin(Map<Object, EventBean[]> keysAndEvents, boolean isNewData, boolean isSynthesize) { EventBean[] events = new EventBean[keysAndEvents.size()]; Object[] keys = new Object[keysAndEvents.size()]; EventBean[][] currentGenerators = null; if (prototype.isSorting()) { currentGenerators = new EventBean[keysAndEvents.size()][]; } int count = 0; for (Map.Entry<Object, EventBean[]> entry : keysAndEvents.entrySet()) { aggregationService.setCurrentAccess(entry.getKey(), agentInstanceContext.getAgentInstanceId(), null); EventBean[] eventsPerStream = entry.getValue(); // Filter the having clause if (prototype.getOptionalHavingNode() != null) { if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().qHavingClauseJoin(eventsPerStream); } Boolean result = (Boolean) prototype.getOptionalHavingNode().evaluate(eventsPerStream, isNewData, agentInstanceContext); if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().aHavingClauseJoin(result); } if ((result == null) || (!result)) { continue; } } events[count] = selectExprProcessor.process(eventsPerStream, isNewData, isSynthesize, agentInstanceContext); keys[count] = entry.getKey(); if (prototype.isSorting()) { currentGenerators[count] = eventsPerStream; } count++; } // Resize if some rows were filtered out if (count != events.length) { if (count == 0) { return null; } EventBean[] outEvents = new EventBean[count]; System.arraycopy(events, 0, outEvents, 0, count); events = outEvents; if (prototype.isSorting()) { Object[] outKeys = new Object[count]; System.arraycopy(keys, 0, outKeys, 0, count); keys = outKeys; EventBean[][] outGens = new EventBean[count][]; System.arraycopy(currentGenerators, 0, outGens, 0, count); currentGenerators = outGens; } } if (prototype.isSorting()) { events = orderByProcessor.sort(events, currentGenerators, keys, isNewData, agentInstanceContext); } return events; } private Object[] generateGroupKeys(EventBean[] events, boolean isNewData) { if (events == null) { return null; } EventBean[] eventsPerStream = new EventBean[1]; Object[] keys = new Object[events.length]; for (int i = 0; i < events.length; i++) { eventsPerStream[0] = events[i]; keys[i] = generateGroupKey(eventsPerStream, isNewData); } return keys; } protected Object[] generateGroupKeys(EventBean[] events, Map<Object, EventBean> eventPerKey, boolean isNewData) { if (events == null) { return null; } EventBean[] eventsPerStream = new EventBean[1]; Object[] keys = new Object[events.length]; for (int i = 0; i < events.length; i++) { eventsPerStream[0] = events[i]; keys[i] = generateGroupKey(eventsPerStream, isNewData); eventPerKey.put(keys[i], events[i]); } return keys; } private Object[] generateGroupKeys(Set<MultiKey<EventBean>> resultSet, Map<Object, EventBean[]> eventPerKey, boolean isNewData) { if (resultSet == null || resultSet.isEmpty()) { return null; } Object[] keys = new Object[resultSet.size()]; int count = 0; for (MultiKey<EventBean> eventsPerStream : resultSet) { keys[count] = generateGroupKey(eventsPerStream.getArray(), isNewData); eventPerKey.put(keys[count], eventsPerStream.getArray()); count++; } return keys; } /** * Returns the optional having expression. * * @return having expression node */ public ExprEvaluator getOptionalHavingNode() { return prototype.getOptionalHavingNode(); } /** * Returns the select expression processor * * @return select processor. */ public SelectExprProcessor getSelectExprProcessor() { return selectExprProcessor; } public Iterator<EventBean> getIterator(Viewable parent) { if (!prototype.isHistoricalOnly()) { return obtainIterator(parent); } aggregationService.clearResults(agentInstanceContext); Iterator<EventBean> it = parent.iterator(); EventBean[] eventsPerStream = new EventBean[1]; for (; it.hasNext(); ) { eventsPerStream[0] = it.next(); Object groupKey = generateGroupKey(eventsPerStream, true); aggregationService.applyEnter(eventsPerStream, groupKey, agentInstanceContext); } ArrayDeque<EventBean> deque = ResultSetProcessorUtil.iteratorToDeque(obtainIterator(parent)); aggregationService.clearResults(agentInstanceContext); return deque.iterator(); } public Iterator<EventBean> obtainIterator(Viewable parent) { if (orderByProcessor == null) { return new ResultSetRowPerGroupIterator(parent.iterator(), this, aggregationService, agentInstanceContext); } return getIteratorSorted(parent.iterator()); } protected Iterator<EventBean> getIteratorSorted(Iterator<EventBean> parentIter) { // Pull all parent events, generate order keys EventBean[] eventsPerStream = new EventBean[1]; List<EventBean> outgoingEvents = new ArrayList<EventBean>(); List<Object> orderKeys = new ArrayList<Object>(); Set<Object> priorSeenGroups = new HashSet<Object>(); for (; parentIter.hasNext(); ) { EventBean candidate = parentIter.next(); eventsPerStream[0] = candidate; Object groupKey = generateGroupKey(eventsPerStream, true); aggregationService.setCurrentAccess(groupKey, agentInstanceContext.getAgentInstanceId(), null); if (prototype.getOptionalHavingNode() != null) { if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().qHavingClauseNonJoin(candidate); } Boolean pass = (Boolean) prototype.getOptionalHavingNode().evaluate(eventsPerStream, true, agentInstanceContext); if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().aHavingClauseNonJoin(pass); } if ((pass == null) || (!pass)) { continue; } } if (priorSeenGroups.contains(groupKey)) { continue; } priorSeenGroups.add(groupKey); outgoingEvents.add(selectExprProcessor.process(eventsPerStream, true, true, agentInstanceContext)); Object orderKey = orderByProcessor.getSortKey(eventsPerStream, true, agentInstanceContext); orderKeys.add(orderKey); } // sort EventBean[] outgoingEventsArr = outgoingEvents.toArray(new EventBean[outgoingEvents.size()]); Object[] orderKeysArr = orderKeys.toArray(new Object[orderKeys.size()]); EventBean[] orderedEvents = orderByProcessor.sort(outgoingEventsArr, orderKeysArr, agentInstanceContext); return new ArrayEventIterator(orderedEvents); } public Iterator<EventBean> getIterator(Set<MultiKey<EventBean>> joinSet) { Map<Object, EventBean[]> keysAndEvents = new HashMap<Object, EventBean[]>(); generateGroupKeys(joinSet, keysAndEvents, true); EventBean[] selectNewEvents = generateOutputEventsJoin(keysAndEvents, true, true); return new ArrayEventIterator(selectNewEvents); } public void clear() { aggregationService.clearResults(agentInstanceContext); } public UniformPair<EventBean[]> processOutputLimitedJoin(List<UniformPair<Set<MultiKey<EventBean>>>> joinEventsSet, boolean generateSynthetic, OutputLimitLimitType outputLimitLimitType) { if (outputLimitLimitType == OutputLimitLimitType.DEFAULT) { return processOutputLimitedJoinDefault(joinEventsSet, generateSynthetic); } else if (outputLimitLimitType == OutputLimitLimitType.ALL) { return processOutputLimitedJoinAll(joinEventsSet, generateSynthetic); } else if (outputLimitLimitType == OutputLimitLimitType.FIRST) { return processOutputLimitedJoinFirst(joinEventsSet, generateSynthetic); } else if (outputLimitLimitType == OutputLimitLimitType.LAST) { return processOutputLimitedJoinLast(joinEventsSet, generateSynthetic); } throw new IllegalStateException("Unrecognized output limit type " + outputLimitLimitType); } public UniformPair<EventBean[]> processOutputLimitedView(List<UniformPair<EventBean[]>> viewEventsList, boolean generateSynthetic, OutputLimitLimitType outputLimitLimitType) { if (outputLimitLimitType == OutputLimitLimitType.DEFAULT) { return processOutputLimitedViewDefault(viewEventsList, generateSynthetic); } else if (outputLimitLimitType == OutputLimitLimitType.ALL) { return processOutputLimitedViewAll(viewEventsList, generateSynthetic); } else if (outputLimitLimitType == OutputLimitLimitType.FIRST) { return processOutputLimitedViewFirst(viewEventsList, generateSynthetic); } else if (outputLimitLimitType == OutputLimitLimitType.LAST) { return processOutputLimitedViewLast(viewEventsList, generateSynthetic); } throw new IllegalStateException("Unrecognized output limit type " + outputLimitLimitType); } public boolean hasAggregation() { return true; } public void removed(Object key) { if (outputAllGroupReps != null) { outputAllGroupReps.remove(key); } if (outputLastHelper != null) { outputLastHelper.remove(key); } if (outputAllGroupReps != null) { outputAllGroupReps.remove(key); } if (outputFirstHelper != null) { outputFirstHelper.remove(key); } } public Object generateGroupKey(EventBean[] eventsPerStream, boolean isNewData) { if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().qResultSetProcessComputeGroupKeys(isNewData, prototype.getGroupKeyNodeExpressions(), eventsPerStream); Object keyObject; if (prototype.getGroupKeyNode() != null) { keyObject = prototype.getGroupKeyNode().evaluate(eventsPerStream, isNewData, agentInstanceContext); } else { ExprEvaluator[] evals = prototype.getGroupKeyNodes(); Object[] keys = new Object[evals.length]; for (int i = 0; i < evals.length; i++) { keys[i] = evals[i].evaluate(eventsPerStream, isNewData, agentInstanceContext); } keyObject = new MultiKeyUntyped(keys); } InstrumentationHelper.get().aResultSetProcessComputeGroupKeys(isNewData, keyObject); return keyObject; } if (prototype.getGroupKeyNode() != null) { return prototype.getGroupKeyNode().evaluate(eventsPerStream, isNewData, agentInstanceContext); } else { ExprEvaluator[] evals = prototype.getGroupKeyNodes(); Object[] keys = new Object[evals.length]; for (int i = 0; i < evals.length; i++) { keys[i] = evals[i].evaluate(eventsPerStream, isNewData, agentInstanceContext); } return new MultiKeyUntyped(keys); } } public void processOutputLimitedLastAllNonBufferedView(EventBean[] newData, EventBean[] oldData, boolean isGenerateSynthetic, boolean isAll) { if (isAll) { outputAllHelper.processView(newData, oldData, isGenerateSynthetic); } else { outputLastHelper.processView(newData, oldData, isGenerateSynthetic); } } public void processOutputLimitedLastAllNonBufferedJoin(Set<MultiKey<EventBean>> newData, Set<MultiKey<EventBean>> oldData, boolean isGenerateSynthetic, boolean isAll) { if (isAll) { outputAllHelper.processJoin(newData, oldData, isGenerateSynthetic); } else { outputLastHelper.processJoin(newData, oldData, isGenerateSynthetic); } } public UniformPair<EventBean[]> continueOutputLimitedLastAllNonBufferedView(boolean isSynthesize, boolean isAll) { if (isAll) { return outputAllHelper.outputView(isSynthesize); } return outputLastHelper.outputView(isSynthesize); } public UniformPair<EventBean[]> continueOutputLimitedLastAllNonBufferedJoin(boolean isSynthesize, boolean isAll) { if (isAll) { return outputAllHelper.outputJoin(isSynthesize); } return outputLastHelper.outputJoin(isSynthesize); } public void stop() { if (outputAllGroupReps != null) { outputAllGroupReps.destroy(); } if (outputAllHelper != null) { outputAllHelper.destroy(); } if (outputLastHelper != null) { outputLastHelper.destroy(); } if (outputFirstHelper != null) { outputFirstHelper.destroy(); } } public AggregationService getAggregationService() { return aggregationService; } public void acceptHelperVisitor(ResultSetProcessorOutputHelperVisitor visitor) { if (outputAllGroupReps != null) { visitor.visit(outputAllGroupReps); } if (outputFirstHelper != null) { visitor.visit(outputFirstHelper); } if (outputLastHelper != null) { visitor.visit(outputLastHelper); } if (outputAllHelper != null) { visitor.visit(outputAllHelper); } } private UniformPair<EventBean[]> processOutputLimitedJoinLast(List<UniformPair<Set<MultiKey<EventBean>>>> joinEventsSet, boolean generateSynthetic) { List<EventBean> newEvents = new LinkedList<EventBean>(); List<EventBean> oldEvents = null; if (prototype.isSelectRStream()) { oldEvents = new LinkedList<EventBean>(); } List<Object> newEventsSortKey = null; List<Object> oldEventsSortKey = null; if (orderByProcessor != null) { newEventsSortKey = new LinkedList<Object>(); if (prototype.isSelectRStream()) { oldEventsSortKey = new LinkedList<Object>(); } } Map<Object, EventBean[]> groupRepsView = new LinkedHashMap<Object, EventBean[]>(); for (UniformPair<Set<MultiKey<EventBean>>> pair : joinEventsSet) { Set<MultiKey<EventBean>> newData = pair.getFirst(); Set<MultiKey<EventBean>> oldData = pair.getSecond(); if (prototype.isUnidirectional()) { this.clear(); } if (newData != null) { // apply new data to aggregates for (MultiKey<EventBean> aNewData : newData) { Object mk = generateGroupKey(aNewData.getArray(), true); // if this is a newly encountered group, generate the remove stream event if (groupRepsView.put(mk, aNewData.getArray()) == null) { if (prototype.isSelectRStream()) { generateOutputBatchedRow(true, mk, aNewData.getArray(), false, generateSynthetic, oldEvents, oldEventsSortKey); } } aggregationService.applyEnter(aNewData.getArray(), mk, agentInstanceContext); } } if (oldData != null) { // apply old data to aggregates for (MultiKey<EventBean> anOldData : oldData) { Object mk = generateGroupKey(anOldData.getArray(), true); if (groupRepsView.put(mk, anOldData.getArray()) == null) { if (prototype.isSelectRStream()) { generateOutputBatchedRow(true, mk, anOldData.getArray(), false, generateSynthetic, oldEvents, oldEventsSortKey); } } aggregationService.applyLeave(anOldData.getArray(), mk, agentInstanceContext); } } } generateOutputBatchedArr(true, groupRepsView.entrySet().iterator(), true, generateSynthetic, newEvents, newEventsSortKey); EventBean[] newEventsArr = (newEvents.isEmpty()) ? null : newEvents.toArray(new EventBean[newEvents.size()]); EventBean[] oldEventsArr = null; if (prototype.isSelectRStream()) { oldEventsArr = (oldEvents.isEmpty()) ? null : oldEvents.toArray(new EventBean[oldEvents.size()]); } if (orderByProcessor != null) { Object[] sortKeysNew = (newEventsSortKey.isEmpty()) ? null : newEventsSortKey.toArray(new Object[newEventsSortKey.size()]); newEventsArr = orderByProcessor.sort(newEventsArr, sortKeysNew, agentInstanceContext); if (prototype.isSelectRStream()) { Object[] sortKeysOld = (oldEventsSortKey.isEmpty()) ? null : oldEventsSortKey.toArray(new Object[oldEventsSortKey.size()]); oldEventsArr = orderByProcessor.sort(oldEventsArr, sortKeysOld, agentInstanceContext); } } if ((newEventsArr == null) && (oldEventsArr == null)) { return null; } return new UniformPair<EventBean[]>(newEventsArr, oldEventsArr); } private UniformPair<EventBean[]> processOutputLimitedJoinFirst(List<UniformPair<Set<MultiKey<EventBean>>>> joinEventsSet, boolean generateSynthetic) { List<EventBean> newEvents = new LinkedList<EventBean>(); List<EventBean> oldEvents = null; if (prototype.isSelectRStream()) { oldEvents = new LinkedList<EventBean>(); } List<Object> newEventsSortKey = null; List<Object> oldEventsSortKey = null; if (orderByProcessor != null) { newEventsSortKey = new LinkedList<Object>(); if (prototype.isSelectRStream()) { oldEventsSortKey = new LinkedList<Object>(); } } Map<Object, EventBean[]> groupRepsView = new LinkedHashMap<Object, EventBean[]>(); if (prototype.getOptionalHavingNode() == null) { for (UniformPair<Set<MultiKey<EventBean>>> pair : joinEventsSet) { Set<MultiKey<EventBean>> newData = pair.getFirst(); Set<MultiKey<EventBean>> oldData = pair.getSecond(); if (newData != null) { // apply new data to aggregates for (MultiKey<EventBean> aNewData : newData) { Object mk = generateGroupKey(aNewData.getArray(), true); OutputConditionPolled outputStateGroup = outputFirstHelper.getOrAllocate(mk, agentInstanceContext, prototype.getOptionalOutputFirstConditionFactory()); boolean pass = outputStateGroup.updateOutputCondition(1, 0); if (pass) { // if this is a newly encountered group, generate the remove stream event if (groupRepsView.put(mk, aNewData.getArray()) == null) { if (prototype.isSelectRStream()) { generateOutputBatchedRow(true, mk, aNewData.getArray(), false, generateSynthetic, oldEvents, oldEventsSortKey); } } } aggregationService.applyEnter(aNewData.getArray(), mk, agentInstanceContext); } } if (oldData != null) { // apply old data to aggregates for (MultiKey<EventBean> anOldData : oldData) { Object mk = generateGroupKey(anOldData.getArray(), true); OutputConditionPolled outputStateGroup = outputFirstHelper.getOrAllocate(mk, agentInstanceContext, prototype.getOptionalOutputFirstConditionFactory()); boolean pass = outputStateGroup.updateOutputCondition(0, 1); if (pass) { if (groupRepsView.put(mk, anOldData.getArray()) == null) { if (prototype.isSelectRStream()) { generateOutputBatchedRow(true, mk, anOldData.getArray(), false, generateSynthetic, oldEvents, oldEventsSortKey); } } } aggregationService.applyLeave(anOldData.getArray(), mk, agentInstanceContext); } } } } else { groupRepsView.clear(); for (UniformPair<Set<MultiKey<EventBean>>> pair : joinEventsSet) { Set<MultiKey<EventBean>> newData = pair.getFirst(); Set<MultiKey<EventBean>> oldData = pair.getSecond(); Object[] newDataMultiKey = generateGroupKeys(newData, true); Object[] oldDataMultiKey = generateGroupKeys(oldData, false); if (newData != null) { // apply new data to aggregates int count = 0; for (MultiKey<EventBean> aNewData : newData) { aggregationService.applyEnter(aNewData.getArray(), newDataMultiKey[count], agentInstanceContext); count++; } } if (oldData != null) { // apply old data to aggregates int count = 0; for (MultiKey<EventBean> anOldData : oldData) { aggregationService.applyLeave(anOldData.getArray(), oldDataMultiKey[count], agentInstanceContext); count++; } } // evaluate having-clause if (newData != null) { int count = 0; for (MultiKey<EventBean> aNewData : newData) { Object mk = newDataMultiKey[count]; aggregationService.setCurrentAccess(mk, agentInstanceContext.getAgentInstanceId(), null); // Filter the having clause if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().qHavingClauseJoin(aNewData.getArray()); } Boolean result = (Boolean) prototype.getOptionalHavingNode().evaluate(aNewData.getArray(), true, agentInstanceContext); if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().aHavingClauseJoin(result); } if ((result == null) || (!result)) { count++; continue; } OutputConditionPolled outputStateGroup = outputFirstHelper.getOrAllocate(mk, agentInstanceContext, prototype.getOptionalOutputFirstConditionFactory()); boolean pass = outputStateGroup.updateOutputCondition(1, 0); if (pass) { if (groupRepsView.put(mk, aNewData.getArray()) == null) { if (prototype.isSelectRStream()) { generateOutputBatchedRow(true, mk, aNewData.getArray(), false, generateSynthetic, oldEvents, oldEventsSortKey); } } } count++; } } // evaluate having-clause if (oldData != null) { int count = 0; for (MultiKey<EventBean> anOldData : oldData) { Object mk = oldDataMultiKey[count]; aggregationService.setCurrentAccess(mk, agentInstanceContext.getAgentInstanceId(), null); // Filter the having clause if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().qHavingClauseJoin(anOldData.getArray()); } Boolean result = (Boolean) prototype.getOptionalHavingNode().evaluate(anOldData.getArray(), false, agentInstanceContext); if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().aHavingClauseJoin(result); } if ((result == null) || (!result)) { count++; continue; } OutputConditionPolled outputStateGroup = outputFirstHelper.getOrAllocate(mk, agentInstanceContext, prototype.getOptionalOutputFirstConditionFactory()); boolean pass = outputStateGroup.updateOutputCondition(0, 1); if (pass) { if (groupRepsView.put(mk, anOldData.getArray()) == null) { if (prototype.isSelectRStream()) { generateOutputBatchedRow(true, mk, anOldData.getArray(), false, generateSynthetic, oldEvents, oldEventsSortKey); } } } count++; } } } } generateOutputBatchedArr(true, groupRepsView.entrySet().iterator(), true, generateSynthetic, newEvents, newEventsSortKey); EventBean[] newEventsArr = (newEvents.isEmpty()) ? null : newEvents.toArray(new EventBean[newEvents.size()]); EventBean[] oldEventsArr = null; if (prototype.isSelectRStream()) { oldEventsArr = (oldEvents.isEmpty()) ? null : oldEvents.toArray(new EventBean[oldEvents.size()]); } if (orderByProcessor != null) { Object[] sortKeysNew = (newEventsSortKey.isEmpty()) ? null : newEventsSortKey.toArray(new Object[newEventsSortKey.size()]); newEventsArr = orderByProcessor.sort(newEventsArr, sortKeysNew, agentInstanceContext); if (prototype.isSelectRStream()) { Object[] sortKeysOld = (oldEventsSortKey.isEmpty()) ? null : oldEventsSortKey.toArray(new Object[oldEventsSortKey.size()]); oldEventsArr = orderByProcessor.sort(oldEventsArr, sortKeysOld, agentInstanceContext); } } if ((newEventsArr == null) && (oldEventsArr == null)) { return null; } return new UniformPair<EventBean[]>(newEventsArr, oldEventsArr); } private UniformPair<EventBean[]> processOutputLimitedJoinAll(List<UniformPair<Set<MultiKey<EventBean>>>> joinEventsSet, boolean generateSynthetic) { List<EventBean> newEvents = new LinkedList<EventBean>(); List<EventBean> oldEvents = null; if (prototype.isSelectRStream()) { oldEvents = new LinkedList<EventBean>(); } List<Object> newEventsSortKey = null; List<Object> oldEventsSortKey = null; if (orderByProcessor != null) { newEventsSortKey = new LinkedList<Object>(); if (prototype.isSelectRStream()) { oldEventsSortKey = new LinkedList<Object>(); } } if (prototype.isSelectRStream()) { generateOutputBatchedArr(true, outputAllGroupReps.entryIterator(), false, generateSynthetic, oldEvents, oldEventsSortKey); } for (UniformPair<Set<MultiKey<EventBean>>> pair : joinEventsSet) { Set<MultiKey<EventBean>> newData = pair.getFirst(); Set<MultiKey<EventBean>> oldData = pair.getSecond(); if (prototype.isUnidirectional()) { this.clear(); } if (newData != null) { // apply new data to aggregates for (MultiKey<EventBean> aNewData : newData) { Object mk = generateGroupKey(aNewData.getArray(), true); // if this is a newly encountered group, generate the remove stream event if (outputAllGroupReps.put(mk, aNewData.getArray()) == null) { if (prototype.isSelectRStream()) { generateOutputBatchedRow(true, mk, aNewData.getArray(), false, generateSynthetic, oldEvents, oldEventsSortKey); } } aggregationService.applyEnter(aNewData.getArray(), mk, agentInstanceContext); } } if (oldData != null) { // apply old data to aggregates for (MultiKey<EventBean> anOldData : oldData) { Object mk = generateGroupKey(anOldData.getArray(), true); if (outputAllGroupReps.put(mk, anOldData.getArray()) == null) { if (prototype.isSelectRStream()) { generateOutputBatchedRow(true, mk, anOldData.getArray(), false, generateSynthetic, oldEvents, oldEventsSortKey); } } aggregationService.applyLeave(anOldData.getArray(), mk, agentInstanceContext); } } } generateOutputBatchedArr(true, outputAllGroupReps.entryIterator(), true, generateSynthetic, newEvents, newEventsSortKey); EventBean[] newEventsArr = (newEvents.isEmpty()) ? null : newEvents.toArray(new EventBean[newEvents.size()]); EventBean[] oldEventsArr = null; if (prototype.isSelectRStream()) { oldEventsArr = (oldEvents.isEmpty()) ? null : oldEvents.toArray(new EventBean[oldEvents.size()]); } if (orderByProcessor != null) { Object[] sortKeysNew = (newEventsSortKey.isEmpty()) ? null : newEventsSortKey.toArray(new Object[newEventsSortKey.size()]); newEventsArr = orderByProcessor.sort(newEventsArr, sortKeysNew, agentInstanceContext); if (prototype.isSelectRStream()) { Object[] sortKeysOld = (oldEventsSortKey.isEmpty()) ? null : oldEventsSortKey.toArray(new Object[oldEventsSortKey.size()]); oldEventsArr = orderByProcessor.sort(oldEventsArr, sortKeysOld, agentInstanceContext); } } if ((newEventsArr == null) && (oldEventsArr == null)) { return null; } return new UniformPair<EventBean[]>(newEventsArr, oldEventsArr); } private UniformPair<EventBean[]> processOutputLimitedJoinDefault(List<UniformPair<Set<MultiKey<EventBean>>>> joinEventsSet, boolean generateSynthetic) { List<EventBean> newEvents = new LinkedList<EventBean>(); List<EventBean> oldEvents = null; if (prototype.isSelectRStream()) { oldEvents = new LinkedList<EventBean>(); } List<Object> newEventsSortKey = null; List<Object> oldEventsSortKey = null; if (orderByProcessor != null) { newEventsSortKey = new LinkedList<Object>(); if (prototype.isSelectRStream()) { oldEventsSortKey = new LinkedList<Object>(); } } Map<Object, EventBean[]> keysAndEvents = new HashMap<Object, EventBean[]>(); for (UniformPair<Set<MultiKey<EventBean>>> pair : joinEventsSet) { Set<MultiKey<EventBean>> newData = pair.getFirst(); Set<MultiKey<EventBean>> oldData = pair.getSecond(); if (prototype.isUnidirectional()) { this.clear(); } Object[] newDataMultiKey = generateGroupKeys(newData, keysAndEvents, true); Object[] oldDataMultiKey = generateGroupKeys(oldData, keysAndEvents, false); if (prototype.isSelectRStream()) { generateOutputBatchedArr(true, keysAndEvents.entrySet().iterator(), false, generateSynthetic, oldEvents, oldEventsSortKey); } if (newData != null) { // apply new data to aggregates int count = 0; for (MultiKey<EventBean> aNewData : newData) { aggregationService.applyEnter(aNewData.getArray(), newDataMultiKey[count], agentInstanceContext); count++; } } if (oldData != null) { // apply old data to aggregates int count = 0; for (MultiKey<EventBean> anOldData : oldData) { aggregationService.applyLeave(anOldData.getArray(), oldDataMultiKey[count], agentInstanceContext); count++; } } generateOutputBatchedArr(true, keysAndEvents.entrySet().iterator(), true, generateSynthetic, newEvents, newEventsSortKey); keysAndEvents.clear(); } EventBean[] newEventsArr = (newEvents.isEmpty()) ? null : newEvents.toArray(new EventBean[newEvents.size()]); EventBean[] oldEventsArr = null; if (prototype.isSelectRStream()) { oldEventsArr = (oldEvents.isEmpty()) ? null : oldEvents.toArray(new EventBean[oldEvents.size()]); } if (orderByProcessor != null) { Object[] sortKeysNew = (newEventsSortKey.isEmpty()) ? null : newEventsSortKey.toArray(new Object[newEventsSortKey.size()]); newEventsArr = orderByProcessor.sort(newEventsArr, sortKeysNew, agentInstanceContext); if (prototype.isSelectRStream()) { Object[] sortKeysOld = (oldEventsSortKey.isEmpty()) ? null : oldEventsSortKey.toArray(new Object[oldEventsSortKey.size()]); oldEventsArr = orderByProcessor.sort(oldEventsArr, sortKeysOld, agentInstanceContext); } } if ((newEventsArr == null) && (oldEventsArr == null)) { return null; } return new UniformPair<EventBean[]>(newEventsArr, oldEventsArr); } private UniformPair<EventBean[]> processOutputLimitedViewLast(List<UniformPair<EventBean[]>> viewEventsList, boolean generateSynthetic) { List<EventBean> newEvents = new LinkedList<EventBean>(); List<EventBean> oldEvents = null; if (prototype.isSelectRStream()) { oldEvents = new LinkedList<EventBean>(); } List<Object> newEventsSortKey = null; List<Object> oldEventsSortKey = null; if (orderByProcessor != null) { newEventsSortKey = new LinkedList<Object>(); if (prototype.isSelectRStream()) { oldEventsSortKey = new LinkedList<Object>(); } } Map<Object, EventBean[]> groupRepsView = new LinkedHashMap<Object, EventBean[]>(); for (UniformPair<EventBean[]> pair : viewEventsList) { EventBean[] newData = pair.getFirst(); EventBean[] oldData = pair.getSecond(); if (newData != null) { // apply new data to aggregates for (EventBean aNewData : newData) { EventBean[] eventsPerStream = new EventBean[]{aNewData}; Object mk = generateGroupKey(eventsPerStream, true); // if this is a newly encountered group, generate the remove stream event if (groupRepsView.put(mk, eventsPerStream) == null) { if (prototype.isSelectRStream()) { generateOutputBatchedRow(false, mk, eventsPerStream, false, generateSynthetic, oldEvents, oldEventsSortKey); } } aggregationService.applyEnter(eventsPerStream, mk, agentInstanceContext); } } if (oldData != null) { // apply old data to aggregates for (EventBean anOldData : oldData) { EventBean[] eventsPerStream = new EventBean[]{anOldData}; Object mk = generateGroupKey(eventsPerStream, true); if (groupRepsView.put(mk, eventsPerStream) == null) { if (prototype.isSelectRStream()) { generateOutputBatchedRow(false, mk, eventsPerStream, false, generateSynthetic, oldEvents, oldEventsSortKey); } } aggregationService.applyLeave(eventsPerStream, mk, agentInstanceContext); } } } generateOutputBatchedArr(false, groupRepsView.entrySet().iterator(), true, generateSynthetic, newEvents, newEventsSortKey); EventBean[] newEventsArr = (newEvents.isEmpty()) ? null : newEvents.toArray(new EventBean[newEvents.size()]); EventBean[] oldEventsArr = null; if (prototype.isSelectRStream()) { oldEventsArr = (oldEvents.isEmpty()) ? null : oldEvents.toArray(new EventBean[oldEvents.size()]); } if (orderByProcessor != null) { Object[] sortKeysNew = (newEventsSortKey.isEmpty()) ? null : newEventsSortKey.toArray(new Object[newEventsSortKey.size()]); newEventsArr = orderByProcessor.sort(newEventsArr, sortKeysNew, agentInstanceContext); if (prototype.isSelectRStream()) { Object[] sortKeysOld = (oldEventsSortKey.isEmpty()) ? null : oldEventsSortKey.toArray(new Object[oldEventsSortKey.size()]); oldEventsArr = orderByProcessor.sort(oldEventsArr, sortKeysOld, agentInstanceContext); } } if ((newEventsArr == null) && (oldEventsArr == null)) { return null; } return new UniformPair<EventBean[]>(newEventsArr, oldEventsArr); } private UniformPair<EventBean[]> processOutputLimitedViewFirst(List<UniformPair<EventBean[]>> viewEventsList, boolean generateSynthetic) { List<EventBean> newEvents = new LinkedList<EventBean>(); List<EventBean> oldEvents = null; if (prototype.isSelectRStream()) { oldEvents = new LinkedList<EventBean>(); } List<Object> newEventsSortKey = null; List<Object> oldEventsSortKey = null; if (orderByProcessor != null) { newEventsSortKey = new LinkedList<Object>(); if (prototype.isSelectRStream()) { oldEventsSortKey = new LinkedList<Object>(); } } Map<Object, EventBean[]> groupRepsView = new LinkedHashMap<Object, EventBean[]>(); if (prototype.getOptionalHavingNode() == null) { for (UniformPair<EventBean[]> pair : viewEventsList) { EventBean[] newData = pair.getFirst(); EventBean[] oldData = pair.getSecond(); if (newData != null) { // apply new data to aggregates for (EventBean aNewData : newData) { EventBean[] eventsPerStream = new EventBean[]{aNewData}; Object mk = generateGroupKey(eventsPerStream, true); OutputConditionPolled outputStateGroup = outputFirstHelper.getOrAllocate(mk, agentInstanceContext, prototype.getOptionalOutputFirstConditionFactory()); boolean pass = outputStateGroup.updateOutputCondition(1, 0); if (pass) { // if this is a newly encountered group, generate the remove stream event if (groupRepsView.put(mk, eventsPerStream) == null) { if (prototype.isSelectRStream()) { generateOutputBatchedRow(false, mk, eventsPerStream, false, generateSynthetic, oldEvents, oldEventsSortKey); } } } aggregationService.applyEnter(eventsPerStream, mk, agentInstanceContext); } } if (oldData != null) { // apply old data to aggregates for (EventBean anOldData : oldData) { EventBean[] eventsPerStream = new EventBean[]{anOldData}; Object mk = generateGroupKey(eventsPerStream, true); OutputConditionPolled outputStateGroup = outputFirstHelper.getOrAllocate(mk, agentInstanceContext, prototype.getOptionalOutputFirstConditionFactory()); boolean pass = outputStateGroup.updateOutputCondition(0, 1); if (pass) { if (groupRepsView.put(mk, eventsPerStream) == null) { if (prototype.isSelectRStream()) { generateOutputBatchedRow(false, mk, eventsPerStream, false, generateSynthetic, oldEvents, oldEventsSortKey); } } } aggregationService.applyLeave(eventsPerStream, mk, agentInstanceContext); } } } } else { // having clause present, having clause evaluates at the level of individual posts EventBean[] eventsPerStreamOneStream = new EventBean[1]; for (UniformPair<EventBean[]> pair : viewEventsList) { EventBean[] newData = pair.getFirst(); EventBean[] oldData = pair.getSecond(); Object[] newDataMultiKey = generateGroupKeys(newData, true); Object[] oldDataMultiKey = generateGroupKeys(oldData, false); if (newData != null) { // apply new data to aggregates for (int i = 0; i < newData.length; i++) { eventsPerStreamOneStream[0] = newData[i]; aggregationService.applyEnter(eventsPerStreamOneStream, newDataMultiKey[i], agentInstanceContext); } } if (oldData != null) { // apply old data to aggregates for (int i = 0; i < oldData.length; i++) { eventsPerStreamOneStream[0] = oldData[i]; aggregationService.applyLeave(eventsPerStreamOneStream, oldDataMultiKey[i], agentInstanceContext); } } // evaluate having-clause if (newData != null) { for (int i = 0; i < newData.length; i++) { Object mk = newDataMultiKey[i]; eventsPerStreamOneStream[0] = newData[i]; aggregationService.setCurrentAccess(mk, agentInstanceContext.getAgentInstanceId(), null); // Filter the having clause if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().qHavingClauseNonJoin(newData[i]); } Boolean result = (Boolean) prototype.getOptionalHavingNode().evaluate(eventsPerStreamOneStream, true, agentInstanceContext); if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().aHavingClauseNonJoin(result); } if ((result == null) || (!result)) { continue; } OutputConditionPolled outputStateGroup = outputFirstHelper.getOrAllocate(mk, agentInstanceContext, prototype.getOptionalOutputFirstConditionFactory()); boolean pass = outputStateGroup.updateOutputCondition(0, 1); if (pass) { EventBean[] eventsPerStream = new EventBean[]{newData[i]}; if (groupRepsView.put(mk, eventsPerStream) == null) { if (prototype.isSelectRStream()) { generateOutputBatchedRow(false, mk, eventsPerStream, true, generateSynthetic, oldEvents, oldEventsSortKey); } } } } } // evaluate having-clause if (oldData != null) { for (int i = 0; i < oldData.length; i++) { Object mk = oldDataMultiKey[i]; eventsPerStreamOneStream[0] = oldData[i]; aggregationService.setCurrentAccess(mk, agentInstanceContext.getAgentInstanceId(), null); // Filter the having clause if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().qHavingClauseNonJoin(oldData[i]); } Boolean result = (Boolean) prototype.getOptionalHavingNode().evaluate(eventsPerStreamOneStream, false, agentInstanceContext); if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().aHavingClauseNonJoin(result); } if ((result == null) || (!result)) { continue; } OutputConditionPolled outputStateGroup = outputFirstHelper.getOrAllocate(mk, agentInstanceContext, prototype.getOptionalOutputFirstConditionFactory()); boolean pass = outputStateGroup.updateOutputCondition(0, 1); if (pass) { EventBean[] eventsPerStream = new EventBean[]{oldData[i]}; if (groupRepsView.put(mk, eventsPerStream) == null) { if (prototype.isSelectRStream()) { generateOutputBatchedRow(false, mk, eventsPerStream, false, generateSynthetic, oldEvents, oldEventsSortKey); } } } } } } } generateOutputBatchedArr(false, groupRepsView.entrySet().iterator(), true, generateSynthetic, newEvents, newEventsSortKey); EventBean[] newEventsArr = (newEvents.isEmpty()) ? null : newEvents.toArray(new EventBean[newEvents.size()]); EventBean[] oldEventsArr = null; if (prototype.isSelectRStream()) { oldEventsArr = (oldEvents.isEmpty()) ? null : oldEvents.toArray(new EventBean[oldEvents.size()]); } if (orderByProcessor != null) { Object[] sortKeysNew = (newEventsSortKey.isEmpty()) ? null : newEventsSortKey.toArray(new Object[newEventsSortKey.size()]); newEventsArr = orderByProcessor.sort(newEventsArr, sortKeysNew, agentInstanceContext); if (prototype.isSelectRStream()) { Object[] sortKeysOld = (oldEventsSortKey.isEmpty()) ? null : oldEventsSortKey.toArray(new Object[oldEventsSortKey.size()]); oldEventsArr = orderByProcessor.sort(oldEventsArr, sortKeysOld, agentInstanceContext); } } if ((newEventsArr == null) && (oldEventsArr == null)) { return null; } return new UniformPair<EventBean[]>(newEventsArr, oldEventsArr); } private UniformPair<EventBean[]> processOutputLimitedViewAll(List<UniformPair<EventBean[]>> viewEventsList, boolean generateSynthetic) { EventBean[] eventsPerStream = new EventBean[1]; List<EventBean> newEvents = new LinkedList<EventBean>(); List<EventBean> oldEvents = null; if (prototype.isSelectRStream()) { oldEvents = new LinkedList<EventBean>(); } List<Object> newEventsSortKey = null; List<Object> oldEventsSortKey = null; if (orderByProcessor != null) { newEventsSortKey = new LinkedList<Object>(); if (prototype.isSelectRStream()) { oldEventsSortKey = new LinkedList<Object>(); } } if (prototype.isSelectRStream()) { generateOutputBatchedArr(false, outputAllGroupReps.entryIterator(), false, generateSynthetic, oldEvents, oldEventsSortKey); } for (UniformPair<EventBean[]> pair : viewEventsList) { EventBean[] newData = pair.getFirst(); EventBean[] oldData = pair.getSecond(); if (newData != null) { // apply new data to aggregates for (EventBean aNewData : newData) { eventsPerStream[0] = aNewData; Object mk = generateGroupKey(eventsPerStream, true); // if this is a newly encountered group, generate the remove stream event if (outputAllGroupReps.put(mk, new EventBean[]{aNewData}) == null) { if (prototype.isSelectRStream()) { generateOutputBatchedRow(false, mk, eventsPerStream, false, generateSynthetic, oldEvents, oldEventsSortKey); } } aggregationService.applyEnter(eventsPerStream, mk, agentInstanceContext); } } if (oldData != null) { // apply old data to aggregates for (EventBean anOldData : oldData) { eventsPerStream[0] = anOldData; Object mk = generateGroupKey(eventsPerStream, true); if (outputAllGroupReps.put(mk, new EventBean[]{anOldData}) == null) { if (prototype.isSelectRStream()) { generateOutputBatchedRow(false, mk, eventsPerStream, false, generateSynthetic, oldEvents, oldEventsSortKey); } } aggregationService.applyLeave(eventsPerStream, mk, agentInstanceContext); } } } generateOutputBatchedArr(false, outputAllGroupReps.entryIterator(), true, generateSynthetic, newEvents, newEventsSortKey); EventBean[] newEventsArr = (newEvents.isEmpty()) ? null : newEvents.toArray(new EventBean[newEvents.size()]); EventBean[] oldEventsArr = null; if (prototype.isSelectRStream()) { oldEventsArr = (oldEvents.isEmpty()) ? null : oldEvents.toArray(new EventBean[oldEvents.size()]); } if (orderByProcessor != null) { Object[] sortKeysNew = (newEventsSortKey.isEmpty()) ? null : newEventsSortKey.toArray(new Object[newEventsSortKey.size()]); newEventsArr = orderByProcessor.sort(newEventsArr, sortKeysNew, agentInstanceContext); if (prototype.isSelectRStream()) { Object[] sortKeysOld = (oldEventsSortKey.isEmpty()) ? null : oldEventsSortKey.toArray(new Object[oldEventsSortKey.size()]); oldEventsArr = orderByProcessor.sort(oldEventsArr, sortKeysOld, agentInstanceContext); } } if ((newEventsArr == null) && (oldEventsArr == null)) { return null; } return new UniformPair<EventBean[]>(newEventsArr, oldEventsArr); } private UniformPair<EventBean[]> processOutputLimitedViewDefault(List<UniformPair<EventBean[]>> viewEventsList, boolean generateSynthetic) { List<EventBean> newEvents = new LinkedList<EventBean>(); List<EventBean> oldEvents = null; if (prototype.isSelectRStream()) { oldEvents = new LinkedList<EventBean>(); } List<Object> newEventsSortKey = null; List<Object> oldEventsSortKey = null; if (orderByProcessor != null) { newEventsSortKey = new LinkedList<Object>(); if (prototype.isSelectRStream()) { oldEventsSortKey = new LinkedList<Object>(); } } Map<Object, EventBean> keysAndEvents = new HashMap<Object, EventBean>(); for (UniformPair<EventBean[]> pair : viewEventsList) { EventBean[] newData = pair.getFirst(); EventBean[] oldData = pair.getSecond(); Object[] newDataMultiKey = generateGroupKeys(newData, keysAndEvents, true); Object[] oldDataMultiKey = generateGroupKeys(oldData, keysAndEvents, false); if (prototype.isSelectRStream()) { generateOutputBatchedRow(keysAndEvents, false, generateSynthetic, oldEvents, oldEventsSortKey, agentInstanceContext); } EventBean[] eventsPerStream = new EventBean[1]; if (newData != null) { // apply new data to aggregates int count = 0; for (EventBean aNewData : newData) { eventsPerStream[0] = aNewData; aggregationService.applyEnter(eventsPerStream, newDataMultiKey[count], agentInstanceContext); count++; } } if (oldData != null) { // apply old data to aggregates int count = 0; for (EventBean anOldData : oldData) { eventsPerStream[0] = anOldData; aggregationService.applyLeave(eventsPerStream, oldDataMultiKey[count], agentInstanceContext); count++; } } generateOutputBatchedRow(keysAndEvents, true, generateSynthetic, newEvents, newEventsSortKey, agentInstanceContext); keysAndEvents.clear(); } EventBean[] newEventsArr = (newEvents.isEmpty()) ? null : newEvents.toArray(new EventBean[newEvents.size()]); EventBean[] oldEventsArr = null; if (prototype.isSelectRStream()) { oldEventsArr = (oldEvents.isEmpty()) ? null : oldEvents.toArray(new EventBean[oldEvents.size()]); } if (orderByProcessor != null) { Object[] sortKeysNew = (newEventsSortKey.isEmpty()) ? null : newEventsSortKey.toArray(new Object[newEventsSortKey.size()]); newEventsArr = orderByProcessor.sort(newEventsArr, sortKeysNew, agentInstanceContext); if (prototype.isSelectRStream()) { Object[] sortKeysOld = (oldEventsSortKey.isEmpty()) ? null : oldEventsSortKey.toArray(new Object[oldEventsSortKey.size()]); oldEventsArr = orderByProcessor.sort(oldEventsArr, sortKeysOld, agentInstanceContext); } } if ((newEventsArr == null) && (oldEventsArr == null)) { return null; } return new UniformPair<EventBean[]>(newEventsArr, oldEventsArr); } private Object[] generateGroupKeys(Set<MultiKey<EventBean>> resultSet, boolean isNewData) { if (resultSet.isEmpty()) { return null; } Object[] keys = new Object[resultSet.size()]; int count = 0; for (MultiKey<EventBean> eventsPerStream : resultSet) { keys[count] = generateGroupKey(eventsPerStream.getArray(), isNewData); count++; } return keys; } }