VirtualBox

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

Last change on this file since 19096 was 19017, checked in by vboxsync, 16 years ago

Main: Fixed deletion of metrics. Not doing this leads to memory leaks & an lock
on the xml file of the VM (which produce other bugs). I reverted r45374 &
r45467 which where quick fixes for this only.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 21.6 KB
Line 
1/* $Id: PerformanceImpl.cpp 19017 2009-04-20 08:12:58Z 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 gMetricNames[i].detachTo(&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 = std::remove_if (
492 m.baseMetrics.begin(), m.baseMetrics.end(), std::bind2nd (
493 std::mem_fun (&pm::BaseMetric::associatedWith), aObject));
494 /* Delete the content of the list as well */
495 BaseMetricList::iterator it1 = it;
496 for (;it1 != m.baseMetrics.end(); ++it1)
497 delete *it1;
498 m.baseMetrics.erase(it, m.baseMetrics.end());
499 LogAleksey(("{%p} " LOG_FN_FMT ": after remove_if: m.baseMetrics.size()=%d\n", this, __PRETTY_FUNCTION__, m.baseMetrics.size()));
500 //LogFlowThisFuncLeave();
501}
502
503void PerformanceCollector::unregisterMetricsFor (const ComPtr <IUnknown> &aObject)
504{
505 //LogFlowThisFuncEnter();
506 AutoCaller autoCaller (this);
507 if (!SUCCEEDED (autoCaller.rc())) return;
508
509 AutoWriteLock alock (this);
510 LogAleksey(("{%p} " LOG_FN_FMT ": obj=%p\n", this, __PRETTY_FUNCTION__, (void *)aObject));
511 MetricList::iterator it = std::remove_if (
512 m.metrics.begin(), m.metrics.end(), std::bind2nd (
513 std::mem_fun (&pm::Metric::associatedWith), aObject));
514 /* Delete the content of the list as well */
515 MetricList::iterator it1 = it;
516 for (;it1 != m.metrics.end(); ++it1)
517 delete *it1;
518 m.metrics.erase(it, m.metrics.end());
519 //LogFlowThisFuncLeave();
520}
521
522// private methods
523///////////////////////////////////////////////////////////////////////////////
524
525/* static */
526void PerformanceCollector::staticSamplerCallback (RTTIMERLR hTimerLR, void *pvUser,
527 uint64_t /* iTick */)
528{
529 AssertReturnVoid (pvUser != NULL);
530 PerformanceCollector *collector = static_cast <PerformanceCollector *> (pvUser);
531 Assert (collector->mMagic == MAGIC);
532 if (collector->mMagic == MAGIC)
533 {
534 collector->samplerCallback();
535 }
536 NOREF (hTimerLR);
537}
538
539void PerformanceCollector::samplerCallback()
540{
541 Log4(("{%p} " LOG_FN_FMT ": ENTER\n", this, __PRETTY_FUNCTION__));
542 AutoWriteLock alock (this);
543
544 pm::CollectorHints hints;
545 uint64_t timestamp = RTTimeMilliTS();
546 BaseMetricList toBeCollected;
547 BaseMetricList::iterator it;
548 /* Compose the list of metrics being collected at this moment */
549 for (it = m.baseMetrics.begin(); it != m.baseMetrics.end(); it++)
550 if ((*it)->collectorBeat(timestamp))
551 {
552 (*it)->preCollect(hints);
553 toBeCollected.push_back(*it);
554 }
555
556 if (toBeCollected.size() == 0)
557 return;
558
559 /* Let know the platform specific code what is being collected */
560 m.hal->preCollect(hints);
561
562 /* Finally, collect the data */
563 std::for_each (toBeCollected.begin(), toBeCollected.end(),
564 std::mem_fun (&pm::BaseMetric::collect));
565 Log4(("{%p} " LOG_FN_FMT ": LEAVE\n", this, __PRETTY_FUNCTION__));
566}
567
568////////////////////////////////////////////////////////////////////////////////
569// PerformanceMetric class
570////////////////////////////////////////////////////////////////////////////////
571
572// constructor / destructor
573////////////////////////////////////////////////////////////////////////////////
574
575PerformanceMetric::PerformanceMetric()
576{
577}
578
579PerformanceMetric::~PerformanceMetric()
580{
581}
582
583HRESULT PerformanceMetric::FinalConstruct()
584{
585 LogFlowThisFunc (("\n"));
586
587 return S_OK;
588}
589
590void PerformanceMetric::FinalRelease()
591{
592 LogFlowThisFunc (("\n"));
593
594 uninit ();
595}
596
597// public initializer/uninitializer for internal purposes only
598////////////////////////////////////////////////////////////////////////////////
599
600HRESULT PerformanceMetric::init (pm::Metric *aMetric)
601{
602 m.name = aMetric->getName();
603 m.object = aMetric->getObject();
604 m.description = aMetric->getDescription();
605 m.period = aMetric->getPeriod();
606 m.count = aMetric->getLength();
607 m.unit = aMetric->getUnit();
608 m.min = aMetric->getMinValue();
609 m.max = aMetric->getMaxValue();
610 return S_OK;
611}
612
613HRESULT PerformanceMetric::init (pm::BaseMetric *aMetric)
614{
615 m.name = aMetric->getName();
616 m.object = aMetric->getObject();
617 m.description = "";
618 m.period = aMetric->getPeriod();
619 m.count = aMetric->getLength();
620 m.unit = aMetric->getUnit();
621 m.min = aMetric->getMinValue();
622 m.max = aMetric->getMaxValue();
623 return S_OK;
624}
625
626void PerformanceMetric::uninit()
627{
628}
629
630STDMETHODIMP PerformanceMetric::COMGETTER(MetricName) (BSTR *aMetricName)
631{
632 /// @todo (r=dmik) why do all these getters not do AutoCaller and
633 /// AutoReadLock? Is the underlying metric a constant object?
634
635 m.name.cloneTo (aMetricName);
636 return S_OK;
637}
638
639STDMETHODIMP PerformanceMetric::COMGETTER(Object) (IUnknown **anObject)
640{
641 m.object.queryInterfaceTo(anObject);
642 return S_OK;
643}
644
645STDMETHODIMP PerformanceMetric::COMGETTER(Description) (BSTR *aDescription)
646{
647 m.description.cloneTo (aDescription);
648 return S_OK;
649}
650
651STDMETHODIMP PerformanceMetric::COMGETTER(Period) (ULONG *aPeriod)
652{
653 *aPeriod = m.period;
654 return S_OK;
655}
656
657STDMETHODIMP PerformanceMetric::COMGETTER(Count) (ULONG *aCount)
658{
659 *aCount = m.count;
660 return S_OK;
661}
662
663STDMETHODIMP PerformanceMetric::COMGETTER(Unit) (BSTR *aUnit)
664{
665 m.unit.cloneTo(aUnit);
666 return S_OK;
667}
668
669STDMETHODIMP PerformanceMetric::COMGETTER(MinimumValue) (LONG *aMinValue)
670{
671 *aMinValue = m.min;
672 return S_OK;
673}
674
675STDMETHODIMP PerformanceMetric::COMGETTER(MaximumValue) (LONG *aMaxValue)
676{
677 *aMaxValue = m.max;
678 return S_OK;
679}
680/* 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