/*
* *************************************************************************************
* Copyright (C) 2008 EsperTech, Inc. All rights reserved. *
* http://esper.codehaus.org *
* 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.multithread;
import junit.framework.TestCase;
import com.espertech.esper.client.*;
import com.espertech.esper.support.bean.SupportMarketDataBean;
import com.espertech.esper.support.util.SupportMTUpdateListener;
import com.espertech.esper.client.EventBean;
import java.util.concurrent.*;
import java.util.Arrays;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Test for multithread-safety of statements that are very similar that is share the same filter and views.
* <p>
* The engine shares locks between statements that share filters and views.
*/
public class TestMTStmtSharedView extends TestCase
{
private static String[] SYMBOLS = {"IBM", "MSFT", "GE"};
private EPServiceProvider engine;
public void setUp()
{
Configuration config = new Configuration();
config.getEngineDefaults().getThreading().setInternalTimerEnabled(false);
engine = EPServiceProviderManager.getProvider("TestMTStmtSharedView", config);
}
public void tearDown()
{
engine.destroy();
}
public void testSharedViews() throws Exception
{
trySend(4, 500, 100);
//trySend(2, 1000, 100);
//trySend(3, 2000, 20);
}
private void trySend(int numThreads, int numRepeats, int numStatements) throws Exception
{
// Create same statement X times
EPStatement stmt[] = new EPStatement[numStatements];
SupportMTUpdateListener listeners[] = new SupportMTUpdateListener[stmt.length];
for (int i = 0; i < stmt.length; i++)
{
stmt[i] = engine.getEPAdministrator().createEPL(
" select * " +
" from " + SupportMarketDataBean.class.getName() + ".std:groupwin(symbol).stat:uni(price)");
listeners[i] = new SupportMTUpdateListener();
stmt[i].addListener(listeners[i]);
}
// Start send threads
// Each threads sends each symbol with price = 0 to numRepeats
long startTime = System.currentTimeMillis();
ExecutorService threadPool = Executors.newFixedThreadPool(numThreads);
Future future[] = new Future[numThreads];
for (int i = 0; i < numThreads; i++)
{
Callable callable = new StmtSharedViewCallable(numRepeats, engine, SYMBOLS);
future[i] = threadPool.submit(callable);
}
// Shut down
threadPool.shutdown();
threadPool.awaitTermination(10, TimeUnit.SECONDS);
for (int i = 0; i < numThreads; i++)
{
assertTrue((Boolean) future[i].get());
}
long endTime = System.currentTimeMillis();
long delta = endTime - startTime;
assertTrue("delta=" + delta + " not less then 5 sec", delta < 5000); // should take less then 5 seconds even for 100 statements as they need to share resources thread-safely
// Assert results
for (SupportMTUpdateListener listener : listeners)
{
assertEquals(numRepeats * numThreads * SYMBOLS.length, listener.getNewDataList().size());
EventBean[] newDataLast = listener.getNewDataList().get(listener.getNewDataList().size() - 1);
assertEquals(1, newDataLast.length);
EventBean result = newDataLast[0];
assertEquals(numRepeats * numThreads, ((Long) result.get("datapoints")).longValue());
assertTrue(Arrays.asList(SYMBOLS).contains(result.get("symbol")));
assertEquals(sumToN(numRepeats) * numThreads, result.get("total"));
listener.reset();
}
for (int i = 0; i < stmt.length; i++)
{
stmt[i].stop();
}
}
private double sumToN(int N)
{
double sum = 0;
for (int i = 0; i < N; i++)
{
sum += i;
}
return sum;
}
private static Log log = LogFactory.getLog(TestMTStmtSharedView.class);
}