/** * Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.integration.timeseries.snapshot; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; import org.fudgemsg.FudgeContext; import org.fudgemsg.FudgeMsg; import org.fudgemsg.MutableFudgeMsg; import org.fudgemsg.wire.FudgeMsgWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.threeten.bp.LocalDate; import org.threeten.bp.format.DateTimeFormatter; import com.google.common.collect.Lists; import com.opengamma.OpenGammaRuntimeException; import com.opengamma.id.ExternalId; import com.opengamma.util.ArgumentChecker; import com.opengamma.util.OpenGammaClock; import com.opengamma.util.fudgemsg.OpenGammaFudgeContext; import com.opengamma.util.monitor.OperationTimer; import com.opengamma.util.redis.RedisConnector; /** * Write last know values in Redis to disk * <p> * output file will be <pre>baseDir/yyyy/mm/dd/observationTime.dump</pre> */ public class RedisLKVFileWriter implements Runnable { private static final Logger s_logger = LoggerFactory.getLogger(RedisLKVFileWriter.class); private static final FudgeContext s_fudgeContext = OpenGammaFudgeContext.getInstance(); /** * Ticks field name */ public static final String TICKS = "1"; /** * Security field name */ public static final String SECURITY = "2"; private BlackList _dataFieldBlackList; private BlackList _schemeBlackList; private String _observationTime; private String _normalizationRuleSetId; private String _globalPrefix = ""; private RedisConnector _redisConnector; private File _baseDir; /** * Gets the dataFieldBlackList. * @return the dataFieldBlackList */ public BlackList getDataFieldBlackList() { return _dataFieldBlackList; } /** * Sets the dataFieldBlackList. * @param dataFieldBlackList the dataFieldBlackList */ public void setDataFieldBlackList(BlackList dataFieldBlackList) { _dataFieldBlackList = dataFieldBlackList; } /** * Gets the schemeBlackList. * @return the schemeBlackList */ public BlackList getSchemeBlackList() { return _schemeBlackList; } /** * Sets the schemeBlackList. * @param schemeBlackList the schemeBlackList */ public void setSchemeBlackList(BlackList schemeBlackList) { _schemeBlackList = schemeBlackList; } /** * Gets the observationTime. * @return the observationTime */ public String getObservationTime() { return _observationTime; } /** * Sets the observationTime. * @param observationTime the observationTime */ public void setObservationTime(String observationTime) { _observationTime = observationTime; } /** * Gets the normalizationRuleSetId. * @return the normalizationRuleSetId */ public String getNormalizationRuleSetId() { return _normalizationRuleSetId; } /** * Sets the normalizationRuleSetId. * @param normalizationRuleSetId the normalizationRuleSetId */ public void setNormalizationRuleSetId(String normalizationRuleSetId) { _normalizationRuleSetId = normalizationRuleSetId; } /** * Gets the globalPrefix. * @return the globalPrefix */ public String getGlobalPrefix() { return _globalPrefix; } /** * Sets the globalPrefix. * @param globalPrefix the globalPrefix */ public void setGlobalPrefix(String globalPrefix) { _globalPrefix = globalPrefix; } /** * Gets the redisConnector. * @return the redisConnector */ public RedisConnector getRedisConnector() { return _redisConnector; } /** * Sets the redisConnector. * @param redisConnector the redisConnector */ public void setRedisConnector(RedisConnector redisConnector) { _redisConnector = redisConnector; } /** * Gets the baseDir. * @return the baseDir */ public File getBaseDir() { return _baseDir; } /** * Sets the baseDir. * @param baseDir the baseDir */ public void setBaseDir(File baseDir) { _baseDir = baseDir; } @Override public void run() { validateState(); RedisLKVSnapshotter redisReader = new RedisLKVSnapshotter(getDataFieldBlackList(), getSchemeBlackList(), getNormalizationRuleSetId(), getGlobalPrefix(), getRedisConnector()); List<FudgeMsg> messages = toFudgeMsg(redisReader.getLastKnownValues()); final File outputFile = getOutputFile(); ensureParentDirectory(outputFile); OperationTimer timer = new OperationTimer(s_logger, "Writing LKV for {} securities to disk", messages.size()); FileOutputStream fos = null; try { fos = new FileOutputStream(outputFile); BufferedOutputStream bos = new BufferedOutputStream(fos, 4096); FudgeMsgWriter fmsw = s_fudgeContext.createMessageWriter(bos); for (FudgeMsg tick : messages) { fmsw.writeMessage(tick); } fmsw.flush(); } catch (FileNotFoundException ex) { throw new OpenGammaRuntimeException("Could not open RedisLKVSnaphot file '" + outputFile.getAbsolutePath() + "'", ex); } finally { IOUtils.closeQuietly(fos); } timer.finished(); } private void ensureParentDirectory(final File outputFile) { try { s_logger.debug("creating directory {}", outputFile.getParent()); FileUtils.forceMkdir(outputFile.getParentFile()); s_logger.debug("directory created"); } catch (IOException ex) { throw new OpenGammaRuntimeException("Error creating directory " + outputFile.getParent(), ex); } } private List<FudgeMsg> toFudgeMsg(Map<ExternalId, Map<String, String>> redisLKV) { List<FudgeMsg> result = Lists.newArrayList(); for (Entry<ExternalId, Map<String, String>> ticksEntry : redisLKV.entrySet()) { MutableFudgeMsg msg = s_fudgeContext.newMessage(); ExternalId externalId = ticksEntry.getKey(); msg.add(SECURITY, externalId.toString()); msg.add(TICKS, ticksToFudgeMsg(ticksEntry.getValue())); result.add(msg); } return result; } public File getOutputFile() { LocalDate today = LocalDate.now(OpenGammaClock.getInstance()); String dateStr = today.toString(DateTimeFormatter.ISO_LOCAL_DATE); String[] dateParts = StringUtils.split(dateStr, "-"); String year = dateParts[0]; String month = dateParts[1]; String day = dateParts[2]; String filename = getObservationTime() + ".dump"; return FileUtils.getFile(getBaseDir(), year, month, day, filename); } private FudgeMsg ticksToFudgeMsg(Map<String, String> ticks) { MutableFudgeMsg ticksMsg = s_fudgeContext.newMessage(); for (Entry<String, String> tickEntry : ticks.entrySet()) { ticksMsg.add(tickEntry.getKey(), Double.valueOf(tickEntry.getValue())); } return ticksMsg; } private void validateState() { ArgumentChecker.notNull(getNormalizationRuleSetId(), "normalization rule set Id"); ArgumentChecker.notNull(getObservationTime(), "observation time"); ArgumentChecker.notNull(getRedisConnector(), "redis connector"); ArgumentChecker.notNull(getBaseDir(), "base directory"); } }