/* *************************************************************************************** * 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.client.SupportConfigFactory; import junit.framework.TestCase; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.List; import java.util.Queue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingDeque; public class TestTableMTGroupedFAFReadFAFWriteChain extends TestCase { private static final Logger log = LoggerFactory.getLogger(TestTableMTGroupedFAFReadFAFWriteChain.class); private EPServiceProvider epService; public void setUp() { Configuration config = SupportConfigFactory.getConfiguration(); epService = EPServiceProviderManager.getDefaultProvider(config); epService.initialize(); } /** * Tests fire-and-forget lock cleanup: * create table MyTable(key int primary key, p0 int) (5 props) * * The following threads are in a chain communicating by queue holding key values: * - Insert: populates MyTable={key=N, p0=N}, last row indicated by -1 * - Select-Table-Access: select MyTable[N].p0 from SupportBean */ public void testMT() throws Exception { tryMT(1000); } private void tryMT(int numInserted) throws Exception { String epl = "create table MyTable (key int primary key, p0 int);"; epService.getEPAdministrator().getDeploymentAdmin().parseDeploy(epl); List<BaseRunnable> runnables = new ArrayList<BaseRunnable>(); LinkedBlockingDeque<Integer> insertOutQ = new LinkedBlockingDeque<Integer>(); InsertRunnable insert = new InsertRunnable(epService, numInserted, insertOutQ); runnables.add(insert); LinkedBlockingDeque<Integer> selectOutQ = new LinkedBlockingDeque<Integer>(); SelectRunnable select = new SelectRunnable(epService, insertOutQ, selectOutQ); runnables.add(select); LinkedBlockingDeque<Integer> updateOutQ = new LinkedBlockingDeque<Integer>(); UpdateRunnable update = new UpdateRunnable(epService, selectOutQ, updateOutQ); runnables.add(update); LinkedBlockingDeque<Integer> deleteOutQ = new LinkedBlockingDeque<Integer>(); DeleteRunnable delete = new DeleteRunnable(epService, updateOutQ, deleteOutQ); runnables.add(delete); // start Thread[] threads = new Thread[runnables.size()]; for (int i = 0; i < runnables.size(); i++) { threads[i] = new Thread(runnables.get(i)); threads[i].start(); } // join for (Thread t : threads) { t.join(); } // assert for (BaseRunnable runnable : runnables) { assertNull(runnable.getException()); assertEquals("failed for " + runnable, numInserted + 1, runnable.getNumberOfOperations()); // account for -1 indicator } } public abstract static class BaseRunnable implements Runnable { protected final EPServiceProvider epService; protected final String workName; protected int numberOfOperations; private Exception exception; protected BaseRunnable(EPServiceProvider epService, String workName) { this.epService = epService; this.workName = workName; } public abstract void runWork() throws InterruptedException; public final void run() { log.info("Starting " + workName); try { runWork(); } catch (Exception ex) { log.error("Exception encountered: " + ex.getMessage(), ex); exception = ex; } log.info("Completed " + workName); } public Exception getException() { return exception; } public int getNumberOfOperations() { return numberOfOperations; } } public static class InsertRunnable extends BaseRunnable { private final int numInserted; private final Queue<Integer> stageOutput; public InsertRunnable(EPServiceProvider epService, int numInserted, Queue<Integer> stageOutput) { super(epService, "Insert"); this.numInserted = numInserted; this.stageOutput = stageOutput; } public void runWork() { EPOnDemandPreparedQueryParameterized q = epService.getEPRuntime().prepareQueryWithParameters("insert into MyTable (key, p0) values (?, ?)"); for (int i = 0; i < numInserted; i++) { process(q, i); } process(q, -1); } private void process(EPOnDemandPreparedQueryParameterized q, int id) { q.setObject(1, id); q.setObject(2, id); epService.getEPRuntime().executeQuery(q); stageOutput.add(id); numberOfOperations++; } } public static class SelectRunnable extends BaseRunnable { private final BlockingQueue<Integer> stageInput; private final Queue<Integer> stageOutput; public SelectRunnable(EPServiceProvider epService, BlockingQueue<Integer> stageInput, Queue<Integer> stageOutput) { super(epService, "Select"); this.stageInput = stageInput; this.stageOutput = stageOutput; } public void runWork() throws InterruptedException { String epl = "select p0 from MyTable where key = ?"; EPOnDemandPreparedQueryParameterized q = epService.getEPRuntime().prepareQueryWithParameters(epl); while (true) { int id = stageInput.take(); process(q, id); if (id == -1) { break; } } } private void process(EPOnDemandPreparedQueryParameterized q, int id) { q.setObject(1, id); EPOnDemandQueryResult result = epService.getEPRuntime().executeQuery(q); assertEquals("failed for id " + id, 1, result.getArray().length); assertEquals(id, result.getArray()[0].get("p0")); stageOutput.add(id); numberOfOperations++; } } public static class UpdateRunnable extends BaseRunnable { private final BlockingQueue<Integer> stageInput; private final Queue<Integer> stageOutput; public UpdateRunnable(EPServiceProvider epService, BlockingQueue<Integer> stageInput, Queue<Integer> stageOutput) { super(epService, "Update"); this.stageInput = stageInput; this.stageOutput = stageOutput; } public void runWork() throws InterruptedException { String epl = "update MyTable set p0 = 99999999 where key = ?"; EPOnDemandPreparedQueryParameterized q = epService.getEPRuntime().prepareQueryWithParameters(epl); while (true) { int id = stageInput.take(); process(q, id); if (id == -1) { break; } } } private void process(EPOnDemandPreparedQueryParameterized q, int id) { q.setObject(1, id); epService.getEPRuntime().executeQuery(q); stageOutput.add(id); numberOfOperations++; } } public static class DeleteRunnable extends BaseRunnable { private final BlockingQueue<Integer> stageInput; private final Queue<Integer> stageOutput; public DeleteRunnable(EPServiceProvider epService, BlockingQueue<Integer> stageInput, Queue<Integer> stageOutput) { super(epService, "Delete"); this.stageInput = stageInput; this.stageOutput = stageOutput; } public void runWork() throws InterruptedException { String epl = "delete from MyTable where key = ?"; EPOnDemandPreparedQueryParameterized q = epService.getEPRuntime().prepareQueryWithParameters(epl); while (true) { int id = stageInput.take(); process(q, id); if (id == -1) { break; } } } private void process(EPOnDemandPreparedQueryParameterized q, int id) { q.setObject(1, id); epService.getEPRuntime().executeQuery(q); stageOutput.add(id); numberOfOperations++; } } }