/**
* Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.enginedb.stats;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
import org.threeten.bp.Clock;
import org.threeten.bp.Instant;
import com.opengamma.elsql.ElSqlBundle;
import com.opengamma.engine.calcnode.stats.FunctionCostsDocument;
import com.opengamma.engine.calcnode.stats.FunctionCostsMaster;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.db.DbConnector;
import com.opengamma.util.db.DbDateUtils;
import com.opengamma.util.db.DbMapSqlParameterSource;
/**
* Database storage of function costs.
* <p>
* This implementation supports history.
*/
public class DbFunctionCostsMaster implements FunctionCostsMaster {
/** Logger. */
private static final Logger s_logger = LoggerFactory.getLogger(DbFunctionCostsMaster.class);
/**
* External SQL bundle.
*/
private ElSqlBundle _externalSqlBundle;
/**
* The database connector.
*/
private final DbConnector _dbConnector;
/**
* The time-source to use.
*/
private Clock _timeSource = Clock.systemUTC();
/**
* Creates an instance.
*
* @param dbConnector the database connector, not null
*/
public DbFunctionCostsMaster(final DbConnector dbConnector) {
ArgumentChecker.notNull(dbConnector, "dbConnector");
s_logger.debug("installed DbConnector: {}", dbConnector);
_dbConnector = dbConnector;
_externalSqlBundle = ElSqlBundle.of(dbConnector.getDialect().getElSqlConfig(), DbFunctionCostsMaster.class);
}
//-------------------------------------------------------------------------
/**
* Gets the external SQL bundle.
*
* @return the external SQL bundle, not null
*/
public ElSqlBundle getElSqlBundle() {
return _externalSqlBundle;
}
/**
* Sets the external SQL bundle.
*
* @param bundle the external SQL bundle, not null
*/
public void setElSqlBundle(ElSqlBundle bundle) {
_externalSqlBundle = bundle;
}
//-------------------------------------------------------------------------
/**
* Gets the database connector.
*
* @return the database connector, not null
*/
public DbConnector getDbConnector() {
return _dbConnector;
}
//-------------------------------------------------------------------------
/**
* Gets the time-source that determines the current time.
*
* @return the time-source, not null
*/
public Clock getClock() {
return _timeSource;
}
/**
* Sets the time-source.
*
* @param timeSource the time-source, not null
*/
public void setClock(final Clock timeSource) {
ArgumentChecker.notNull(timeSource, "timeSource");
s_logger.debug("installed Clock: {}", timeSource);
_timeSource = timeSource;
}
//-------------------------------------------------------------------------
public int getSchemaVersion() {
final DbMapSqlParameterSource args = new DbMapSqlParameterSource().addValue("version_key", "schema_patch");
final NamedParameterJdbcOperations namedJdbc = getDbConnector().getJdbcTemplate();
final String sql = getElSqlBundle().getSql("GetSchemaVersion", args);
String version = namedJdbc.queryForObject(sql, args, String.class);
return Integer.parseInt(version);
}
//-------------------------------------------------------------------------
@Override
public FunctionCostsDocument load(final String configuration, final String functionId, Instant versionAsOf) {
s_logger.debug("load: {} {}", configuration, functionId);
if (versionAsOf == null) {
versionAsOf = Instant.now(getClock());
}
final DbMapSqlParameterSource args = new DbMapSqlParameterSource()
.addValue("configuration", configuration.trim())
.addValue("function", functionId.trim())
.addTimestamp("version_instant", versionAsOf)
.addValue("paging_offset", 0)
.addValue("paging_fetch", 1);
final FunctionCostsDocumentExtractor extractor = new FunctionCostsDocumentExtractor();
final NamedParameterJdbcOperations namedJdbc = getDbConnector().getJdbcTemplate();
final String sql = getElSqlBundle().getSql("GetCosts", args);
final List<FunctionCostsDocument> docs = namedJdbc.query(sql, args, extractor);
return docs.isEmpty() ? null : docs.get(0);
}
//-------------------------------------------------------------------------
@Override
public FunctionCostsDocument store(final FunctionCostsDocument costs) {
ArgumentChecker.notNull(costs, "costs");
ArgumentChecker.notNull(costs.getConfigurationName(), "costs.configurationName");
ArgumentChecker.notNull(costs.getFunctionId(), "costs.functionId");
costs.setVersion(Instant.now(getClock()));
final DbMapSqlParameterSource args = new DbMapSqlParameterSource()
.addValue("configuration", costs.getConfigurationName().trim())
.addValue("function", costs.getFunctionId().trim())
.addTimestamp("version_instant", costs.getVersion())
.addValue("invocation_cost", costs.getInvocationCost())
.addValue("data_input_cost", costs.getDataInputCost())
.addValue("data_output_cost", costs.getDataOutputCost());
final String sql = getElSqlBundle().getSql("InsertCosts", args);
getDbConnector().getJdbcTemplate().update(sql, args);
// delete older data
final DbMapSqlParameterSource deleteArgs = new DbMapSqlParameterSource()
.addValue("configuration", costs.getConfigurationName().trim())
.addValue("function", costs.getFunctionId().trim())
.addValue("offset_zero", 0)
.addValue("keep_rows", 20);
final String deleteSql = getElSqlBundle().getSql("DeleteOld", deleteArgs);
getDbConnector().getJdbcTemplate().update(deleteSql, deleteArgs);
return costs;
}
//-------------------------------------------------------------------------
/**
* Returns a string summary of this master.
*
* @return the string summary, not null
*/
@Override
public String toString() {
return getClass().getSimpleName();
}
//-------------------------------------------------------------------------
/**
* Mapper from SQL rows to a FunctionCostsDocument.
*/
protected final class FunctionCostsDocumentExtractor implements ResultSetExtractor<List<FunctionCostsDocument>> {
private List<FunctionCostsDocument> _documents = new ArrayList<FunctionCostsDocument>();
@Override
public List<FunctionCostsDocument> extractData(final ResultSet rs) throws SQLException, DataAccessException {
while (rs.next()) {
FunctionCostsDocument doc = new FunctionCostsDocument();
doc.setConfigurationName(rs.getString("CONFIGURATION"));
doc.setFunctionId(rs.getString("FUNCTION_NAME"));
doc.setVersion(DbDateUtils.fromSqlTimestamp(rs.getTimestamp("VERSION_INSTANT")));
doc.setInvocationCost(rs.getDouble("INVOCATION_COST"));
doc.setDataInputCost(rs.getDouble("DATA_INPUT_COST"));
doc.setDataOutputCost(rs.getDouble("DATA_OUTPUT_COST"));
_documents.add(doc);
}
return _documents;
}
}
}