/** * Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.engine.target.lazy; import java.util.Collection; import java.util.Collections; import java.util.concurrent.atomic.AtomicInteger; import com.opengamma.DataNotFoundException; import com.opengamma.core.position.PortfolioNode; import com.opengamma.core.position.Position; import com.opengamma.core.position.Trade; import com.opengamma.core.security.Security; import com.opengamma.core.security.SecurityLink; import com.opengamma.core.security.SecuritySource; import com.opengamma.engine.CachingComputationTargetResolver; import com.opengamma.id.VersionCorrection; /** * Shared state used by {@link LazyResolvedPortfolio}, {@link LazyResolvedPortfolioNode}, {@link LazyResolvedPosition} and {@link LazyResolvedTrade}. */ public class LazyResolveContext { /** * Resolution context bound to a specific resolution version/correction. */ public class AtVersionCorrection extends LazyResolveContext { private final CachingComputationTargetResolver.AtVersionCorrection _targetResolver; private final VersionCorrection _versionCorrection; public AtVersionCorrection(final LazyResolveContext context, final VersionCorrection versionCorrection) { super(context.getSecuritySource(), context.getRawTargetResolver()); _versionCorrection = versionCorrection; _targetResolver = (getRawTargetResolver() != null) ? getRawTargetResolver().atVersionCorrection(versionCorrection) : null; } protected Security resolveLinkImpl(final SecurityLink link) { try { return link.resolve(getSecuritySource(), _versionCorrection); } catch (DataNotFoundException e) { return null; } } public Security resolveLink(final SecurityLink link) { final Security target = link.getTarget(); if (target != null) { return target; } final Security security = resolveLinkImpl(link); if (security != null) { cacheSecurity(security); } return security; } public CachingComputationTargetResolver.AtVersionCorrection getTargetResolver() { return _targetResolver; } public void cacheSecurity(final Security security) { if (getTargetResolver() != null) { getTargetResolver().cacheTargets(Collections.singleton(security)); } } public void cachePosition(final Position position) { if (getTargetResolver() != null) { getTargetResolver().cacheTargets(Collections.singleton(position)); } } public void cachePositions(final Collection<Position> positions) { if (getTargetResolver() != null) { getTargetResolver().cacheTargets(positions); } } public void cachePortfolioNode(final PortfolioNode portfolioNode) { if (getTargetResolver() != null) { getTargetResolver().cacheTargets(Collections.singleton(portfolioNode)); } } public void cachePortfolioNodes(final Collection<PortfolioNode> portfolioNodes) { if (getTargetResolver() != null) { getTargetResolver().cacheTargets(portfolioNodes); } } public void cacheTrade(final Trade trade) { if (getTargetResolver() != null) { getTargetResolver().cacheTargets(Collections.singleton(trade)); } } public void cacheTrades(final Collection<Trade> trades) { if (getTargetResolver() != null) { getTargetResolver().cacheTargets(trades); } } } private final SecuritySource _securities; private final CachingComputationTargetResolver _targetResolver; private static final ThreadLocal<AtomicInteger> s_writeCount = new ThreadLocal<AtomicInteger>(); public LazyResolveContext(final SecuritySource securities, final CachingComputationTargetResolver targetResolver) { _securities = securities; _targetResolver = targetResolver; } public AtVersionCorrection atVersionCorrection(final VersionCorrection versionCorrection) { return new AtVersionCorrection(this, versionCorrection); } public SecuritySource getSecuritySource() { return _securities; } public CachingComputationTargetResolver getRawTargetResolver() { return _targetResolver; } /** * Called by a thread at the start of any serialization operations which might result in further call backs to the cache. This is to allow a cache to detect such scenarios and work around an * re-entrance problems that its underlying implementation might otherwise experience. Each call from a thread must be balanced by a call to {@link #endWrite}. */ public static void beginWrite() { AtomicInteger c = s_writeCount.get(); if (c == null) { c = new AtomicInteger(1); s_writeCount.set(c); } else { c.incrementAndGet(); } } /** * Tests if the calling thread is between calls to {@link #beginWrite} and {@link #endWrite}. The call will be potentially re-entrant to the underlying cache and should be deferred if the cache * can't support this. * * @return true if the thread is engaged in serialization behavior, false otherwise */ public static boolean isWriting() { final AtomicInteger c = s_writeCount.get(); return (c != null) && (c.get() > 0); } /** * Called by a thread at the end of any serialization operations flagged by a previous call to {@link #beginWrite}. */ public static void endWrite() { s_writeCount.get().decrementAndGet(); } }