/** * Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.bbg.referencedata.statistics; import java.util.Iterator; import java.util.Map.Entry; import java.util.Set; import java.util.TreeMap; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import org.threeten.bp.Clock; import org.threeten.bp.LocalDate; /** * A {@link BloombergReferenceDataStatistics} which stores statistics for several days into the past. */ public class DailyBloombergReferenceDataStatistics implements BloombergReferenceDataStatistics { /** * The number of days that the statistics should be kept. */ private static final int DAYS_TO_KEEP = 60; private final MapBloombergReferenceDataStatistics _allTimeStatistics = new MapBloombergReferenceDataStatistics(); //TODO keep old snapshots, not old statistics? private final ReadWriteLock _mapLock = new ReentrantReadWriteLock(); private final Lock _mapReadLock = _mapLock.readLock(); private final Lock _mapWriteLock = _mapLock.writeLock(); private final TreeMap<LocalDate, MapBloombergReferenceDataStatistics> _dailyTimeStatistics = new TreeMap<LocalDate, MapBloombergReferenceDataStatistics>(); @Override public void recordStatistics(Set<String> securities, Set<String> fields) { _allTimeStatistics.recordStatistics(securities, fields); MapBloombergReferenceDataStatistics todaysStats = getTodaysStats(); todaysStats.recordStatistics(securities, fields); } public Snapshot getAllTimeSnapshot() { return _allTimeStatistics.getSnapshot(); } public MapBloombergReferenceDataStatistics getAllTimeStats() { return _allTimeStatistics; } public Snapshot getTodaysSnapshot() { MapBloombergReferenceDataStatistics stats = getTodaysStats(); return stats.getSnapshot(); } public TreeMap<LocalDate, Snapshot> getSnapshotsMap() { _mapReadLock.lock(); try { TreeMap<LocalDate, Snapshot> ret = new TreeMap<LocalDate, Snapshot>(); for (Entry<LocalDate, MapBloombergReferenceDataStatistics> e : _dailyTimeStatistics.entrySet()) { ret.put(e.getKey(), e.getValue().getSnapshot()); } return ret; } finally { _mapReadLock.unlock(); } } public MapBloombergReferenceDataStatistics getTodaysStats() { LocalDate today = getToday(); MapBloombergReferenceDataStatistics todaysStats; _mapReadLock.lock(); try { todaysStats = _dailyTimeStatistics.get(today); } finally { _mapReadLock.unlock(); } if (todaysStats == null) { //Only take the write lock when the day ticks over _mapWriteLock.lock(); try { todaysStats = _dailyTimeStatistics.get(today); _dailyTimeStatistics.put(today, new MapBloombergReferenceDataStatistics()); trim(_dailyTimeStatistics); todaysStats = _dailyTimeStatistics.get(today); } finally { _mapWriteLock.unlock(); } } return todaysStats; } private void trim(TreeMap<LocalDate, MapBloombergReferenceDataStatistics> dailyTimeStatistics) { int toRemove = dailyTimeStatistics.size() - DAYS_TO_KEEP; if (toRemove <= 0) { return; } Iterator<Entry<LocalDate, MapBloombergReferenceDataStatistics>> iterator = dailyTimeStatistics.entrySet().iterator(); for (int i = 0; i < toRemove; i++) { iterator.next(); iterator.remove(); } } private LocalDate getToday() { //I think 0000 UTC is when bloomberg tips over Clock clock = Clock.systemUTC(); return LocalDate.now(clock); } }