/**
* Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.engine.view.worker.cache;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.threeten.bp.Instant;
import com.google.common.collect.MapMaker;
import com.opengamma.core.config.ConfigSource;
import com.opengamma.core.position.Portfolio;
import com.opengamma.engine.ComputationTargetResolver;
import com.opengamma.engine.ComputationTargetSpecification;
import com.opengamma.engine.depgraph.DependencyGraph;
import com.opengamma.engine.depgraph.DependencyGraphExplorer;
import com.opengamma.engine.function.CompiledFunctionService;
import com.opengamma.engine.target.ComputationTargetReference;
import com.opengamma.engine.target.ComputationTargetType;
import com.opengamma.engine.view.ViewDefinition;
import com.opengamma.engine.view.compilation.CompiledViewCalculationConfiguration;
import com.opengamma.engine.view.compilation.CompiledViewDefinitionWithGraphs;
import com.opengamma.engine.view.compilation.CompiledViewDefinitionWithGraphsImpl;
import com.opengamma.id.UniqueId;
import com.opengamma.id.VersionCorrection;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.ehcache.EHCacheUtils;
/**
* An EH-Cache based implementation of {@link ViewExecutionCache}.
*/
public class EHCacheViewExecutionCache implements ViewExecutionCache {
private static final Logger s_logger = LoggerFactory.getLogger(EHCacheViewExecutionCache.class);
private static final String COMPILED_VIEW_DEFINITIONS = "compiledViewDefinitions";
private static final Map<Serializable, EHCacheViewExecutionCache> s_instance2identifier = new MapMaker().weakValues().makeMap();
private static final AtomicInteger s_nextIdentifier = new AtomicInteger(0);
private final Serializable _identifier;
private final CacheManager _cacheManager;
private final ComputationTargetResolver _targetResolver;
private final ConcurrentMap<ViewExecutionCacheKey, CompiledViewDefinitionWithGraphs> _compiledViewDefinitionsFrontCache = new MapMaker().weakValues().makeMap();
private final Cache _compiledViewDefinitions;
/**
* Creates a new instance.
*
* @param cacheManager the cache manager, not null
* @param targetResolver the target resolver for portfolio and view definition objects, not null
*/
public EHCacheViewExecutionCache(final CacheManager cacheManager, final ComputationTargetResolver targetResolver) {
ArgumentChecker.notNull(cacheManager, "cacheManager");
ArgumentChecker.notNull(targetResolver, "targetResolver");
_identifier = s_nextIdentifier.getAndIncrement();
_cacheManager = cacheManager;
_targetResolver = targetResolver;
EHCacheUtils.addCache(_cacheManager, COMPILED_VIEW_DEFINITIONS);
_compiledViewDefinitions = EHCacheUtils.getCacheFromManager(_cacheManager, COMPILED_VIEW_DEFINITIONS);
s_instance2identifier.put(_identifier, this);
}
/**
* Creates a new instance.
*
* @param cacheManager the cache manager, not null
* @param cfs the compiled function service, holding a computation target resolver, not null
*/
public EHCacheViewExecutionCache(final CacheManager cacheManager, final CompiledFunctionService cfs) {
this(cacheManager, cfs.getFunctionCompilationContext().getRawComputationTargetResolver());
}
/**
* Creates a new instance
*
* @param cacheManager the cache manager, not null
* @param configSource not used
* @param cfs the compiled function service, holding a computation target resolver, not null
* @deprecated Kept for compatibility with existing Spring config files only
*/
@Deprecated
public EHCacheViewExecutionCache(final CacheManager cacheManager, final ConfigSource configSource, final CompiledFunctionService cfs) {
this(cacheManager, cfs.getFunctionCompilationContext().getRawComputationTargetResolver());
}
/**
* For testing only.
*/
/* package */void clearFrontCache() {
_compiledViewDefinitionsFrontCache.clear();
}
protected Serializable instance() {
return _identifier;
}
protected static EHCacheViewExecutionCache instance(final Serializable identifier) {
return s_instance2identifier.get(identifier);
}
public ComputationTargetResolver getTargetResolver() {
return _targetResolver;
}
/* package */static final class CompiledViewDefinitionWithGraphsReader implements Serializable {
private static final long serialVersionUID = 1L;
private final Serializable _parent;
private final VersionCorrection _versionCorrection;
private final String _compilationId;
private final UniqueId _viewDefinition;
private final Collection<DependencyGraph> _graphs;
private final Map<ComputationTargetReference, UniqueId> _resolutions;
private final UniqueId _portfolio;
private final long _functionInitId;
private final Collection<CompiledViewCalculationConfiguration> _calcConfigs;
private final Instant _validFrom;
private final Instant _validTo;
public CompiledViewDefinitionWithGraphsReader(EHCacheViewExecutionCache parent, CompiledViewDefinitionWithGraphs viewDef) {
_parent = parent.instance();
_versionCorrection = viewDef.getResolverVersionCorrection();
_compilationId = viewDef.getCompilationIdentifier();
_viewDefinition = viewDef.getViewDefinition().getUniqueId();
final Collection<DependencyGraphExplorer> graphs = viewDef.getDependencyGraphExplorers();
_graphs = new ArrayList<>(graphs.size());
for (DependencyGraphExplorer explorer : graphs) {
_graphs.add(explorer.getWholeGraph());
}
_resolutions = viewDef.getResolvedIdentifiers();
_portfolio = viewDef.getPortfolio().getUniqueId();
_functionInitId = ((CompiledViewDefinitionWithGraphsImpl) viewDef).getFunctionInitId();
_calcConfigs = new ArrayList<CompiledViewCalculationConfiguration>(viewDef.getCompiledCalculationConfigurations());
_validFrom = viewDef.getValidFrom();
_validTo = viewDef.getValidTo();
}
private Object readResolve() {
final EHCacheViewExecutionCache parent = instance(_parent);
final ViewDefinition viewDefinition = (ViewDefinition) parent.getTargetResolver()
.resolve(new ComputationTargetSpecification(ComputationTargetType.of(ViewDefinition.class), _viewDefinition), VersionCorrection.LATEST).getValue();
final Portfolio portfolio = (Portfolio) parent.getTargetResolver().resolve(new ComputationTargetSpecification(ComputationTargetType.PORTFOLIO, _portfolio), _versionCorrection).getValue();
CompiledViewDefinitionWithGraphsImpl compiledViewDef = new CompiledViewDefinitionWithGraphsImpl(_versionCorrection, _compilationId, viewDefinition, _graphs, _resolutions, portfolio,
_functionInitId, _calcConfigs, _validFrom, _validTo);
return parent.new CompiledViewDefinitionWithGraphsHolder(compiledViewDef);
}
}
/* package */final class CompiledViewDefinitionWithGraphsHolder implements Serializable {
private static final long serialVersionUID = 1L;
private CompiledViewDefinitionWithGraphs _viewDefinition;
public CompiledViewDefinitionWithGraphsHolder(final CompiledViewDefinitionWithGraphs viewDefinition) {
_viewDefinition = viewDefinition;
}
public CompiledViewDefinitionWithGraphs get() {
return _viewDefinition;
}
private Object writeReplace() {
return new CompiledViewDefinitionWithGraphsReader(EHCacheViewExecutionCache.this, _viewDefinition);
}
}
@Override
public CompiledViewDefinitionWithGraphs getCompiledViewDefinitionWithGraphs(ViewExecutionCacheKey key) {
CompiledViewDefinitionWithGraphs graphs = _compiledViewDefinitionsFrontCache.get(key);
if (graphs != null) {
s_logger.debug("Front cache hit CompiledViewDefinitionWithGraphs for {}", key);
return graphs;
}
final Element element = _compiledViewDefinitions.get(key);
if (element != null) {
s_logger.debug("EHCache hit CompiledViewDefinitionWithGraphs for {}", key);
graphs = ((CompiledViewDefinitionWithGraphsHolder) element.getObjectValue()).get();
final CompiledViewDefinitionWithGraphs existing = _compiledViewDefinitionsFrontCache.putIfAbsent(key, graphs);
if (existing != null) {
graphs = existing;
}
} else {
s_logger.debug("EHCache miss CompiledViewDefinitionWithGraphs for {}", key);
}
return graphs;
}
@Override
public void setCompiledViewDefinitionWithGraphs(ViewExecutionCacheKey key, CompiledViewDefinitionWithGraphs viewDefinition) {
CompiledViewDefinitionWithGraphs existing = _compiledViewDefinitionsFrontCache.put(key, viewDefinition);
if (existing != null) {
if (existing == viewDefinition) {
return;
}
}
s_logger.info("Storing CompiledViewDefinitionWithGraphs for {}", key);
_compiledViewDefinitions.put(new Element(key, new CompiledViewDefinitionWithGraphsHolder(viewDefinition)));
}
@Override
public void clear() {
_compiledViewDefinitionsFrontCache.clear();
s_logger.info("Clearing all CompiledViewDefinitionWithGraphs");
_compiledViewDefinitions.removeAll();
}
}