/*
* *************************************************************************************
* 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 com.espertech.esper.client.Configuration;
import com.espertech.esper.client.EPServiceProvider;
import com.espertech.esper.client.EPServiceProviderManager;
import com.espertech.esper.support.client.SupportConfigFactory;
import junit.framework.TestCase;
import java.util.Random;
/**
* Test for multithread-safety for a simple aggregation case using count(*).
*/
public class TestMTStmtNamedWindowMultiple extends TestCase
{
private EPServiceProvider engine;
public void setUp()
{
Configuration config = SupportConfigFactory.getConfiguration();
config.addEventType("OrderEvent", OrderEvent.class.getName());
config.addEventType("OrderCancelEvent", OrderCancelEvent.class.getName());
engine = EPServiceProviderManager.getProvider("TestMTStmtNamedWindowMultiple", config);
}
public void tearDown()
{
engine.destroy();
}
public void testInsertDeleteSelect() throws Exception
{
tryCount(10, 500, 3);
}
public void tryCount(int numUsers, int numOrders, int numThreads) throws Exception
{
for (int i = 0; i < numUsers; i++)
{
engine.getEPAdministrator().createEPL("@Name('create_" + i + "') create window MyWindow_" + i + ".std:unique(orderId) as select * from OrderEvent");
engine.getEPAdministrator().createEPL("@Name('insert_" + i + "') insert into MyWindow_" + i + " select * from OrderEvent(userId = 'user" + i + "')");
engine.getEPAdministrator().createEPL("on OrderCancelEvent as d delete from MyWindow_" + i + " w where w.orderId = d.orderId");
engine.getEPAdministrator().createEPL("@Name('select_" + i + "') on OrderEvent as s select sum(w.price) from MyWindow_" + i + " w where w.side = s.side group by w.side");
}
RunnableOrderSim[] runnables = new RunnableOrderSim[numThreads];
Thread[] threads = new Thread[numThreads];
for (int i = 0; i < numThreads; i++)
{
runnables[i] = new RunnableOrderSim(engine, i, numUsers, numOrders);
threads[i] = new Thread(runnables[i]);
}
for (int i = 0; i < threads.length; i++)
{
threads[i].start();
}
for (int i = 0; i < threads.length; i++)
{
threads[i].join();
assertTrue(runnables[i].getStatus());
}
}
public class RunnableOrderSim implements Runnable
{
private final EPServiceProvider engine;
private final int threadId;
private final int numUsers;
private final int numOrders;
private final Random random = new Random();
private boolean status;
public RunnableOrderSim(EPServiceProvider engine, int threadId, int numUsers, int numOrders)
{
this.engine = engine;
this.threadId = threadId;
this.numUsers = numUsers;
this.numOrders = numOrders;
}
public void run()
{
String[] orderIds = new String[10];
for (int i = 0; i < orderIds.length; i++)
{
orderIds[i] = "order_" + i + "_" + threadId;
}
for (int i = 0; i < numOrders; i++)
{
if (random.nextInt() % 3 == 0)
{
String orderId = orderIds[random.nextInt(orderIds.length)];
for (int j = 0; j < numUsers; j++)
{
OrderCancelEvent theEvent = new OrderCancelEvent("user" + j, orderId);
engine.getEPRuntime().sendEvent(theEvent);
}
}
else
{
String orderId = orderIds[random.nextInt(orderIds.length)];
for (int j = 0; j < numUsers; j++)
{
OrderEvent theEvent = new OrderEvent("user" + j, orderId, 1000, "B");
engine.getEPRuntime().sendEvent(theEvent);
}
}
}
status = true;
}
public boolean getStatus()
{
return status;
}
}
public class OrderEvent
{
private final String userId;
private final String orderId;
private final double price;
private final String side;
public OrderEvent(String userId, String orderId, double price, String side)
{
this.userId = userId;
this.orderId = orderId;
this.price = price;
this.side = side;
}
public String getUserId()
{
return userId;
}
public String getOrderId()
{
return orderId;
}
public double getPrice()
{
return price;
}
public String getSide()
{
return side;
}
}
public class OrderCancelEvent
{
private final String userId;
private final String orderId;
public OrderCancelEvent(String userId, String orderId)
{
this.userId = userId;
this.orderId = orderId;
}
public String getUserId()
{
return userId;
}
public String getOrderId()
{
return orderId;
}
}
}