VirtualBox

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

Last change on this file since 39252 was 37423, checked in by vboxsync, 14 years ago

Ran the source code massager (scm).

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