/* *************************************************************************************** * 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.nwtable; import com.espertech.esper.client.*; import com.espertech.esper.supportregression.bean.SupportBean; import com.espertech.esper.supportregression.bean.SupportBean_S0; import com.espertech.esper.supportregression.client.SupportConfigFactory; import junit.framework.TestCase; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class TestTableMTUngroupedAccessReadInotTableWriteIterate extends TestCase { private static final Logger log = LoggerFactory.getLogger(TestTableMTUngroupedAccessReadInotTableWriteIterate.class); private EPServiceProvider epService; public void setUp() { Configuration config = SupportConfigFactory.getConfiguration(); config.addEventType(SupportBean.class); config.addEventType(SupportBean_S0.class); epService = EPServiceProviderManager.getDefaultProvider(config); epService.initialize(); } /** * Proof that multiple threads iterating the same statement * can safely access a row that is currently changing. */ public void testMT() throws Exception { tryMT(3, 3); } private void tryMT(int numReadThreads, int numSeconds) throws Exception { String eplCreateVariable = "create table vartotal (s0 sum(int), s1 sum(double), s2 sum(long))"; epService.getEPAdministrator().createEPL(eplCreateVariable); String eplInto = "into table vartotal select sum(intPrimitive) as s0, " + "sum(doublePrimitive) as s1, sum(longPrimitive) as s2 from SupportBean"; epService.getEPAdministrator().createEPL(eplInto); epService.getEPRuntime().sendEvent(makeSupportBean("E", 1, 1, 1)); EPStatement iterateStatement = epService.getEPAdministrator().createEPL("select vartotal.s0 as c0, vartotal.s1 as c1, vartotal.s2 as c2 from SupportBean_S0#lastevent"); epService.getEPRuntime().sendEvent(new SupportBean_S0(0)); // setup writer WriteRunnable writeRunnable = new WriteRunnable(epService); Thread writeThread = new Thread(writeRunnable); // setup readers Thread[] readThreads = new Thread[numReadThreads]; ReadRunnable[] readRunnables = new ReadRunnable[numReadThreads]; for (int i = 0; i < readThreads.length; i++) { readRunnables[i] = new ReadRunnable(iterateStatement); readThreads[i] = new Thread(readRunnables[i]); } // start for (Thread readThread : readThreads) { readThread.start(); } writeThread.start(); // wait Thread.sleep(numSeconds * 1000); // shutdown writeRunnable.setShutdown(true); for (ReadRunnable readRunnable : readRunnables) { readRunnable.setShutdown(true); } // join log.info("Waiting for completion"); writeThread.join(); for (Thread readThread : readThreads) { readThread.join(); } // assert assertNull(writeRunnable.getException()); assertTrue(writeRunnable.numEvents > 100); for (ReadRunnable readRunnable : readRunnables) { assertNull(readRunnable.getException()); assertTrue(readRunnable.numQueries > 100); } } private static SupportBean makeSupportBean(String theString, int intPrimitive, double doublePrimitive, long longPrimitive) { SupportBean b = new SupportBean(theString, intPrimitive); b.setDoublePrimitive(doublePrimitive); b.setLongPrimitive(longPrimitive); return b; } public static class WriteRunnable implements Runnable { private final EPServiceProvider epService; private RuntimeException exception; private boolean shutdown; private int numEvents; public WriteRunnable(EPServiceProvider epService) { this.epService = epService; } public void setShutdown(boolean shutdown) { this.shutdown = shutdown; } public void run() { log.info("Started event send for write"); try { while(!shutdown) { epService.getEPRuntime().sendEvent(makeSupportBean("E", 1, 1, 1)); numEvents++; } } catch (RuntimeException ex) { log.error("Exception encountered: " + ex.getMessage(), ex); exception = ex; } log.info("Completed event send for write"); } public RuntimeException getException() { return exception; } } public static class ReadRunnable implements Runnable { private final EPStatement iterateStatement; private RuntimeException exception; private boolean shutdown; private int numQueries; public ReadRunnable(EPStatement iterateStatement) { this.iterateStatement = iterateStatement; } public void setShutdown(boolean shutdown) { this.shutdown = shutdown; } public void run() { log.info("Started event send for read"); try { while(!shutdown) { SafeIterator<EventBean> iterator = iterateStatement.safeIterator(); try { EventBean event = iterator.next(); int c0 = (Integer) event.get("c0"); assertEquals((double) c0, event.get("c1")); assertEquals((long) c0, event.get("c2")); } finally { iterator.close(); } numQueries++; } } catch (RuntimeException ex) { log.error("Exception encountered: " + ex.getMessage(), ex); exception = ex; } log.info("Completed event send for read"); } public RuntimeException getException() { return exception; } } }