/*
* StreamCruncher: Copyright (c) 2006-2008, Ashwin Jayaprakash. All Rights Reserved.
* Contact: ashwin {dot} jayaprakash {at} gmail {dot} com
* Web: http://www.StreamCruncher.com
*
* This file is part of StreamCruncher.
*
* StreamCruncher is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* StreamCruncher is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with StreamCruncher. If not, see <http://www.gnu.org/licenses/>.
*/
package streamcruncher.innards.core.partition.inmem;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import streamcruncher.api.artifact.RowSpec;
import streamcruncher.innards.core.WhereClauseSpec;
import streamcruncher.innards.core.filter.TableFilter;
import streamcruncher.innards.core.partition.Row;
import streamcruncher.innards.core.partition.RowStatus;
import streamcruncher.innards.expression.Statement;
import streamcruncher.innards.impl.expression.ExpressionEvaluationException;
import streamcruncher.innards.impl.expression.OgnlRowEvaluator;
import streamcruncher.util.AppendOnlyPrimitiveLongList;
/*
* Author: Ashwin Jayaprakash Date: Sep 4, 2007 Time: 8:15:49 PM
*/
public class InMemMaster {
protected final InMemSpec memSpec;
protected final InMemPartitionDataProducer dataProducer;
protected final OgnlRowEvaluator rowFilter;
protected final OgnlRowEvaluator[] columnEvaluators;
protected final int partitionTableRowIdPosition;
protected final HashMap<Long, Object[]> rowIdAndDataMap;
protected final RowStatus rowStatus;
public InMemMaster(String queryName, InMemSpec memSpec, TableFilter source)
throws ExpressionEvaluationException {
this.memSpec = memSpec;
List<InMemPartitionDataProducer> producerList = Util
.convertToList(new TableFilter[] { source });
this.dataProducer = producerList.get(0);
// ---------------
OgnlRowEvaluator eventFilter = null;
RowSpec rowSpec = memSpec.getPartitionTableSpec().getRowSpec();
RowStatus tmpRowStatus = null;
WhereClauseSpec whereClauseSpec = this.memSpec.getWhereClauseSpec();
String whereClauseStr = null;
if (whereClauseSpec != null) {
whereClauseStr = whereClauseSpec.getWhereClause();
if (whereClauseStr != null && whereClauseStr.length() > 0) {
eventFilter = new OgnlRowEvaluator(queryName, whereClauseStr, rowSpec,
whereClauseSpec.getContext(), whereClauseSpec.getSubQueries());
}
tmpRowStatus = (RowStatus) whereClauseSpec.getContext().get(RowStatus.class.getName());
}
this.rowFilter = eventFilter;
this.rowStatus = tmpRowStatus;
// ---------------
Statement statement = memSpec.getStatement();
List<WhereClauseSpec> columnExpressions = statement.getColumnExpressions();
// Create a shared Context first.
Map<String, Object> commonSharedContext = new HashMap<String, Object>();
for (WhereClauseSpec spec : columnExpressions) {
commonSharedContext.putAll(spec.getContext());
}
this.columnEvaluators = new OgnlRowEvaluator[columnExpressions.size()];
int x = 0;
for (WhereClauseSpec spec : columnExpressions) {
this.columnEvaluators[x++] = new OgnlRowEvaluator(queryName, spec.getWhereClause(),
rowSpec, commonSharedContext, spec.getSubQueries());
}
// ---------------
this.partitionTableRowIdPosition = memSpec.getPartitionTableSpec().getRowSpec()
.getIdColumnPosition();
this.rowIdAndDataMap = new HashMap<Long, Object[]>();
}
public List<Object[]> onCycleEnd() throws ExpressionEvaluationException {
List<Object[]> results = new LinkedList<Object[]>();
AppendOnlyPrimitiveLongList removals = dataProducer.retrieveDeadRowIdsInBatch();
if (removals != null) {
long[] ids = removals.removeAvailable();
while (ids.length > 0) {
for (int i = 0; i < ids.length; i++) {
Object[] columns = rowIdAndDataMap.remove(ids[i]);
if (rowStatus == null || rowStatus == RowStatus.DEAD) {
results.add(columns);
}
}
ids = removals.removeAvailable();
}
}
List<Row> rows = dataProducer.retrieveNewRowsInBatch();
if (rows != null) {
for (Row row : rows) {
Object[] columns = row.getColumns();
if (rowStatus != null && rowStatus == RowStatus.NEW) {
results.add(columns);
}
else {
Long id = (Long) columns[partitionTableRowIdPosition];
rowIdAndDataMap.put(id, columns);
}
}
}
if (rowStatus != null && rowStatus == RowStatus.NOT_DEAD) {
for (Entry<Long, Object[]> entry : rowIdAndDataMap.entrySet()) {
results.add(entry.getValue());
}
}
List<Object[]> retVal = Util.filterRows(memSpec.getStatement(), rowFilter,
columnEvaluators, results);
return retVal;
}
}