VirtualBox

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

Last change on this file since 14902 was 14772, checked in by vboxsync, 16 years ago

Added vim modelines to aid following coding guidelines, like no tabs,
similar to what is already in the xidl file.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 21.3 KB
Line 
1/* $Id: PerformanceImpl.cpp 14772 2008-11-28 12:41:22Z 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_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 (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/* 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