VirtualBox

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

Last change on this file since 21809 was 21395, checked in by vboxsync, 15 years ago

Stop performance counter sampling when the host goes into suspend mode. Restart it during resume.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 21.7 KB
Line 
1/* $Id: PerformanceImpl.cpp 21395 2009-07-08 13:30:34Z 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#include "PerformanceImpl.h"
25
26#include "Logging.h"
27
28#include <iprt/process.h>
29
30#include <VBox/err.h>
31#include <VBox/settings.h>
32
33#include <vector>
34#include <algorithm>
35#include <functional>
36
37#include "Performance.h"
38
39static Bstr gMetricNames[] =
40{
41 "CPU/Load/User",
42 "CPU/Load/User:avg",
43 "CPU/Load/User:min",
44 "CPU/Load/User:max",
45 "CPU/Load/Kernel",
46 "CPU/Load/Kernel:avg",
47 "CPU/Load/Kernel:min",
48 "CPU/Load/Kernel:max",
49 "CPU/Load/Idle",
50 "CPU/Load/Idle:avg",
51 "CPU/Load/Idle:min",
52 "CPU/Load/Idle:max",
53 "CPU/MHz",
54 "CPU/MHz:avg",
55 "CPU/MHz:min",
56 "CPU/MHz:max",
57 "RAM/Usage/Total",
58 "RAM/Usage/Total:avg",
59 "RAM/Usage/Total:min",
60 "RAM/Usage/Total:max",
61 "RAM/Usage/Used",
62 "RAM/Usage/Used:avg",
63 "RAM/Usage/Used:min",
64 "RAM/Usage/Used:max",
65 "RAM/Usage/Free",
66 "RAM/Usage/Free:avg",
67 "RAM/Usage/Free:min",
68 "RAM/Usage/Free:max",
69};
70
71////////////////////////////////////////////////////////////////////////////////
72// PerformanceCollector class
73////////////////////////////////////////////////////////////////////////////////
74
75// constructor / destructor
76////////////////////////////////////////////////////////////////////////////////
77
78PerformanceCollector::PerformanceCollector() : mMagic(0) {}
79
80PerformanceCollector::~PerformanceCollector() {}
81
82HRESULT PerformanceCollector::FinalConstruct()
83{
84 LogFlowThisFunc (("\n"));
85
86 return S_OK;
87}
88
89void PerformanceCollector::FinalRelease()
90{
91 LogFlowThisFunc (("\n"));
92}
93
94// public initializer/uninitializer for internal purposes only
95////////////////////////////////////////////////////////////////////////////////
96
97/**
98 * Initializes the PerformanceCollector object.
99 */
100HRESULT PerformanceCollector::init()
101{
102 /* Enclose the state transition NotReady->InInit->Ready */
103 AutoInitSpan autoInitSpan (this);
104 AssertReturn (autoInitSpan.isOk(), E_FAIL);
105
106 LogFlowThisFuncEnter();
107
108 HRESULT rc = S_OK;
109
110 m.hal = pm::createHAL();
111
112 /* Let the sampler know it gets a valid collector. */
113 mMagic = MAGIC;
114
115 /* Start resource usage sampler */
116 int vrc = RTTimerLRCreate (&m.sampler, VBOX_USAGE_SAMPLER_MIN_INTERVAL,
117 &PerformanceCollector::staticSamplerCallback, this);
118 AssertMsgRC (vrc, ("Failed to create resource usage "
119 "sampling timer(%Rra)\n", vrc));
120 if (RT_FAILURE (vrc))
121 rc = E_FAIL;
122
123 if (SUCCEEDED (rc))
124 autoInitSpan.setSucceeded();
125
126 LogFlowThisFuncLeave();
127
128 return rc;
129}
130
131/**
132 * Uninitializes the PerformanceCollector object.
133 *
134 * Called either from FinalRelease() or by the parent when it gets destroyed.
135 */
136void PerformanceCollector::uninit()
137{
138 LogFlowThisFuncEnter();
139
140 /* Enclose the state transition Ready->InUninit->NotReady */
141 AutoUninitSpan autoUninitSpan (this);
142 if (autoUninitSpan.uninitDone())
143 {
144 LogFlowThisFunc (("Already uninitialized.\n"));
145 LogFlowThisFuncLeave();
146 return;
147 }
148
149 mMagic = 0;
150
151 /* Destroy resource usage sampler */
152 int vrc = RTTimerLRDestroy (m.sampler);
153 AssertMsgRC (vrc, ("Failed to destroy resource usage "
154 "sampling timer (%Rra)\n", vrc));
155 m.sampler = NULL;
156
157 //delete m.factory;
158 //m.factory = NULL;
159
160 delete m.hal;
161 m.hal = NULL;
162
163 LogFlowThisFuncLeave();
164}
165
166// IPerformanceCollector properties
167////////////////////////////////////////////////////////////////////////////////
168
169STDMETHODIMP
170PerformanceCollector::COMGETTER(MetricNames) (ComSafeArrayOut (BSTR, theMetricNames))
171{
172 if (ComSafeArrayOutIsNull (theMetricNames))
173 return E_POINTER;
174
175 AutoCaller autoCaller (this);
176 CheckComRCReturnRC (autoCaller.rc());
177
178 AutoReadLock alock (this);
179
180 com::SafeArray <BSTR> metricNames(RT_ELEMENTS(gMetricNames));
181 for (size_t i = 0; i < RT_ELEMENTS(gMetricNames); i++)
182 {
183 Bstr(gMetricNames[i]).cloneTo(&metricNames[i]);
184 }
185 //gMetricNames.detachTo(ComSafeArrayOutArg (theMetricNames));
186 metricNames.detachTo (ComSafeArrayOutArg (theMetricNames));
187
188 return S_OK;
189}
190
191// IPerformanceCollector methods
192////////////////////////////////////////////////////////////////////////////////
193
194HRESULT PerformanceCollector::toIPerformanceMetric(pm::Metric *src, IPerformanceMetric **dst)
195{
196 ComObjPtr <PerformanceMetric> metric;
197 HRESULT rc = metric.createObject();
198 if (SUCCEEDED (rc))
199 rc = metric->init (src);
200 AssertComRCReturnRC (rc);
201 metric.queryInterfaceTo (dst);
202 return rc;
203}
204
205HRESULT PerformanceCollector::toIPerformanceMetric(pm::BaseMetric *src, IPerformanceMetric **dst)
206{
207 ComObjPtr <PerformanceMetric> metric;
208 HRESULT rc = metric.createObject();
209 if (SUCCEEDED (rc))
210 rc = metric->init (src);
211 AssertComRCReturnRC (rc);
212 metric.queryInterfaceTo (dst);
213 return rc;
214}
215
216STDMETHODIMP
217PerformanceCollector::GetMetrics (ComSafeArrayIn (IN_BSTR, metricNames),
218 ComSafeArrayIn (IUnknown *, objects),
219 ComSafeArrayOut (IPerformanceMetric *, outMetrics))
220{
221 LogFlowThisFuncEnter();
222 //LogFlowThisFunc (("mState=%d, mType=%d\n", mState, mType));
223
224 HRESULT rc = S_OK;
225
226 AutoCaller autoCaller (this);
227 CheckComRCReturnRC (autoCaller.rc());
228
229 pm::Filter filter (ComSafeArrayInArg (metricNames),
230 ComSafeArrayInArg (objects));
231
232 AutoReadLock alock (this);
233
234 MetricList filteredMetrics;
235 MetricList::iterator it;
236 for (it = m.metrics.begin(); it != m.metrics.end(); ++it)
237 if (filter.match ((*it)->getObject(), (*it)->getName()))
238 filteredMetrics.push_back (*it);
239
240 com::SafeIfaceArray<IPerformanceMetric> retMetrics (filteredMetrics.size());
241 int i = 0;
242 for (it = filteredMetrics.begin(); it != filteredMetrics.end(); ++it)
243 {
244 ComObjPtr <PerformanceMetric> metric;
245 rc = metric.createObject();
246 if (SUCCEEDED (rc))
247 rc = metric->init (*it);
248 AssertComRCReturnRC (rc);
249 LogFlow (("PerformanceCollector::GetMetrics() store a metric at "
250 "retMetrics[%d]...\n", i));
251 metric.queryInterfaceTo (&retMetrics [i++]);
252 }
253 retMetrics.detachTo (ComSafeArrayOutArg(outMetrics));
254 LogFlowThisFuncLeave();
255 return rc;
256}
257
258STDMETHODIMP
259PerformanceCollector::SetupMetrics (ComSafeArrayIn (IN_BSTR, metricNames),
260 ComSafeArrayIn (IUnknown *, objects),
261 ULONG aPeriod, ULONG aCount,
262 ComSafeArrayOut (IPerformanceMetric *,
263 outMetrics))
264{
265 AutoCaller autoCaller (this);
266 CheckComRCReturnRC (autoCaller.rc());
267
268 pm::Filter filter (ComSafeArrayInArg (metricNames),
269 ComSafeArrayInArg (objects));
270
271 AutoWriteLock alock (this);
272
273 HRESULT rc = S_OK;
274 BaseMetricList filteredMetrics;
275 BaseMetricList::iterator it;
276 for (it = m.baseMetrics.begin(); it != m.baseMetrics.end(); ++it)
277 if (filter.match((*it)->getObject(), (*it)->getName()))
278 {
279 LogFlow (("PerformanceCollector::SetupMetrics() setting period to %u,"
280 " count to %u for %s\n", aPeriod, aCount, (*it)->getName()));
281 (*it)->init(aPeriod, aCount);
282 if (aPeriod == 0 || aCount == 0)
283 {
284 LogFlow (("PerformanceCollector::SetupMetrics() disabling %s\n",
285 (*it)->getName()));
286 (*it)->disable();
287 }
288 else
289 {
290 LogFlow (("PerformanceCollector::SetupMetrics() enabling %s\n",
291 (*it)->getName()));
292 (*it)->enable();
293 }
294 filteredMetrics.push_back(*it);
295 }
296
297 com::SafeIfaceArray<IPerformanceMetric> retMetrics (filteredMetrics.size());
298 int i = 0;
299 for (it = filteredMetrics.begin();
300 it != filteredMetrics.end() && SUCCEEDED (rc); ++it)
301 rc = toIPerformanceMetric(*it, &retMetrics [i++]);
302 retMetrics.detachTo (ComSafeArrayOutArg(outMetrics));
303
304 LogFlowThisFuncLeave();
305 return rc;
306}
307
308STDMETHODIMP
309PerformanceCollector::EnableMetrics (ComSafeArrayIn (IN_BSTR, metricNames),
310 ComSafeArrayIn (IUnknown *, objects),
311 ComSafeArrayOut (IPerformanceMetric *,
312 outMetrics))
313{
314 AutoCaller autoCaller (this);
315 CheckComRCReturnRC (autoCaller.rc());
316
317 pm::Filter filter (ComSafeArrayInArg (metricNames),
318 ComSafeArrayInArg (objects));
319
320 AutoWriteLock alock (this); /* Write lock is not needed atm since we are */
321 /* fiddling with enable bit only, but we */
322 /* care for those who come next :-). */
323
324 HRESULT rc = S_OK;
325 BaseMetricList filteredMetrics;
326 BaseMetricList::iterator it;
327 for (it = m.baseMetrics.begin(); it != m.baseMetrics.end(); ++it)
328 if (filter.match((*it)->getObject(), (*it)->getName()))
329 {
330 (*it)->enable();
331 filteredMetrics.push_back(*it);
332 }
333
334 com::SafeIfaceArray<IPerformanceMetric> retMetrics (filteredMetrics.size());
335 int i = 0;
336 for (it = filteredMetrics.begin();
337 it != filteredMetrics.end() && SUCCEEDED (rc); ++it)
338 rc = toIPerformanceMetric(*it, &retMetrics [i++]);
339 retMetrics.detachTo (ComSafeArrayOutArg(outMetrics));
340
341 LogFlowThisFuncLeave();
342 return rc;
343}
344
345STDMETHODIMP
346PerformanceCollector::DisableMetrics (ComSafeArrayIn (IN_BSTR, metricNames),
347 ComSafeArrayIn (IUnknown *, objects),
348 ComSafeArrayOut (IPerformanceMetric *,
349 outMetrics))
350{
351 AutoCaller autoCaller (this);
352 CheckComRCReturnRC (autoCaller.rc());
353
354 pm::Filter filter (ComSafeArrayInArg (metricNames),
355 ComSafeArrayInArg (objects));
356
357 AutoWriteLock alock (this); /* Write lock is not needed atm since we are */
358 /* fiddling with enable bit only, but we */
359 /* care for those who come next :-). */
360
361 HRESULT rc = S_OK;
362 BaseMetricList filteredMetrics;
363 BaseMetricList::iterator it;
364 for (it = m.baseMetrics.begin(); it != m.baseMetrics.end(); ++it)
365 if (filter.match((*it)->getObject(), (*it)->getName()))
366 {
367 (*it)->disable();
368 filteredMetrics.push_back(*it);
369 }
370
371 com::SafeIfaceArray<IPerformanceMetric> retMetrics (filteredMetrics.size());
372 int i = 0;
373 for (it = filteredMetrics.begin();
374 it != filteredMetrics.end() && SUCCEEDED (rc); ++it)
375 rc = toIPerformanceMetric(*it, &retMetrics [i++]);
376 retMetrics.detachTo (ComSafeArrayOutArg(outMetrics));
377
378 LogFlowThisFuncLeave();
379 return rc;
380}
381
382STDMETHODIMP
383PerformanceCollector::QueryMetricsData (ComSafeArrayIn (IN_BSTR, metricNames),
384 ComSafeArrayIn (IUnknown *, objects),
385 ComSafeArrayOut (BSTR, outMetricNames),
386 ComSafeArrayOut (IUnknown *, outObjects),
387 ComSafeArrayOut (BSTR, outUnits),
388 ComSafeArrayOut (ULONG, outScales),
389 ComSafeArrayOut (ULONG, outSequenceNumbers),
390 ComSafeArrayOut (ULONG, outDataIndices),
391 ComSafeArrayOut (ULONG, outDataLengths),
392 ComSafeArrayOut (LONG, outData))
393{
394 AutoCaller autoCaller (this);
395 CheckComRCReturnRC (autoCaller.rc());
396
397 pm::Filter filter (ComSafeArrayInArg (metricNames),
398 ComSafeArrayInArg (objects));
399
400 AutoReadLock alock (this);
401
402 /* Let's compute the size of the resulting flat array */
403 size_t flatSize = 0;
404 MetricList filteredMetrics;
405 MetricList::iterator it;
406 for (it = m.metrics.begin(); it != m.metrics.end(); ++it)
407 if (filter.match ((*it)->getObject(), (*it)->getName()))
408 {
409 filteredMetrics.push_back (*it);
410 flatSize += (*it)->getLength();
411 }
412
413 int i = 0;
414 size_t flatIndex = 0;
415 size_t numberOfMetrics = filteredMetrics.size();
416 com::SafeArray <BSTR> retNames (numberOfMetrics);
417 com::SafeIfaceArray <IUnknown> retObjects (numberOfMetrics);
418 com::SafeArray <BSTR> retUnits (numberOfMetrics);
419 com::SafeArray <ULONG> retScales (numberOfMetrics);
420 com::SafeArray <ULONG> retSequenceNumbers (numberOfMetrics);
421 com::SafeArray <ULONG> retIndices (numberOfMetrics);
422 com::SafeArray <ULONG> retLengths (numberOfMetrics);
423 com::SafeArray <LONG> retData (flatSize);
424
425 for (it = filteredMetrics.begin(); it != filteredMetrics.end(); ++it, ++i)
426 {
427 ULONG *values, length, sequenceNumber;
428 /* @todo We may want to revise the query method to get rid of excessive alloc/memcpy calls. */
429 (*it)->query(&values, &length, &sequenceNumber);
430 LogFlow (("PerformanceCollector::QueryMetricsData() querying metric %s "
431 "returned %d values.\n", (*it)->getName(), length));
432 memcpy(retData.raw() + flatIndex, values, length * sizeof(*values));
433 Bstr tmp((*it)->getName());
434 tmp.detachTo(&retNames[i]);
435 (*it)->getObject().queryInterfaceTo (&retObjects[i]);
436 tmp = (*it)->getUnit();
437 tmp.detachTo(&retUnits[i]);
438 retScales[i] = (*it)->getScale();
439 retSequenceNumbers[i] = sequenceNumber;
440 retLengths[i] = length;
441 retIndices[i] = (ULONG)flatIndex;
442 flatIndex += length;
443 }
444
445 retNames.detachTo (ComSafeArrayOutArg (outMetricNames));
446 retObjects.detachTo (ComSafeArrayOutArg (outObjects));
447 retUnits.detachTo (ComSafeArrayOutArg (outUnits));
448 retScales.detachTo (ComSafeArrayOutArg (outScales));
449 retSequenceNumbers.detachTo (ComSafeArrayOutArg (outSequenceNumbers));
450 retIndices.detachTo (ComSafeArrayOutArg (outDataIndices));
451 retLengths.detachTo (ComSafeArrayOutArg (outDataLengths));
452 retData.detachTo (ComSafeArrayOutArg (outData));
453 return S_OK;
454}
455
456// public methods for internal purposes
457///////////////////////////////////////////////////////////////////////////////
458
459void PerformanceCollector::registerBaseMetric (pm::BaseMetric *baseMetric)
460{
461 //LogFlowThisFuncEnter();
462 AutoCaller autoCaller (this);
463 if (!SUCCEEDED (autoCaller.rc())) return;
464
465 AutoWriteLock alock (this);
466 LogAleksey(("{%p} " LOG_FN_FMT ": obj=%p name=%s\n", this, __PRETTY_FUNCTION__, (void *)baseMetric->getObject(), baseMetric->getName()));
467 m.baseMetrics.push_back (baseMetric);
468 //LogFlowThisFuncLeave();
469}
470
471void PerformanceCollector::registerMetric (pm::Metric *metric)
472{
473 //LogFlowThisFuncEnter();
474 AutoCaller autoCaller (this);
475 if (!SUCCEEDED (autoCaller.rc())) return;
476
477 AutoWriteLock alock (this);
478 LogAleksey(("{%p} " LOG_FN_FMT ": obj=%p name=%s\n", this, __PRETTY_FUNCTION__, (void *)metric->getObject(), metric->getName()));
479 m.metrics.push_back (metric);
480 //LogFlowThisFuncLeave();
481}
482
483void PerformanceCollector::unregisterBaseMetricsFor (const ComPtr <IUnknown> &aObject)
484{
485 //LogFlowThisFuncEnter();
486 AutoCaller autoCaller (this);
487 if (!SUCCEEDED (autoCaller.rc())) return;
488
489 AutoWriteLock alock (this);
490 LogAleksey(("{%p} " LOG_FN_FMT ": before remove_if: m.baseMetrics.size()=%d\n", this, __PRETTY_FUNCTION__, m.baseMetrics.size()));
491 BaseMetricList::iterator it;
492 for (it = m.baseMetrics.begin(); it != m.baseMetrics.end();)
493 if ((*it)->associatedWith(aObject))
494 {
495 delete *it;
496 m.baseMetrics.erase(it++);
497 }
498 else
499 ++it;
500 LogAleksey(("{%p} " LOG_FN_FMT ": after remove_if: m.baseMetrics.size()=%d\n", this, __PRETTY_FUNCTION__, m.baseMetrics.size()));
501 //LogFlowThisFuncLeave();
502}
503
504void PerformanceCollector::unregisterMetricsFor (const ComPtr <IUnknown> &aObject)
505{
506 //LogFlowThisFuncEnter();
507 AutoCaller autoCaller (this);
508 if (!SUCCEEDED (autoCaller.rc())) return;
509
510 AutoWriteLock alock (this);
511 LogAleksey(("{%p} " LOG_FN_FMT ": obj=%p\n", this, __PRETTY_FUNCTION__, (void *)aObject));
512 MetricList::iterator it;
513 for (it = m.metrics.begin(); it != m.metrics.end();)
514 if ((*it)->associatedWith(aObject))
515 {
516 delete *it;
517 m.metrics.erase(it++);
518 }
519 else
520 ++it;
521 //LogFlowThisFuncLeave();
522}
523
524void PerformanceCollector::suspendSampling()
525{
526 AutoCaller autoCaller (this);
527 if (!SUCCEEDED (autoCaller.rc())) return;
528
529 int rc = RTTimerLRStop(m.sampler);
530 AssertRC(rc);
531}
532
533void PerformanceCollector::resumeSampling()
534{
535 AutoCaller autoCaller (this);
536 if (!SUCCEEDED (autoCaller.rc())) return;
537
538 int rc = RTTimerLRStart(m.sampler, 0);
539 AssertRC(rc);
540}
541
542
543// private methods
544///////////////////////////////////////////////////////////////////////////////
545
546/* static */
547void PerformanceCollector::staticSamplerCallback (RTTIMERLR hTimerLR, void *pvUser,
548 uint64_t /* iTick */)
549{
550 AssertReturnVoid (pvUser != NULL);
551 PerformanceCollector *collector = static_cast <PerformanceCollector *> (pvUser);
552 Assert (collector->mMagic == MAGIC);
553 if (collector->mMagic == MAGIC)
554 {
555 collector->samplerCallback();
556 }
557 NOREF (hTimerLR);
558}
559
560void PerformanceCollector::samplerCallback()
561{
562 Log4(("{%p} " LOG_FN_FMT ": ENTER\n", this, __PRETTY_FUNCTION__));
563 AutoWriteLock alock (this);
564
565 pm::CollectorHints hints;
566 uint64_t timestamp = RTTimeMilliTS();
567 BaseMetricList toBeCollected;
568 BaseMetricList::iterator it;
569 /* Compose the list of metrics being collected at this moment */
570 for (it = m.baseMetrics.begin(); it != m.baseMetrics.end(); it++)
571 if ((*it)->collectorBeat(timestamp))
572 {
573 (*it)->preCollect(hints);
574 toBeCollected.push_back(*it);
575 }
576
577 if (toBeCollected.size() == 0)
578 return;
579
580 /* Let know the platform specific code what is being collected */
581 m.hal->preCollect(hints);
582
583 /* Finally, collect the data */
584 std::for_each (toBeCollected.begin(), toBeCollected.end(),
585 std::mem_fun (&pm::BaseMetric::collect));
586 Log4(("{%p} " LOG_FN_FMT ": LEAVE\n", this, __PRETTY_FUNCTION__));
587}
588
589////////////////////////////////////////////////////////////////////////////////
590// PerformanceMetric class
591////////////////////////////////////////////////////////////////////////////////
592
593// constructor / destructor
594////////////////////////////////////////////////////////////////////////////////
595
596PerformanceMetric::PerformanceMetric()
597{
598}
599
600PerformanceMetric::~PerformanceMetric()
601{
602}
603
604HRESULT PerformanceMetric::FinalConstruct()
605{
606 LogFlowThisFunc (("\n"));
607
608 return S_OK;
609}
610
611void PerformanceMetric::FinalRelease()
612{
613 LogFlowThisFunc (("\n"));
614
615 uninit ();
616}
617
618// public initializer/uninitializer for internal purposes only
619////////////////////////////////////////////////////////////////////////////////
620
621HRESULT PerformanceMetric::init (pm::Metric *aMetric)
622{
623 m.name = aMetric->getName();
624 m.object = aMetric->getObject();
625 m.description = aMetric->getDescription();
626 m.period = aMetric->getPeriod();
627 m.count = aMetric->getLength();
628 m.unit = aMetric->getUnit();
629 m.min = aMetric->getMinValue();
630 m.max = aMetric->getMaxValue();
631 return S_OK;
632}
633
634HRESULT PerformanceMetric::init (pm::BaseMetric *aMetric)
635{
636 m.name = aMetric->getName();
637 m.object = aMetric->getObject();
638 m.description = "";
639 m.period = aMetric->getPeriod();
640 m.count = aMetric->getLength();
641 m.unit = aMetric->getUnit();
642 m.min = aMetric->getMinValue();
643 m.max = aMetric->getMaxValue();
644 return S_OK;
645}
646
647void PerformanceMetric::uninit()
648{
649}
650
651STDMETHODIMP PerformanceMetric::COMGETTER(MetricName) (BSTR *aMetricName)
652{
653 /// @todo (r=dmik) why do all these getters not do AutoCaller and
654 /// AutoReadLock? Is the underlying metric a constant object?
655
656 m.name.cloneTo (aMetricName);
657 return S_OK;
658}
659
660STDMETHODIMP PerformanceMetric::COMGETTER(Object) (IUnknown **anObject)
661{
662 m.object.queryInterfaceTo(anObject);
663 return S_OK;
664}
665
666STDMETHODIMP PerformanceMetric::COMGETTER(Description) (BSTR *aDescription)
667{
668 m.description.cloneTo (aDescription);
669 return S_OK;
670}
671
672STDMETHODIMP PerformanceMetric::COMGETTER(Period) (ULONG *aPeriod)
673{
674 *aPeriod = m.period;
675 return S_OK;
676}
677
678STDMETHODIMP PerformanceMetric::COMGETTER(Count) (ULONG *aCount)
679{
680 *aCount = m.count;
681 return S_OK;
682}
683
684STDMETHODIMP PerformanceMetric::COMGETTER(Unit) (BSTR *aUnit)
685{
686 m.unit.cloneTo(aUnit);
687 return S_OK;
688}
689
690STDMETHODIMP PerformanceMetric::COMGETTER(MinimumValue) (LONG *aMinValue)
691{
692 *aMinValue = m.min;
693 return S_OK;
694}
695
696STDMETHODIMP PerformanceMetric::COMGETTER(MaximumValue) (LONG *aMaxValue)
697{
698 *aMaxValue = m.max;
699 return S_OK;
700}
701/* 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