/** * 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 static org.testng.AssertJUnit.assertFalse; import static org.testng.AssertJUnit.assertNotNull; import static org.testng.AssertJUnit.assertNull; import static org.testng.AssertJUnit.assertTrue; import java.util.ArrayList; import java.util.Arrays; import java.util.BitSet; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Random; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicBoolean; import org.fudgemsg.FudgeContext; import org.fudgemsg.FudgeMsg; import org.fudgemsg.MutableFudgeMsg; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testng.annotations.Test; import com.opengamma.engine.ComputationTargetSpecification; import com.opengamma.engine.cache.FudgeMessageStore; import com.opengamma.engine.cache.IdentifierMap; import com.opengamma.engine.cache.InMemoryViewComputationCacheSource; import com.opengamma.engine.cache.RemoteCacheClient; import com.opengamma.engine.cache.RemoteFudgeMessageStore; import com.opengamma.engine.cache.RemoteIdentifierMap; import com.opengamma.engine.cache.ViewComputationCacheKey; import com.opengamma.engine.cache.ViewComputationCacheServer; 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.fudgemsg.OpenGammaFudgeContext; import com.opengamma.util.test.TestGroup; /** * */ @Test(groups = TestGroup.INTEGRATION) public class RemoteCacheRequestResponseTest { private static final Logger s_logger = LoggerFactory.getLogger(RemoteCacheRequestResponseTest.class); private static final FudgeContext s_fudgeContext = OpenGammaFudgeContext.getInstance(); @Test(timeOut = 10000l) public void singleThreadSpecLookupDifferentIdentifierValues() { InMemoryViewComputationCacheSource cache = new InMemoryViewComputationCacheSource(s_fudgeContext); ViewComputationCacheServer server = new ViewComputationCacheServer(cache); DirectFudgeConnection conduit = new DirectFudgeConnection(cache.getFudgeContext()); RemoteCacheClient client = new RemoteCacheClient(conduit.getEnd1()); conduit.connectEnd2(server); IdentifierMap identifierMap = new RemoteIdentifierMap(client); final ValueSpecification[] valueSpec = new ValueSpecification[10]; for (int i = 0; i < valueSpec.length; i++) { valueSpec[i] = new ValueSpecification("Test Value", ComputationTargetSpecification.of(UniqueId.of("Kirk", "Value" + i)), ValueProperties.with(ValuePropertyNames.FUNCTION, "mockFunctionId").get()); } // Make single value calls s_logger.debug("Begin single value lookup"); final BitSet seenIds = new BitSet(); for (int i = 0; i < valueSpec.length; i++) { long id = identifierMap.getIdentifier(valueSpec[i]); assertTrue(id <= Integer.MAX_VALUE); assertFalse(seenIds.get((int) id)); seenIds.set((int) id); } s_logger.debug("End single value lookup"); // Make a bulk lookup call s_logger.debug("Begin bulk lookup"); final Map<ValueSpecification, Long> identifiers = identifierMap.getIdentifiers(Arrays.asList(valueSpec)); assertNotNull(identifiers); assertEquals(valueSpec.length, identifiers.size()); for (ValueSpecification spec : valueSpec) { assertTrue(identifiers.containsKey(spec)); assertTrue(seenIds.get((int) (long) identifiers.get(spec))); } s_logger.debug("End bulk lookup"); } @Test(timeOut = 10000l) public void singleThreadLookupDifferentIdentifierValuesRepeated() { InMemoryViewComputationCacheSource cache = new InMemoryViewComputationCacheSource(s_fudgeContext); ViewComputationCacheServer server = new ViewComputationCacheServer(cache); DirectFudgeConnection conduit = new DirectFudgeConnection(cache.getFudgeContext()); conduit.connectEnd2(server); RemoteCacheClient client = new RemoteCacheClient(conduit.getEnd1()); IdentifierMap identifierMap = new RemoteIdentifierMap(client); Map<String, Long> _idsByValueName = new HashMap<String, Long>(); for (int i = 0; i < 10; i++) { String valueName = "Value" + i; ValueSpecification valueSpec = new ValueSpecification("Test Value", ComputationTargetSpecification.of(UniqueId.of("Kirk", valueName)), ValueProperties.with(ValuePropertyNames.FUNCTION, "mockFunctionId").get()); long id = identifierMap.getIdentifier(valueSpec); _idsByValueName.put(valueName, id); } for (int i = 0; i < 10; i++) { String valueName = "Value" + i; ValueSpecification valueSpec = new ValueSpecification("Test Value", ComputationTargetSpecification.of(UniqueId.of("Kirk", valueName)), ValueProperties.with(ValuePropertyNames.FUNCTION, "mockFunctionId").get()); long id = identifierMap.getIdentifier(valueSpec); assertEquals(_idsByValueName.get(valueName), new Long(id)); } } @Test(timeOut = 30000l) public void multiThreadLookupDifferentIdentifierValuesRepeatedSharedClient() throws InterruptedException { InMemoryViewComputationCacheSource cache = new InMemoryViewComputationCacheSource(s_fudgeContext); ViewComputationCacheServer server = new ViewComputationCacheServer(cache); DirectFudgeConnection conduit1 = new DirectFudgeConnection(cache.getFudgeContext()); conduit1.connectEnd2(server); DirectFudgeConnection conduit2 = new DirectFudgeConnection(cache.getFudgeContext()); conduit2.connectEnd2(server); final RemoteCacheClient client = new RemoteCacheClient(conduit1.getEnd1(), conduit2.getEnd1()); final IdentifierMap identifierMap = new RemoteIdentifierMap(client); final ConcurrentMap<String, Long> _idsByValueName = new ConcurrentHashMap<String, Long>(); final Random rand = new Random(); final AtomicBoolean failed = new AtomicBoolean(false); List<Thread> threads = new ArrayList<Thread>(); for (int i = 0; i < 10; i++) { Thread t = new Thread(new Runnable() { @Override public void run() { try { for (int j = 0; j < 1000; j++) { int randomValue = rand.nextInt(100); String valueName = "Value" + randomValue; ValueSpecification valueSpec = new ValueSpecification("Test Value", ComputationTargetSpecification.of(UniqueId.of("Kirk", valueName)), ValueProperties.with(ValuePropertyNames.FUNCTION, "mockFunctionId").get()); long id = identifierMap.getIdentifier(valueSpec); Long previousValue = _idsByValueName.putIfAbsent(valueName, id); if (previousValue != null) { assertEquals(previousValue, new Long(id)); } } } catch (Exception e) { s_logger.error("Failed", e); failed.set(true); } } }); threads.add(t); } for (Thread t : threads) { t.start(); } for (Thread t : threads) { t.join(); } assertFalse("One thread failed. Check logs.", failed.get()); } @Test(timeOut = 30000l) public void multiThreadLookupDifferentIdentifierValuesRepeatedDifferentClient() throws InterruptedException { InMemoryViewComputationCacheSource cache = new InMemoryViewComputationCacheSource(s_fudgeContext); final ViewComputationCacheServer server = new ViewComputationCacheServer(cache); final ConcurrentMap<String, Long> _idsByValueName = new ConcurrentHashMap<String, Long>(); final Random rand = new Random(); final AtomicBoolean failed = new AtomicBoolean(false); List<Thread> threads = new ArrayList<Thread>(); for (int i = 0; i < 10; i++) { final DirectFudgeConnection conduit = new DirectFudgeConnection(cache.getFudgeContext()); conduit.connectEnd2(server); Thread t = new Thread(new Runnable() { @Override public void run() { final RemoteCacheClient client = new RemoteCacheClient(conduit.getEnd1()); final IdentifierMap identifierMap = new RemoteIdentifierMap(client); try { for (int j = 0; j < 1000; j++) { int randomValue = rand.nextInt(100); String valueName = "Value" + randomValue; ValueSpecification valueSpec = new ValueSpecification("Test Value", ComputationTargetSpecification.of(UniqueId.of("Kirk", valueName)), ValueProperties.with(ValuePropertyNames.FUNCTION, "mockFunctionId").get()); long id = identifierMap.getIdentifier(valueSpec); Long previousValue = _idsByValueName.putIfAbsent(valueName, id); if (previousValue != null) { assertEquals(previousValue, new Long(id)); } } } catch (Exception e) { s_logger.error("Failed", e); failed.set(true); } } }); threads.add(t); } for (Thread t : threads) { t.start(); } for (Thread t : threads) { t.join(); } assertFalse("One thread failed. Check logs.", failed.get()); } // @Test(timeout=10000l) @Test public void singleThreadPutLoad() throws InterruptedException { InMemoryViewComputationCacheSource cache = new InMemoryViewComputationCacheSource(s_fudgeContext); ViewComputationCacheServer server = new ViewComputationCacheServer(cache); DirectFudgeConnection conduit = new DirectFudgeConnection(cache.getFudgeContext()); conduit.connectEnd2(server); RemoteCacheClient client = new RemoteCacheClient(conduit.getEnd1()); FudgeMessageStore dataStore = new RemoteFudgeMessageStore(client, new ViewComputationCacheKey(UniqueId.of("Test", "ViewCycle1"), "Config1")); // Single value final MutableFudgeMsg inputValue1 = s_fudgeContext.newMessage(); for (int i = 0; i < 32; i++) { inputValue1.add(i, Integer.toString(i)); } long identifier1 = 1L; dataStore.put(identifier1, inputValue1); FudgeMsg outputValue = dataStore.get(identifier1); assertNotNull(outputValue); assertEquals(inputValue1.getAllFields(), outputValue.getAllFields()); outputValue = dataStore.get(identifier1 + 1); assertNull(outputValue); outputValue = dataStore.get(identifier1); assertNotNull(outputValue); assertEquals(inputValue1.getAllFields(), outputValue.getAllFields()); // Multiple value final MutableFudgeMsg inputValue2 = s_fudgeContext.newMessage(); for (int i = 32; i < 64; i++) { inputValue2.add(i, Integer.toString(i)); } final Map<Long, FudgeMsg> inputMap = new HashMap<Long, FudgeMsg>(); identifier1++; long identifier2 = identifier1 + 1; inputMap.put(identifier1, inputValue1); inputMap.put(identifier2, inputValue2); dataStore.put(inputMap); final Map<Long, FudgeMsg> outputMap = dataStore.get(Arrays.asList(identifier1, identifier2)); assertEquals(2, outputMap.size()); assertEquals(inputValue1.getAllFields(), outputMap.get(identifier1).getAllFields()); assertEquals(inputValue2.getAllFields(), outputMap.get(identifier2).getAllFields()); } @Test(timeOut = 10000l) public void singleThreadPutLoadPurgeLoad() throws InterruptedException { InMemoryViewComputationCacheSource cache = new InMemoryViewComputationCacheSource(s_fudgeContext); ViewComputationCacheServer server = new ViewComputationCacheServer(cache); DirectFudgeConnection conduit = new DirectFudgeConnection(cache.getFudgeContext()); conduit.connectEnd2(server); RemoteCacheClient client = new RemoteCacheClient(conduit.getEnd1()); FudgeMessageStore dataStore = new RemoteFudgeMessageStore(client, new ViewComputationCacheKey( UniqueId.of("Test", "ViewCycle1"), "Config1")); final MutableFudgeMsg inputValue = s_fudgeContext.newMessage(); for (int i = 0; i < 32; i++) { inputValue.add(i, Integer.toString(i)); } final long identifier = 1L; dataStore.put(identifier, inputValue); FudgeMsg outputValue = dataStore.get(identifier); assertNotNull(outputValue); assertEquals(inputValue.getAllFields(), outputValue.getAllFields()); dataStore.delete(); outputValue = dataStore.get(identifier); assertNull(outputValue); } }