VirtualBox

source: vbox/trunk/src/VBox/Main/PerformanceImpl.cpp@ 10692

Last change on this file since 10692 was 10679, checked in by vboxsync, 17 years ago

Filtering sketched. There is a crash in VirtualBox::uninit on Windows.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.5 KB
Line 
1/* $Id: PerformanceImpl.cpp 10679 2008-07-15 18:59:56Z vboxsync $ */
2
3/** @file
4 *
5 * VBox Performance API COM Classes implementation
6 */
7
8/*
9 * Copyright (C) 2008 Sun Microsystems, Inc.
10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.virtualbox.org. This file is free software;
13 * you can redistribute it and/or modify it under the terms of the GNU
14 * General Public License (GPL) as published by the Free Software
15 * Foundation, in version 2 as it comes in the "COPYING" file of the
16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18 *
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
20 * Clara, CA 95054 USA or visit http://www.sun.com if you need
21 * additional information or have any questions.
22 */
23
24#if defined(RT_OS_WINDOWS)
25#elif defined(RT_OS_LINUX)
26#endif
27
28#include "PerformanceImpl.h"
29
30#include "Logging.h"
31
32#include <VBox/err.h>
33#include <iprt/process.h>
34
35#include <vector>
36#include <algorithm>
37#include <functional>
38
39static Bstr gMetricNames[] =
40{
41 "CPU/Load/User:avg",
42 "CPU/Load/User:min",
43 "CPU/Load/User:max",
44 "CPU/Load/Kernel:avg",
45 "CPU/Load/Kernel:min",
46 "CPU/Load/Kernel:max",
47 "CPU/Load/Idle:avg",
48 "CPU/Load/Idle:min",
49 "CPU/Load/Idle:max",
50 "CPU/MHz:avg",
51 "CPU/MHz:min",
52 "CPU/MHz:max",
53 "RAM/Usage/Total:avg",
54 "RAM/Usage/Total:min",
55 "RAM/Usage/Total:max",
56 "RAM/Usage/Used:avg",
57 "RAM/Usage/Used:min",
58 "RAM/Usage/Used:max",
59 "RAM/Usage/Free:avg",
60 "RAM/Usage/Free:min",
61 "RAM/Usage/Free:max",
62};
63
64////////////////////////////////////////////////////////////////////////////////
65// PerformanceCollector class
66////////////////////////////////////////////////////////////////////////////////
67
68// constructor / destructor
69////////////////////////////////////////////////////////////////////////////////
70
71PerformanceCollector::PerformanceCollector() {}
72
73PerformanceCollector::~PerformanceCollector() {}
74
75HRESULT PerformanceCollector::FinalConstruct()
76{
77 LogFlowThisFunc (("\n"));
78
79 return S_OK;
80}
81
82void PerformanceCollector::FinalRelease()
83{
84 LogFlowThisFunc (("\n"));
85}
86
87// public initializer/uninitializer for internal purposes only
88////////////////////////////////////////////////////////////////////////////////
89
90/**
91 * Initializes the PerformanceCollector object.
92 */
93HRESULT PerformanceCollector::init()
94{
95 /* Enclose the state transition NotReady->InInit->Ready */
96 AutoInitSpan autoInitSpan (this);
97 AssertReturn (autoInitSpan.isOk(), E_UNEXPECTED);
98
99 LogFlowThisFuncEnter();
100
101 HRESULT rc = S_OK;
102
103 /* @todo Obviously other platforms must be added as well. */
104 m.mFactory = new pm::MetricFactoryLinux();
105 /* Start resource usage sampler */
106
107 int vrc = RTTimerCreate (&m.mSampler, VBOX_USAGE_SAMPLER_MIN_INTERVAL,
108 &PerformanceCollector::staticSamplerCallback, this);
109 AssertMsgRC (vrc, ("Failed to create resource usage "
110 "sampling timer(%Rra)\n", vrc));
111 if (RT_FAILURE (vrc))
112 rc = E_FAIL;
113
114 if (SUCCEEDED (rc))
115 autoInitSpan.setSucceeded();
116
117 LogFlowThisFuncLeave();
118
119 return rc;
120}
121
122/**
123 * Uninitializes the PerformanceCollector object.
124 *
125 * Called either from FinalRelease() or by the parent when it gets destroyed.
126 */
127void PerformanceCollector::uninit()
128{
129 LogFlowThisFuncEnter();
130
131 /* Enclose the state transition Ready->InUninit->NotReady */
132 AutoUninitSpan autoUninitSpan (this);
133 if (autoUninitSpan.uninitDone())
134 {
135 LogFlowThisFunc (("Already uninitialized.\n"));
136 LogFlowThisFuncLeave();
137 return;
138 }
139
140 /* Destroy resource usage sampler */
141 int vrc = RTTimerDestroy (m.mSampler);
142 AssertMsgRC (vrc, ("Failed to destroy resource usage "
143 "sampling timer (%Rra)\n", vrc));
144 m.mSampler = NULL;
145
146 delete m.mFactory;
147 m.mFactory = NULL;
148
149 LogFlowThisFuncLeave();
150}
151
152// IPerformanceCollector properties
153////////////////////////////////////////////////////////////////////////////////
154
155STDMETHODIMP
156PerformanceCollector::COMGETTER(MetricNames) (ComSafeArrayOut (BSTR, theMetricNames))
157{
158 if (ComSafeArrayOutIsNull (theMetricNames))
159 return E_POINTER;
160
161 AutoCaller autoCaller (this);
162 CheckComRCReturnRC (autoCaller.rc());
163
164 AutoReadLock alock (this);
165
166 com::SafeArray <BSTR> metricNames(RT_ELEMENTS(gMetricNames));
167 for (size_t i = 0; i < RT_ELEMENTS(gMetricNames); i++)
168 {
169 gMetricNames[i].detachTo(&metricNames[i]);
170 }
171 //gMetricNames.detachTo(ComSafeArrayOutArg (theMetricNames));
172 metricNames.detachTo (ComSafeArrayOutArg (theMetricNames));
173
174 return S_OK;
175}
176
177// IPerformanceCollector methods
178////////////////////////////////////////////////////////////////////////////////
179
180STDMETHODIMP PerformanceCollector::GetMetrics(ComSafeArrayIn(const BSTR, metricNames),
181 ComSafeArrayIn(IUnknown *, objects),
182 ComSafeArrayOut(IPerformanceMetric *, metrics))
183{
184 //LogFlowThisFunc (("mState=%d, mType=%d\n", mState, mType));
185
186 AutoCaller autoCaller (this);
187 CheckComRCReturnRC (autoCaller.rc());
188
189 return E_NOTIMPL;
190}
191
192STDMETHODIMP PerformanceCollector::SetupMetrics (ComSafeArrayIn(const BSTR, metricNames),
193 ComSafeArrayIn(IUnknown *, objects),
194 ULONG aPeriod, ULONG aCount)
195{
196 pm::Filter filter(ComSafeArrayInArg(metricNames), ComSafeArrayInArg(objects));
197
198 BaseMetricList::iterator it;
199 for (it = m.mBaseMetrics.begin(); it != m.mBaseMetrics.end(); ++it)
200 if (filter.match((*it)->getObject(), (*it)->getName()))
201 (*it)->init(aPeriod, aCount);
202
203 return S_OK;
204}
205
206STDMETHODIMP PerformanceCollector::EnableMetrics (ComSafeArrayIn(const BSTR, metricNames),
207 ComSafeArrayIn(IUnknown *, objects))
208{
209 return E_NOTIMPL;
210}
211
212STDMETHODIMP PerformanceCollector::DisableMetrics (ComSafeArrayIn(const BSTR, metricNames),
213 ComSafeArrayIn(IUnknown *, objects))
214{
215 return E_NOTIMPL;
216}
217
218STDMETHODIMP PerformanceCollector::QueryMetricsData (ComSafeArrayIn(const BSTR, metricNames),
219 ComSafeArrayIn(IUnknown *, objects),
220 ComSafeArrayOut(BSTR, outMetricNames),
221 ComSafeArrayOut(IUnknown *, outObjects),
222 ComSafeArrayOut(ULONG, outDataIndices),
223 ComSafeArrayOut(ULONG, outDataLengths),
224 ComSafeArrayOut(LONG, outData))
225{
226 AutoCaller autoCaller (this);
227 CheckComRCReturnRC (autoCaller.rc());
228
229 /// @todo r=dmik don't we need to lock this for reading?
230
231 int i;
232 MetricList::const_iterator it;
233 /* Let's compute the size of the resulting flat array */
234 size_t flatSize = 0, numberOfMetrics = 0;
235 for (it = m.mMetrics.begin(); it != m.mMetrics.end(); ++it)
236 {
237 /* @todo Filtering goes here! */
238 flatSize += (*it)->getLength();
239 ++numberOfMetrics;
240 }
241 size_t flatIndex = 0;
242 com::SafeArray<BSTR> retNames(numberOfMetrics);
243 com::SafeIfaceArray<IUnknown> retObjects(numberOfMetrics);
244 com::SafeArray<ULONG> retIndices(numberOfMetrics);
245 com::SafeArray<ULONG> retLengths(numberOfMetrics);
246 com::SafeArray<LONG> retData(flatSize);
247 for (it = m.mMetrics.begin(), i = 0; it != m.mMetrics.end(); ++it)
248 {
249 /* @todo Filtering goes here! */
250 unsigned long *values, length;
251 /* @todo We may want to revise the query method to get rid of excessive alloc/memcpy calls. */
252 (*it)->query(&values, &length);
253 memcpy(retData.raw() + flatIndex, values, length * sizeof(*values));
254 Bstr tmp((*it)->getName());
255 tmp.detachTo(&retNames[i]);
256 retObjects[i] = (*it)->getObject();
257 retLengths[i] = length;
258 retIndices[i] = flatIndex;
259 ++i;
260 flatIndex += length;
261 }
262 retNames.detachTo(ComSafeArrayOutArg(outMetricNames));
263 retObjects.detachTo(ComSafeArrayOutArg(outObjects));
264 retIndices.detachTo(ComSafeArrayOutArg(outDataIndices));
265 retLengths.detachTo(ComSafeArrayOutArg(outDataLengths));
266 retData.detachTo(ComSafeArrayOutArg(outData));
267 return S_OK;
268}
269
270// public methods for internal purposes
271///////////////////////////////////////////////////////////////////////////////
272
273void PerformanceCollector::registerBaseMetric (pm::BaseMetric *baseMetric)
274{
275 m.mBaseMetrics.push_back (baseMetric);
276}
277
278void PerformanceCollector::registerMetric (pm::Metric *metric)
279{
280 m.mMetrics.push_back (metric);
281}
282
283void PerformanceCollector::unregisterBaseMetricsFor (const ComPtr <IUnknown> &aObject)
284{
285 std::remove_if (m.mBaseMetrics.begin(), m.mBaseMetrics.end(),
286 std::bind2nd (std::mem_fun (&pm::BaseMetric::associatedWith),
287 aObject));
288}
289
290void PerformanceCollector::unregisterMetricsFor (const ComPtr <IUnknown> &aObject)
291{
292 std::remove_if (m.mMetrics.begin(), m.mMetrics.end(),
293 std::bind2nd (std::mem_fun (&pm::Metric::associatedWith),
294 aObject));
295}
296
297// private methods
298///////////////////////////////////////////////////////////////////////////////
299
300/* static */
301void PerformanceCollector::staticSamplerCallback (PRTTIMER pTimer, void *pvUser,
302 uint64_t iTick)
303{
304 AssertReturnVoid (pvUser != NULL);
305 static_cast <PerformanceCollector *> (pvUser)->samplerCallback();
306}
307
308void PerformanceCollector::samplerCallback()
309{
310}
311
312////////////////////////////////////////////////////////////////////////////////
313// PerformanceMetric class
314////////////////////////////////////////////////////////////////////////////////
315
316// constructor / destructor
317////////////////////////////////////////////////////////////////////////////////
318
319PerformanceMetric::PerformanceMetric()
320{
321 mMetric = 0;
322}
323
324PerformanceMetric::~PerformanceMetric()
325{
326}
327
328HRESULT PerformanceMetric::FinalConstruct()
329{
330 LogFlowThisFunc (("\n"));
331
332 return S_OK;
333}
334
335void PerformanceMetric::FinalRelease()
336{
337 LogFlowThisFunc (("\n"));
338
339 uninit ();
340}
341
342// public initializer/uninitializer for internal purposes only
343////////////////////////////////////////////////////////////////////////////////
344
345HRESULT PerformanceMetric::init (pm::Metric *aMetric)
346{
347 mMetric = aMetric;
348 return S_OK;
349}
350
351void PerformanceMetric::uninit()
352{
353}
354
355STDMETHODIMP PerformanceMetric::COMGETTER(MetricName) (BSTR *aMetricName)
356{
357 Bstr tmp (mMetric->getName());
358 tmp.detachTo (aMetricName);
359 return S_OK;
360}
361
362STDMETHODIMP PerformanceMetric::COMGETTER(Object) (IUnknown **anObject)
363{
364 *anObject = mMetric->getObject();
365 return S_OK;
366}
367
368STDMETHODIMP PerformanceMetric::COMGETTER(Period) (unsigned long *aPeriod)
369{
370 *aPeriod = mMetric->getPeriod();
371 return S_OK;
372}
373
374STDMETHODIMP PerformanceMetric::COMGETTER(Count) (unsigned long *aCount)
375{
376 *aCount = mMetric->getLength();
377 return S_OK;
378}
379
380STDMETHODIMP PerformanceMetric::COMGETTER(Unit) (BSTR *aUnit)
381{
382 Bstr tmp(mMetric->getUnit());
383 tmp.detachTo(aUnit);
384 return S_OK;
385}
386
387STDMETHODIMP PerformanceMetric::COMGETTER(MinValue) (long *aMinValue)
388{
389 *aMinValue = mMetric->getMinValue();
390 return S_OK;
391}
392
393STDMETHODIMP PerformanceMetric::COMGETTER(MaxValue) (long *aMaxValue)
394{
395 *aMaxValue = mMetric->getMaxValue();
396 return S_OK;
397}
398
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette