/* * 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.stream; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import streamcruncher.api.artifact.RowSpec; import streamcruncher.api.artifact.TableSpec; import streamcruncher.boot.Registry; import streamcruncher.innards.db.DatabaseInterface; import streamcruncher.innards.util.Helper; import streamcruncher.kernel.DBQueryOutput; import streamcruncher.kernel.DirectQueryOutput; import streamcruncher.kernel.QueryOutput; /* * Author: Ashwin Jayaprakash Date: Jan 19, 2006 Time: 1:32:36 PM */ public class OutStream { protected final String schema; protected final String name; protected final String resultTblIdColumn; protected final int totalResultColumns; protected final String queryName; protected final LinkedBlockingQueue<QueryOutput> queueOfIdPairs; protected DatabaseInterface dbInterface; protected String resultFetchetSQL; protected String deleteSQL; // ------------- protected final int hashCode; protected final String str; // ------------- /** * @param schema * @param name * @param queryName */ public OutStream(String queryName, TableSpec resultTableSpec) { this.schema = resultTableSpec.getSchema(); this.name = resultTableSpec.getName(); RowSpec spec = resultTableSpec.getRowSpec(); String[] columns = spec.getColumnNames(); // Auto generated Id column for the Output Stream. this.resultTblIdColumn = columns[spec.getIdColumnPosition()]; this.totalResultColumns = columns.length; this.queryName = queryName; this.queueOfIdPairs = new LinkedBlockingQueue<QueryOutput>(); // ------------- int hash = (schema + ".").hashCode(); hash = hash + (37 * (name + " ").hashCode()); hash = hash + (37 * (queryName + " ").hashCode()); this.hashCode = hash; this.str = schema + "." + name + "-" + queryName; // -------------- init(); } /** * @return the queryName */ public String getQueryName() { return queryName; } // ------------- protected void init() { dbInterface = Registry.getImplFor(DatabaseInterface.class); resultFetchetSQL = getResultFetcherSQL(); deleteSQL = getDeleteSQL(); } protected String getResultFetcherSQL() { String tbl = (schema == null) ? name : (schema + "." + name); return "select * from " + tbl + " where " + resultTblIdColumn + " > ? and " + resultTblIdColumn + " <= ?"; } protected String getDeleteSQL() { String tbl = (schema == null) ? name : (schema + "." + name); return "delete from " + tbl + " where " + resultTblIdColumn + " <= ?"; } // ------------- /** * @param queryOutputInfo */ public void addNextWindowRange(QueryOutput queryOutput) { queueOfIdPairs.add(queryOutput); } /** * Blocks until at least one Event is available. * * @return * @throws SQLException * @throws InterruptedException */ public List<Object[]> takeEvents() throws SQLException, InterruptedException { QueryOutput output = queueOfIdPairs.take(); List<Object[]> events = null; if (output instanceof DBQueryOutput) { events = takeEvents((DBQueryOutput) output); } else { events = takeEvents((DirectQueryOutput) output); } return events; } /** * @param timeout * @param timeUnit * @return Empty array if the operation timed out. * @throws InterruptedException * @throws SQLException */ public List<Object[]> takeEvents(long timeout, TimeUnit timeUnit) throws InterruptedException, SQLException { List<Object[]> events = null; QueryOutput output = queueOfIdPairs.poll(timeout, timeUnit); if (output != null) { if (output instanceof DBQueryOutput) { events = takeEvents((DBQueryOutput) output); } else { events = takeEvents((DirectQueryOutput) output); } } else { events = new ArrayList<Object[]>(); } return events; } protected List<Object[]> takeEvents(DirectQueryOutput output) { return output.getOutput(); } protected List<Object[]> takeEvents(DBQueryOutput output) throws SQLException { Connection connection = null; PreparedStatement statement = null; ResultSet resultSet = null; ArrayList<Object[]> rows = new ArrayList<Object[]>(output.getRows()); try { connection = dbInterface.createConnection(); connection.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED); statement = connection.prepareStatement(deleteSQL); statement.setLong(1, output.getStartIdExclusive()); statement.execute(); Helper.closeStatement(statement); // ------------- statement = connection.prepareStatement(resultFetchetSQL); statement.setLong(1, output.getStartIdExclusive()); statement.setLong(2, output.getEndIdInclusive()); resultSet = statement.executeQuery(); int resultColumns = totalResultColumns - 1; while (resultSet.next()) { Object[] row = new Object[resultColumns]; for (int i = 2 /* Skip the first auto-id column. */; i <= totalResultColumns; i++) { row[i - 2] = resultSet.getObject(i); } rows.add(row); } } finally { Helper.closeResultSet(resultSet); Helper.closeStatement(statement); Helper.closeConnection(connection); } return rows; } // ------------- @Override public boolean equals(Object obj) { if (obj instanceof OutStream) { OutStream that = (OutStream) obj; String thisStr = toString(); String thatStr = that.toString(); return thisStr.equals(thatStr); } return false; } @Override public int hashCode() { return hashCode; } @Override public String toString() { return str; } }