VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxManage/VBoxManageMetrics.cpp@ 85551

Last change on this file since 85551 was 85121, checked in by vboxsync, 4 years ago

iprt/cdefs.h: Refactored the typedef use of DECLCALLBACK as well as DECLCALLBACKMEMBER to wrap the whole expression, similar to the DECLR?CALLBACKMEMBER macros. This allows adding a throw() at the end when compiling with the VC++ compiler to indicate that the callbacks won't throw anything, so we can stop supressing the C5039 warning about passing functions that can potential throw C++ exceptions to extern C code that can't necessarily cope with such (unwind,++). Introduced a few _EX variations that allows specifying different/no calling convention too, as that's handy when dynamically resolving host APIs. Fixed numerous places missing DECLCALLBACK and such. Left two angry @todos regarding use of CreateThread. bugref:9794

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.7 KB
Line 
1/* $Id: VBoxManageMetrics.cpp 85121 2020-07-08 19:33:26Z vboxsync $ */
2/** @file
3 * VBoxManage - The 'metrics' command.
4 */
5
6/*
7 * Copyright (C) 2006-2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#ifndef VBOX_ONLY_DOCS
19
20
21/*********************************************************************************************************************************
22* Header Files *
23*********************************************************************************************************************************/
24#include <VBox/com/com.h>
25#include <VBox/com/array.h>
26#include <VBox/com/ErrorInfo.h>
27#include <VBox/com/errorprint.h>
28#include <VBox/com/VirtualBox.h>
29
30#include <iprt/asm.h>
31#include <iprt/stream.h>
32#include <iprt/string.h>
33#include <iprt/time.h>
34#include <iprt/thread.h>
35#include <VBox/log.h>
36
37#include <set>
38#include <utility>
39
40#include "VBoxManage.h"
41using namespace com;
42
43
44// funcs
45///////////////////////////////////////////////////////////////////////////////
46
47
48static HRESULT parseFilterParameters(int argc, char *argv[],
49 ComPtr<IVirtualBox> aVirtualBox,
50 ComSafeArrayOut(BSTR, outMetrics),
51 ComSafeArrayOut(IUnknown *, outObjects))
52{
53 HRESULT rc = S_OK;
54 com::SafeArray<BSTR> retMetrics(1);
55 com::SafeIfaceArray <IUnknown> retObjects;
56
57 Bstr metricNames, baseNames;
58
59 /* Metric list */
60 if (argc > 1)
61 metricNames = argv[1];
62 else
63 {
64 metricNames = L"*";
65 baseNames = L"*";
66 }
67 metricNames.cloneTo(&retMetrics[0]);
68
69 /* Object name */
70 if (argc > 0 && strcmp(argv[0], "*"))
71 {
72 if (!strcmp(argv[0], "host"))
73 {
74 ComPtr<IHost> host;
75 CHECK_ERROR(aVirtualBox, COMGETTER(Host)(host.asOutParam()));
76 retObjects.reset(1);
77 host.queryInterfaceTo(&retObjects[0]);
78 }
79 else
80 {
81 ComPtr<IMachine> machine;
82 rc = aVirtualBox->FindMachine(Bstr(argv[0]).raw(),
83 machine.asOutParam());
84 if (SUCCEEDED(rc))
85 {
86 retObjects.reset(1);
87 machine.queryInterfaceTo(&retObjects[0]);
88 }
89 else
90 {
91 errorArgument("Invalid machine name: '%s'", argv[0]);
92 return rc;
93 }
94 }
95
96 }
97
98 retMetrics.detachTo(ComSafeArrayOutArg(outMetrics));
99 retObjects.detachTo(ComSafeArrayOutArg(outObjects));
100
101 return rc;
102}
103
104static Bstr toBaseName(Utf8Str& aFullName)
105{
106 char *pszRaw = aFullName.mutableRaw();
107 /*
108 * Currently there are two metrics which base name is the same as the
109 * sub-metric name: CPU/MHz and Net/<iface>/LinkSpeed.
110 */
111 if (pszRaw && strcmp(pszRaw, "CPU/MHz") && !RTStrSimplePatternMatch("Net/*/LinkSpeed", pszRaw))
112 {
113 char *pszSlash = strrchr(pszRaw, '/');
114 if (pszSlash)
115 {
116 *pszSlash = 0;
117 aFullName.jolt();
118 }
119 }
120 return Bstr(aFullName);
121}
122
123static Bstr getObjectName(ComPtr<IUnknown> aObject)
124{
125 HRESULT rc;
126
127 ComPtr<IHost> host = aObject;
128 if (!host.isNull())
129 return Bstr("host");
130
131 ComPtr<IMachine> machine = aObject;
132 if (!machine.isNull())
133 {
134 Bstr name;
135 CHECK_ERROR(machine, COMGETTER(Name)(name.asOutParam()));
136 if (SUCCEEDED(rc))
137 return name;
138 }
139 return Bstr("unknown");
140}
141
142static void listAffectedMetrics(ComSafeArrayIn(IPerformanceMetric*, aMetrics))
143{
144 HRESULT rc;
145 com::SafeIfaceArray<IPerformanceMetric> metrics(ComSafeArrayInArg(aMetrics));
146 if (metrics.size())
147 {
148 ComPtr<IUnknown> object;
149 Bstr metricName;
150 RTPrintf("The following metrics were modified:\n\n"
151 "Object Metric\n"
152 "---------- --------------------\n");
153 for (size_t i = 0; i < metrics.size(); i++)
154 {
155 CHECK_ERROR(metrics[i], COMGETTER(Object)(object.asOutParam()));
156 CHECK_ERROR(metrics[i], COMGETTER(MetricName)(metricName.asOutParam()));
157 RTPrintf("%-10ls %-20ls\n",
158 getObjectName(object).raw(), metricName.raw());
159 }
160 RTPrintf("\n");
161 }
162 else
163 {
164 RTMsgError("No metrics match the specified filter!");
165 }
166}
167
168/**
169 * list
170 */
171static RTEXITCODE handleMetricsList(int argc, char *argv[],
172 ComPtr<IVirtualBox> aVirtualBox,
173 ComPtr<IPerformanceCollector> performanceCollector)
174{
175 HRESULT rc;
176 com::SafeArray<BSTR> metrics;
177 com::SafeIfaceArray<IUnknown> objects;
178
179 rc = parseFilterParameters(argc - 1, &argv[1], aVirtualBox,
180 ComSafeArrayAsOutParam(metrics),
181 ComSafeArrayAsOutParam(objects));
182 if (FAILED(rc))
183 return RTEXITCODE_FAILURE;
184
185 com::SafeIfaceArray<IPerformanceMetric> metricInfo;
186
187 CHECK_ERROR(performanceCollector,
188 GetMetrics(ComSafeArrayAsInParam(metrics),
189 ComSafeArrayAsInParam(objects),
190 ComSafeArrayAsOutParam(metricInfo)));
191
192 ComPtr<IUnknown> object;
193 Bstr metricName, unit, description;
194 ULONG period, count;
195 LONG minimum, maximum;
196 RTPrintf(
197"Object Metric Unit Minimum Maximum Period Count Description\n"
198"--------------- ---------------------------------------- ---- ---------- ---------- ---------- ---------- -----------\n");
199 for (size_t i = 0; i < metricInfo.size(); i++)
200 {
201 CHECK_ERROR(metricInfo[i], COMGETTER(Object)(object.asOutParam()));
202 CHECK_ERROR(metricInfo[i], COMGETTER(MetricName)(metricName.asOutParam()));
203 CHECK_ERROR(metricInfo[i], COMGETTER(Period)(&period));
204 CHECK_ERROR(metricInfo[i], COMGETTER(Count)(&count));
205 CHECK_ERROR(metricInfo[i], COMGETTER(MinimumValue)(&minimum));
206 CHECK_ERROR(metricInfo[i], COMGETTER(MaximumValue)(&maximum));
207 CHECK_ERROR(metricInfo[i], COMGETTER(Unit)(unit.asOutParam()));
208 CHECK_ERROR(metricInfo[i], COMGETTER(Description)(description.asOutParam()));
209 RTPrintf("%-15ls %-40ls %-4ls %10d %10d %10u %10u %ls\n",
210 getObjectName(object).raw(), metricName.raw(), unit.raw(),
211 minimum, maximum, period, count, description.raw());
212 }
213
214 return RTEXITCODE_SUCCESS;
215}
216
217/**
218 * Metrics setup
219 */
220static RTEXITCODE handleMetricsSetup(int argc, char *argv[],
221 ComPtr<IVirtualBox> aVirtualBox,
222 ComPtr<IPerformanceCollector> performanceCollector)
223{
224 HRESULT rc;
225 com::SafeArray<BSTR> metrics;
226 com::SafeIfaceArray<IUnknown> objects;
227 uint32_t period = 1, samples = 1;
228 bool listMatches = false;
229 int i;
230
231 for (i = 1; i < argc; i++)
232 {
233 if ( !strcmp(argv[i], "--period")
234 || !strcmp(argv[i], "-period"))
235 {
236 if (argc <= i + 1)
237 return errorArgument("Missing argument to '%s'", argv[i]);
238 if ( VINF_SUCCESS != RTStrToUInt32Full(argv[++i], 10, &period)
239 || !period)
240 return errorArgument("Invalid value for 'period' parameter: '%s'", argv[i]);
241 }
242 else if ( !strcmp(argv[i], "--samples")
243 || !strcmp(argv[i], "-samples"))
244 {
245 if (argc <= i + 1)
246 return errorArgument("Missing argument to '%s'", argv[i]);
247 if ( VINF_SUCCESS != RTStrToUInt32Full(argv[++i], 10, &samples)
248 || !samples)
249 return errorArgument("Invalid value for 'samples' parameter: '%s'", argv[i]);
250 }
251 else if ( !strcmp(argv[i], "--list")
252 || !strcmp(argv[i], "-list"))
253 listMatches = true;
254 else
255 break; /* The rest of params should define the filter */
256 }
257
258 rc = parseFilterParameters(argc - i, &argv[i], aVirtualBox,
259 ComSafeArrayAsOutParam(metrics),
260 ComSafeArrayAsOutParam(objects));
261 if (FAILED(rc))
262 return RTEXITCODE_FAILURE;
263
264 com::SafeIfaceArray<IPerformanceMetric> affectedMetrics;
265 CHECK_ERROR(performanceCollector,
266 SetupMetrics(ComSafeArrayAsInParam(metrics),
267 ComSafeArrayAsInParam(objects), period, samples,
268 ComSafeArrayAsOutParam(affectedMetrics)));
269 if (FAILED(rc))
270 return RTEXITCODE_SYNTAX; /** @todo figure out why we must return 2 here. */
271
272 if (listMatches)
273 listAffectedMetrics(ComSafeArrayAsInParam(affectedMetrics));
274
275 return RTEXITCODE_SUCCESS;
276}
277
278/**
279 * metrics query
280 */
281static RTEXITCODE handleMetricsQuery(int argc, char *argv[],
282 ComPtr<IVirtualBox> aVirtualBox,
283 ComPtr<IPerformanceCollector> performanceCollector)
284{
285 HRESULT rc;
286 com::SafeArray<BSTR> metrics;
287 com::SafeIfaceArray<IUnknown> objects;
288
289 rc = parseFilterParameters(argc - 1, &argv[1], aVirtualBox,
290 ComSafeArrayAsOutParam(metrics),
291 ComSafeArrayAsOutParam(objects));
292 if (FAILED(rc))
293 return RTEXITCODE_FAILURE;
294
295 com::SafeArray<BSTR> retNames;
296 com::SafeIfaceArray<IUnknown> retObjects;
297 com::SafeArray<BSTR> retUnits;
298 com::SafeArray<ULONG> retScales;
299 com::SafeArray<ULONG> retSequenceNumbers;
300 com::SafeArray<ULONG> retIndices;
301 com::SafeArray<ULONG> retLengths;
302 com::SafeArray<LONG> retData;
303 CHECK_ERROR(performanceCollector, QueryMetricsData(ComSafeArrayAsInParam(metrics),
304 ComSafeArrayAsInParam(objects),
305 ComSafeArrayAsOutParam(retNames),
306 ComSafeArrayAsOutParam(retObjects),
307 ComSafeArrayAsOutParam(retUnits),
308 ComSafeArrayAsOutParam(retScales),
309 ComSafeArrayAsOutParam(retSequenceNumbers),
310 ComSafeArrayAsOutParam(retIndices),
311 ComSafeArrayAsOutParam(retLengths),
312 ComSafeArrayAsOutParam(retData)) );
313
314 RTPrintf("Object Metric Values\n"
315 "--------------- ---------------------------------------- --------------------------------------------\n");
316 for (unsigned i = 0; i < retNames.size(); i++)
317 {
318 Bstr metricUnit(retUnits[i]);
319 Bstr metricName(retNames[i]);
320 RTPrintf("%-15ls %-40ls ", getObjectName(retObjects[i]).raw(), metricName.raw());
321 const char *separator = "";
322 for (unsigned j = 0; j < retLengths[i]; j++)
323 {
324 if (retScales[i] == 1)
325 RTPrintf("%s%d %ls", separator, retData[retIndices[i] + j], metricUnit.raw());
326 else
327 RTPrintf("%s%d.%02d%ls", separator, retData[retIndices[i] + j] / retScales[i],
328 (retData[retIndices[i] + j] * 100 / retScales[i]) % 100, metricUnit.raw());
329 separator = ", ";
330 }
331 RTPrintf("\n");
332 }
333
334 return RTEXITCODE_SUCCESS;
335}
336
337static void getTimestamp(char *pts, size_t tsSize)
338{
339 *pts = 0;
340 AssertReturnVoid(tsSize >= 13); /* 3+3+3+3+1 */
341 RTTIMESPEC TimeSpec;
342 RTTIME Time;
343 RTTimeExplode(&Time, RTTimeNow(&TimeSpec));
344 pts += RTStrFormatNumber(pts, Time.u8Hour, 10, 2, 0, RTSTR_F_ZEROPAD);
345 *pts++ = ':';
346 pts += RTStrFormatNumber(pts, Time.u8Minute, 10, 2, 0, RTSTR_F_ZEROPAD);
347 *pts++ = ':';
348 pts += RTStrFormatNumber(pts, Time.u8Second, 10, 2, 0, RTSTR_F_ZEROPAD);
349 *pts++ = '.';
350 pts += RTStrFormatNumber(pts, Time.u32Nanosecond / 1000000, 10, 3, 0, RTSTR_F_ZEROPAD);
351 *pts = 0;
352}
353
354/** Used by the handleMetricsCollect loop. */
355static bool volatile g_fKeepGoing = true;
356
357#ifdef RT_OS_WINDOWS
358/**
359 * Handler routine for catching Ctrl-C, Ctrl-Break and closing of
360 * the console.
361 *
362 * @returns true if handled, false if not handled.
363 * @param dwCtrlType The type of control signal.
364 *
365 * @remarks This is called on a new thread.
366 */
367static BOOL WINAPI ctrlHandler(DWORD dwCtrlType) RT_NOTHROW_DEF
368{
369 switch (dwCtrlType)
370 {
371 /* Ctrl-C or Ctrl-Break or Close */
372 case CTRL_C_EVENT:
373 case CTRL_BREAK_EVENT:
374 case CTRL_CLOSE_EVENT:
375 /* Let's shut down gracefully. */
376 ASMAtomicWriteBool(&g_fKeepGoing, false);
377 return TRUE;
378 }
379 /* Don't care about the rest -- let it die a horrible death. */
380 return FALSE;
381}
382#endif /* RT_OS_WINDOWS */
383
384/**
385 * collect
386 */
387static RTEXITCODE handleMetricsCollect(int argc, char *argv[],
388 ComPtr<IVirtualBox> aVirtualBox,
389 ComPtr<IPerformanceCollector> performanceCollector)
390{
391 HRESULT rc;
392 com::SafeArray<BSTR> metrics;
393 com::SafeIfaceArray<IUnknown> objects;
394 uint32_t period = 1, samples = 1;
395 bool isDetached = false, listMatches = false;
396 int i;
397 for (i = 1; i < argc; i++)
398 {
399 if ( !strcmp(argv[i], "--period")
400 || !strcmp(argv[i], "-period"))
401 {
402 if (argc <= i + 1)
403 return errorArgument("Missing argument to '%s'", argv[i]);
404 if ( VINF_SUCCESS != RTStrToUInt32Full(argv[++i], 10, &period)
405 || !period)
406 return errorArgument("Invalid value for 'period' parameter: '%s'", argv[i]);
407 }
408 else if ( !strcmp(argv[i], "--samples")
409 || !strcmp(argv[i], "-samples"))
410 {
411 if (argc <= i + 1)
412 return errorArgument("Missing argument to '%s'", argv[i]);
413 if ( VINF_SUCCESS != RTStrToUInt32Full(argv[++i], 10, &samples)
414 || !samples)
415 return errorArgument("Invalid value for 'samples' parameter: '%s'", argv[i]);
416 }
417 else if ( !strcmp(argv[i], "--list")
418 || !strcmp(argv[i], "-list"))
419 listMatches = true;
420 else if ( !strcmp(argv[i], "--detach")
421 || !strcmp(argv[i], "-detach"))
422 isDetached = true;
423 else
424 break; /* The rest of params should define the filter */
425 }
426
427 rc = parseFilterParameters(argc - i, &argv[i], aVirtualBox,
428 ComSafeArrayAsOutParam(metrics),
429 ComSafeArrayAsOutParam(objects));
430 if (FAILED(rc))
431 return RTEXITCODE_FAILURE;
432
433 com::SafeIfaceArray<IPerformanceMetric> metricInfo;
434
435 CHECK_ERROR(performanceCollector,
436 GetMetrics(ComSafeArrayAsInParam(metrics),
437 ComSafeArrayAsInParam(objects),
438 ComSafeArrayAsOutParam(metricInfo)));
439
440 std::set<std::pair<ComPtr<IUnknown>,Bstr> > baseMetrics;
441 ComPtr<IUnknown> objectFiltered;
442 Bstr metricNameFiltered;
443 for (i = 0; i < (int)metricInfo.size(); i++)
444 {
445 CHECK_ERROR(metricInfo[i], COMGETTER(Object)(objectFiltered.asOutParam()));
446 CHECK_ERROR(metricInfo[i], COMGETTER(MetricName)(metricNameFiltered.asOutParam()));
447 Utf8Str baseMetricName(metricNameFiltered);
448 baseMetrics.insert(std::make_pair(objectFiltered, toBaseName(baseMetricName)));
449 }
450 com::SafeArray<BSTR> baseMetricsFiltered(baseMetrics.size());
451 com::SafeIfaceArray<IUnknown> objectsFiltered(baseMetrics.size());
452 std::set<std::pair<ComPtr<IUnknown>,Bstr> >::iterator it;
453 i = 0;
454 for (it = baseMetrics.begin(); it != baseMetrics.end(); ++it)
455 {
456 it->first.queryInterfaceTo(&objectsFiltered[i]);
457 Bstr(it->second).detachTo(&baseMetricsFiltered[i++]);
458 }
459 com::SafeIfaceArray<IPerformanceMetric> affectedMetrics;
460 CHECK_ERROR(performanceCollector,
461 SetupMetrics(ComSafeArrayAsInParam(baseMetricsFiltered),
462 ComSafeArrayAsInParam(objectsFiltered), period, samples,
463 ComSafeArrayAsOutParam(affectedMetrics)));
464 if (FAILED(rc))
465 return RTEXITCODE_SYNTAX; /** @todo figure out why we must return 2 here. */
466
467 if (listMatches)
468 listAffectedMetrics(ComSafeArrayAsInParam(affectedMetrics));
469 if (!affectedMetrics.size())
470 return RTEXITCODE_FAILURE;
471
472 if (isDetached)
473 {
474 RTMsgWarning("The background process holding collected metrics will shutdown\n"
475 "in few seconds, discarding all collected data and parameters.");
476 return RTEXITCODE_SUCCESS;
477 }
478
479#ifdef RT_OS_WINDOWS
480 SetConsoleCtrlHandler(ctrlHandler, true);
481#endif /* RT_OS_WINDOWS */
482
483 RTPrintf("Time stamp Object Metric Value\n");
484
485 while (g_fKeepGoing)
486 {
487 RTPrintf("------------ ---------- -------------------- --------------------\n");
488 RTThreadSleep(period * 1000); // Sleep for 'period' seconds
489 char ts[15];
490
491 getTimestamp(ts, sizeof(ts));
492 com::SafeArray<BSTR> retNames;
493 com::SafeIfaceArray<IUnknown> retObjects;
494 com::SafeArray<BSTR> retUnits;
495 com::SafeArray<ULONG> retScales;
496 com::SafeArray<ULONG> retSequenceNumbers;
497 com::SafeArray<ULONG> retIndices;
498 com::SafeArray<ULONG> retLengths;
499 com::SafeArray<LONG> retData;
500 CHECK_ERROR(performanceCollector, QueryMetricsData(ComSafeArrayAsInParam(metrics),
501 ComSafeArrayAsInParam(objects),
502 ComSafeArrayAsOutParam(retNames),
503 ComSafeArrayAsOutParam(retObjects),
504 ComSafeArrayAsOutParam(retUnits),
505 ComSafeArrayAsOutParam(retScales),
506 ComSafeArrayAsOutParam(retSequenceNumbers),
507 ComSafeArrayAsOutParam(retIndices),
508 ComSafeArrayAsOutParam(retLengths),
509 ComSafeArrayAsOutParam(retData)) );
510 for (unsigned j = 0; j < retNames.size(); j++)
511 {
512 Bstr metricUnit(retUnits[j]);
513 Bstr metricName(retNames[j]);
514 RTPrintf("%-12s %-10ls %-20ls ", ts, getObjectName(retObjects[j]).raw(), metricName.raw());
515 const char *separator = "";
516 for (unsigned k = 0; k < retLengths[j]; k++)
517 {
518 if (retScales[j] == 1)
519 RTPrintf("%s%d %ls", separator, retData[retIndices[j] + k], metricUnit.raw());
520 else
521 RTPrintf("%s%d.%02d%ls", separator, retData[retIndices[j] + k] / retScales[j],
522 (retData[retIndices[j] + k] * 100 / retScales[j]) % 100, metricUnit.raw());
523 separator = ", ";
524 }
525 RTPrintf("\n");
526 }
527 RTStrmFlush(g_pStdOut);
528 }
529
530#ifdef RT_OS_WINDOWS
531 SetConsoleCtrlHandler(ctrlHandler, false);
532#endif /* RT_OS_WINDOWS */
533
534 return RTEXITCODE_SUCCESS;
535}
536
537/**
538 * Enable metrics
539 */
540static RTEXITCODE handleMetricsEnable(int argc, char *argv[],
541 ComPtr<IVirtualBox> aVirtualBox,
542 ComPtr<IPerformanceCollector> performanceCollector)
543{
544 HRESULT rc;
545 com::SafeArray<BSTR> metrics;
546 com::SafeIfaceArray<IUnknown> objects;
547 bool listMatches = false;
548 int i;
549
550 for (i = 1; i < argc; i++)
551 {
552 if ( !strcmp(argv[i], "--list")
553 || !strcmp(argv[i], "-list"))
554 listMatches = true;
555 else
556 break; /* The rest of params should define the filter */
557 }
558
559 rc = parseFilterParameters(argc - i, &argv[i], aVirtualBox,
560 ComSafeArrayAsOutParam(metrics),
561 ComSafeArrayAsOutParam(objects));
562 if (FAILED(rc))
563 return RTEXITCODE_FAILURE;
564
565 com::SafeIfaceArray<IPerformanceMetric> affectedMetrics;
566 CHECK_ERROR(performanceCollector,
567 EnableMetrics(ComSafeArrayAsInParam(metrics),
568 ComSafeArrayAsInParam(objects),
569 ComSafeArrayAsOutParam(affectedMetrics)));
570 if (FAILED(rc))
571 return RTEXITCODE_SYNTAX; /** @todo figure out why we must return 2 here. */
572
573 if (listMatches)
574 listAffectedMetrics(ComSafeArrayAsInParam(affectedMetrics));
575
576 return RTEXITCODE_SUCCESS;
577}
578
579/**
580 * Disable metrics
581 */
582static RTEXITCODE handleMetricsDisable(int argc, char *argv[],
583 ComPtr<IVirtualBox> aVirtualBox,
584 ComPtr<IPerformanceCollector> performanceCollector)
585{
586 HRESULT rc;
587 com::SafeArray<BSTR> metrics;
588 com::SafeIfaceArray<IUnknown> objects;
589 bool listMatches = false;
590 int i;
591
592 for (i = 1; i < argc; i++)
593 {
594 if ( !strcmp(argv[i], "--list")
595 || !strcmp(argv[i], "-list"))
596 listMatches = true;
597 else
598 break; /* The rest of params should define the filter */
599 }
600
601 rc = parseFilterParameters(argc - i, &argv[i], aVirtualBox,
602 ComSafeArrayAsOutParam(metrics),
603 ComSafeArrayAsOutParam(objects));
604 if (FAILED(rc))
605 return RTEXITCODE_FAILURE;
606
607 com::SafeIfaceArray<IPerformanceMetric> affectedMetrics;
608 CHECK_ERROR(performanceCollector,
609 DisableMetrics(ComSafeArrayAsInParam(metrics),
610 ComSafeArrayAsInParam(objects),
611 ComSafeArrayAsOutParam(affectedMetrics)));
612 if (FAILED(rc))
613 return RTEXITCODE_SYNTAX; /** @todo figure out why we must return 2 here. */
614
615 if (listMatches)
616 listAffectedMetrics(ComSafeArrayAsInParam(affectedMetrics));
617
618 return RTEXITCODE_SUCCESS;
619}
620
621
622RTEXITCODE handleMetrics(HandlerArg *a)
623{
624 /* at least one option: subcommand name */
625 if (a->argc < 1)
626 return errorSyntax(USAGE_METRICS, "Subcommand missing");
627
628 ComPtr<IPerformanceCollector> performanceCollector;
629 CHECK_ERROR2I_RET(a->virtualBox, COMGETTER(PerformanceCollector)(performanceCollector.asOutParam()), RTEXITCODE_FAILURE);
630
631 RTEXITCODE rcExit;
632 if (!strcmp(a->argv[0], "list"))
633 rcExit = handleMetricsList(a->argc, a->argv, a->virtualBox, performanceCollector);
634 else if (!strcmp(a->argv[0], "setup"))
635 rcExit = handleMetricsSetup(a->argc, a->argv, a->virtualBox, performanceCollector);
636 else if (!strcmp(a->argv[0], "query"))
637 rcExit = handleMetricsQuery(a->argc, a->argv, a->virtualBox, performanceCollector);
638 else if (!strcmp(a->argv[0], "collect"))
639 rcExit = handleMetricsCollect(a->argc, a->argv, a->virtualBox, performanceCollector);
640 else if (!strcmp(a->argv[0], "enable"))
641 rcExit = handleMetricsEnable(a->argc, a->argv, a->virtualBox, performanceCollector);
642 else if (!strcmp(a->argv[0], "disable"))
643 rcExit = handleMetricsDisable(a->argc, a->argv, a->virtualBox, performanceCollector);
644 else
645 return errorSyntax(USAGE_METRICS, "Invalid subcommand '%s'", a->argv[0]);
646
647 return rcExit;
648}
649
650#endif /* !VBOX_ONLY_DOCS */
651
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