~ubuntu-branches/ubuntu/raring/virtualbox-ose/raring

« back to all changes in this revision

Viewing changes to src/VBox/Main/src-server/PerformanceImpl.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Felix Geyer
  • Date: 2011-01-30 23:27:25 UTC
  • mfrom: (0.3.12 upstream)
  • Revision ID: james.westby@ubuntu.com-20110130232725-2ouajjd2ggdet0zd
Tags: 4.0.2-dfsg-1ubuntu1
* Merge from Debian unstable, remaining changes:
  - Add Apport hook.
    - debian/virtualbox-ose.files/source_virtualbox-ose.py
    - debian/virtualbox-ose.install
  - Drop *-source packages.
* Drop ubuntu-01-fix-build-gcc45.patch, fixed upstream.
* Drop ubuntu-02-as-needed.patch, added to the Debian package.

Show diffs side-by-side

added added

removed removed

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