/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package org.hyperic.hq.plugin.mssql; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.net.URL; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hyperic.hq.product.MetricValue; import org.hyperic.hq.product.PluginException; import org.hyperic.sigar.win32.Pdh; import org.hyperic.sigar.win32.Win32Exception; /** * * @author Administrator */ public class PDH { private static final Log log = LogFactory.getLog(PDH.class); private static native long pdhOpenQuery() throws PluginException; // private static native void pdhCloseQuery(long query) throws PluginException; private static native long pdhAddCounter(long query, String path) throws PluginException; private static native void pdhRemoveCounter(long counter) throws PluginException; private static native void PdhCollectQueryData(long query) throws PluginException; private static native double PdhGetFormattedCounterValue(long counter) throws PluginException; private static native String[] pdhGetInstances(String path) throws PluginException; private static final class InstanceIndex { long index = 0; } public static String[] getInstances(String path) throws PluginException { String[] instances = pdhGetInstances(path); /* PdhEnumObjectItems() does not include the instance index */ HashMap names = new HashMap(instances.length); for (int i = 0; i < instances.length; i++) { InstanceIndex ix = (InstanceIndex) names.get(instances[i]); if (ix == null) { ix = new InstanceIndex(); names.put(instances[i], ix); } else { ix.index++; instances[i] = instances[i] + "#" + ix.index; } } return instances; } public static Map<String, Double> getFormattedValues(List<String> paths) throws PluginException, InterruptedException { Map<String, Double> res = new HashMap<String, Double>(); long q = PDH.pdhOpenQuery(); Map<String, Long> counters = new HashMap<String, Long>(); for (String path : paths) { try { counters.put(path, addCounter(path, q)); } catch (PluginException ex) { log.debug("[getFormattedValues] Error adding metric => path:'" + path + "' ex:" + ex); res.put(path, Double.NaN); } } if (counters.size() > 0) { try { PdhCollectQueryData(q); Thread.sleep(1000); PdhCollectQueryData(q); for (String path : paths) { try { Long c = counters.get(path); if (c != null) { Double val = PdhGetFormattedCounterValue(c); log.debug("[getFormattedValues] path:'" + path + "' val:" + val); res.put(path, val); } } catch (PluginException ex) { log.debug("[getFormattedValues] Error getting metric value => path:'" + path + "' ex:" + ex); } } } finally { for (Long counter : counters.values()) { try { pdhRemoveCounter(counter); } catch (PluginException ex) { log.debug("[getFormattedValues] Error removing counter => ex:" + ex); } } // pdhCloseQuery(q); } } return res; } /** * Adding counters. * * In order to support localization additional steps are being done: (1) Counters should be translated to localized * counterparts in order to support localized windows systems. (2) Some metrics are missing the '/sec' suffix which * would make translation fail. */ private static long addCounter(String path, long q) throws PluginException { long counter; try { counter = pdhAddCounter(q, Pdh.translate(path)); } catch (Win32Exception e) { log.debug("couldn't add counter. trying again with '/sec' suffix...", e); try{ counter = pdhAddCounter(q, Pdh.translate(path + "/sec")); }catch(Win32Exception winex) { log.warn("couldn't add counter. trying again with '/sec' suffix...", winex); throw new PluginException("Second try to add counter fail. ", winex); } } return counter; } public static double getValue(String path) throws PluginException { double res = MetricValue.NONE.getValue(); long q = PDH.pdhOpenQuery(); long counter = addCounter(path, q); try { PdhCollectQueryData(q); res = PdhGetFormattedCounterValue(counter); } finally { pdhRemoveCounter(counter); // pdhCloseQuery(q); } return res; } static { String os = System.getProperty("os.arch"); log.debug("[static] os: " + os); String libName = "system_pdh.dll"; String libPathInJar = "/priv_lib/"; libPathInJar += os.contains("64") ? "x64/" : "win32/"; // libPathInJar += log.isDebugEnabled() ? "Debug/" : "Release/"; libPathInJar += libName; try { URL in = PDH.class.getClassLoader().getResource(libPathInJar); if (in == null) { throw new FileNotFoundException(libPathInJar); } File out = new File(System.getProperty("java.io.tmpdir") , libName); log.info("[static] Reading dll fom: " + in); log.info("[static] Writing dll to: " + out.getAbsolutePath()); InputStream inStream = in.openStream(); OutputStream outStream = new FileOutputStream(out); byte[] buffer = new byte[1024]; int length; while ((length = inStream.read(buffer)) > 0) { outStream.write(buffer, 0, length); } inStream.close(); outStream.close(); System.load(out.getAbsolutePath()); } catch (Exception e) { log.error(e, e); } } }