VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/PerformanceImpl.cpp@ 56307

Last change on this file since 56307 was 55988, checked in by vboxsync, 10 years ago

iprt/log.h,SUPDrv: Replaced the 'personal' logging groups with 6 more generic logging levels (7 thru 12) and a 'Warn' level. The 'Warn' level is enabled by 'group.e' together with level 1 logging. Modified the new RTLog[Rel][Get]DefaultInstanceEx functions to only take one 32-bit parameter to minimize call setup time and size. Major support driver version bump. LogAleksey=Log7, LogBird=Log8, LogSunlover=Log9, none of the other personal macros was used. Log*Warning got renamed to Log1*Warning so as to not confuse it with the LogWarn/LogRelWarn macros.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 29.0 KB
Line 
1/* $Id: PerformanceImpl.cpp 55988 2015-05-20 23:24:44Z vboxsync $ */
2
3/** @file
4 *
5 * VBox Performance API COM Classes implementation
6 */
7
8/*
9 * Copyright (C) 2008-2012 Oracle Corporation
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
20/*
21 * Rules of engagement:
22 * 1) All performance objects must be destroyed by PerformanceCollector only!
23 * 2) All public methods of PerformanceCollector must be protected with
24 * read or write lock.
25 * 3) samplerCallback only uses the write lock during the third phase
26 * which pulls data into SubMetric objects. This is where object destruction
27 * and all list modifications are done. The pre-collection phases are
28 * run without any locks which is only possible because:
29 * 4) Public methods of PerformanceCollector as well as pre-collection methods
30 cannot modify lists or destroy objects, and:
31 * 5) Pre-collection methods cannot modify metric data.
32 */
33
34#include "PerformanceImpl.h"
35
36#include "AutoCaller.h"
37#include "Logging.h"
38
39#include <iprt/process.h>
40
41#include <VBox/err.h>
42#include <VBox/settings.h>
43
44#include <vector>
45#include <algorithm>
46#include <functional>
47
48#include "Performance.h"
49
50static const char *g_papcszMetricNames[] =
51{
52 "CPU/Load/User",
53 "CPU/Load/User:avg",
54 "CPU/Load/User:min",
55 "CPU/Load/User:max",
56 "CPU/Load/Kernel",
57 "CPU/Load/Kernel:avg",
58 "CPU/Load/Kernel:min",
59 "CPU/Load/Kernel:max",
60 "CPU/Load/Idle",
61 "CPU/Load/Idle:avg",
62 "CPU/Load/Idle:min",
63 "CPU/Load/Idle:max",
64 "CPU/MHz",
65 "CPU/MHz:avg",
66 "CPU/MHz:min",
67 "CPU/MHz:max",
68 "Net/*/Load/Rx",
69 "Net/*/Load/Rx:avg",
70 "Net/*/Load/Rx:min",
71 "Net/*/Load/Rx:max",
72 "Net/*/Load/Tx",
73 "Net/*/Load/Tx:avg",
74 "Net/*/Load/Tx:min",
75 "Net/*/Load/Tx:max",
76 "RAM/Usage/Total",
77 "RAM/Usage/Total:avg",
78 "RAM/Usage/Total:min",
79 "RAM/Usage/Total:max",
80 "RAM/Usage/Used",
81 "RAM/Usage/Used:avg",
82 "RAM/Usage/Used:min",
83 "RAM/Usage/Used:max",
84 "RAM/Usage/Free",
85 "RAM/Usage/Free:avg",
86 "RAM/Usage/Free:min",
87 "RAM/Usage/Free:max",
88 "RAM/VMM/Used",
89 "RAM/VMM/Used:avg",
90 "RAM/VMM/Used:min",
91 "RAM/VMM/Used:max",
92 "RAM/VMM/Free",
93 "RAM/VMM/Free:avg",
94 "RAM/VMM/Free:min",
95 "RAM/VMM/Free:max",
96 "RAM/VMM/Ballooned",
97 "RAM/VMM/Ballooned:avg",
98 "RAM/VMM/Ballooned:min",
99 "RAM/VMM/Ballooned:max",
100 "RAM/VMM/Shared",
101 "RAM/VMM/Shared:avg",
102 "RAM/VMM/Shared:min",
103 "RAM/VMM/Shared:max",
104 "Guest/CPU/Load/User",
105 "Guest/CPU/Load/User:avg",
106 "Guest/CPU/Load/User:min",
107 "Guest/CPU/Load/User:max",
108 "Guest/CPU/Load/Kernel",
109 "Guest/CPU/Load/Kernel:avg",
110 "Guest/CPU/Load/Kernel:min",
111 "Guest/CPU/Load/Kernel:max",
112 "Guest/CPU/Load/Idle",
113 "Guest/CPU/Load/Idle:avg",
114 "Guest/CPU/Load/Idle:min",
115 "Guest/CPU/Load/Idle:max",
116 "Guest/RAM/Usage/Total",
117 "Guest/RAM/Usage/Total:avg",
118 "Guest/RAM/Usage/Total:min",
119 "Guest/RAM/Usage/Total:max",
120 "Guest/RAM/Usage/Free",
121 "Guest/RAM/Usage/Free:avg",
122 "Guest/RAM/Usage/Free:min",
123 "Guest/RAM/Usage/Free:max",
124 "Guest/RAM/Usage/Balloon",
125 "Guest/RAM/Usage/Balloon:avg",
126 "Guest/RAM/Usage/Balloon:min",
127 "Guest/RAM/Usage/Balloon:max",
128 "Guest/RAM/Usage/Shared",
129 "Guest/RAM/Usage/Shared:avg",
130 "Guest/RAM/Usage/Shared:min",
131 "Guest/RAM/Usage/Shared:max",
132 "Guest/RAM/Usage/Cache",
133 "Guest/RAM/Usage/Cache:avg",
134 "Guest/RAM/Usage/Cache:min",
135 "Guest/RAM/Usage/Cache:max",
136 "Guest/Pagefile/Usage/Total",
137 "Guest/Pagefile/Usage/Total:avg",
138 "Guest/Pagefile/Usage/Total:min",
139 "Guest/Pagefile/Usage/Total:max",
140};
141
142////////////////////////////////////////////////////////////////////////////////
143// PerformanceCollector class
144////////////////////////////////////////////////////////////////////////////////
145
146// constructor / destructor
147////////////////////////////////////////////////////////////////////////////////
148
149PerformanceCollector::PerformanceCollector()
150 : mMagic(0), mUnknownGuest("unknown guest")
151{
152}
153
154PerformanceCollector::~PerformanceCollector() {}
155
156HRESULT PerformanceCollector::FinalConstruct()
157{
158 LogFlowThisFunc(("\n"));
159
160 return BaseFinalConstruct();
161}
162
163void PerformanceCollector::FinalRelease()
164{
165 LogFlowThisFunc(("\n"));
166 BaseFinalRelease();
167}
168
169// public initializer/uninitializer for internal purposes only
170////////////////////////////////////////////////////////////////////////////////
171
172/**
173 * Initializes the PerformanceCollector object.
174 */
175HRESULT PerformanceCollector::init()
176{
177 /* Enclose the state transition NotReady->InInit->Ready */
178 AutoInitSpan autoInitSpan(this);
179 AssertReturn(autoInitSpan.isOk(), E_FAIL);
180
181 LogFlowThisFuncEnter();
182
183 HRESULT rc = S_OK;
184
185 m.hal = pm::createHAL();
186 m.gm = new pm::CollectorGuestManager;
187
188 /* Let the sampler know it gets a valid collector. */
189 mMagic = MAGIC;
190
191 /* Start resource usage sampler */
192 int vrc = RTTimerLRCreate (&m.sampler, VBOX_USAGE_SAMPLER_MIN_INTERVAL,
193 &PerformanceCollector::staticSamplerCallback, this);
194 AssertMsgRC (vrc, ("Failed to create resource usage "
195 "sampling timer(%Rra)\n", vrc));
196 if (RT_FAILURE(vrc))
197 rc = E_FAIL;
198
199 if (SUCCEEDED(rc))
200 autoInitSpan.setSucceeded();
201
202 LogFlowThisFuncLeave();
203
204 return rc;
205}
206
207/**
208 * Uninitializes the PerformanceCollector object.
209 *
210 * Called either from FinalRelease() or by the parent when it gets destroyed.
211 */
212void PerformanceCollector::uninit()
213{
214 LogFlowThisFuncEnter();
215
216 /* Enclose the state transition Ready->InUninit->NotReady */
217 AutoUninitSpan autoUninitSpan(this);
218 if (autoUninitSpan.uninitDone())
219 {
220 LogFlowThisFunc(("Already uninitialized.\n"));
221 LogFlowThisFuncLeave();
222 return;
223 }
224
225 mMagic = 0;
226
227 /* Destroy unregistered metrics */
228 BaseMetricList::iterator it;
229 for (it = m.baseMetrics.begin(); it != m.baseMetrics.end();)
230 if ((*it)->isUnregistered())
231 {
232 delete *it;
233 it = m.baseMetrics.erase(it);
234 }
235 else
236 ++it;
237 Assert(m.baseMetrics.size() == 0);
238 /*
239 * Now when we have destroyed all base metrics that could
240 * try to pull data from unregistered CollectorGuest objects
241 * it is safe to destroy them as well.
242 */
243 m.gm->destroyUnregistered();
244
245 /* Destroy resource usage sampler */
246 int vrc = RTTimerLRDestroy (m.sampler);
247 AssertMsgRC (vrc, ("Failed to destroy resource usage "
248 "sampling timer (%Rra)\n", vrc));
249 m.sampler = NULL;
250
251 //delete m.factory;
252 //m.factory = NULL;
253
254 delete m.gm;
255 m.gm = NULL;
256 delete m.hal;
257 m.hal = NULL;
258
259 LogFlowThisFuncLeave();
260}
261
262// IPerformanceCollector properties
263////////////////////////////////////////////////////////////////////////////////
264
265STDMETHODIMP PerformanceCollector::COMGETTER(MetricNames)(ComSafeArrayOut(BSTR, theMetricNames))
266{
267 if (ComSafeArrayOutIsNull(theMetricNames))
268 return E_POINTER;
269
270 AutoCaller autoCaller(this);
271 if (FAILED(autoCaller.rc())) return autoCaller.rc();
272
273 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
274
275 com::SafeArray<BSTR> metricNames(RT_ELEMENTS(g_papcszMetricNames));
276 for (size_t i = 0; i < RT_ELEMENTS(g_papcszMetricNames); i++)
277 {
278 Bstr tmp(g_papcszMetricNames[i]); /* gcc-3.3 cruft */
279 tmp.cloneTo(&metricNames[i]);
280 }
281 //gMetricNames.detachTo(ComSafeArrayOutArg(theMetricNames));
282 metricNames.detachTo(ComSafeArrayOutArg(theMetricNames));
283
284 return S_OK;
285}
286
287// IPerformanceCollector methods
288////////////////////////////////////////////////////////////////////////////////
289
290HRESULT PerformanceCollector::toIPerformanceMetric(pm::Metric *src, IPerformanceMetric **dst)
291{
292 ComObjPtr<PerformanceMetric> metric;
293 HRESULT rc = metric.createObject();
294 if (SUCCEEDED(rc))
295 rc = metric->init (src);
296 AssertComRCReturnRC(rc);
297 metric.queryInterfaceTo(dst);
298 return rc;
299}
300
301HRESULT PerformanceCollector::toIPerformanceMetric(pm::BaseMetric *src, IPerformanceMetric **dst)
302{
303 ComObjPtr<PerformanceMetric> metric;
304 HRESULT rc = metric.createObject();
305 if (SUCCEEDED(rc))
306 rc = metric->init (src);
307 AssertComRCReturnRC(rc);
308 metric.queryInterfaceTo(dst);
309 return rc;
310}
311
312const Utf8Str& PerformanceCollector::getFailedGuestName()
313{
314 pm::CollectorGuest *pGuest = m.gm->getBlockedGuest();
315 if (pGuest)
316 return pGuest->getVMName();
317 return mUnknownGuest;
318}
319
320STDMETHODIMP PerformanceCollector::GetMetrics(ComSafeArrayIn(IN_BSTR, metricNames),
321 ComSafeArrayIn(IUnknown *, objects),
322 ComSafeArrayOut(IPerformanceMetric *, outMetrics))
323{
324 LogFlowThisFuncEnter();
325 //LogFlowThisFunc(("mState=%d, mType=%d\n", mState, mType));
326
327 HRESULT rc = S_OK;
328
329 AutoCaller autoCaller(this);
330 if (FAILED(autoCaller.rc())) return autoCaller.rc();
331
332 pm::Filter filter (ComSafeArrayInArg (metricNames),
333 ComSafeArrayInArg (objects));
334
335 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
336
337 MetricList filteredMetrics;
338 MetricList::iterator it;
339 for (it = m.metrics.begin(); it != m.metrics.end(); ++it)
340 if (filter.match ((*it)->getObject(), (*it)->getName()))
341 filteredMetrics.push_back (*it);
342
343 com::SafeIfaceArray<IPerformanceMetric> retMetrics (filteredMetrics.size());
344 int i = 0;
345 for (it = filteredMetrics.begin(); it != filteredMetrics.end(); ++it)
346 {
347 ComObjPtr<PerformanceMetric> metric;
348 rc = metric.createObject();
349 if (SUCCEEDED(rc))
350 rc = metric->init (*it);
351 AssertComRCReturnRC(rc);
352 LogFlow (("PerformanceCollector::GetMetrics() store a metric at "
353 "retMetrics[%d]...\n", i));
354 metric.queryInterfaceTo(&retMetrics[i++]);
355 }
356 retMetrics.detachTo(ComSafeArrayOutArg(outMetrics));
357 LogFlowThisFuncLeave();
358 return rc;
359}
360
361STDMETHODIMP PerformanceCollector::SetupMetrics(ComSafeArrayIn(IN_BSTR, metricNames),
362 ComSafeArrayIn(IUnknown *, objects),
363 ULONG aPeriod,
364 ULONG aCount,
365 ComSafeArrayOut(IPerformanceMetric *, outMetrics))
366{
367 AutoCaller autoCaller(this);
368 if (FAILED(autoCaller.rc())) return autoCaller.rc();
369
370 pm::Filter filter(ComSafeArrayInArg (metricNames),
371 ComSafeArrayInArg (objects));
372
373 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
374
375 HRESULT rc = S_OK;
376 BaseMetricList filteredMetrics;
377 BaseMetricList::iterator it;
378 for (it = m.baseMetrics.begin(); it != m.baseMetrics.end(); ++it)
379 if (filter.match((*it)->getObject(), (*it)->getName()))
380 {
381 LogFlow (("PerformanceCollector::SetupMetrics() setting period to %u,"
382 " count to %u for %s\n", aPeriod, aCount, (*it)->getName()));
383 (*it)->init(aPeriod, aCount);
384 if (aPeriod == 0 || aCount == 0)
385 {
386 LogFlow (("PerformanceCollector::SetupMetrics() disabling %s\n",
387 (*it)->getName()));
388 rc = (*it)->disable();
389 if (FAILED(rc))
390 break;
391 }
392 else
393 {
394 LogFlow (("PerformanceCollector::SetupMetrics() enabling %s\n",
395 (*it)->getName()));
396 rc = (*it)->enable();
397 if (FAILED(rc))
398 break;
399 }
400 filteredMetrics.push_back(*it);
401 }
402
403 com::SafeIfaceArray<IPerformanceMetric> retMetrics(filteredMetrics.size());
404 int i = 0;
405 for (it = filteredMetrics.begin();
406 it != filteredMetrics.end() && SUCCEEDED(rc); ++it)
407 rc = toIPerformanceMetric(*it, &retMetrics[i++]);
408 retMetrics.detachTo(ComSafeArrayOutArg(outMetrics));
409
410 LogFlowThisFuncLeave();
411
412 if (FAILED(rc))
413 return setError(E_FAIL, "Failed to setup metrics for '%s'",
414 getFailedGuestName().c_str());
415 return rc;
416}
417
418STDMETHODIMP PerformanceCollector::EnableMetrics(ComSafeArrayIn(IN_BSTR, metricNames),
419 ComSafeArrayIn(IUnknown *, objects),
420 ComSafeArrayOut(IPerformanceMetric *, outMetrics))
421{
422 AutoCaller autoCaller(this);
423 if (FAILED(autoCaller.rc())) return autoCaller.rc();
424
425 pm::Filter filter(ComSafeArrayInArg(metricNames),
426 ComSafeArrayInArg(objects));
427
428 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); /* Write lock is not needed atm since we are */
429 /* fiddling with enable bit only, but we */
430 /* care for those who come next :-). */
431
432 HRESULT rc = S_OK;
433 BaseMetricList filteredMetrics;
434 BaseMetricList::iterator it;
435 for (it = m.baseMetrics.begin(); it != m.baseMetrics.end(); ++it)
436 if (filter.match((*it)->getObject(), (*it)->getName()))
437 {
438 rc = (*it)->enable();
439 if (FAILED(rc))
440 break;
441 filteredMetrics.push_back(*it);
442 }
443
444 com::SafeIfaceArray<IPerformanceMetric> retMetrics(filteredMetrics.size());
445 int i = 0;
446 for (it = filteredMetrics.begin();
447 it != filteredMetrics.end() && SUCCEEDED(rc); ++it)
448 rc = toIPerformanceMetric(*it, &retMetrics[i++]);
449 retMetrics.detachTo(ComSafeArrayOutArg(outMetrics));
450
451 LogFlowThisFuncLeave();
452
453 if (FAILED(rc))
454 return setError(E_FAIL, "Failed to enable metrics for '%s'",
455 getFailedGuestName().c_str());
456 return rc;
457}
458
459STDMETHODIMP PerformanceCollector::DisableMetrics(ComSafeArrayIn(IN_BSTR, metricNames),
460 ComSafeArrayIn(IUnknown *, objects),
461 ComSafeArrayOut(IPerformanceMetric *, outMetrics))
462{
463 AutoCaller autoCaller(this);
464 if (FAILED(autoCaller.rc())) return autoCaller.rc();
465
466 pm::Filter filter(ComSafeArrayInArg(metricNames),
467 ComSafeArrayInArg(objects));
468
469 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); /* Write lock is not needed atm since we are */
470 /* fiddling with enable bit only, but we */
471 /* care for those who come next :-). */
472
473 HRESULT rc = S_OK;
474 BaseMetricList filteredMetrics;
475 BaseMetricList::iterator it;
476 for (it = m.baseMetrics.begin(); it != m.baseMetrics.end(); ++it)
477 if (filter.match((*it)->getObject(), (*it)->getName()))
478 {
479 rc = (*it)->disable();
480 if (FAILED(rc))
481 break;
482 filteredMetrics.push_back(*it);
483 }
484
485 com::SafeIfaceArray<IPerformanceMetric> retMetrics(filteredMetrics.size());
486 int i = 0;
487 for (it = filteredMetrics.begin();
488 it != filteredMetrics.end() && SUCCEEDED(rc); ++it)
489 rc = toIPerformanceMetric(*it, &retMetrics[i++]);
490 retMetrics.detachTo(ComSafeArrayOutArg(outMetrics));
491
492 LogFlowThisFuncLeave();
493
494 if (FAILED(rc))
495 return setError(E_FAIL, "Failed to disable metrics for '%s'",
496 getFailedGuestName().c_str());
497 return rc;
498}
499
500STDMETHODIMP PerformanceCollector::QueryMetricsData(ComSafeArrayIn (IN_BSTR, metricNames),
501 ComSafeArrayIn (IUnknown *, objects),
502 ComSafeArrayOut(BSTR, outMetricNames),
503 ComSafeArrayOut(IUnknown *, outObjects),
504 ComSafeArrayOut(BSTR, outUnits),
505 ComSafeArrayOut(ULONG, outScales),
506 ComSafeArrayOut(ULONG, outSequenceNumbers),
507 ComSafeArrayOut(ULONG, outDataIndices),
508 ComSafeArrayOut(ULONG, outDataLengths),
509 ComSafeArrayOut(LONG, outData))
510{
511 AutoCaller autoCaller(this);
512 if (FAILED(autoCaller.rc())) return autoCaller.rc();
513
514 pm::Filter filter(ComSafeArrayInArg(metricNames),
515 ComSafeArrayInArg(objects));
516
517 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
518
519 /* Let's compute the size of the resulting flat array */
520 size_t flatSize = 0;
521 MetricList filteredMetrics;
522 MetricList::iterator it;
523 for (it = m.metrics.begin(); it != m.metrics.end(); ++it)
524 if (filter.match ((*it)->getObject(), (*it)->getName()))
525 {
526 filteredMetrics.push_back (*it);
527 flatSize += (*it)->getLength();
528 }
529
530 int i = 0;
531 size_t flatIndex = 0;
532 size_t numberOfMetrics = filteredMetrics.size();
533 com::SafeArray<BSTR> retNames(numberOfMetrics);
534 com::SafeIfaceArray<IUnknown> retObjects(numberOfMetrics);
535 com::SafeArray<BSTR> retUnits(numberOfMetrics);
536 com::SafeArray<ULONG> retScales(numberOfMetrics);
537 com::SafeArray<ULONG> retSequenceNumbers(numberOfMetrics);
538 com::SafeArray<ULONG> retIndices(numberOfMetrics);
539 com::SafeArray<ULONG> retLengths(numberOfMetrics);
540 com::SafeArray<LONG> retData(flatSize);
541
542 for (it = filteredMetrics.begin(); it != filteredMetrics.end(); ++it, ++i)
543 {
544 ULONG *values, length, sequenceNumber;
545 /* @todo We may want to revise the query method to get rid of excessive alloc/memcpy calls. */
546 (*it)->query(&values, &length, &sequenceNumber);
547 LogFlow (("PerformanceCollector::QueryMetricsData() querying metric %s "
548 "returned %d values.\n", (*it)->getName(), length));
549 memcpy(retData.raw() + flatIndex, values, length * sizeof(*values));
550 RTMemFree(values);
551 Bstr tmp((*it)->getName());
552 tmp.detachTo(&retNames[i]);
553 (*it)->getObject().queryInterfaceTo(&retObjects[i]);
554 tmp = (*it)->getUnit();
555 tmp.detachTo(&retUnits[i]);
556 retScales[i] = (*it)->getScale();
557 retSequenceNumbers[i] = sequenceNumber;
558 retLengths[i] = length;
559 retIndices[i] = (ULONG)flatIndex;
560 flatIndex += length;
561 }
562
563 retNames.detachTo(ComSafeArrayOutArg(outMetricNames));
564 retObjects.detachTo(ComSafeArrayOutArg(outObjects));
565 retUnits.detachTo(ComSafeArrayOutArg(outUnits));
566 retScales.detachTo(ComSafeArrayOutArg(outScales));
567 retSequenceNumbers.detachTo(ComSafeArrayOutArg(outSequenceNumbers));
568 retIndices.detachTo(ComSafeArrayOutArg(outDataIndices));
569 retLengths.detachTo(ComSafeArrayOutArg(outDataLengths));
570 retData.detachTo(ComSafeArrayOutArg(outData));
571 return S_OK;
572}
573
574// public methods for internal purposes
575///////////////////////////////////////////////////////////////////////////////
576
577void PerformanceCollector::registerBaseMetric(pm::BaseMetric *baseMetric)
578{
579 //LogFlowThisFuncEnter();
580 AutoCaller autoCaller(this);
581 if (!SUCCEEDED(autoCaller.rc())) return;
582
583 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
584 Log7(("{%p} " LOG_FN_FMT ": obj=%p name=%s\n", this, __PRETTY_FUNCTION__,
585 (void *)baseMetric->getObject(), baseMetric->getName()));
586 m.baseMetrics.push_back (baseMetric);
587 //LogFlowThisFuncLeave();
588}
589
590void PerformanceCollector::registerMetric(pm::Metric *metric)
591{
592 //LogFlowThisFuncEnter();
593 AutoCaller autoCaller(this);
594 if (!SUCCEEDED(autoCaller.rc())) return;
595
596 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
597 Log7(("{%p} " LOG_FN_FMT ": obj=%p name=%s\n", this, __PRETTY_FUNCTION__, (void *)metric->getObject(), metric->getName()));
598 m.metrics.push_back (metric);
599 //LogFlowThisFuncLeave();
600}
601
602void PerformanceCollector::unregisterBaseMetricsFor(const ComPtr<IUnknown> &aObject, const Utf8Str name)
603{
604 //LogFlowThisFuncEnter();
605 AutoCaller autoCaller(this);
606 if (!SUCCEEDED(autoCaller.rc())) return;
607
608 pm::Filter filter(name, aObject);
609
610 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
611 int n = 0;
612 BaseMetricList::iterator it;
613 for (it = m.baseMetrics.begin(); it != m.baseMetrics.end(); ++it)
614 if (filter.match((*it)->getObject(), (*it)->getName()))
615 {
616 (*it)->unregister();
617 ++n;
618 }
619 Log7(("{%p} " LOG_FN_FMT ": obj=%p, name=%s, marked %d metrics\n",
620 this, __PRETTY_FUNCTION__, (void *)aObject, name.c_str(), n));
621 //LogFlowThisFuncLeave();
622}
623
624void PerformanceCollector::unregisterMetricsFor(const ComPtr<IUnknown> &aObject, const Utf8Str name)
625{
626 //LogFlowThisFuncEnter();
627 AutoCaller autoCaller(this);
628 if (!SUCCEEDED(autoCaller.rc())) return;
629
630 pm::Filter filter(name, aObject);
631
632 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
633 Log7(("{%p} " LOG_FN_FMT ": obj=%p, name=%s\n", this, __PRETTY_FUNCTION__, (void *)aObject, name.c_str()));
634 MetricList::iterator it;
635 for (it = m.metrics.begin(); it != m.metrics.end();)
636 if (filter.match((*it)->getObject(), (*it)->getName()))
637 {
638 delete *it;
639 it = m.metrics.erase(it);
640 }
641 else
642 ++it;
643 //LogFlowThisFuncLeave();
644}
645
646void PerformanceCollector::registerGuest(pm::CollectorGuest* pGuest)
647{
648 AutoCaller autoCaller(this);
649 if (!SUCCEEDED(autoCaller.rc())) return;
650
651 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
652 m.gm->registerGuest(pGuest);
653}
654
655void PerformanceCollector::unregisterGuest(pm::CollectorGuest* pGuest)
656{
657 AutoCaller autoCaller(this);
658 if (!SUCCEEDED(autoCaller.rc())) return;
659
660 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
661 m.gm->unregisterGuest(pGuest);
662}
663
664void PerformanceCollector::suspendSampling()
665{
666 AutoCaller autoCaller(this);
667 if (!SUCCEEDED(autoCaller.rc())) return;
668
669 int rc = RTTimerLRStop(m.sampler);
670 if ( RT_FAILURE(rc)
671 && rc != VERR_TIMER_SUSPENDED) /* calling suspendSampling() successively shouldn't assert. See @bugref{3495}. */
672 AssertMsgFailed(("PerformanceCollector::suspendSampling(): RTTimerLRStop returned %Rrc\n", rc));
673}
674
675void PerformanceCollector::resumeSampling()
676{
677 AutoCaller autoCaller(this);
678 if (!SUCCEEDED(autoCaller.rc())) return;
679
680 int rc = RTTimerLRStart(m.sampler, 0);
681 if ( RT_FAILURE(rc)
682 && rc != VERR_TIMER_ACTIVE) /* calling resumeSampling() successively shouldn't assert. See @bugref{3495}. */
683 AssertMsgFailed(("PerformanceCollector::resumeSampling(): RTTimerLRStart returned %Rrc\n", rc));
684}
685
686
687// private methods
688///////////////////////////////////////////////////////////////////////////////
689
690/* static */
691void PerformanceCollector::staticSamplerCallback(RTTIMERLR hTimerLR, void *pvUser,
692 uint64_t iTick)
693{
694 AssertReturnVoid (pvUser != NULL);
695 PerformanceCollector *collector = static_cast <PerformanceCollector *> (pvUser);
696 Assert(collector->mMagic == MAGIC);
697 if (collector->mMagic == MAGIC)
698 collector->samplerCallback(iTick);
699
700 NOREF (hTimerLR);
701}
702
703/*
704 * Metrics collection is a three stage process:
705 * 1) Pre-collection (hinting)
706 * At this stage we compose the list of all metrics to be collected
707 * If any metrics cannot be collected separately or if it is more
708 * efficient to collect several metric at once, these metrics should
709 * use hints to mark that they will need to be collected.
710 * 2) Pre-collection (bulk)
711 * Using hints set at stage 1 platform-specific HAL
712 * instance collects all marked host-related metrics.
713 * Hinted guest-related metrics then get collected by CollectorGuestManager.
714 * 3) Collection
715 * Metrics that are collected individually get collected and stored. Values
716 * saved in HAL and CollectorGuestManager are extracted and stored to
717 * individual metrics.
718 */
719void PerformanceCollector::samplerCallback(uint64_t iTick)
720{
721 Log4(("{%p} " LOG_FN_FMT ": ENTER\n", this, __PRETTY_FUNCTION__));
722 /* No locking until stage 3!*/
723
724 pm::CollectorHints hints;
725 uint64_t timestamp = RTTimeMilliTS();
726 BaseMetricList toBeCollected;
727 BaseMetricList::iterator it;
728 /* Compose the list of metrics being collected at this moment */
729 for (it = m.baseMetrics.begin(); it != m.baseMetrics.end(); ++it)
730 if ((*it)->collectorBeat(timestamp))
731 {
732 (*it)->preCollect(hints, iTick);
733 toBeCollected.push_back(*it);
734 }
735
736 if (toBeCollected.size() == 0)
737 {
738 Log4(("{%p} " LOG_FN_FMT ": LEAVE (nothing to collect)\n", this, __PRETTY_FUNCTION__));
739 return;
740 }
741
742 /* Let know the platform specific code what is being collected */
743 m.hal->preCollect(hints, iTick);
744#if 0
745 /* Guest stats are now pushed by guests themselves */
746 /* Collect the data in bulk from all hinted guests */
747 m.gm->preCollect(hints, iTick);
748#endif
749
750 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
751 /*
752 * Before we can collect data we need to go through both lists
753 * again to see if any base metrics are marked as unregistered.
754 * Those should be destroyed now.
755 */
756 Log7(("{%p} " LOG_FN_FMT ": before remove_if: toBeCollected.size()=%d\n", this, __PRETTY_FUNCTION__, toBeCollected.size()));
757 toBeCollected.remove_if(std::mem_fun(&pm::BaseMetric::isUnregistered));
758 Log7(("{%p} " LOG_FN_FMT ": after remove_if: toBeCollected.size()=%d\n", this, __PRETTY_FUNCTION__, toBeCollected.size()));
759 Log7(("{%p} " LOG_FN_FMT ": before remove_if: m.baseMetrics.size()=%d\n", this, __PRETTY_FUNCTION__, m.baseMetrics.size()));
760 for (it = m.baseMetrics.begin(); it != m.baseMetrics.end();)
761 if ((*it)->isUnregistered())
762 {
763 delete *it;
764 it = m.baseMetrics.erase(it);
765 }
766 else
767 ++it;
768 Log7(("{%p} " LOG_FN_FMT ": after remove_if: m.baseMetrics.size()=%d\n", this, __PRETTY_FUNCTION__, m.baseMetrics.size()));
769 /*
770 * Now when we have destroyed all base metrics that could
771 * try to pull data from unregistered CollectorGuest objects
772 * it is safe to destroy them as well.
773 */
774 m.gm->destroyUnregistered();
775
776 /* Finally, collect the data */
777 std::for_each (toBeCollected.begin(), toBeCollected.end(),
778 std::mem_fun (&pm::BaseMetric::collect));
779 Log4(("{%p} " LOG_FN_FMT ": LEAVE\n", this, __PRETTY_FUNCTION__));
780}
781
782////////////////////////////////////////////////////////////////////////////////
783// PerformanceMetric class
784////////////////////////////////////////////////////////////////////////////////
785
786// constructor / destructor
787////////////////////////////////////////////////////////////////////////////////
788
789PerformanceMetric::PerformanceMetric()
790{
791}
792
793PerformanceMetric::~PerformanceMetric()
794{
795}
796
797HRESULT PerformanceMetric::FinalConstruct()
798{
799 LogFlowThisFunc(("\n"));
800
801 return BaseFinalConstruct();
802}
803
804void PerformanceMetric::FinalRelease()
805{
806 LogFlowThisFunc(("\n"));
807
808 uninit ();
809
810 BaseFinalRelease();
811}
812
813// public initializer/uninitializer for internal purposes only
814////////////////////////////////////////////////////////////////////////////////
815
816HRESULT PerformanceMetric::init(pm::Metric *aMetric)
817{
818 m.name = aMetric->getName();
819 m.object = aMetric->getObject();
820 m.description = aMetric->getDescription();
821 m.period = aMetric->getPeriod();
822 m.count = aMetric->getLength();
823 m.unit = aMetric->getUnit();
824 m.min = aMetric->getMinValue();
825 m.max = aMetric->getMaxValue();
826 return S_OK;
827}
828
829HRESULT PerformanceMetric::init(pm::BaseMetric *aMetric)
830{
831 m.name = aMetric->getName();
832 m.object = aMetric->getObject();
833 m.description = "";
834 m.period = aMetric->getPeriod();
835 m.count = aMetric->getLength();
836 m.unit = aMetric->getUnit();
837 m.min = aMetric->getMinValue();
838 m.max = aMetric->getMaxValue();
839 return S_OK;
840}
841
842void PerformanceMetric::uninit()
843{
844}
845
846STDMETHODIMP PerformanceMetric::COMGETTER(MetricName)(BSTR *aMetricName)
847{
848 /// @todo (r=dmik) why do all these getters not do AutoCaller and
849 /// AutoReadLock? Is the underlying metric a constant object?
850
851 m.name.cloneTo(aMetricName);
852 return S_OK;
853}
854
855STDMETHODIMP PerformanceMetric::COMGETTER(Object)(IUnknown **anObject)
856{
857 m.object.queryInterfaceTo(anObject);
858 return S_OK;
859}
860
861STDMETHODIMP PerformanceMetric::COMGETTER(Description)(BSTR *aDescription)
862{
863 m.description.cloneTo(aDescription);
864 return S_OK;
865}
866
867STDMETHODIMP PerformanceMetric::COMGETTER(Period)(ULONG *aPeriod)
868{
869 *aPeriod = m.period;
870 return S_OK;
871}
872
873STDMETHODIMP PerformanceMetric::COMGETTER(Count)(ULONG *aCount)
874{
875 *aCount = m.count;
876 return S_OK;
877}
878
879STDMETHODIMP PerformanceMetric::COMGETTER(Unit)(BSTR *aUnit)
880{
881 m.unit.cloneTo(aUnit);
882 return S_OK;
883}
884
885STDMETHODIMP PerformanceMetric::COMGETTER(MinimumValue)(LONG *aMinValue)
886{
887 *aMinValue = m.min;
888 return S_OK;
889}
890
891STDMETHODIMP PerformanceMetric::COMGETTER(MaximumValue)(LONG *aMaxValue)
892{
893 *aMaxValue = m.max;
894 return S_OK;
895}
896/* vi: set tabstop=4 shiftwidth=4 expandtab: */
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