PerformanceImpl.cpp revision a22ec79dbd472646c0bb325fe23fba65e84b0ba0
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync/* $Id$ */
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync/** @file
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync *
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync * VBox Performance API COM Classes implementation
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync */
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync/*
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync * Copyright (C) 2008 Sun Microsystems, Inc.
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync *
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync * available from http://www.virtualbox.org. This file is free software;
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync * you can redistribute it and/or modify it under the terms of the GNU
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync * General Public License (GPL) as published by the Free Software
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync *
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync * additional information or have any questions.
a29514824e39ac5a1f61fb4edc54365db9e769ffvboxsync */
a29514824e39ac5a1f61fb4edc54365db9e769ffvboxsync
a29514824e39ac5a1f61fb4edc54365db9e769ffvboxsync#include "PerformanceImpl.h"
a29514824e39ac5a1f61fb4edc54365db9e769ffvboxsync
a29514824e39ac5a1f61fb4edc54365db9e769ffvboxsync#include "Logging.h"
a29514824e39ac5a1f61fb4edc54365db9e769ffvboxsync
a29514824e39ac5a1f61fb4edc54365db9e769ffvboxsync#include <iprt/process.h>
a29514824e39ac5a1f61fb4edc54365db9e769ffvboxsync
a29514824e39ac5a1f61fb4edc54365db9e769ffvboxsync#include <VBox/err.h>
a29514824e39ac5a1f61fb4edc54365db9e769ffvboxsync#include <VBox/settings.h>
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync#include <vector>
020e605b23c3a12ea9f74c85456da2b83338b7dfvboxsync#include <algorithm>
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync#include <functional>
020e605b23c3a12ea9f74c85456da2b83338b7dfvboxsync
020e605b23c3a12ea9f74c85456da2b83338b7dfvboxsync#include "Performance.h"
b0857f8608931dbbc92393a6cb8f478e65e7c2f1vboxsync
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsyncstatic Bstr gMetricNames[] =
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync{
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync "CPU/Load/User",
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync "CPU/Load/User:avg",
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync "CPU/Load/User:min",
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync "CPU/Load/User:max",
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync "CPU/Load/Kernel",
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync "CPU/Load/Kernel:avg",
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync "CPU/Load/Kernel:min",
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync "CPU/Load/Kernel:max",
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync "CPU/Load/Idle",
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync "CPU/Load/Idle:avg",
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync "CPU/Load/Idle:min",
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync "CPU/Load/Idle:max",
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync "CPU/MHz",
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync "CPU/MHz:avg",
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync "CPU/MHz:min",
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync "CPU/MHz:max",
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync "RAM/Usage/Total",
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync "RAM/Usage/Total:avg",
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync "RAM/Usage/Total:min",
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync "RAM/Usage/Total:max",
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync "RAM/Usage/Used",
c04329c1821d23bc561f56aee79d64af1b6aaf59vboxsync "RAM/Usage/Used:avg",
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync "RAM/Usage/Used:min",
bb424850773b1cf1ae7a69650e7841f0cda3b350vboxsync "RAM/Usage/Used:max",
c04329c1821d23bc561f56aee79d64af1b6aaf59vboxsync "RAM/Usage/Free",
bb424850773b1cf1ae7a69650e7841f0cda3b350vboxsync "RAM/Usage/Free:avg",
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync "RAM/Usage/Free:min",
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync "RAM/Usage/Free:max",
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync};
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync////////////////////////////////////////////////////////////////////////////////
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync// PerformanceCollector class
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync////////////////////////////////////////////////////////////////////////////////
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync// constructor / destructor
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync////////////////////////////////////////////////////////////////////////////////
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsyncPerformanceCollector::PerformanceCollector() : mMagic(0) {}
020e605b23c3a12ea9f74c85456da2b83338b7dfvboxsync
020e605b23c3a12ea9f74c85456da2b83338b7dfvboxsyncPerformanceCollector::~PerformanceCollector() {}
020e605b23c3a12ea9f74c85456da2b83338b7dfvboxsync
020e605b23c3a12ea9f74c85456da2b83338b7dfvboxsyncHRESULT PerformanceCollector::FinalConstruct()
020e605b23c3a12ea9f74c85456da2b83338b7dfvboxsync{
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync LogFlowThisFunc(("\n"));
b0857f8608931dbbc92393a6cb8f478e65e7c2f1vboxsync
b0857f8608931dbbc92393a6cb8f478e65e7c2f1vboxsync return S_OK;
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync}
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsyncvoid PerformanceCollector::FinalRelease()
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync{
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync LogFlowThisFunc(("\n"));
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync}
e83ee7cc9435a283e124399e410366174ae96a8avboxsync
020e605b23c3a12ea9f74c85456da2b83338b7dfvboxsync// public initializer/uninitializer for internal purposes only
e83ee7cc9435a283e124399e410366174ae96a8avboxsync////////////////////////////////////////////////////////////////////////////////
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync/**
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync * Initializes the PerformanceCollector object.
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync */
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsyncHRESULT PerformanceCollector::init()
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync{
020e605b23c3a12ea9f74c85456da2b83338b7dfvboxsync /* Enclose the state transition NotReady->InInit->Ready */
020e605b23c3a12ea9f74c85456da2b83338b7dfvboxsync AutoInitSpan autoInitSpan(this);
a29514824e39ac5a1f61fb4edc54365db9e769ffvboxsync AssertReturn(autoInitSpan.isOk(), E_FAIL);
a29514824e39ac5a1f61fb4edc54365db9e769ffvboxsync
a29514824e39ac5a1f61fb4edc54365db9e769ffvboxsync LogFlowThisFuncEnter();
a29514824e39ac5a1f61fb4edc54365db9e769ffvboxsync
020e605b23c3a12ea9f74c85456da2b83338b7dfvboxsync HRESULT rc = S_OK;
020e605b23c3a12ea9f74c85456da2b83338b7dfvboxsync
020e605b23c3a12ea9f74c85456da2b83338b7dfvboxsync m.hal = pm::createHAL();
020e605b23c3a12ea9f74c85456da2b83338b7dfvboxsync
020e605b23c3a12ea9f74c85456da2b83338b7dfvboxsync /* Let the sampler know it gets a valid collector. */
b0857f8608931dbbc92393a6cb8f478e65e7c2f1vboxsync mMagic = MAGIC;
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync /* Start resource usage sampler */
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync int vrc = RTTimerLRCreate (&m.sampler, VBOX_USAGE_SAMPLER_MIN_INTERVAL,
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync &PerformanceCollector::staticSamplerCallback, this);
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync AssertMsgRC (vrc, ("Failed to create resource usage "
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync "sampling timer(%Rra)\n", vrc));
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync if (RT_FAILURE(vrc))
67be63ee622575061bd19d462a747767ddca9900vboxsync rc = E_FAIL;
67be63ee622575061bd19d462a747767ddca9900vboxsync
b0857f8608931dbbc92393a6cb8f478e65e7c2f1vboxsync if (SUCCEEDED(rc))
b0857f8608931dbbc92393a6cb8f478e65e7c2f1vboxsync autoInitSpan.setSucceeded();
b0857f8608931dbbc92393a6cb8f478e65e7c2f1vboxsync
b0857f8608931dbbc92393a6cb8f478e65e7c2f1vboxsync LogFlowThisFuncLeave();
b0857f8608931dbbc92393a6cb8f478e65e7c2f1vboxsync
b0857f8608931dbbc92393a6cb8f478e65e7c2f1vboxsync return rc;
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync}
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync/**
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync * Uninitializes the PerformanceCollector object.
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync *
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync * Called either from FinalRelease() or by the parent when it gets destroyed.
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync */
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsyncvoid PerformanceCollector::uninit()
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync{
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync LogFlowThisFuncEnter();
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync /* Enclose the state transition Ready->InUninit->NotReady */
b0857f8608931dbbc92393a6cb8f478e65e7c2f1vboxsync AutoUninitSpan autoUninitSpan(this);
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync if (autoUninitSpan.uninitDone())
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync {
b0857f8608931dbbc92393a6cb8f478e65e7c2f1vboxsync LogFlowThisFunc(("Already uninitialized.\n"));
b0857f8608931dbbc92393a6cb8f478e65e7c2f1vboxsync LogFlowThisFuncLeave();
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync return;
b0857f8608931dbbc92393a6cb8f478e65e7c2f1vboxsync }
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync mMagic = 0;
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync /* Destroy resource usage sampler */
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync int vrc = RTTimerLRDestroy (m.sampler);
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync AssertMsgRC (vrc, ("Failed to destroy resource usage "
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync "sampling timer (%Rra)\n", vrc));
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync m.sampler = NULL;
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync //delete m.factory;
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync //m.factory = NULL;
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync delete m.hal;
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync m.hal = NULL;
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync LogFlowThisFuncLeave();
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync}
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync// IPerformanceCollector properties
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync////////////////////////////////////////////////////////////////////////////////
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsyncSTDMETHODIMP
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsyncPerformanceCollector::COMGETTER(MetricNames) (ComSafeArrayOut(BSTR, theMetricNames))
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync{
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync if (ComSafeArrayOutIsNull(theMetricNames))
c04329c1821d23bc561f56aee79d64af1b6aaf59vboxsync return E_POINTER;
c04329c1821d23bc561f56aee79d64af1b6aaf59vboxsync
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync AutoCaller autoCaller(this);
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync CheckComRCReturnRC(autoCaller.rc());
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync AutoReadLock alock(this);
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync com::SafeArray<BSTR> metricNames(RT_ELEMENTS(gMetricNames));
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync for (size_t i = 0; i < RT_ELEMENTS(gMetricNames); i++)
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync {
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync Bstr tmp(gMetricNames[i]); /* gcc-3.3 cruft */
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync tmp.cloneTo(&metricNames[i]);
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync }
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync //gMetricNames.detachTo(ComSafeArrayOutArg(theMetricNames));
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync metricNames.detachTo(ComSafeArrayOutArg(theMetricNames));
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync return S_OK;
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync}
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync// IPerformanceCollector methods
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync////////////////////////////////////////////////////////////////////////////////
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsyncHRESULT PerformanceCollector::toIPerformanceMetric(pm::Metric *src, IPerformanceMetric **dst)
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync{
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync ComObjPtr<PerformanceMetric> metric;
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync HRESULT rc = metric.createObject();
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync if (SUCCEEDED(rc))
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync rc = metric->init (src);
c04329c1821d23bc561f56aee79d64af1b6aaf59vboxsync AssertComRCReturnRC(rc);
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync metric.queryInterfaceTo(dst);
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync return rc;
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync}
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsyncHRESULT PerformanceCollector::toIPerformanceMetric(pm::BaseMetric *src, IPerformanceMetric **dst)
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync{
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync ComObjPtr<PerformanceMetric> metric;
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync HRESULT rc = metric.createObject();
a29514824e39ac5a1f61fb4edc54365db9e769ffvboxsync if (SUCCEEDED(rc))
a29514824e39ac5a1f61fb4edc54365db9e769ffvboxsync rc = metric->init (src);
bb424850773b1cf1ae7a69650e7841f0cda3b350vboxsync AssertComRCReturnRC(rc);
bb424850773b1cf1ae7a69650e7841f0cda3b350vboxsync metric.queryInterfaceTo(dst);
bb424850773b1cf1ae7a69650e7841f0cda3b350vboxsync return rc;
a29514824e39ac5a1f61fb4edc54365db9e769ffvboxsync}
bb424850773b1cf1ae7a69650e7841f0cda3b350vboxsync
bb424850773b1cf1ae7a69650e7841f0cda3b350vboxsyncSTDMETHODIMP
bb424850773b1cf1ae7a69650e7841f0cda3b350vboxsyncPerformanceCollector::GetMetrics (ComSafeArrayIn (IN_BSTR, metricNames),
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync ComSafeArrayIn (IUnknown *, objects),
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync ComSafeArrayOut(IPerformanceMetric *, outMetrics))
bb424850773b1cf1ae7a69650e7841f0cda3b350vboxsync{
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync LogFlowThisFuncEnter();
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync //LogFlowThisFunc(("mState=%d, mType=%d\n", mState, mType));
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync HRESULT rc = S_OK;
020e605b23c3a12ea9f74c85456da2b83338b7dfvboxsync
020e605b23c3a12ea9f74c85456da2b83338b7dfvboxsync AutoCaller autoCaller(this);
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync CheckComRCReturnRC(autoCaller.rc());
020e605b23c3a12ea9f74c85456da2b83338b7dfvboxsync
bb424850773b1cf1ae7a69650e7841f0cda3b350vboxsync pm::Filter filter (ComSafeArrayInArg (metricNames),
bb424850773b1cf1ae7a69650e7841f0cda3b350vboxsync ComSafeArrayInArg (objects));
998f9a06af7dba98c7d2368b4a554b5f323937f6vboxsync
bb424850773b1cf1ae7a69650e7841f0cda3b350vboxsync AutoReadLock alock(this);
bb424850773b1cf1ae7a69650e7841f0cda3b350vboxsync
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync MetricList filteredMetrics;
998f9a06af7dba98c7d2368b4a554b5f323937f6vboxsync MetricList::iterator it;
998f9a06af7dba98c7d2368b4a554b5f323937f6vboxsync for (it = m.metrics.begin(); it != m.metrics.end(); ++it)
998f9a06af7dba98c7d2368b4a554b5f323937f6vboxsync if (filter.match ((*it)->getObject(), (*it)->getName()))
998f9a06af7dba98c7d2368b4a554b5f323937f6vboxsync filteredMetrics.push_back (*it);
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync com::SafeIfaceArray<IPerformanceMetric> retMetrics (filteredMetrics.size());
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync int i = 0;
0c1a49387cf675cfb205c773eae123c59ffea2c4vboxsync for (it = filteredMetrics.begin(); it != filteredMetrics.end(); ++it)
{
ComObjPtr<PerformanceMetric> metric;
rc = metric.createObject();
if (SUCCEEDED(rc))
rc = metric->init (*it);
AssertComRCReturnRC(rc);
LogFlow (("PerformanceCollector::GetMetrics() store a metric at "
"retMetrics[%d]...\n", i));
metric.queryInterfaceTo(&retMetrics [i++]);
}
retMetrics.detachTo(ComSafeArrayOutArg(outMetrics));
LogFlowThisFuncLeave();
return rc;
}
STDMETHODIMP
PerformanceCollector::SetupMetrics (ComSafeArrayIn (IN_BSTR, metricNames),
ComSafeArrayIn (IUnknown *, objects),
ULONG aPeriod, ULONG aCount,
ComSafeArrayOut(IPerformanceMetric *,
outMetrics))
{
AutoCaller autoCaller(this);
CheckComRCReturnRC(autoCaller.rc());
pm::Filter filter (ComSafeArrayInArg (metricNames),
ComSafeArrayInArg (objects));
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] = (ULONG)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;
for (it = m.baseMetrics.begin(); it != m.baseMetrics.end();)
if ((*it)->associatedWith(aObject))
{
/** @todo r=bird: This looks dodgy and needs to be tested with a VBOX_WITH_DEBUG_VCC_CRT. How to reproduce? */
delete *it;
m.baseMetrics.erase(it++);
}
else
++it;
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;
for (it = m.metrics.begin(); it != m.metrics.end();)
if ((*it)->associatedWith(aObject))
{
/** @todo r=bird: This looks dodgy and needs to be tested with a VBOX_WITH_DEBUG_VCC_CRT. How to reproduce? */
delete *it;
m.metrics.erase(it++);
}
else
++it;
//LogFlowThisFuncLeave();
}
void PerformanceCollector::suspendSampling()
{
AutoCaller autoCaller(this);
if (!SUCCEEDED(autoCaller.rc())) return;
int rc = RTTimerLRStop(m.sampler);
AssertRC(rc);
}
void PerformanceCollector::resumeSampling()
{
AutoCaller autoCaller(this);
if (!SUCCEEDED(autoCaller.rc())) return;
int rc = RTTimerLRStart(m.sampler, 0);
AssertRC(rc);
}
// 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: */