/** * NOTE: This copyright does *not* cover user programs that use HQ * program services by normal system calls through the application * program interfaces provided as part of the Hyperic Plug-in Development * Kit or the Hyperic Client Development Kit - this is merely considered * normal use of the program, and does *not* fall under the heading of * "derived work". * * Copyright (C) [2009-2010], VMware, Inc. * This file is part of HQ. * * HQ is free software; you can redistribute it and/or modify * it under the terms version 2 of the GNU General Public License as * published by the Free Software Foundation. This program is distributed * in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA. * */ package org.hyperic.hq.measurement.server.mbean; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import java.util.Properties; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hibernate.SessionFactory; import org.hibernate.engine.SessionFactoryImplementor; import org.hyperic.hibernate.dialect.HQDialect; import org.hyperic.hq.common.shared.HQConstants; import org.hyperic.hq.common.shared.ServerConfigManager; import org.hyperic.hq.measurement.MeasurementConstants; import org.hyperic.hq.measurement.server.session.DataPoint; import org.hyperic.hq.measurement.server.session.Measurement; import org.hyperic.hq.measurement.server.session.MeasurementUnionStatementBuilder; import org.hyperic.hq.measurement.shared.DataManager; import org.hyperic.hq.measurement.shared.MeasurementManager; import org.hyperic.hq.product.MetricValue; import org.hyperic.util.StringUtil; import org.hyperic.util.TimeUtil; import org.hyperic.util.jdbc.DBUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jmx.export.annotation.ManagedOperation; import org.springframework.jmx.export.annotation.ManagedResource; import org.springframework.stereotype.Service; /** * MBean used for testing purposes. When the populate() method is invoked, * we will look up all measurements that are currently scheduled, filling in * the detailed measurement data to simulate an environment that has been * running for as long as the 'keep detailed metric data' setting. * * */ @ManagedResource("hyperic.jmx:type=Service,name=DataPopulator") @Service public class DataPopulatorService implements DataPopulatorServiceMBean { private final Log log = LogFactory.getLog(DataPopulatorService.class); private DBUtil dbUtil; private MeasurementManager measurementManager; private DataManager dataManager; private ServerConfigManager serverConfigManager; private SessionFactory sessionFactory; @Autowired public DataPopulatorService(DBUtil dbUtil, MeasurementManager measurementManager, DataManager dataManager, ServerConfigManager serverConfigManager, SessionFactory sessionFactory) { this.dbUtil = dbUtil; this.measurementManager = measurementManager; this.dataManager = dataManager; this.serverConfigManager = serverConfigManager; this.sessionFactory = sessionFactory; } /** * */ @ManagedOperation public void stop() {} /** * */ @ManagedOperation public void start() {} /** * */ @ManagedOperation public void populate() throws Exception { populate(Long.MAX_VALUE); } /** * */ @ManagedOperation public void populate(long max) throws Exception { long detailedPurgeInterval = getDetailedPurgeInterval(); String cats[] = MeasurementConstants.VALID_CATEGORIES; long start = System.currentTimeMillis(); long num = 0; log.info("Starting data populatation at " + TimeUtil.toString(start)); List<Measurement> measurements = new ArrayList<Measurement>(); for (int i = 0; i < cats.length; i++) { log.info("Loading " + cats[i] + " measurements."); List<Measurement> meas = measurementManager.findMeasurementsByCategory(cats[i]); measurements.addAll(meas); } log.info("Loaded " + measurements.size() + " measurements"); List<DataPoint> dps = new ArrayList<DataPoint>(); max = (max < measurements.size()) ? max : measurements.size(); for (int i = 0; i < max; i++ ) { Measurement m = measurements.get(i); log.info("Loaded last data point for " + m.getId()); dps.add(getLastDataPoint(m.getId())); } for (int i = 0; i < dps.size(); i++) { Measurement m = measurements.get(i); DataPoint dp = dps.get(i); if (dp == null) { continue; // No data for this metric id. } List<DataPoint> data = genData(m, dp, detailedPurgeInterval); log.info("Inserting " + data.size() + " data points"); dataManager.addData(data); num += data.size(); } long duration = System.currentTimeMillis() - start; double rate = num / (duration/1000); log.info("Inserted " + num + " metrics in " + StringUtil.formatDuration(duration) + " (" + rate + " per second)"); } private DataPoint getLastDataPoint(Integer mid) throws Exception { String table = MeasurementUnionStatementBuilder.getUnionStatement( getDetailedPurgeInterval(), mid.intValue(), (HQDialect) ((SessionFactoryImplementor) sessionFactory) .getDialect()); final String SQL = "SELECT timestamp, value FROM " + table + " WHERE measurement_id = ? AND timestamp = " + "(SELECT min(timestamp) FROM " + table + " WHERE measurement_id = ?)"; Connection conn = null; PreparedStatement stmt = null; ResultSet rs = null; try { conn = dbUtil.getConnection(); stmt = conn.prepareStatement(SQL); stmt.setInt(1, mid.intValue()); stmt.setInt(2, mid.intValue()); rs = stmt.executeQuery(); if (!rs.next()) { log.info("No metric data found for " + mid); return null; } MetricValue mv = new MetricValue(); mv.setTimestamp(rs.getLong(1)); mv.setValue(rs.getDouble(2)); return new DataPoint(mid, mv); } catch (SQLException e) { log.error("Error querying last data points", e); throw e; } finally { DBUtil.closeConnection(log, conn); } } private long getDetailedPurgeInterval() throws Exception { Properties conf = serverConfigManager.getConfig(); String purgeRawString = conf.getProperty(HQConstants.DataPurgeRaw); return Long.parseLong(purgeRawString); } private List<DataPoint> genData(Measurement dm, DataPoint dp, long range) { ArrayList<DataPoint> data = new ArrayList<DataPoint>(); long last = dp.getMetricValue().getTimestamp(); long end = System.currentTimeMillis() - range; double value = dp.getMetricValue().getValue(); while (last > end) { last = last - dm.getInterval(); MetricValue v = new MetricValue(value, last); DataPoint d = new DataPoint(dm.getId(), v); data.add(d); } return data; } }