/** * Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.engine.cache; import static org.testng.AssertJUnit.assertEquals; import java.io.File; import java.io.IOException; import java.util.HashSet; import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import org.apache.commons.io.FileUtils; import org.fudgemsg.FudgeContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testng.annotations.AfterClass; import org.testng.annotations.AfterMethod; import org.testng.annotations.Test; import com.opengamma.OpenGammaRuntimeException; import com.opengamma.engine.value.ValueSpecification; import com.opengamma.util.fudgemsg.OpenGammaFudgeContext; import com.opengamma.util.test.TestGroup; import com.sleepycat.je.Environment; import com.sleepycat.je.EnvironmentConfig; // TODO kirk 2010-08-02 -- We should have concurrency performance tests as well. // The correctness is largely taken care of by the database transactions, which go // far beyond normal synchronization in handling concurrency. /** * A simple unit test of {@link BerkeleyDBIdentifierMap}. */ @Test(groups = TestGroup.INTEGRATION) public class BerkeleyDBValueIdentifierMapTest extends AbstractIdentifierMapTest { private static final Logger s_logger = LoggerFactory.getLogger(BerkeleyDBValueIdentifierMapTest.class); private static Set<File> s_dbDirsToDelete = new HashSet<File>(); private Environment _currDBEnvironment; protected File createDbDir(String methodName) { File tmpDir = new File(System.getProperty("java.io.tmpdir")); File dbDir = new File(tmpDir, "BerkeleyDBValueSpecification-" + System.currentTimeMillis() + "-" + methodName); dbDir.mkdirs(); s_dbDirsToDelete.add(dbDir); return dbDir; } protected Environment createDbEnvironment(File dbDir) { EnvironmentConfig envConfig = new EnvironmentConfig(); envConfig.setAllowCreate(true); envConfig.setTransactional(true); Environment dbEnvironment = new Environment(dbDir, envConfig); return dbEnvironment; } @AfterClass(alwaysRun = true) public static void deleteDbDirs() { for (File f : s_dbDirsToDelete) { try { s_logger.info("Deleting temp directory {}", f); FileUtils.deleteDirectory(f); } catch (IOException ioe) { s_logger.warn("Unable to recursively delete directory {}", f); // Just swallow it. } } s_dbDirsToDelete.clear(); } @Override protected IdentifierMap createIdentifierMap(String testName) { File dbDir = createDbDir("simpleOperation"); _currDBEnvironment = createDbEnvironment(dbDir); FudgeContext fudgeContext = OpenGammaFudgeContext.getInstance(); BerkeleyDBIdentifierMap idMap = new BerkeleyDBIdentifierMap(_currDBEnvironment, fudgeContext); idMap.start(); return idMap; } @AfterMethod public void tearDownEnvironment() { if (_currDBEnvironment != null) { _currDBEnvironment.close(); _currDBEnvironment = null; } } @Test public void reloadPreservesMaxValue() throws IOException { File dbDir = createDbDir("reloadPreservesMaxValue"); Environment dbEnvironment = createDbEnvironment(dbDir); FudgeContext fudgeContext = OpenGammaFudgeContext.getInstance(); BerkeleyDBIdentifierMap idSource = new BerkeleyDBIdentifierMap(dbEnvironment, fudgeContext); idSource.start(); String valueName = "value-5"; ValueSpecification valueSpec = getValueSpec(valueName); long initialIdentifier = idSource.getIdentifier(valueSpec); // Cycle everything to simulate a clean shutdown and restart. idSource.stop(); dbEnvironment.close(); dbEnvironment = createDbEnvironment(dbDir); idSource = new BerkeleyDBIdentifierMap(dbEnvironment, fudgeContext); idSource.start(); // Check we get the same thing back. valueName = "value-5"; valueSpec = getValueSpec(valueName); long identifier = idSource.getIdentifier(valueSpec); assertEquals(initialIdentifier, identifier); // Check that the next one is the previous max + 1 valueName = "value-99999"; valueSpec = getValueSpec(valueName); identifier = idSource.getIdentifier(valueSpec); assertEquals(initialIdentifier + 1, identifier); } @Test(timeOut = 30000) public void interruptThread() throws Throwable { final ExecutorService threads = Executors.newSingleThreadExecutor(); try { final Thread main = Thread.currentThread(); final Runnable interrupter = new Runnable() { @Override public void run() { try { Thread.sleep(1000); main.interrupt(); } catch (InterruptedException e) { throw new OpenGammaRuntimeException("Interrupted", e); } } }; threads.submit(interrupter); int count = 0; do { try { getPerformanceTest(); } catch (OpenGammaRuntimeException e) { assertEquals("Interrupted", e.getMessage()); count++; if (count <= 5) { threads.submit(interrupter); } else { break; } } finally { tearDownEnvironment(); } } while (true); } finally { threads.shutdown(); Thread.interrupted(); threads.awaitTermination(5, TimeUnit.SECONDS); } } }