/*
* 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.test.func;
import java.sql.Timestamp;
import java.util.EnumMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import streamcruncher.api.InputSession;
import streamcruncher.api.OutputSession;
import streamcruncher.api.ParsedQuery;
import streamcruncher.api.ParserParameters;
import streamcruncher.api.QueryConfig;
import streamcruncher.api.StreamCruncher;
import streamcruncher.api.StreamCruncherException;
import streamcruncher.api.QueryConfig.QuerySchedulePolicy;
import streamcruncher.api.artifact.RowSpec;
/*
* Author: Ashwin Jayaprakash Date: Oct 15, 2006 Time: 11:35:36 AM
*/
/**
* Generates test data for 3 Streams - for Correlation tests.
*/
public abstract class MultiStreamEventGenerator {
protected StreamCruncher cruncher;
protected LinkedBlockingQueue<Long> eventIds;
protected EnumMap<MultiStreamEventGenerator.EventType, Cache> cacheMap;
protected MultiStreamEventGenerator() {
cruncher = new StreamCruncher();
}
protected void init() throws Exception {
String[] columnNames = { "levela", "levelb", "event_time", "event_id" };
String[] columnTypes = getStage1ColumnTypes();
RowSpec rowSpec = new RowSpec(columnNames, columnTypes, 3, 2);
cruncher.registerInStream(EventType.stg1_event.name(), rowSpec, 4096);
// ---------
columnNames = new String[] { "levela", "levelb", "event_time", "event_id" };
columnTypes = getStage2ColumnTypes();
rowSpec = new RowSpec(columnNames, columnTypes, 3, 2);
cruncher.registerInStream(EventType.stg2_event.name(), rowSpec, 4096);
// ---------
columnNames = new String[] { "levela", "levelb", "event_time", "event_id" };
columnTypes = getStage3ColumnTypes();
rowSpec = new RowSpec(columnNames, columnTypes, 3, 2);
cruncher.registerInStream(EventType.stg3_event.name(), rowSpec, 4096);
// ---------
beforeQueryParse();
eventIds = new LinkedBlockingQueue<Long>();
cacheMap = new EnumMap<EventType, Cache>(EventType.class);
// ---------
String rql = getRQL();
columnNames = getResultColumnNames();
columnTypes = getResultColumnTypes();
String queryName = "event_correlation_rql";
ParserParameters parameters = new ParserParameters();
parameters.setQuery(rql);
parameters.setQueryName(queryName);
parameters.setResultColumnTypes(columnTypes);
ParsedQuery parsedQuery = cruncher.parseQuery(parameters);
QueryConfig config = parsedQuery.getQueryConfig();
config.setQuerySchedulePolicy(new QueryConfig.QuerySchedulePolicyValue(
QuerySchedulePolicy.ATLEAST_OR_SOONER, Integer.MAX_VALUE));
modifyQueryConfig(config);
cruncher.registerQuery(parsedQuery);
}
protected void beforeQueryParse() {
}
protected void modifyQueryConfig(QueryConfig config) {
}
protected abstract String[] getStage1ColumnTypes();
protected abstract String[] getStage2ColumnTypes();
protected abstract String[] getStage3ColumnTypes();
protected abstract String getRQL();
protected abstract String[] getResultColumnNames();
protected abstract String[] getResultColumnTypes();
protected String getRQLColumnsCSV() {
String[] columns = getResultColumnNames();
String csv = "";
for (int i = 0; i < columns.length; i++) {
if (csv != "") {
csv = csv + ", ";
}
csv = csv + columns[i];
}
return csv;
}
protected abstract Event[] createEventArray();
protected Iterator<Event> getEvents() {
final Event[] eventSequence = createEventArray();
Iterator<Event> iter = new Iterator<Event>() {
int counter = 0;
public boolean hasNext() {
return !(counter == eventSequence.length);
}
public Event next() {
Event retVal = eventSequence[counter++];
Object[] data = retVal.getData();
for (int i = 0; i < data.length; i++) {
if (data[i] == null) {
data[i] = new Timestamp(System.currentTimeMillis());
}
}
for (Object object : data) {
System.out.print(object + " ");
}
System.out.println();
return retVal;
}
public void remove() {
throw new UnsupportedOperationException();
}
};
return iter;
}
protected List<BatchResult> test() throws Exception {
InputSession inputSession1 = cruncher.createInputSession(EventType.stg1_event.name());
inputSession1.start();
cacheMap.put(EventType.stg1_event, new Cache(inputSession1));
InputSession inputSession2 = cruncher.createInputSession(EventType.stg2_event.name());
inputSession2.start();
cacheMap.put(EventType.stg2_event, new Cache(inputSession2));
InputSession inputSession3 = cruncher.createInputSession(EventType.stg3_event.name());
inputSession3.start();
cacheMap.put(EventType.stg3_event, new Cache(inputSession3));
OutputSession outputSession = cruncher.createOutputSession("event_correlation_rql");
// --------------
Iterator<Event> events = getEvents();
for (; events.hasNext();) {
Event event = events.next();
handleEvent(event);
}
// --------------
List<BatchResult> results = fetchResults(outputSession);
verify(results);
Cache cache = cacheMap.get(EventType.stg1_event);
cache.inputSession.close();
cache = cacheMap.get(EventType.stg2_event);
cache.inputSession.close();
cache = cacheMap.get(EventType.stg3_event);
cache.inputSession.close();
outputSession.close();
return results;
}
protected void handleEvent(Event event) throws InterruptedException {
EventType type = event.type;
Cache cache = cacheMap.get(type);
if (type == EventType.pause) {
Long time = (Long) event.data[0];
Thread.sleep(time);
}
else {
cache.inputSession.submitEvent(event.data);
}
}
protected List<BatchResult> fetchResults(OutputSession outputSession) throws Exception {
outputSession.start();
int pollTimeSec = 10;
List<BatchResult> results = new LinkedList<BatchResult>();
while (true) {
try {
List<Object[]> events = outputSession.readEvents(pollTimeSec, TimeUnit.SECONDS);
if (events.size() == 0) {
if (results.size() > 0) {
throw new InterruptedException("Timed out!");
}
System.err.println("Retrying..");
continue;
}
BatchResult batchResult = new BatchResult();
for (Object[] objects : events) {
batchResult.addRow(objects);
}
results.add(batchResult);
System.err.println("Got result batch.");
}
catch (InterruptedException e) {
if (pollTimeSec == 10) {
pollTimeSec = 5;
}
else if (pollTimeSec > 1) {
pollTimeSec--;
}
else {
break;
}
System.err.println("Retrying for more results...");
}
}
outputSession.close();
return results;
}
protected abstract void verify(List<BatchResult> results);
protected void discard() {
try {
cruncher.unregisterQuery("event_correlation_rql");
}
catch (RuntimeException e) {
e.printStackTrace(System.err);
}
try {
cruncher.unregisterInStream(EventType.stg1_event.name());
}
catch (StreamCruncherException e) {
e.printStackTrace(System.err);
}
try {
cruncher.unregisterInStream(EventType.stg2_event.name());
}
catch (StreamCruncherException e) {
e.printStackTrace(System.err);
}
try {
cruncher.unregisterInStream(EventType.stg3_event.name());
}
catch (StreamCruncherException e) {
e.printStackTrace(System.err);
}
cruncher = null;
}
// ---------------
public static enum EventType {
stg1_event, stg2_event, stg3_event, pause;
}
public static class Event {
protected final EventType type;
protected Object[] data;
protected final int idPosition;
public Event(EventType type, Object[] data, int idPosition) {
this.type = type;
this.data = data;
this.idPosition = idPosition;
}
public Object[] getData() {
return data;
}
public void setData(Object[] data) {
this.data = data;
}
public EventType getType() {
return type;
}
public int getIdPosition() {
return idPosition;
}
}
protected static class Cache {
protected final InputSession inputSession;
public Cache(InputSession inputSession) {
this.inputSession = inputSession;
}
}
}