Java tutorial
/* * 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) [2004, 2005, 2006], Hyperic, 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.shared; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.text.DateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hyperic.hq.measurement.MeasurementConstants; import org.hyperic.util.jdbc.DBUtil; public class MeasTabManagerUtil { private static Calendar _baseCal = Calendar.getInstance(); private static final String logCtx = MeasTabManagerUtil.class.getName(); private static final Log _log = LogFactory.getLog(logCtx); public static final int NUMBER_OF_TABLES = 18, NUMBER_OF_TABLES_PER_DAY = 2; public static final String MEAS_TABLE = "HQ_METRIC_DATA"; public static final String MEAS_VIEW = MEAS_TABLE; public static final String OLD_MEAS_TABLE = MEAS_TABLE + "_COMPAT"; private static final String TAB_MEAS = MeasurementConstants.TAB_MEAS; static { _baseCal.set(2006, 0, 1, 0, 0); } public static long getBaseTime() { return _baseCal.getTimeInMillis(); } public static MeasRange[] getMetricRanges(long begin, long end) { List<MeasRange> ranges = MeasRangeObj.getInstance().getRanges(); List<MeasRange> rtn = new ArrayList<MeasRange>(ranges.size()); for (MeasRange range : ranges) { long rBegin = range.getMinTimestamp(); long rEnd = range.getMaxTimestamp(); if (begin > rEnd || end < rBegin) { continue; } rtn.add(range); } return (MeasRange[]) rtn.toArray(new MeasRange[0]); } /** * Get the array of tables that fall in the time range */ public static String[] getMetricTables(long begin, long end) { List<MeasRange> ranges = MeasRangeObj.getInstance().getRanges(); String[] tables = new String[ranges.size()]; int i = 0; for (MeasRange range : ranges) { long rBegin = range.getMinTimestamp(); long rEnd = range.getMaxTimestamp(); if (begin > rEnd || end < rBegin) { continue; } tables[i++] = range.getTable(); } // Now we want to trim the empties String[] retTables = new String[i]; for (i = 0; i < retTables.length; i++) { retTables[i] = tables[i]; } return retTables; } public static String getMeasInStmt(Collection<Integer> measIds, boolean prependAnd) { if (measIds.isEmpty()) { return ""; } StringBuilder rtn = new StringBuilder(); rtn.append(" " + ((prependAnd) ? "AND" : "") + " measurement_id"); // mysql gets a perf boost from using "=" as apposed to "in" if (measIds.size() == 1) { rtn.append(" = " + measIds.iterator().next()); return rtn.toString(); } rtn.append(" in ("); for (Integer measId : measIds) { if (measId == null) { continue; } rtn.append(measId).append(","); } rtn.deleteCharAt(rtn.length() - 1); rtn.append(")"); return rtn.toString(); } public static String getMeasInStmt(Integer[] measIds, boolean prependAnd) { if (measIds.length == 0) { return ""; } StringBuilder rtn = new StringBuilder(); rtn.append(" " + ((prependAnd) ? "AND" : "") + " measurement_id"); // mysql gets a perf boost from using "=" as apposed to "in" if (measIds.length == 1) { rtn.append(" = " + measIds[0]); return rtn.toString(); } rtn.append(" in ("); for (int i = 0; i < measIds.length; i++) { if (measIds[i] == null) { continue; } rtn.append(measIds[i]).append(","); } rtn.deleteCharAt(rtn.length() - 1); rtn.append(")"); return rtn.toString(); } private static int getDayOfPeriod(Calendar cal, long timems) { int rtn = 0; cal.clear(); cal.setTime(new java.util.Date(timems)); Calendar currCal = Calendar.getInstance(); currCal.setTime(new java.util.Date(timems)); while (cal.get(Calendar.YEAR) >= _baseCal.get(Calendar.YEAR)) { if (cal.get(Calendar.YEAR) == currCal.get(Calendar.YEAR)) { rtn += currCal.get(Calendar.DAY_OF_YEAR); } else { rtn += cal.get(Calendar.DAY_OF_YEAR); } cal.add(Calendar.YEAR, -1); cal.set(Calendar.MONTH, 11); cal.set(Calendar.DAY_OF_MONTH, 31); cal.set(Calendar.HOUR_OF_DAY, 23); cal.set(Calendar.MINUTE, 0); } return rtn; } public static String getMeasTabname(long timems) { Calendar cal = Calendar.getInstance(); return getMeasTabname(cal, timems); } public static String getMeasTabname(Calendar cal, long timems) { int dayofperiod = getDayOfPeriod(cal, timems); cal.clear(); cal.setTime(new java.util.Date(timems)); _log.debug("dayofperiod -> " + dayofperiod); int hourofday = cal.get(Calendar.HOUR_OF_DAY); int numdaytables = NUMBER_OF_TABLES / NUMBER_OF_TABLES_PER_DAY; int daytable = dayofperiod % numdaytables; int dayincr = 24 / NUMBER_OF_TABLES_PER_DAY; int dayslice = 0; for (int i = dayincr; i < 24; i += dayincr) { if (hourofday < i) { break; } dayslice++; } return MEAS_TABLE + "_" + daytable + "D_" + dayslice + "S"; } public static long getMeasTabEndTime(Calendar cal, long timems) { cal.clear(); cal.setTime(new java.util.Date(timems)); int incr = 24 / NUMBER_OF_TABLES_PER_DAY; for (int i = incr; i <= 24; i += incr) { if (cal.get(Calendar.HOUR_OF_DAY) < i) { cal.set(Calendar.HOUR_OF_DAY, i - 1); break; } } cal.set(Calendar.MINUTE, 59); cal.set(Calendar.SECOND, 59); cal.set(Calendar.MILLISECOND, 999); return cal.getTimeInMillis(); } public static long getMeasTabEndTime(long timems) { Calendar cal = Calendar.getInstance(); return getMeasTabEndTime(cal, timems); } public static long getMeasTabStartTime(Calendar cal, long timems) { cal.clear(); cal.setTime(new java.util.Date(timems)); int incr = 24 / NUMBER_OF_TABLES_PER_DAY; for (int i = incr; i <= 24; i += incr) { if (cal.get(Calendar.HOUR_OF_DAY) < i) { cal.set(Calendar.HOUR_OF_DAY, i - incr); break; } } cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); return cal.getTimeInMillis(); } public static long getMeasTabStartTime(long timems) { Calendar cal = Calendar.getInstance(); return getMeasTabStartTime(cal, timems); } public static long getPrevMeasTabTime(long timems) { Calendar cal = Calendar.getInstance(); return getPrevMeasTabTime(cal, timems); } public static long getPrevMeasTabTime(Calendar cal, long timems) { cal.clear(); cal.setTime(new java.util.Date(timems)); long rtn = -1; // need to do this because of DST // add() and roll() don't work right String currTable = getMeasTabname(timems); _log.debug("(getPrevMeasTabTime) before -> " + getDateStr(timems) + ", " + currTable); String newTable; int incr = 24 / NUMBER_OF_TABLES_PER_DAY / 3; incr = ((incr < 1) ? 1 : incr) * -1; do { cal.add(Calendar.HOUR_OF_DAY, incr); rtn = cal.getTimeInMillis(); _log.debug("subtracting 1 hour: " + getDateStr(rtn)); newTable = getMeasTabname(rtn); } while (currTable.equals(newTable)); _log.debug("(getPrevMeasTabTime) after -> " + getDateStr(rtn) + ", " + newTable); return rtn; } public static List<Integer> getMeasIdsFromTemplateIds(Connection conn, Integer[] tids) throws SQLException { List<Integer> rtn = new ArrayList<Integer>(); StringBuffer tidsConj = new StringBuffer(DBUtil.composeConjunctions("template_id", tids.length)); DBUtil.replacePlaceHolders(tidsConj, tids); final String sql = new StringBuilder(tidsConj.length() + 64).append("SELECT distinct id FROM ") .append(TAB_MEAS).append(" WHERE ").append(tidsConj).toString(); Statement stmt = null; ResultSet rs = null; try { stmt = conn.createStatement(); rs = stmt.executeQuery(sql); while (rs.next()) { rtn.add(new Integer(rs.getInt(1))); } } finally { DBUtil.closeResultSet(logCtx, rs); DBUtil.closeStatement(logCtx, stmt); } return rtn; } public static List<Integer> getMeasIds(Connection conn, Integer[] tids, Integer[] iids) throws SQLException { List<Integer> rtn = new ArrayList<Integer>(); StringBuffer iidsConj = new StringBuffer(DBUtil.composeConjunctions("instance_id", iids.length)); DBUtil.replacePlaceHolders(iidsConj, iids); StringBuffer tidsConj = new StringBuffer(DBUtil.composeConjunctions("template_id", tids.length)); DBUtil.replacePlaceHolders(tidsConj, tids); final String sql = new StringBuilder(iidsConj.length() + tidsConj.length() + 64) .append("SELECT distinct id FROM ").append(TAB_MEAS).append(" WHERE ").append(iidsConj) .append(" AND ").append(tidsConj).toString(); Statement stmt = null; ResultSet rs = null; try { stmt = conn.createStatement(); rs = stmt.executeQuery(sql); while (rs.next()) { rtn.add(new Integer(rs.getInt(1))); } } finally { DBUtil.closeResultSet(logCtx, rs); DBUtil.closeStatement(logCtx, stmt); } return rtn; } /** * This is meant to be a regression test for the measurement rollover * scheme */ public static void main(String[] args) { long regressTime = System.currentTimeMillis() + 50 * 3600000; for (int i = 0; i < 2000; i++) { Calendar cal = Calendar.getInstance(); cal.setTime(new java.util.Date(regressTime)); cal.add(Calendar.DAY_OF_YEAR, (NUMBER_OF_TABLES / NUMBER_OF_TABLES_PER_DAY)); regressTime = cal.getTimeInMillis(); String firstTable = getMeasTabname(regressTime); String[] a = firstTable.split("_"); int prevslice = Integer.parseInt(a[4].substring(0, 1)); int prevday = Integer.parseInt(a[3].substring(0, 1)); int prevyear = getYear(regressTime); long currTime = getPrevMeasTabTime(regressTime); String currTable = getMeasTabname(currTime); int curryear; long prevTime = 0l; String prevTable = null; System.out.println("Number: " + i); System.out.println("Date: " + getDateStr(regressTime)); System.out.println("First Table: " + firstTable); do { System.out.println(currTable); a = currTable.split("_"); boolean rollslice = (prevslice == 0); int currslice = Integer.parseInt(a[4].substring(0, 1)); int currday = Integer.parseInt(a[3].substring(0, 1)); curryear = getYear(currTime); if (prevTable != null && prevTable.equals(currTable)) { System.out.println("ERROR: " + prevTable + " == " + currTable); System.exit(1); } else if ((currslice == (NUMBER_OF_TABLES_PER_DAY - 1) && prevslice != 0) || currslice == prevslice) { System.out.println("slice ERROR:" + "\nFirst -> " + getDateStr(regressTime) + ", " + firstTable + "\nPrevious -> " + getDateStr(prevTime) + ", " + prevTable + "\nCurrent -> " + getDateStr(currTime) + ", " + currTable); System.out.println("Current slice -> " + currslice); System.out.println("Previous slice -> " + prevslice); System.exit(1); } else if (rollslice && (currday != ((NUMBER_OF_TABLES / NUMBER_OF_TABLES_PER_DAY) - 1) && prevday == 0) || rollslice && (currday != (prevday - 1)) && prevday != 0) { System.out.println("day ERROR:" + "\nFirst -> " + getDateStr(regressTime) + ", " + firstTable + "\nPrevious -> " + getDateStr(prevTime) + ", " + prevTable + "\nCurrent -> " + getDateStr(currTime) + ", " + currTable); System.out.println("Current Day -> " + currday); System.out.println("Previous Day -> " + prevday); System.out.println("Current Year -> " + curryear); System.out.println("Previous Year -> " + prevyear); System.exit(1); } prevslice = currslice; prevday = currday; prevTable = currTable; prevTime = currTime; currTime = getPrevMeasTabTime(currTime); currTable = getMeasTabname(currTime); prevyear = curryear; } while (!firstTable.equals(currTable)); System.out.println("End -> " + currTable); } System.out.println(getDateStr(regressTime)); } private static int getYear(long timems) { Calendar cal = Calendar.getInstance(); cal.setTime(new java.util.Date(timems)); return cal.get(Calendar.YEAR); } private static String getDateStr(long timems) { return DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT) .format(new java.util.Date(timems)); } }