/**
* 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.util.HashSet;
import java.util.Set;
import net.sf.ehcache.CacheManager;
import org.fudgemsg.FudgeContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.opengamma.engine.ComputationTargetSpecification;
import com.opengamma.engine.value.ComputedValue;
import com.opengamma.engine.value.ValueProperties;
import com.opengamma.engine.value.ValuePropertyNames;
import com.opengamma.engine.value.ValueSpecification;
import com.opengamma.id.UniqueId;
import com.opengamma.transport.DirectFudgeConnection;
import com.opengamma.util.ehcache.EHCacheUtils;
import com.opengamma.util.fudgemsg.OpenGammaFudgeContext;
import com.opengamma.util.money.Currency;
import com.opengamma.util.test.TestGroup;
/**
* Test.
*/
@Test(groups = {TestGroup.UNIT, "ehcache"})
public class ReleaseCacheMessageTest {
private static final Logger s_logger = LoggerFactory.getLogger(ReleaseCacheMessageTest.class);
private static final FudgeContext s_fudgeContext = OpenGammaFudgeContext.getInstance();
private CacheManager _cacheManager;
@BeforeClass
public void setUpClass() {
_cacheManager = EHCacheUtils.createTestCacheManager(getClass());
}
@AfterClass
public void tearDownClass() {
EHCacheUtils.shutdownQuiet(_cacheManager);
}
@BeforeMethod
public void setUp() {
EHCacheUtils.clear(_cacheManager);
}
//-------------------------------------------------------------------------
private static class ReportingBinaryDataStoreFactory implements BinaryDataStoreFactory {
private final Set<ViewComputationCacheKey> _cachesCreated = new HashSet<ViewComputationCacheKey>();
private final Set<ViewComputationCacheKey> _cachesDestroyed = new HashSet<ViewComputationCacheKey>();
private final String _name;
public ReportingBinaryDataStoreFactory(final String name) {
_name = name;
}
@Override
public BinaryDataStore createDataStore(final ViewComputationCacheKey cacheKey) {
s_logger.debug("{} cache created - {}", _name, cacheKey);
_cachesCreated.add(cacheKey);
return new InMemoryBinaryDataStore() {
@Override
public void delete() {
s_logger.debug("{} cache destroyed - {}", _name, cacheKey);
_cachesDestroyed.add(cacheKey);
super.delete();
}
};
}
}
//-------------------------------------------------------------------------
private void putStuffIntoCache(final ViewComputationCache cache) {
final ComputationTargetSpecification target = ComputationTargetSpecification.of(Currency.USD);
final ValueSpecification valueSpec = new ValueSpecification("Value", target, ValueProperties.with(ValuePropertyNames.FUNCTION, "function ID").get());
cache.putPrivateValue(new ComputedValue(valueSpec, "Bar"));
cache.putSharedValue(new ComputedValue(valueSpec, "Bar"));
}
private void pause () {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
}
private void delayedEquals(final int expectedSize, final Set<ViewComputationCacheKey> set) {
for (int i = 0; i < 5; i++) {
if (expectedSize == set.size()) {
return;
} else if (expectedSize < set.size()) {
break;
}
pause ();
}
Assert.fail("expected=" + expectedSize + ", was=" + set.size());
}
@Test
public void testCacheReleaseMessage() {
final ReportingBinaryDataStoreFactory privateServerStore = new ReportingBinaryDataStoreFactory("server private");
final ReportingBinaryDataStoreFactory sharedStore = new ReportingBinaryDataStoreFactory("server shared");
final DefaultViewComputationCacheSource cacheSource = new DefaultViewComputationCacheSource(
new InMemoryIdentifierMap(), s_fudgeContext, new DefaultFudgeMessageStoreFactory(privateServerStore,
s_fudgeContext), new DefaultFudgeMessageStoreFactory(sharedStore, s_fudgeContext));
s_logger.info("Creating server local caches");
UniqueId viewCycle1Id = UniqueId.of("Test", "ViewCycle", "1");
UniqueId viewCycle2Id = UniqueId.of("Test", "ViewCycle", "2");
UniqueId viewCycle3Id = UniqueId.of("Test", "ViewCycle", "3");
UniqueId viewCycle4Id = UniqueId.of("Test", "ViewCycle", "4");
putStuffIntoCache(cacheSource.getCache(viewCycle1Id, "Config 1"));
putStuffIntoCache(cacheSource.getCache(viewCycle1Id, "Config 2"));
putStuffIntoCache(cacheSource.getCache(viewCycle2Id, "Config 1"));
putStuffIntoCache(cacheSource.getCache(viewCycle2Id, "Config 2"));
putStuffIntoCache(cacheSource.getCache(viewCycle3Id, "Config 1"));
putStuffIntoCache(cacheSource.getCache(viewCycle3Id, "Config 2"));
putStuffIntoCache(cacheSource.getCache(viewCycle4Id, "Config 1"));
putStuffIntoCache(cacheSource.getCache(viewCycle4Id, "Config 2"));
assertEquals(8, privateServerStore._cachesCreated.size());
assertEquals(0, privateServerStore._cachesDestroyed.size());
assertEquals(8, sharedStore._cachesCreated.size());
assertEquals(0, sharedStore._cachesDestroyed.size());
s_logger.info("Releasing server local caches");
cacheSource.releaseCaches(viewCycle1Id);
assertEquals(2, privateServerStore._cachesDestroyed.size());
assertEquals(2, sharedStore._cachesDestroyed.size());
cacheSource.releaseCaches(viewCycle3Id);
assertEquals(4, privateServerStore._cachesDestroyed.size());
assertEquals(4, sharedStore._cachesDestroyed.size());
final ViewComputationCacheServer server = new ViewComputationCacheServer(cacheSource);
final ReportingBinaryDataStoreFactory privateClientStore = new ReportingBinaryDataStoreFactory("client private");
final DirectFudgeConnection conduit = new DirectFudgeConnection(cacheSource.getFudgeContext());
conduit.connectEnd1(server);
final RemoteViewComputationCacheSource remoteSource = new RemoteViewComputationCacheSource(new RemoteCacheClient(
conduit.getEnd2()), new DefaultFudgeMessageStoreFactory(privateClientStore, s_fudgeContext), _cacheManager);
s_logger.info("Using server cache at remote client");
putStuffIntoCache(remoteSource.getCache(viewCycle2Id, "Config 1"));
assertEquals(8, privateServerStore._cachesCreated.size());
assertEquals(8, sharedStore._cachesCreated.size());
assertEquals(1, privateClientStore._cachesCreated.size());
assertEquals(0, privateClientStore._cachesDestroyed.size());
s_logger.info("Releasing cache used by remote client");
cacheSource.releaseCaches(viewCycle2Id);
assertEquals(6, privateServerStore._cachesDestroyed.size());
assertEquals(6, sharedStore._cachesDestroyed.size());
delayedEquals(1, privateClientStore._cachesDestroyed);
s_logger.info("Releasing cache not used by remote client");
cacheSource.releaseCaches(viewCycle4Id);
assertEquals(8, privateServerStore._cachesDestroyed.size());
assertEquals(8, sharedStore._cachesDestroyed.size());
for (int i = 0; i < 5; i++) {
assertEquals(1, privateClientStore._cachesDestroyed.size());
pause ();
}
s_logger.info("Using new cache at remote client");
UniqueId viewCycle5Id = UniqueId.of("Test", "ViewCycle", "5");
putStuffIntoCache(remoteSource.getCache(viewCycle5Id, "Config 1"));
assertEquals(9, privateServerStore._cachesCreated.size());
assertEquals(9, sharedStore._cachesCreated.size());
assertEquals(2, privateClientStore._cachesCreated.size());
s_logger.info("Releasing cache used by remote client");
cacheSource.releaseCaches(viewCycle5Id);
assertEquals(9, privateServerStore._cachesDestroyed.size());
assertEquals(9, sharedStore._cachesDestroyed.size());
delayedEquals(2, privateClientStore._cachesDestroyed);
}
}