/*
* 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.kernel;
import java.awt.Window;
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Collections;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicLong;
import streamcruncher.boot.Registry;
import streamcruncher.innards.core.filter.FilteredTable;
import streamcruncher.innards.core.filter.TableFilter;
import streamcruncher.innards.core.partition.Partitioner;
import streamcruncher.innards.db.DatabaseInterface;
import streamcruncher.util.FixedKeyHashMap;
/*
* Author: Ashwin Jayaprakash Date: Aug 9, 2006 Time: 1:42:08 PM
*/
/**
* There is one context, per Query. Once created, the <b>same context</b> will
* be used throughout the Query's life.
*/
public class QueryContext implements Serializable {
private static final long serialVersionUID = 1L;
protected final FilteredTable[] filteredTables;
/**
* General purpose storage. Will not be serialized.
*/
protected transient final ConcurrentMap map;
protected transient final DatabaseInterface databaseInterface;
protected final QueryConfig queryConfig;
/**
* Current Time in Milliseconds.
*/
protected transient long currentTime;
/**
* Used for Partition's version-column, because
* {@link System#currentTimeMillis()} does not change between fast,
* successive runs on "MS Windows".
*/
protected final AtomicLong runCount;
protected final Set<String> keys;
/**
* The timestamps at which the Events in the Functions, will expire; in
* sorted order.
*/
protected transient final FixedKeyHashMap<String, SortedSet<Long>> eventExpirationTimes;
/**
* The total number of Rows that are still in the Buffers which, forces the
* Query to be scheduled.
*/
protected transient final FixedKeyHashMap<String, Integer> totalUnprocessedBufferedRows;
/**
* When the Query is about to be run, the
* {@linkplain Partitioner Partitions} (TableFilters) are executed. Since
* Partitions support pre-Filters, this Run could've been triggered by
* Events that do not make it through the Filter and thus result in a
* spurious Run. To avoid this, a Partition is allowed to Veto a scheduled
* Run of the Query, provided the Windows or other Partitions do not
* genuinely require a Run.
*/
protected transient final ConcurrentMap<TableFilter, Boolean> tblFilterAndRequireQryRunFlg;
protected transient final ConcurrentMap<Window, Boolean> windowAndRequireQryRunFlg;
// ----------------------
/**
* @param filteredTables
* @param queryConfig
*/
public QueryContext(FilteredTable[] filteredTables, QueryConfig queryConfig) {
this.filteredTables = filteredTables;
this.queryConfig = queryConfig;
this.map = new ConcurrentHashMap();
this.databaseInterface = Registry.getImplFor(DatabaseInterface.class);
this.keys = Collections.unmodifiableSet(queryConfig.getKeys());
this.eventExpirationTimes = new FixedKeyHashMap<String, SortedSet<Long>>(keys, null);
for (String key : keys) {
this.eventExpirationTimes.put(key, new TreeSet<Long>());
}
this.totalUnprocessedBufferedRows = new FixedKeyHashMap<String, Integer>(keys, 0);
this.runCount = new AtomicLong(0);
this.tblFilterAndRequireQryRunFlg = new ConcurrentHashMap<TableFilter, Boolean>();
this.windowAndRequireQryRunFlg = new ConcurrentHashMap<Window, Boolean>();
}
/**
* @return Creates a new instance, so that references to other components
* like {@link #databaseInterface} etc are loaded afresh.
* @throws ObjectStreamException
*/
protected Object readResolve() throws ObjectStreamException {
return new QueryContext(filteredTables, queryConfig);
}
// ----------------------
public QueryConfig getQueryConfig() {
return queryConfig;
}
public long getRunCount() {
return runCount.get();
}
/**
* @return
*/
public long getCurrentTime() {
return currentTime;
}
/**
* @return Unmodifiable.
*/
public Set<String> getKeys() {
return keys;
}
/**
* @param fqn
* {@link Window}'s or {@link FilteredTable}'s
* {@linkplain Window#getSourceTableFQN() FQN}.
* @return Returns the eventExpirationTimes. Use
* {@link java.util.Set#isEmpty()} instead of
* <code>size() > 0</code>.
*/
public SortedSet<Long> getEventExpirationTimes(String fqn) {
return eventExpirationTimes.get(fqn);
}
public Set<String> getEventExpirationTimeKeys() {
return eventExpirationTimes.getKeys();
}
/**
* @param fqn
* @return Returns the totalUnprocessedBufferedRows.
*/
public int getTotalUnprocessedBufferedRows(String fqn) {
return totalUnprocessedBufferedRows.get(fqn);
}
public Set<String> getTotalUnprocessedBufferedRowKeys() {
return totalUnprocessedBufferedRows.getKeys();
}
/**
* @param fqn
* @param unprocessedBufferedRows
*/
public void setTotalUnprocessedBufferedRows(String fqn, int unprocessedBufferedRows) {
this.totalUnprocessedBufferedRows.put(fqn, unprocessedBufferedRows);
}
/**
* @param currentTime
*/
public void setCurrentTime(long currentTime) {
this.currentTime = currentTime;
}
public void incrementRunCount() {
this.runCount.incrementAndGet();
}
/**
* @throws SQLException
*/
public Connection createConnection() throws SQLException {
return databaseInterface.createConnection();
}
public ConcurrentMap getMap() {
return map;
}
// ----------------------
public void discard() {
map.clear();
eventExpirationTimes.clear();
totalUnprocessedBufferedRows.clear();
}
}