/*
***************************************************************************************
* 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.epl.variable;
import com.espertech.esper.core.start.EPStatementStartMethod;
import com.espertech.esper.core.support.SupportEngineImportServiceFactory;
import com.espertech.esper.core.support.SupportEventAdapterService;
import com.espertech.esper.epl.core.EngineImportService;
import com.espertech.esper.schedule.SchedulingServiceImpl;
import com.espertech.esper.timer.TimeSourceServiceImpl;
import junit.framework.TestCase;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
public class TestVariableService extends TestCase {
private VariableService service;
private EngineImportService engineImportService;
public void setUp() {
service = new VariableServiceImpl(10000, new SchedulingServiceImpl(new TimeSourceServiceImpl()), SupportEventAdapterService.getService(), null);
engineImportService = SupportEngineImportServiceFactory.make();
}
public void testPerfSetVersion() {
long start = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
service.setLocalVersion();
}
long end = System.currentTimeMillis();
long delta = (end - start);
assertTrue("delta=" + delta, delta < 100);
}
public void testMultithreadedZero() throws Exception {
tryMT(4, 5000, 8);
}
public void testMultithreadedOne() throws Exception {
tryMT(2, 10000, 4);
}
// Start N threads
// each thread performs X loops
// each loop gets a unique number Y from a shared object and performs setVersion in the synchronized block
// then the thread performs reads, write and read of shared variables, writing the number Y
// ==> the reads should not see any higher number (unless watemarks reached)
// ==> reads should produce the exact same result unless setVersion called
private void tryMT(int numThreads, int numLoops, int numVariables) throws Exception {
VariableVersionCoord coord = new VariableVersionCoord(service);
// create variables
String[] variables = new String[numVariables];
for (int i = 0; i < numVariables; i++) {
char c = 'A';
c += i;
variables[i] = Character.toString(c);
service.createNewVariable(null, variables[i], Integer.class.getName(), false, false, false, 0, engineImportService);
service.allocateVariableState(variables[i], EPStatementStartMethod.DEFAULT_AGENT_INSTANCE_ID, null, false);
}
ExecutorService threadPool = Executors.newFixedThreadPool(numThreads);
VariableServiceCallable[] callables = new VariableServiceCallable[numThreads];
Future future[] = new Future[numThreads];
for (int i = 0; i < numThreads; i++) {
callables[i] = new VariableServiceCallable(variables, service, coord, numLoops);
future[i] = threadPool.submit(callables[i]);
}
threadPool.shutdown();
threadPool.awaitTermination(10, TimeUnit.SECONDS);
for (int i = 0; i < numThreads; i++) {
assertTrue((Boolean) future[i].get());
}
//System.out.println(service.toString());
// Verify results per thread
for (int i = 0; i < callables.length; i++) {
int[][] result = callables[i].getResults();
int[] marks = callables[i].getMarks();
}
}
public void testReadWrite() throws Exception {
assertNull(service.getReader("a", EPStatementStartMethod.DEFAULT_AGENT_INSTANCE_ID));
service.createNewVariable(null, "a", Long.class.getName(), false, false, false, 100L, engineImportService);
service.allocateVariableState("a", EPStatementStartMethod.DEFAULT_AGENT_INSTANCE_ID, null, false);
VariableReader reader = service.getReader("a", EPStatementStartMethod.DEFAULT_AGENT_INSTANCE_ID);
assertEquals(Long.class, reader.getVariableMetaData().getType());
assertEquals(100L, reader.getValue());
service.write(reader.getVariableMetaData().getVariableNumber(), EPStatementStartMethod.DEFAULT_AGENT_INSTANCE_ID, 101L);
service.commit();
assertEquals(100L, reader.getValue());
service.setLocalVersion();
assertEquals(101L, reader.getValue());
service.write(reader.getVariableMetaData().getVariableNumber(), EPStatementStartMethod.DEFAULT_AGENT_INSTANCE_ID, 102L);
service.commit();
assertEquals(101L, reader.getValue());
service.setLocalVersion();
assertEquals(102L, reader.getValue());
}
public void testRollover() throws Exception {
service = new VariableServiceImpl(VariableServiceImpl.ROLLOVER_READER_BOUNDARY - 100, 10000, new SchedulingServiceImpl(new TimeSourceServiceImpl()), SupportEventAdapterService.getService(), null);
String[] variables = "a,b,c,d".split(",");
VariableReader readers[] = new VariableReader[variables.length];
for (int i = 0; i < variables.length; i++) {
service.createNewVariable(null, variables[i], Long.class.getName(), false, false, false, 100L, engineImportService);
service.allocateVariableState(variables[i], EPStatementStartMethod.DEFAULT_AGENT_INSTANCE_ID, null, false);
readers[i] = service.getReader(variables[i], EPStatementStartMethod.DEFAULT_AGENT_INSTANCE_ID);
}
for (int i = 0; i < 1000; i++) {
for (int j = 0; j < variables.length; j++) {
service.write(readers[j].getVariableMetaData().getVariableNumber(), EPStatementStartMethod.DEFAULT_AGENT_INSTANCE_ID, 100L + i);
service.commit();
}
readCompare(variables, 100L + i);
}
}
private void readCompare(String[] variables, Object value) {
service.setLocalVersion();
for (int i = 0; i < variables.length; i++) {
assertEquals(value, service.getReader(variables[i], EPStatementStartMethod.DEFAULT_AGENT_INSTANCE_ID).getValue());
}
}
public void testInvalid() throws Exception {
service.createNewVariable(null, "a", Long.class.getName(), false, false, false, null, engineImportService);
service.allocateVariableState("a", EPStatementStartMethod.DEFAULT_AGENT_INSTANCE_ID, null, false);
assertNull(service.getReader("dummy", EPStatementStartMethod.DEFAULT_AGENT_INSTANCE_ID));
try {
service.createNewVariable(null, "a", Long.class.getName(), false, false, false, null, engineImportService);
fail();
} catch (VariableExistsException e) {
assertEquals("Variable by name 'a' has already been created", e.getMessage());
}
}
}