/* *************************************************************************************** * 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.table.mgmt; import com.espertech.esper.client.EPException; import com.espertech.esper.client.EventBean; import com.espertech.esper.client.EventPropertyGetter; import com.espertech.esper.collection.MultiKeyUntyped; import com.espertech.esper.collection.Pair; import com.espertech.esper.core.context.util.AgentInstanceContext; import com.espertech.esper.epl.agg.access.AggregationServicePassThru; import com.espertech.esper.epl.expression.core.ExprEvaluatorContext; import com.espertech.esper.epl.expression.core.ExprValidationException; import com.espertech.esper.epl.join.plan.QueryPlanIndexItem; import com.espertech.esper.epl.join.table.*; import com.espertech.esper.epl.lookup.EventTableIndexRepository; import com.espertech.esper.epl.lookup.EventTableIndexRepositoryEntry; import com.espertech.esper.epl.lookup.IndexMultiKey; import com.espertech.esper.event.ObjectArrayBackedEventBean; import com.espertech.esper.metrics.instrumentation.InstrumentationHelper; import com.espertech.esper.util.CollectionUtil; import java.util.*; public class TableStateInstanceGroupedImpl extends TableStateInstance implements TableStateInstanceGrouped { private final Map<Object, ObjectArrayBackedEventBean> rows = new HashMap<Object, ObjectArrayBackedEventBean>(); private final IndexMultiKey primaryIndexKey; public TableStateInstanceGroupedImpl(TableMetadata tableMetadata, AgentInstanceContext agentInstanceContext) { super(tableMetadata, agentInstanceContext); List<EventPropertyGetter> indexGetters = new ArrayList<EventPropertyGetter>(); List<String> keyNames = new ArrayList<String>(); for (Map.Entry<String, TableMetadataColumn> entry : tableMetadata.getTableColumns().entrySet()) { if (entry.getValue().isKey()) { keyNames.add(entry.getKey()); indexGetters.add(tableMetadata.getInternalEventType().getGetter(entry.getKey())); } } String tableName = "primary-" + tableMetadata.getTableName(); EventTableOrganization organization = new EventTableOrganization(tableName, true, false, 0, CollectionUtil.toArray(keyNames), EventTableOrganizationType.HASH); EventTable table; if (indexGetters.size() == 1) { Map<Object, EventBean> tableMap = (Map<Object, EventBean>) (Map<Object, ?>) rows; table = new PropertyIndexedEventTableSingleUnique(indexGetters.get(0), organization, tableMap); } else { EventPropertyGetter[] getters = indexGetters.toArray(new EventPropertyGetter[indexGetters.size()]); Map<MultiKeyUntyped, EventBean> tableMap = (Map<MultiKeyUntyped, EventBean>) (Map<?, ?>) rows; table = new PropertyIndexedEventTableUnique(getters, organization, tableMap); } Pair<int[], IndexMultiKey> pair = TableServiceUtil.getIndexMultikeyForKeys(tableMetadata.getTableColumns(), tableMetadata.getInternalEventType()); primaryIndexKey = pair.getSecond(); indexRepository.addIndex(primaryIndexKey, new EventTableIndexRepositoryEntry(tableName, table)); } public EventTable getIndex(String indexName) { if (indexName.equals(tableMetadata.getTableName())) { return indexRepository.getIndexByDesc(primaryIndexKey); } return indexRepository.getExplicitIndexByName(indexName); } public Map<Object, ObjectArrayBackedEventBean> getRows() { return rows; } public void addEvent(EventBean theEvent) { if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().qTableAddEvent(theEvent); } try { for (EventTable table : indexRepository.getTables()) { table.add(theEvent, agentInstanceContext); } } catch (EPException ex) { for (EventTable table : indexRepository.getTables()) { table.remove(theEvent, agentInstanceContext); } throw ex; } finally { if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().aTableAddEvent(); } } } public void deleteEvent(EventBean matchingEvent) { if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().qTableDeleteEvent(matchingEvent); } for (EventTable table : indexRepository.getTables()) { table.remove(matchingEvent, agentInstanceContext); } if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().aTableDeleteEvent(); } } public Iterable<EventBean> getIterableTableScan() { return new PrimaryIndexIterable(rows); } public void addExplicitIndex(String explicitIndexName, QueryPlanIndexItem explicitIndexDesc, boolean isRecoveringResilient, boolean allowIndexExists) throws ExprValidationException { indexRepository.validateAddExplicitIndex(explicitIndexName, explicitIndexDesc, tableMetadata.getInternalEventType(), new PrimaryIndexIterable(rows), getAgentInstanceContext(), isRecoveringResilient || allowIndexExists, null); } public String[] getSecondaryIndexes() { return indexRepository.getExplicitIndexNames(); } public EventTableIndexRepository getIndexRepository() { return indexRepository; } public Collection<EventBean> getEventCollection() { return (Collection<EventBean>) (Collection<?>) rows.values(); } public ObjectArrayBackedEventBean getRowForGroupKey(Object groupKey) { return rows.get(groupKey); } public Set<Object> getGroupKeys() { return rows.keySet(); } public void clear() { clearInstance(); } public void clearInstance() { rows.clear(); for (EventTable table : indexRepository.getTables()) { table.destroy(); } } public void destroyInstance() { clearInstance(); } public ObjectArrayBackedEventBean getCreateRowIntoTable(Object groupByKey, ExprEvaluatorContext exprEvaluatorContext) { ObjectArrayBackedEventBean bean = getRows().get(groupByKey); if (bean != null) { return bean; } ObjectArrayBackedEventBean row = tableMetadata.getRowFactory().makeOA(exprEvaluatorContext.getAgentInstanceId(), groupByKey, null, getAggregationServicePassThru()); addEvent(row); return row; } public int getRowCount() { return rows.size(); } public AggregationServicePassThru getAggregationServicePassThru() { return null; } private static class PrimaryIndexIterable implements Iterable<EventBean> { private final Map<Object, ObjectArrayBackedEventBean> rows; private PrimaryIndexIterable(Map<Object, ObjectArrayBackedEventBean> rows) { this.rows = rows; } public Iterator<EventBean> iterator() { return (Iterator<EventBean>) (Iterator<?>) rows.values().iterator(); } } }