VirtualBox

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

Last change on this file since 13538 was 13082, checked in by vboxsync, 16 years ago

PerfAPI: Backward compatibility broken. setup, enable, disable and query methods replaced with their Ex counterparts.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 21.2 KB
Line 
1/* $Id: PerformanceImpl.cpp 13082 2008-10-08 14:36:19Z vboxsync $ */
2
3/** @file
4 *
5 * VBox Performance API COM Classes implementation
6 */
7
8/*
9 * Copyright (C) 2008 Sun Microsystems, Inc.
10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.virtualbox.org. This file is free software;
13 * you can redistribute it and/or modify it under the terms of the GNU
14 * General Public License (GPL) as published by the Free Software
15 * Foundation, in version 2 as it comes in the "COPYING" file of the
16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18 *
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
20 * Clara, CA 95054 USA or visit http://www.sun.com if you need
21 * additional information or have any questions.
22 */
23
24#if defined(RT_OS_WINDOWS)
25#elif defined(RT_OS_LINUX)
26#endif
27
28#include "PerformanceImpl.h"
29
30#include "Logging.h"
31
32#include <VBox/err.h>
33#include <iprt/process.h>
34
35#include <vector>
36#include <algorithm>
37#include <functional>
38
39static Bstr gMetricNames[] =
40{
41 "CPU/Load/User",
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_UNEXPECTED);
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 (INPTR 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 (INPTR 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 (INPTR 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 (INPTR 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 (INPTR 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] = 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 m.baseMetrics.erase(it, m.baseMetrics.end());
495 LogAleksey(("{%p} " LOG_FN_FMT ": after remove_if: m.baseMetrics.size()=%d\n", this, __PRETTY_FUNCTION__, m.baseMetrics.size()));
496 //LogFlowThisFuncLeave();
497}
498
499void PerformanceCollector::unregisterMetricsFor (const ComPtr <IUnknown> &aObject)
500{
501 //LogFlowThisFuncEnter();
502 AutoCaller autoCaller (this);
503 if (!SUCCEEDED (autoCaller.rc())) return;
504
505 AutoWriteLock alock (this);
506 LogAleksey(("{%p} " LOG_FN_FMT ": obj=%p\n", this, __PRETTY_FUNCTION__, (void *)aObject));
507 MetricList::iterator it = std::remove_if (
508 m.metrics.begin(), m.metrics.end(), std::bind2nd (
509 std::mem_fun (&pm::Metric::associatedWith), aObject));
510 m.metrics.erase(it, m.metrics.end());
511 //LogFlowThisFuncLeave();
512}
513
514// private methods
515///////////////////////////////////////////////////////////////////////////////
516
517/* static */
518void PerformanceCollector::staticSamplerCallback (RTTIMERLR hTimerLR, void *pvUser,
519 uint64_t iTick)
520{
521 AssertReturnVoid (pvUser != NULL);
522 PerformanceCollector *collector = static_cast <PerformanceCollector *> (pvUser);
523 Assert (collector->mMagic == MAGIC);
524 if (collector->mMagic == MAGIC)
525 {
526 collector->samplerCallback();
527 }
528 NOREF (hTimerLR);
529}
530
531void PerformanceCollector::samplerCallback()
532{
533 Log4(("{%p} " LOG_FN_FMT ": ENTER\n", this, __PRETTY_FUNCTION__));
534 AutoWriteLock alock (this);
535
536 pm::CollectorHints hints;
537 uint64_t timestamp = RTTimeMilliTS();
538 BaseMetricList toBeCollected;
539 BaseMetricList::iterator it;
540 /* Compose the list of metrics being collected at this moment */
541 for (it = m.baseMetrics.begin(); it != m.baseMetrics.end(); it++)
542 if ((*it)->collectorBeat(timestamp))
543 {
544 (*it)->preCollect(hints);
545 toBeCollected.push_back(*it);
546 }
547
548 if (toBeCollected.size() == 0)
549 return;
550
551 /* Let know the platform specific code what is being collected */
552 m.hal->preCollect(hints);
553
554 /* Finally, collect the data */
555 std::for_each (toBeCollected.begin(), toBeCollected.end(),
556 std::mem_fun (&pm::BaseMetric::collect));
557 Log4(("{%p} " LOG_FN_FMT ": LEAVE\n", this, __PRETTY_FUNCTION__));
558}
559
560////////////////////////////////////////////////////////////////////////////////
561// PerformanceMetric class
562////////////////////////////////////////////////////////////////////////////////
563
564// constructor / destructor
565////////////////////////////////////////////////////////////////////////////////
566
567PerformanceMetric::PerformanceMetric()
568{
569}
570
571PerformanceMetric::~PerformanceMetric()
572{
573}
574
575HRESULT PerformanceMetric::FinalConstruct()
576{
577 LogFlowThisFunc (("\n"));
578
579 return S_OK;
580}
581
582void PerformanceMetric::FinalRelease()
583{
584 LogFlowThisFunc (("\n"));
585
586 uninit ();
587}
588
589// public initializer/uninitializer for internal purposes only
590////////////////////////////////////////////////////////////////////////////////
591
592HRESULT PerformanceMetric::init (pm::Metric *aMetric)
593{
594 m.name = aMetric->getName();
595 m.object = aMetric->getObject();
596 m.description = aMetric->getDescription();
597 m.period = aMetric->getPeriod();
598 m.count = aMetric->getLength();
599 m.unit = aMetric->getUnit();
600 m.min = aMetric->getMinValue();
601 m.max = aMetric->getMaxValue();
602 return S_OK;
603}
604
605HRESULT PerformanceMetric::init (pm::BaseMetric *aMetric)
606{
607 m.name = aMetric->getName();
608 m.object = aMetric->getObject();
609 m.description = "";
610 m.period = aMetric->getPeriod();
611 m.count = aMetric->getLength();
612 m.unit = aMetric->getUnit();
613 m.min = aMetric->getMinValue();
614 m.max = aMetric->getMaxValue();
615 return S_OK;
616}
617
618void PerformanceMetric::uninit()
619{
620}
621
622STDMETHODIMP PerformanceMetric::COMGETTER(MetricName) (BSTR *aMetricName)
623{
624 /// @todo (r=dmik) why do all these getters not do AutoCaller and
625 /// AutoReadLock? Is the underlying metric a constant object?
626
627 m.name.cloneTo (aMetricName);
628 return S_OK;
629}
630
631STDMETHODIMP PerformanceMetric::COMGETTER(Object) (IUnknown **anObject)
632{
633 m.object.queryInterfaceTo(anObject);
634 return S_OK;
635}
636
637STDMETHODIMP PerformanceMetric::COMGETTER(Description) (BSTR *aDescription)
638{
639 m.description.cloneTo (aDescription);
640 return S_OK;
641}
642
643STDMETHODIMP PerformanceMetric::COMGETTER(Period) (ULONG *aPeriod)
644{
645 *aPeriod = m.period;
646 return S_OK;
647}
648
649STDMETHODIMP PerformanceMetric::COMGETTER(Count) (ULONG *aCount)
650{
651 *aCount = m.count;
652 return S_OK;
653}
654
655STDMETHODIMP PerformanceMetric::COMGETTER(Unit) (BSTR *aUnit)
656{
657 m.unit.cloneTo(aUnit);
658 return S_OK;
659}
660
661STDMETHODIMP PerformanceMetric::COMGETTER(MinimumValue) (LONG *aMinValue)
662{
663 *aMinValue = m.min;
664 return S_OK;
665}
666
667STDMETHODIMP PerformanceMetric::COMGETTER(MaximumValue) (LONG *aMaxValue)
668{
669 *aMaxValue = m.max;
670 return S_OK;
671}
672
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use