PerformanceImpl.cpp revision f72cbd6a549c34992fa79cce84600fe2b92b3299
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync/* $Id$ */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync/** @file
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync *
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * VBox Performance API COM Classes implementation
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync/*
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Copyright (C) 2008 Sun Microsystems, Inc.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync *
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * available from http://www.virtualbox.org. This file is free software;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * you can redistribute it and/or modify it under the terms of the GNU
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * General Public License (GPL) as published by the Free Software
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync *
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * additional information or have any questions.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#if defined(RT_OS_WINDOWS)
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync#elif defined(RT_OS_LINUX)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#endif
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#include "PerformanceImpl.h"
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#include "Logging.h"
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#include <VBox/err.h>
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#include <iprt/process.h>
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#include <vector>
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#include <algorithm>
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync#include <functional>
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncstatic Bstr gMetricNames[] =
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync{
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync "CPU/Load/User",
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync "CPU/Load/User:avg",
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync "CPU/Load/User:min",
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync "CPU/Load/User:max",
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync "CPU/Load/Kernel",
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync "CPU/Load/Kernel:avg",
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync "CPU/Load/Kernel:min",
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync "CPU/Load/Kernel:max",
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync "CPU/Load/Idle",
8608612b77e4d9bccdd4ff30a40ce7cc68966570vboxsync "CPU/Load/Idle:avg",
8608612b77e4d9bccdd4ff30a40ce7cc68966570vboxsync "CPU/Load/Idle:min",
8608612b77e4d9bccdd4ff30a40ce7cc68966570vboxsync "CPU/Load/Idle:max",
8608612b77e4d9bccdd4ff30a40ce7cc68966570vboxsync "CPU/MHz",
8608612b77e4d9bccdd4ff30a40ce7cc68966570vboxsync "CPU/MHz:avg",
8608612b77e4d9bccdd4ff30a40ce7cc68966570vboxsync "CPU/MHz:min",
8608612b77e4d9bccdd4ff30a40ce7cc68966570vboxsync "CPU/MHz:max",
8608612b77e4d9bccdd4ff30a40ce7cc68966570vboxsync "RAM/Usage/Total",
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync "RAM/Usage/Total:avg",
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync "RAM/Usage/Total:min",
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync "RAM/Usage/Total:max",
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync "RAM/Usage/Used",
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync "RAM/Usage/Used:avg",
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync "RAM/Usage/Used:min",
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync "RAM/Usage/Used:max",
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync "RAM/Usage/Free",
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync "RAM/Usage/Free:avg",
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync "RAM/Usage/Free:min",
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync "RAM/Usage/Free:max",
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync};
864051af8bf1aae6d2b5c52529b348234f22541dvboxsync
864051af8bf1aae6d2b5c52529b348234f22541dvboxsync////////////////////////////////////////////////////////////////////////////////
022e56bff837db399121bc76e4f404a6cd959d6evboxsync// PerformanceCollector class
864051af8bf1aae6d2b5c52529b348234f22541dvboxsync////////////////////////////////////////////////////////////////////////////////
022e56bff837db399121bc76e4f404a6cd959d6evboxsync
022e56bff837db399121bc76e4f404a6cd959d6evboxsync// constructor / destructor
022e56bff837db399121bc76e4f404a6cd959d6evboxsync////////////////////////////////////////////////////////////////////////////////
022e56bff837db399121bc76e4f404a6cd959d6evboxsync
022e56bff837db399121bc76e4f404a6cd959d6evboxsyncPerformanceCollector::PerformanceCollector() : mMagic(0) {}
022e56bff837db399121bc76e4f404a6cd959d6evboxsync
022e56bff837db399121bc76e4f404a6cd959d6evboxsyncPerformanceCollector::~PerformanceCollector() {}
022e56bff837db399121bc76e4f404a6cd959d6evboxsync
022e56bff837db399121bc76e4f404a6cd959d6evboxsyncHRESULT PerformanceCollector::FinalConstruct()
022e56bff837db399121bc76e4f404a6cd959d6evboxsync{
022e56bff837db399121bc76e4f404a6cd959d6evboxsync LogFlowThisFunc (("\n"));
022e56bff837db399121bc76e4f404a6cd959d6evboxsync
022e56bff837db399121bc76e4f404a6cd959d6evboxsync return S_OK;
864051af8bf1aae6d2b5c52529b348234f22541dvboxsync}
864051af8bf1aae6d2b5c52529b348234f22541dvboxsync
864051af8bf1aae6d2b5c52529b348234f22541dvboxsyncvoid PerformanceCollector::FinalRelease()
c6ccc50e63b794d6ef52f52de638eeb08c61417evboxsync{
c6ccc50e63b794d6ef52f52de638eeb08c61417evboxsync LogFlowThisFunc (("\n"));
864051af8bf1aae6d2b5c52529b348234f22541dvboxsync}
864051af8bf1aae6d2b5c52529b348234f22541dvboxsync
864051af8bf1aae6d2b5c52529b348234f22541dvboxsync// public initializer/uninitializer for internal purposes only
c6ccc50e63b794d6ef52f52de638eeb08c61417evboxsync////////////////////////////////////////////////////////////////////////////////
c6ccc50e63b794d6ef52f52de638eeb08c61417evboxsync
864051af8bf1aae6d2b5c52529b348234f22541dvboxsync/**
864051af8bf1aae6d2b5c52529b348234f22541dvboxsync * Initializes the PerformanceCollector object.
864051af8bf1aae6d2b5c52529b348234f22541dvboxsync */
864051af8bf1aae6d2b5c52529b348234f22541dvboxsyncHRESULT PerformanceCollector::init()
864051af8bf1aae6d2b5c52529b348234f22541dvboxsync{
864051af8bf1aae6d2b5c52529b348234f22541dvboxsync /* Enclose the state transition NotReady->InInit->Ready */
864051af8bf1aae6d2b5c52529b348234f22541dvboxsync AutoInitSpan autoInitSpan (this);
c6ccc50e63b794d6ef52f52de638eeb08c61417evboxsync AssertReturn (autoInitSpan.isOk(), E_FAIL);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync LogFlowThisFuncEnter();
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync HRESULT rc = S_OK;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync m.hal = pm::createHAL();
f53ba2efceac1847585b2052ee98569305e9802dvboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* Let the sampler know it gets a valid collector. */
81b3101ea5e60964f67c97185bbd43dbf75c5ab5vboxsync mMagic = MAGIC;
81b3101ea5e60964f67c97185bbd43dbf75c5ab5vboxsync
864051af8bf1aae6d2b5c52529b348234f22541dvboxsync /* Start resource usage sampler */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync int vrc = RTTimerLRCreate (&m.sampler, VBOX_USAGE_SAMPLER_MIN_INTERVAL,
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync &PerformanceCollector::staticSamplerCallback, this);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync AssertMsgRC (vrc, ("Failed to create resource usage "
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync "sampling timer(%Rra)\n", vrc));
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (RT_FAILURE (vrc))
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync rc = E_FAIL;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (SUCCEEDED (rc))
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync autoInitSpan.setSucceeded();
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync LogFlowThisFuncLeave();
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return rc;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync}
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync/**
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Uninitializes the PerformanceCollector object.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync *
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Called either from FinalRelease() or by the parent when it gets destroyed.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncvoid PerformanceCollector::uninit()
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync{
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync LogFlowThisFuncEnter();
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* Enclose the state transition Ready->InUninit->NotReady */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync AutoUninitSpan autoUninitSpan (this);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (autoUninitSpan.uninitDone())
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync LogFlowThisFunc (("Already uninitialized.\n"));
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync LogFlowThisFuncLeave();
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync mMagic = 0;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* Destroy resource usage sampler */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync int vrc = RTTimerLRDestroy (m.sampler);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync AssertMsgRC (vrc, ("Failed to destroy resource usage "
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync "sampling timer (%Rra)\n", vrc));
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync m.sampler = NULL;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync //delete m.factory;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync //m.factory = NULL;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync delete m.hal;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync m.hal = NULL;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync LogFlowThisFuncLeave();
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync}
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync// IPerformanceCollector properties
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync////////////////////////////////////////////////////////////////////////////////
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncSTDMETHODIMP
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncPerformanceCollector::COMGETTER(MetricNames) (ComSafeArrayOut (BSTR, theMetricNames))
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync{
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (ComSafeArrayOutIsNull (theMetricNames))
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return E_POINTER;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync AutoCaller autoCaller (this);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync CheckComRCReturnRC (autoCaller.rc());
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync AutoReadLock alock (this);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync com::SafeArray <BSTR> metricNames(RT_ELEMENTS(gMetricNames));
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync for (size_t i = 0; i < RT_ELEMENTS(gMetricNames); i++)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync gMetricNames[i].detachTo(&metricNames[i]);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync //gMetricNames.detachTo(ComSafeArrayOutArg (theMetricNames));
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync metricNames.detachTo (ComSafeArrayOutArg (theMetricNames));
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return S_OK;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync}
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync// IPerformanceCollector methods
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync////////////////////////////////////////////////////////////////////////////////
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncHRESULT PerformanceCollector::toIPerformanceMetric(pm::Metric *src, IPerformanceMetric **dst)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync{
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync ComObjPtr <PerformanceMetric> metric;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync HRESULT rc = metric.createObject();
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (SUCCEEDED (rc))
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync rc = metric->init (src);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync AssertComRCReturnRC (rc);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync metric.queryInterfaceTo (dst);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return rc;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync}
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncHRESULT PerformanceCollector::toIPerformanceMetric(pm::BaseMetric *src, IPerformanceMetric **dst)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync{
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync ComObjPtr <PerformanceMetric> metric;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync HRESULT rc = metric.createObject();
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (SUCCEEDED (rc))
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync rc = metric->init (src);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync AssertComRCReturnRC (rc);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync metric.queryInterfaceTo (dst);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return rc;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync}
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncSTDMETHODIMP
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncPerformanceCollector::GetMetrics (ComSafeArrayIn (IN_BSTR, metricNames),
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync ComSafeArrayIn (IUnknown *, objects),
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync ComSafeArrayOut (IPerformanceMetric *, outMetrics))
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync{
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync LogFlowThisFuncEnter();
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync //LogFlowThisFunc (("mState=%d, mType=%d\n", mState, mType));
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync HRESULT rc = S_OK;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync AutoCaller autoCaller (this);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync CheckComRCReturnRC (autoCaller.rc());
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync pm::Filter filter (ComSafeArrayInArg (metricNames),
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync ComSafeArrayInArg (objects));
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync AutoReadLock alock (this);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync MetricList filteredMetrics;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync MetricList::iterator it;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync for (it = m.metrics.begin(); it != m.metrics.end(); ++it)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (filter.match ((*it)->getObject(), (*it)->getName()))
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync filteredMetrics.push_back (*it);
f53ba2efceac1847585b2052ee98569305e9802dvboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync com::SafeIfaceArray<IPerformanceMetric> retMetrics (filteredMetrics.size());
81b3101ea5e60964f67c97185bbd43dbf75c5ab5vboxsync int i = 0;
81b3101ea5e60964f67c97185bbd43dbf75c5ab5vboxsync for (it = filteredMetrics.begin(); it != filteredMetrics.end(); ++it)
864051af8bf1aae6d2b5c52529b348234f22541dvboxsync {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync ComObjPtr <PerformanceMetric> metric;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync rc = metric.createObject();
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (SUCCEEDED (rc))
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync rc = metric->init (*it);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync AssertComRCReturnRC (rc);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync LogFlow (("PerformanceCollector::GetMetrics() store a metric at "
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync "retMetrics[%d]...\n", i));
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync metric.queryInterfaceTo (&retMetrics [i++]);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync }
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync retMetrics.detachTo (ComSafeArrayOutArg(outMetrics));
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync LogFlowThisFuncLeave();
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return rc;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync}
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncSTDMETHODIMP
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncPerformanceCollector::SetupMetrics (ComSafeArrayIn (IN_BSTR, metricNames),
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync ComSafeArrayIn (IUnknown *, objects),
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync ULONG aPeriod, ULONG aCount,
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync ComSafeArrayOut (IPerformanceMetric *,
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync outMetrics))
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync{
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync AutoCaller autoCaller (this);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync CheckComRCReturnRC (autoCaller.rc());
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync pm::Filter filter (ComSafeArrayInArg (metricNames),
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync ComSafeArrayInArg (objects));
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync AutoWriteLock alock (this);
HRESULT rc = S_OK;
BaseMetricList filteredMetrics;
BaseMetricList::iterator it;
for (it = m.baseMetrics.begin(); it != m.baseMetrics.end(); ++it)
if (filter.match((*it)->getObject(), (*it)->getName()))
{
LogFlow (("PerformanceCollector::SetupMetrics() setting period to %u,"
" count to %u for %s\n", aPeriod, aCount, (*it)->getName()));
(*it)->init(aPeriod, aCount);
if (aPeriod == 0 || aCount == 0)
{
LogFlow (("PerformanceCollector::SetupMetrics() disabling %s\n",
(*it)->getName()));
(*it)->disable();
}
else
{
LogFlow (("PerformanceCollector::SetupMetrics() enabling %s\n",
(*it)->getName()));
(*it)->enable();
}
filteredMetrics.push_back(*it);
}
com::SafeIfaceArray<IPerformanceMetric> retMetrics (filteredMetrics.size());
int i = 0;
for (it = filteredMetrics.begin();
it != filteredMetrics.end() && SUCCEEDED (rc); ++it)
rc = toIPerformanceMetric(*it, &retMetrics [i++]);
retMetrics.detachTo (ComSafeArrayOutArg(outMetrics));
LogFlowThisFuncLeave();
return rc;
}
STDMETHODIMP
PerformanceCollector::EnableMetrics (ComSafeArrayIn (IN_BSTR, metricNames),
ComSafeArrayIn (IUnknown *, objects),
ComSafeArrayOut (IPerformanceMetric *,
outMetrics))
{
AutoCaller autoCaller (this);
CheckComRCReturnRC (autoCaller.rc());
pm::Filter filter (ComSafeArrayInArg (metricNames),
ComSafeArrayInArg (objects));
AutoWriteLock alock (this); /* Write lock is not needed atm since we are */
/* fiddling with enable bit only, but we */
/* care for those who come next :-). */
HRESULT rc = S_OK;
BaseMetricList filteredMetrics;
BaseMetricList::iterator it;
for (it = m.baseMetrics.begin(); it != m.baseMetrics.end(); ++it)
if (filter.match((*it)->getObject(), (*it)->getName()))
{
(*it)->enable();
filteredMetrics.push_back(*it);
}
com::SafeIfaceArray<IPerformanceMetric> retMetrics (filteredMetrics.size());
int i = 0;
for (it = filteredMetrics.begin();
it != filteredMetrics.end() && SUCCEEDED (rc); ++it)
rc = toIPerformanceMetric(*it, &retMetrics [i++]);
retMetrics.detachTo (ComSafeArrayOutArg(outMetrics));
LogFlowThisFuncLeave();
return rc;
}
STDMETHODIMP
PerformanceCollector::DisableMetrics (ComSafeArrayIn (IN_BSTR, metricNames),
ComSafeArrayIn (IUnknown *, objects),
ComSafeArrayOut (IPerformanceMetric *,
outMetrics))
{
AutoCaller autoCaller (this);
CheckComRCReturnRC (autoCaller.rc());
pm::Filter filter (ComSafeArrayInArg (metricNames),
ComSafeArrayInArg (objects));
AutoWriteLock alock (this); /* Write lock is not needed atm since we are */
/* fiddling with enable bit only, but we */
/* care for those who come next :-). */
HRESULT rc = S_OK;
BaseMetricList filteredMetrics;
BaseMetricList::iterator it;
for (it = m.baseMetrics.begin(); it != m.baseMetrics.end(); ++it)
if (filter.match((*it)->getObject(), (*it)->getName()))
{
(*it)->disable();
filteredMetrics.push_back(*it);
}
com::SafeIfaceArray<IPerformanceMetric> retMetrics (filteredMetrics.size());
int i = 0;
for (it = filteredMetrics.begin();
it != filteredMetrics.end() && SUCCEEDED (rc); ++it)
rc = toIPerformanceMetric(*it, &retMetrics [i++]);
retMetrics.detachTo (ComSafeArrayOutArg(outMetrics));
LogFlowThisFuncLeave();
return rc;
}
STDMETHODIMP
PerformanceCollector::QueryMetricsData (ComSafeArrayIn (IN_BSTR, metricNames),
ComSafeArrayIn (IUnknown *, objects),
ComSafeArrayOut (BSTR, outMetricNames),
ComSafeArrayOut (IUnknown *, outObjects),
ComSafeArrayOut (BSTR, outUnits),
ComSafeArrayOut (ULONG, outScales),
ComSafeArrayOut (ULONG, outSequenceNumbers),
ComSafeArrayOut (ULONG, outDataIndices),
ComSafeArrayOut (ULONG, outDataLengths),
ComSafeArrayOut (LONG, outData))
{
AutoCaller autoCaller (this);
CheckComRCReturnRC (autoCaller.rc());
pm::Filter filter (ComSafeArrayInArg (metricNames),
ComSafeArrayInArg (objects));
AutoReadLock alock (this);
/* Let's compute the size of the resulting flat array */
size_t flatSize = 0;
MetricList filteredMetrics;
MetricList::iterator it;
for (it = m.metrics.begin(); it != m.metrics.end(); ++it)
if (filter.match ((*it)->getObject(), (*it)->getName()))
{
filteredMetrics.push_back (*it);
flatSize += (*it)->getLength();
}
int i = 0;
size_t flatIndex = 0;
size_t numberOfMetrics = filteredMetrics.size();
com::SafeArray <BSTR> retNames (numberOfMetrics);
com::SafeIfaceArray <IUnknown> retObjects (numberOfMetrics);
com::SafeArray <BSTR> retUnits (numberOfMetrics);
com::SafeArray <ULONG> retScales (numberOfMetrics);
com::SafeArray <ULONG> retSequenceNumbers (numberOfMetrics);
com::SafeArray <ULONG> retIndices (numberOfMetrics);
com::SafeArray <ULONG> retLengths (numberOfMetrics);
com::SafeArray <LONG> retData (flatSize);
for (it = filteredMetrics.begin(); it != filteredMetrics.end(); ++it, ++i)
{
ULONG *values, length, sequenceNumber;
/* @todo We may want to revise the query method to get rid of excessive alloc/memcpy calls. */
(*it)->query(&values, &length, &sequenceNumber);
LogFlow (("PerformanceCollector::QueryMetricsData() querying metric %s "
"returned %d values.\n", (*it)->getName(), length));
memcpy(retData.raw() + flatIndex, values, length * sizeof(*values));
Bstr tmp((*it)->getName());
tmp.detachTo(&retNames[i]);
(*it)->getObject().queryInterfaceTo (&retObjects[i]);
tmp = (*it)->getUnit();
tmp.detachTo(&retUnits[i]);
retScales[i] = (*it)->getScale();
retSequenceNumbers[i] = sequenceNumber;
retLengths[i] = length;
retIndices[i] = flatIndex;
flatIndex += length;
}
retNames.detachTo (ComSafeArrayOutArg (outMetricNames));
retObjects.detachTo (ComSafeArrayOutArg (outObjects));
retUnits.detachTo (ComSafeArrayOutArg (outUnits));
retScales.detachTo (ComSafeArrayOutArg (outScales));
retSequenceNumbers.detachTo (ComSafeArrayOutArg (outSequenceNumbers));
retIndices.detachTo (ComSafeArrayOutArg (outDataIndices));
retLengths.detachTo (ComSafeArrayOutArg (outDataLengths));
retData.detachTo (ComSafeArrayOutArg (outData));
return S_OK;
}
// public methods for internal purposes
///////////////////////////////////////////////////////////////////////////////
void PerformanceCollector::registerBaseMetric (pm::BaseMetric *baseMetric)
{
//LogFlowThisFuncEnter();
AutoCaller autoCaller (this);
if (!SUCCEEDED (autoCaller.rc())) return;
AutoWriteLock alock (this);
LogAleksey(("{%p} " LOG_FN_FMT ": obj=%p name=%s\n", this, __PRETTY_FUNCTION__, (void *)baseMetric->getObject(), baseMetric->getName()));
m.baseMetrics.push_back (baseMetric);
//LogFlowThisFuncLeave();
}
void PerformanceCollector::registerMetric (pm::Metric *metric)
{
//LogFlowThisFuncEnter();
AutoCaller autoCaller (this);
if (!SUCCEEDED (autoCaller.rc())) return;
AutoWriteLock alock (this);
LogAleksey(("{%p} " LOG_FN_FMT ": obj=%p name=%s\n", this, __PRETTY_FUNCTION__, (void *)metric->getObject(), metric->getName()));
m.metrics.push_back (metric);
//LogFlowThisFuncLeave();
}
void PerformanceCollector::unregisterBaseMetricsFor (const ComPtr <IUnknown> &aObject)
{
//LogFlowThisFuncEnter();
AutoCaller autoCaller (this);
if (!SUCCEEDED (autoCaller.rc())) return;
AutoWriteLock alock (this);
LogAleksey(("{%p} " LOG_FN_FMT ": before remove_if: m.baseMetrics.size()=%d\n", this, __PRETTY_FUNCTION__, m.baseMetrics.size()));
BaseMetricList::iterator it = std::remove_if (
m.baseMetrics.begin(), m.baseMetrics.end(), std::bind2nd (
std::mem_fun (&pm::BaseMetric::associatedWith), aObject));
m.baseMetrics.erase(it, m.baseMetrics.end());
LogAleksey(("{%p} " LOG_FN_FMT ": after remove_if: m.baseMetrics.size()=%d\n", this, __PRETTY_FUNCTION__, m.baseMetrics.size()));
//LogFlowThisFuncLeave();
}
void PerformanceCollector::unregisterMetricsFor (const ComPtr <IUnknown> &aObject)
{
//LogFlowThisFuncEnter();
AutoCaller autoCaller (this);
if (!SUCCEEDED (autoCaller.rc())) return;
AutoWriteLock alock (this);
LogAleksey(("{%p} " LOG_FN_FMT ": obj=%p\n", this, __PRETTY_FUNCTION__, (void *)aObject));
MetricList::iterator it = std::remove_if (
m.metrics.begin(), m.metrics.end(), std::bind2nd (
std::mem_fun (&pm::Metric::associatedWith), aObject));
m.metrics.erase(it, m.metrics.end());
//LogFlowThisFuncLeave();
}
// private methods
///////////////////////////////////////////////////////////////////////////////
/* static */
void PerformanceCollector::staticSamplerCallback (RTTIMERLR hTimerLR, void *pvUser,
uint64_t iTick)
{
AssertReturnVoid (pvUser != NULL);
PerformanceCollector *collector = static_cast <PerformanceCollector *> (pvUser);
Assert (collector->mMagic == MAGIC);
if (collector->mMagic == MAGIC)
{
collector->samplerCallback();
}
NOREF (hTimerLR);
}
void PerformanceCollector::samplerCallback()
{
Log4(("{%p} " LOG_FN_FMT ": ENTER\n", this, __PRETTY_FUNCTION__));
AutoWriteLock alock (this);
pm::CollectorHints hints;
uint64_t timestamp = RTTimeMilliTS();
BaseMetricList toBeCollected;
BaseMetricList::iterator it;
/* Compose the list of metrics being collected at this moment */
for (it = m.baseMetrics.begin(); it != m.baseMetrics.end(); it++)
if ((*it)->collectorBeat(timestamp))
{
(*it)->preCollect(hints);
toBeCollected.push_back(*it);
}
if (toBeCollected.size() == 0)
return;
/* Let know the platform specific code what is being collected */
m.hal->preCollect(hints);
/* Finally, collect the data */
std::for_each (toBeCollected.begin(), toBeCollected.end(),
std::mem_fun (&pm::BaseMetric::collect));
Log4(("{%p} " LOG_FN_FMT ": LEAVE\n", this, __PRETTY_FUNCTION__));
}
////////////////////////////////////////////////////////////////////////////////
// PerformanceMetric class
////////////////////////////////////////////////////////////////////////////////
// constructor / destructor
////////////////////////////////////////////////////////////////////////////////
PerformanceMetric::PerformanceMetric()
{
}
PerformanceMetric::~PerformanceMetric()
{
}
HRESULT PerformanceMetric::FinalConstruct()
{
LogFlowThisFunc (("\n"));
return S_OK;
}
void PerformanceMetric::FinalRelease()
{
LogFlowThisFunc (("\n"));
uninit ();
}
// public initializer/uninitializer for internal purposes only
////////////////////////////////////////////////////////////////////////////////
HRESULT PerformanceMetric::init (pm::Metric *aMetric)
{
m.name = aMetric->getName();
m.object = aMetric->getObject();
m.description = aMetric->getDescription();
m.period = aMetric->getPeriod();
m.count = aMetric->getLength();
m.unit = aMetric->getUnit();
m.min = aMetric->getMinValue();
m.max = aMetric->getMaxValue();
return S_OK;
}
HRESULT PerformanceMetric::init (pm::BaseMetric *aMetric)
{
m.name = aMetric->getName();
m.object = aMetric->getObject();
m.description = "";
m.period = aMetric->getPeriod();
m.count = aMetric->getLength();
m.unit = aMetric->getUnit();
m.min = aMetric->getMinValue();
m.max = aMetric->getMaxValue();
return S_OK;
}
void PerformanceMetric::uninit()
{
}
STDMETHODIMP PerformanceMetric::COMGETTER(MetricName) (BSTR *aMetricName)
{
/// @todo (r=dmik) why do all these getters not do AutoCaller and
/// AutoReadLock? Is the underlying metric a constant object?
m.name.cloneTo (aMetricName);
return S_OK;
}
STDMETHODIMP PerformanceMetric::COMGETTER(Object) (IUnknown **anObject)
{
m.object.queryInterfaceTo(anObject);
return S_OK;
}
STDMETHODIMP PerformanceMetric::COMGETTER(Description) (BSTR *aDescription)
{
m.description.cloneTo (aDescription);
return S_OK;
}
STDMETHODIMP PerformanceMetric::COMGETTER(Period) (ULONG *aPeriod)
{
*aPeriod = m.period;
return S_OK;
}
STDMETHODIMP PerformanceMetric::COMGETTER(Count) (ULONG *aCount)
{
*aCount = m.count;
return S_OK;
}
STDMETHODIMP PerformanceMetric::COMGETTER(Unit) (BSTR *aUnit)
{
m.unit.cloneTo(aUnit);
return S_OK;
}
STDMETHODIMP PerformanceMetric::COMGETTER(MinimumValue) (LONG *aMinValue)
{
*aMinValue = m.min;
return S_OK;
}
STDMETHODIMP PerformanceMetric::COMGETTER(MaximumValue) (LONG *aMaxValue)
{
*aMaxValue = m.max;
return S_OK;
}
/* vi: set tabstop=4 shiftwidth=4 expandtab: */