/*
***************************************************************************************
* Copyright (C) 2006 EsperTech, Inc. All rights reserved. *
* http://www.espertech.com/esper *
* 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.regression.multithread;
import com.espertech.esper.client.*;
import com.espertech.esper.client.scopetest.SupportUpdateListener;
import com.espertech.esper.client.time.CurrentTimeEvent;
import com.espertech.esper.supportregression.bean.SupportBean;
import com.espertech.esper.supportregression.client.SupportConfigFactory;
import junit.framework.TestCase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.Map;
public class TestMTContextSegmented extends TestCase
{
private static final Logger log = LoggerFactory.getLogger(TestMTContextSegmented.class);
private EPServiceProvider epService;
private SupportUpdateListener listener;
public void setUp()
{
Configuration config = SupportConfigFactory.getConfiguration();
config.addEventType("SupportBean", SupportBean.class);
epService = EPServiceProviderManager.getDefaultProvider(config);
epService.initialize();
listener = new SupportUpdateListener();
}
public void tearDown() {
listener = null;
}
public void testSegmentedContext() throws Exception
{
String[] choices = "A,B,C,D".split(",");
trySend(4, 1000, choices);
}
private void trySend(int numThreads, int numEvents, String[] choices) throws Exception
{
if (numEvents < choices.length) {
throw new IllegalArgumentException("Number of events must at least match number of choices");
}
epService.getEPRuntime().sendEvent(new CurrentTimeEvent(0));
epService.getEPAdministrator().createEPL("create variable boolean myvar = false");
epService.getEPAdministrator().createEPL("create context SegmentedByString as partition by theString from SupportBean");
EPStatement stmt = epService.getEPAdministrator().createEPL("context SegmentedByString select theString, count(*) - 1 as cnt from SupportBean output snapshot when myvar = true");
stmt.addListener(listener);
// preload - since concurrently sending same-category events an event can be dropped
for (int i = 0; i < choices.length; i++) {
epService.getEPRuntime().sendEvent(new SupportBean(choices[i], 0));
}
EventRunnable[] runnables = new EventRunnable[numThreads];
for (int i = 0; i < runnables.length; i++) {
runnables[i] = new EventRunnable(epService, numEvents, choices);
}
// start
Thread[] threads = new Thread[runnables.length];
for (int i = 0; i < runnables.length; i++) {
threads[i] = new Thread(runnables[i]);
threads[i].start();
}
// join
log.info("Waiting for completion");
for (int i = 0; i < runnables.length; i++) {
threads[i].join();
}
Map<String, Long> totals = new HashMap<String, Long>();
for (String choice : choices) {
totals.put(choice, 0L);
}
// verify
int sum = 0;
for (int i = 0; i < runnables.length; i++) {
assertNull(runnables[i].getException());
for (Map.Entry<String, Integer> entry : runnables[i].getTotals().entrySet()) {
Long current = totals.get(entry.getKey());
current += entry.getValue();
sum += entry.getValue();
totals.put(entry.getKey(), current);
//System.out.println("Thread " + i + " key " + entry.getKey() + " count " + entry.getValue());
}
}
assertEquals(numThreads * numEvents, sum);
epService.getEPRuntime().setVariableValue("myvar", true);
epService.getEPRuntime().sendEvent(new CurrentTimeEvent(10000));
EventBean[] result = listener.getLastNewData();
assertEquals(choices.length, result.length);
for (EventBean item : result) {
String theString = (String) item.get("theString");
Long count = (Long) item.get("cnt");
//System.out.println("String " + string + " count " + count);
assertEquals(count, totals.get(theString));
}
}
public static class EventRunnable implements Runnable {
private final EPServiceProvider epService;
private final int numEvents;
private final String[] choices;
private final Map<String, Integer> totals = new HashMap<String, Integer>();
private RuntimeException exception;
public EventRunnable(EPServiceProvider epService, int numEvents, String[] choices) {
this.epService = epService;
this.numEvents = numEvents;
this.choices = choices;
}
public void run() {
log.info("Started event send");
try {
for (int i = 0; i < numEvents; i++) {
String chosen = choices[i % choices.length];
epService.getEPRuntime().sendEvent(new SupportBean(chosen, 1));
Integer current = totals.get(chosen);
if (current == null) {
current = 0;
}
current += 1;
totals.put(chosen, current);
}
}
catch (RuntimeException ex) {
log.error("Exception encountered: " + ex.getMessage(), ex);
exception = ex;
}
log.info("Completed event send");
}
public RuntimeException getException() {
return exception;
}
public Map<String, Integer> getTotals() {
return totals;
}
}
}