/** * Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.sesame.marketdata; import java.util.HashSet; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import com.opengamma.id.ExternalIdBundle; /** * Client which subscribes to market data via the LiveDataManager. * As {@link LiveDataManager} keeps track of which client has which * subscriptions the client needs to be used across multiple engine * cycles for a view. */ // Note name is because LiveDataClient is already used elsewhere in OG public class LDClient implements LDListener { /** * The manager to get the live data from. */ private final LiveDataManager _liveDataManager; /** * The latest set of values retrieved from the market data manager. */ private final AtomicReference<ImmutableLiveDataResults> _latestSnapshot = new AtomicReference<>(DefaultImmutableLiveDataResults.EMPTY); /** * Flag indicating whether updated values are available * from the live data manager. As it will be read and * written from multiple threads we must ensure we have * a consistent value, hence using the atomic reference. * <p> * Note that we initialise to true as if we don't and no * subscriptions need to be made (as another client has * requested the data already) and no data updates are * received from the provider, then we will create an * empty snapshot. */ private final AtomicBoolean _valuesPending = new AtomicBoolean(true); /** * Create the client. * * @param liveDataManager the live data manager */ public LDClient(LiveDataManager liveDataManager) { _liveDataManager = liveDataManager; } @Override public void valueUpdated() { _valuesPending.set(true); } /** * Subscribe to market data. * * @param requests the data to be subscribed to */ public void subscribe(Set<ExternalIdBundle> requests) { if (!requests.isEmpty()) { Set<ExternalIdBundle> subscriptions = new HashSet<>(); for (ExternalIdBundle id : requests) { if (!_latestSnapshot.get().containsTicker(id)) { subscriptions.add(id); } } if (!subscriptions.isEmpty()) { _liveDataManager.subscribe(this, subscriptions); } } } // TODO - should handle unsubscription once the market data source needs it /** * Wait until results for all market data are available. */ public void waitForSubscriptions() { _liveDataManager.waitForAllData(this); } /** * Get the latest market data if it has been updated since last * requested. If not updated the previous snapshot will be * returned. * * @return the latest market data */ public ImmutableLiveDataResults retrieveLatestData() { if (_valuesPending.compareAndSet(true, false)) { _latestSnapshot.set(_liveDataManager.snapshot(this)); } return _latestSnapshot.get(); } /** * Remove all subscriptions for this client. To be called when * this client has completed all its work. */ public void dispose() { _liveDataManager.unregister(this); } }