VirtualBox

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

Last change on this file since 61226 was 59922, checked in by vboxsync, 9 years ago

FE/VBoxManage: VBoxManageMetrics.cpp: Slightly tweaked output for metrics listing/querying.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 24.1 KB
Line 
1/* $Id: VBoxManageMetrics.cpp 59922 2016-03-04 12:05:32Z vboxsync $ */
2/** @file
3 * VBoxManage - The 'metrics' command.
4 */
5
6/*
7 * Copyright (C) 2006-2015 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<IVirtualBox> aVirtualBox,
124 ComPtr<IUnknown> aObject)
125{
126 HRESULT rc;
127
128 ComPtr<IHost> host = aObject;
129 if (!host.isNull())
130 return Bstr("host");
131
132 ComPtr<IMachine> machine = aObject;
133 if (!machine.isNull())
134 {
135 Bstr name;
136 CHECK_ERROR(machine, COMGETTER(Name)(name.asOutParam()));
137 if (SUCCEEDED(rc))
138 return name;
139 }
140 return Bstr("unknown");
141}
142
143static void listAffectedMetrics(ComPtr<IVirtualBox> aVirtualBox,
144 ComSafeArrayIn(IPerformanceMetric*, aMetrics))
145{
146 HRESULT rc;
147 com::SafeIfaceArray<IPerformanceMetric> metrics(ComSafeArrayInArg(aMetrics));
148 if (metrics.size())
149 {
150 ComPtr<IUnknown> object;
151 Bstr metricName;
152 RTPrintf("The following metrics were modified:\n\n"
153 "Object Metric\n"
154 "---------- --------------------\n");
155 for (size_t i = 0; i < metrics.size(); i++)
156 {
157 CHECK_ERROR(metrics[i], COMGETTER(Object)(object.asOutParam()));
158 CHECK_ERROR(metrics[i], COMGETTER(MetricName)(metricName.asOutParam()));
159 RTPrintf("%-10ls %-20ls\n",
160 getObjectName(aVirtualBox, object).raw(), metricName.raw());
161 }
162 RTPrintf("\n");
163 }
164 else
165 {
166 RTMsgError("No metrics match the specified filter!");
167 }
168}
169
170/**
171 * list
172 */
173static RTEXITCODE handleMetricsList(int argc, char *argv[],
174 ComPtr<IVirtualBox> aVirtualBox,
175 ComPtr<IPerformanceCollector> performanceCollector)
176{
177 HRESULT rc;
178 com::SafeArray<BSTR> metrics;
179 com::SafeIfaceArray<IUnknown> objects;
180
181 rc = parseFilterParameters(argc - 1, &argv[1], aVirtualBox,
182 ComSafeArrayAsOutParam(metrics),
183 ComSafeArrayAsOutParam(objects));
184 if (FAILED(rc))
185 return RTEXITCODE_FAILURE;
186
187 com::SafeIfaceArray<IPerformanceMetric> metricInfo;
188
189 CHECK_ERROR(performanceCollector,
190 GetMetrics(ComSafeArrayAsInParam(metrics),
191 ComSafeArrayAsInParam(objects),
192 ComSafeArrayAsOutParam(metricInfo)));
193
194 ComPtr<IUnknown> object;
195 Bstr metricName, unit, description;
196 ULONG period, count;
197 LONG minimum, maximum;
198 RTPrintf(
199"Object Metric Unit Minimum Maximum Period Count Description\n"
200"--------------- ---------------------------------------- ---- ---------- ---------- ---------- ---------- -----------\n");
201 for (size_t i = 0; i < metricInfo.size(); i++)
202 {
203 CHECK_ERROR(metricInfo[i], COMGETTER(Object)(object.asOutParam()));
204 CHECK_ERROR(metricInfo[i], COMGETTER(MetricName)(metricName.asOutParam()));
205 CHECK_ERROR(metricInfo[i], COMGETTER(Period)(&period));
206 CHECK_ERROR(metricInfo[i], COMGETTER(Count)(&count));
207 CHECK_ERROR(metricInfo[i], COMGETTER(MinimumValue)(&minimum));
208 CHECK_ERROR(metricInfo[i], COMGETTER(MaximumValue)(&maximum));
209 CHECK_ERROR(metricInfo[i], COMGETTER(Unit)(unit.asOutParam()));
210 CHECK_ERROR(metricInfo[i], COMGETTER(Description)(description.asOutParam()));
211 RTPrintf("%-15ls %-40ls %-4ls %10d %10d %10u %10u %ls\n",
212 getObjectName(aVirtualBox, object).raw(), metricName.raw(), unit.raw(),
213 minimum, maximum, period, count, description.raw());
214 }
215
216 return RTEXITCODE_SUCCESS;
217}
218
219/**
220 * Metrics setup
221 */
222static RTEXITCODE handleMetricsSetup(int argc, char *argv[],
223 ComPtr<IVirtualBox> aVirtualBox,
224 ComPtr<IPerformanceCollector> performanceCollector)
225{
226 HRESULT rc;
227 com::SafeArray<BSTR> metrics;
228 com::SafeIfaceArray<IUnknown> objects;
229 uint32_t period = 1, samples = 1;
230 bool listMatches = false;
231 int i;
232
233 for (i = 1; i < argc; i++)
234 {
235 if ( !strcmp(argv[i], "--period")
236 || !strcmp(argv[i], "-period"))
237 {
238 if (argc <= i + 1)
239 return errorArgument("Missing argument to '%s'", argv[i]);
240 if ( VINF_SUCCESS != RTStrToUInt32Full(argv[++i], 10, &period)
241 || !period)
242 return errorArgument("Invalid value for 'period' parameter: '%s'", argv[i]);
243 }
244 else if ( !strcmp(argv[i], "--samples")
245 || !strcmp(argv[i], "-samples"))
246 {
247 if (argc <= i + 1)
248 return errorArgument("Missing argument to '%s'", argv[i]);
249 if ( VINF_SUCCESS != RTStrToUInt32Full(argv[++i], 10, &samples)
250 || !samples)
251 return errorArgument("Invalid value for 'samples' parameter: '%s'", argv[i]);
252 }
253 else if ( !strcmp(argv[i], "--list")
254 || !strcmp(argv[i], "-list"))
255 listMatches = true;
256 else
257 break; /* The rest of params should define the filter */
258 }
259
260 rc = parseFilterParameters(argc - i, &argv[i], aVirtualBox,
261 ComSafeArrayAsOutParam(metrics),
262 ComSafeArrayAsOutParam(objects));
263 if (FAILED(rc))
264 return RTEXITCODE_FAILURE;
265
266 com::SafeIfaceArray<IPerformanceMetric> affectedMetrics;
267 CHECK_ERROR(performanceCollector,
268 SetupMetrics(ComSafeArrayAsInParam(metrics),
269 ComSafeArrayAsInParam(objects), period, samples,
270 ComSafeArrayAsOutParam(affectedMetrics)));
271 if (FAILED(rc))
272 return RTEXITCODE_SYNTAX; /** @todo figure out why we must return 2 here. */
273
274 if (listMatches)
275 listAffectedMetrics(aVirtualBox,
276 ComSafeArrayAsInParam(affectedMetrics));
277
278 return RTEXITCODE_SUCCESS;
279}
280
281/**
282 * metrics query
283 */
284static RTEXITCODE handleMetricsQuery(int argc, char *argv[],
285 ComPtr<IVirtualBox> aVirtualBox,
286 ComPtr<IPerformanceCollector> performanceCollector)
287{
288 HRESULT rc;
289 com::SafeArray<BSTR> metrics;
290 com::SafeIfaceArray<IUnknown> objects;
291
292 rc = parseFilterParameters(argc - 1, &argv[1], aVirtualBox,
293 ComSafeArrayAsOutParam(metrics),
294 ComSafeArrayAsOutParam(objects));
295 if (FAILED(rc))
296 return RTEXITCODE_FAILURE;
297
298 com::SafeArray<BSTR> retNames;
299 com::SafeIfaceArray<IUnknown> retObjects;
300 com::SafeArray<BSTR> retUnits;
301 com::SafeArray<ULONG> retScales;
302 com::SafeArray<ULONG> retSequenceNumbers;
303 com::SafeArray<ULONG> retIndices;
304 com::SafeArray<ULONG> retLengths;
305 com::SafeArray<LONG> retData;
306 CHECK_ERROR(performanceCollector, QueryMetricsData(ComSafeArrayAsInParam(metrics),
307 ComSafeArrayAsInParam(objects),
308 ComSafeArrayAsOutParam(retNames),
309 ComSafeArrayAsOutParam(retObjects),
310 ComSafeArrayAsOutParam(retUnits),
311 ComSafeArrayAsOutParam(retScales),
312 ComSafeArrayAsOutParam(retSequenceNumbers),
313 ComSafeArrayAsOutParam(retIndices),
314 ComSafeArrayAsOutParam(retLengths),
315 ComSafeArrayAsOutParam(retData)) );
316
317 RTPrintf("Object Metric Values\n"
318 "--------------- ---------------------------------------- --------------------------------------------\n");
319 for (unsigned i = 0; i < retNames.size(); i++)
320 {
321 Bstr metricUnit(retUnits[i]);
322 Bstr metricName(retNames[i]);
323 RTPrintf("%-15ls %-40ls ", getObjectName(aVirtualBox, retObjects[i]).raw(), metricName.raw());
324 const char *separator = "";
325 for (unsigned j = 0; j < retLengths[i]; j++)
326 {
327 if (retScales[i] == 1)
328 RTPrintf("%s%d %ls", separator, retData[retIndices[i] + j], metricUnit.raw());
329 else
330 RTPrintf("%s%d.%02d%ls", separator, retData[retIndices[i] + j] / retScales[i],
331 (retData[retIndices[i] + j] * 100 / retScales[i]) % 100, metricUnit.raw());
332 separator = ", ";
333 }
334 RTPrintf("\n");
335 }
336
337 return RTEXITCODE_SUCCESS;
338}
339
340static void getTimestamp(char *pts, size_t tsSize)
341{
342 *pts = 0;
343 AssertReturnVoid(tsSize >= 13); /* 3+3+3+3+1 */
344 RTTIMESPEC TimeSpec;
345 RTTIME Time;
346 RTTimeExplode(&Time, RTTimeNow(&TimeSpec));
347 pts += RTStrFormatNumber(pts, Time.u8Hour, 10, 2, 0, RTSTR_F_ZEROPAD);
348 *pts++ = ':';
349 pts += RTStrFormatNumber(pts, Time.u8Minute, 10, 2, 0, RTSTR_F_ZEROPAD);
350 *pts++ = ':';
351 pts += RTStrFormatNumber(pts, Time.u8Second, 10, 2, 0, RTSTR_F_ZEROPAD);
352 *pts++ = '.';
353 pts += RTStrFormatNumber(pts, Time.u32Nanosecond / 1000000, 10, 3, 0, RTSTR_F_ZEROPAD);
354 *pts = 0;
355}
356
357/** Used by the handleMetricsCollect loop. */
358static bool volatile g_fKeepGoing = true;
359
360#ifdef RT_OS_WINDOWS
361/**
362 * Handler routine for catching Ctrl-C, Ctrl-Break and closing of
363 * the console.
364 *
365 * @returns true if handled, false if not handled.
366 * @param dwCtrlType The type of control signal.
367 *
368 * @remarks This is called on a new thread.
369 */
370static BOOL WINAPI ctrlHandler(DWORD dwCtrlType)
371{
372 switch (dwCtrlType)
373 {
374 /* Ctrl-C or Ctrl-Break or Close */
375 case CTRL_C_EVENT:
376 case CTRL_BREAK_EVENT:
377 case CTRL_CLOSE_EVENT:
378 /* Let's shut down gracefully. */
379 ASMAtomicWriteBool(&g_fKeepGoing, false);
380 return TRUE;
381 }
382 /* Don't care about the rest -- let it die a horrible death. */
383 return FALSE;
384}
385#endif /* RT_OS_WINDOWS */
386
387/**
388 * collect
389 */
390static RTEXITCODE handleMetricsCollect(int argc, char *argv[],
391 ComPtr<IVirtualBox> aVirtualBox,
392 ComPtr<IPerformanceCollector> performanceCollector)
393{
394 HRESULT rc;
395 com::SafeArray<BSTR> metrics;
396 com::SafeIfaceArray<IUnknown> objects;
397 uint32_t period = 1, samples = 1;
398 bool isDetached = false, listMatches = false;
399 int i;
400 for (i = 1; i < argc; i++)
401 {
402 if ( !strcmp(argv[i], "--period")
403 || !strcmp(argv[i], "-period"))
404 {
405 if (argc <= i + 1)
406 return errorArgument("Missing argument to '%s'", argv[i]);
407 if ( VINF_SUCCESS != RTStrToUInt32Full(argv[++i], 10, &period)
408 || !period)
409 return errorArgument("Invalid value for 'period' parameter: '%s'", argv[i]);
410 }
411 else if ( !strcmp(argv[i], "--samples")
412 || !strcmp(argv[i], "-samples"))
413 {
414 if (argc <= i + 1)
415 return errorArgument("Missing argument to '%s'", argv[i]);
416 if ( VINF_SUCCESS != RTStrToUInt32Full(argv[++i], 10, &samples)
417 || !samples)
418 return errorArgument("Invalid value for 'samples' parameter: '%s'", argv[i]);
419 }
420 else if ( !strcmp(argv[i], "--list")
421 || !strcmp(argv[i], "-list"))
422 listMatches = true;
423 else if ( !strcmp(argv[i], "--detach")
424 || !strcmp(argv[i], "-detach"))
425 isDetached = true;
426 else
427 break; /* The rest of params should define the filter */
428 }
429
430 rc = parseFilterParameters(argc - i, &argv[i], aVirtualBox,
431 ComSafeArrayAsOutParam(metrics),
432 ComSafeArrayAsOutParam(objects));
433 if (FAILED(rc))
434 return RTEXITCODE_FAILURE;
435
436 com::SafeIfaceArray<IPerformanceMetric> metricInfo;
437
438 CHECK_ERROR(performanceCollector,
439 GetMetrics(ComSafeArrayAsInParam(metrics),
440 ComSafeArrayAsInParam(objects),
441 ComSafeArrayAsOutParam(metricInfo)));
442
443 std::set<std::pair<ComPtr<IUnknown>,Bstr> > baseMetrics;
444 ComPtr<IUnknown> objectFiltered;
445 Bstr metricNameFiltered;
446 for (i = 0; i < (int)metricInfo.size(); i++)
447 {
448 CHECK_ERROR(metricInfo[i], COMGETTER(Object)(objectFiltered.asOutParam()));
449 CHECK_ERROR(metricInfo[i], COMGETTER(MetricName)(metricNameFiltered.asOutParam()));
450 Utf8Str baseMetricName(metricNameFiltered);
451 baseMetrics.insert(std::make_pair(objectFiltered, toBaseName(baseMetricName)));
452 }
453 com::SafeArray<BSTR> baseMetricsFiltered(baseMetrics.size());
454 com::SafeIfaceArray<IUnknown> objectsFiltered(baseMetrics.size());
455 std::set<std::pair<ComPtr<IUnknown>,Bstr> >::iterator it;
456 i = 0;
457 for (it = baseMetrics.begin(); it != baseMetrics.end(); ++it)
458 {
459 it->first.queryInterfaceTo(&objectsFiltered[i]);
460 Bstr(it->second).detachTo(&baseMetricsFiltered[i++]);
461 }
462 com::SafeIfaceArray<IPerformanceMetric> affectedMetrics;
463 CHECK_ERROR(performanceCollector,
464 SetupMetrics(ComSafeArrayAsInParam(baseMetricsFiltered),
465 ComSafeArrayAsInParam(objectsFiltered), period, samples,
466 ComSafeArrayAsOutParam(affectedMetrics)));
467 if (FAILED(rc))
468 return RTEXITCODE_SYNTAX; /** @todo figure out why we must return 2 here. */
469
470 if (listMatches)
471 listAffectedMetrics(aVirtualBox,
472 ComSafeArrayAsInParam(affectedMetrics));
473 if (!affectedMetrics.size())
474 return RTEXITCODE_FAILURE;
475
476 if (isDetached)
477 {
478 RTMsgWarning("The background process holding collected metrics will shutdown\n"
479 "in few seconds, discarding all collected data and parameters.");
480 return RTEXITCODE_SUCCESS;
481 }
482
483#ifdef RT_OS_WINDOWS
484 SetConsoleCtrlHandler(ctrlHandler, true);
485#endif /* RT_OS_WINDOWS */
486
487 RTPrintf("Time stamp Object Metric Value\n");
488
489 while (g_fKeepGoing)
490 {
491 RTPrintf("------------ ---------- -------------------- --------------------\n");
492 RTThreadSleep(period * 1000); // Sleep for 'period' seconds
493 char ts[15];
494
495 getTimestamp(ts, sizeof(ts));
496 com::SafeArray<BSTR> retNames;
497 com::SafeIfaceArray<IUnknown> retObjects;
498 com::SafeArray<BSTR> retUnits;
499 com::SafeArray<ULONG> retScales;
500 com::SafeArray<ULONG> retSequenceNumbers;
501 com::SafeArray<ULONG> retIndices;
502 com::SafeArray<ULONG> retLengths;
503 com::SafeArray<LONG> retData;
504 CHECK_ERROR(performanceCollector, QueryMetricsData(ComSafeArrayAsInParam(metrics),
505 ComSafeArrayAsInParam(objects),
506 ComSafeArrayAsOutParam(retNames),
507 ComSafeArrayAsOutParam(retObjects),
508 ComSafeArrayAsOutParam(retUnits),
509 ComSafeArrayAsOutParam(retScales),
510 ComSafeArrayAsOutParam(retSequenceNumbers),
511 ComSafeArrayAsOutParam(retIndices),
512 ComSafeArrayAsOutParam(retLengths),
513 ComSafeArrayAsOutParam(retData)) );
514 for (unsigned j = 0; j < retNames.size(); j++)
515 {
516 Bstr metricUnit(retUnits[j]);
517 Bstr metricName(retNames[j]);
518 RTPrintf("%-12s %-10ls %-20ls ", ts, getObjectName(aVirtualBox, retObjects[j]).raw(), metricName.raw());
519 const char *separator = "";
520 for (unsigned k = 0; k < retLengths[j]; k++)
521 {
522 if (retScales[j] == 1)
523 RTPrintf("%s%d %ls", separator, retData[retIndices[j] + k], metricUnit.raw());
524 else
525 RTPrintf("%s%d.%02d%ls", separator, retData[retIndices[j] + k] / retScales[j],
526 (retData[retIndices[j] + k] * 100 / retScales[j]) % 100, metricUnit.raw());
527 separator = ", ";
528 }
529 RTPrintf("\n");
530 }
531 RTStrmFlush(g_pStdOut);
532 }
533
534#ifdef RT_OS_WINDOWS
535 SetConsoleCtrlHandler(ctrlHandler, false);
536#endif /* RT_OS_WINDOWS */
537
538 return RTEXITCODE_SUCCESS;
539}
540
541/**
542 * Enable metrics
543 */
544static RTEXITCODE handleMetricsEnable(int argc, char *argv[],
545 ComPtr<IVirtualBox> aVirtualBox,
546 ComPtr<IPerformanceCollector> performanceCollector)
547{
548 HRESULT rc;
549 com::SafeArray<BSTR> metrics;
550 com::SafeIfaceArray<IUnknown> objects;
551 bool listMatches = false;
552 int i;
553
554 for (i = 1; i < argc; i++)
555 {
556 if ( !strcmp(argv[i], "--list")
557 || !strcmp(argv[i], "-list"))
558 listMatches = true;
559 else
560 break; /* The rest of params should define the filter */
561 }
562
563 rc = parseFilterParameters(argc - i, &argv[i], aVirtualBox,
564 ComSafeArrayAsOutParam(metrics),
565 ComSafeArrayAsOutParam(objects));
566 if (FAILED(rc))
567 return RTEXITCODE_FAILURE;
568
569 com::SafeIfaceArray<IPerformanceMetric> affectedMetrics;
570 CHECK_ERROR(performanceCollector,
571 EnableMetrics(ComSafeArrayAsInParam(metrics),
572 ComSafeArrayAsInParam(objects),
573 ComSafeArrayAsOutParam(affectedMetrics)));
574 if (FAILED(rc))
575 return RTEXITCODE_SYNTAX; /** @todo figure out why we must return 2 here. */
576
577 if (listMatches)
578 listAffectedMetrics(aVirtualBox,
579 ComSafeArrayAsInParam(affectedMetrics));
580
581 return RTEXITCODE_SUCCESS;
582}
583
584/**
585 * Disable metrics
586 */
587static RTEXITCODE handleMetricsDisable(int argc, char *argv[],
588 ComPtr<IVirtualBox> aVirtualBox,
589 ComPtr<IPerformanceCollector> performanceCollector)
590{
591 HRESULT rc;
592 com::SafeArray<BSTR> metrics;
593 com::SafeIfaceArray<IUnknown> objects;
594 bool listMatches = false;
595 int i;
596
597 for (i = 1; i < argc; i++)
598 {
599 if ( !strcmp(argv[i], "--list")
600 || !strcmp(argv[i], "-list"))
601 listMatches = true;
602 else
603 break; /* The rest of params should define the filter */
604 }
605
606 rc = parseFilterParameters(argc - i, &argv[i], aVirtualBox,
607 ComSafeArrayAsOutParam(metrics),
608 ComSafeArrayAsOutParam(objects));
609 if (FAILED(rc))
610 return RTEXITCODE_FAILURE;
611
612 com::SafeIfaceArray<IPerformanceMetric> affectedMetrics;
613 CHECK_ERROR(performanceCollector,
614 DisableMetrics(ComSafeArrayAsInParam(metrics),
615 ComSafeArrayAsInParam(objects),
616 ComSafeArrayAsOutParam(affectedMetrics)));
617 if (FAILED(rc))
618 return RTEXITCODE_SYNTAX; /** @todo figure out why we must return 2 here. */
619
620 if (listMatches)
621 listAffectedMetrics(aVirtualBox,
622 ComSafeArrayAsInParam(affectedMetrics));
623
624 return RTEXITCODE_SUCCESS;
625}
626
627
628RTEXITCODE handleMetrics(HandlerArg *a)
629{
630 /* at least one option: subcommand name */
631 if (a->argc < 1)
632 return errorSyntax(USAGE_METRICS, "Subcommand missing");
633
634 ComPtr<IPerformanceCollector> performanceCollector;
635 CHECK_ERROR2I_RET(a->virtualBox, COMGETTER(PerformanceCollector)(performanceCollector.asOutParam()), RTEXITCODE_FAILURE);
636
637 RTEXITCODE rcExit;
638 if (!strcmp(a->argv[0], "list"))
639 rcExit = handleMetricsList(a->argc, a->argv, a->virtualBox, performanceCollector);
640 else if (!strcmp(a->argv[0], "setup"))
641 rcExit = handleMetricsSetup(a->argc, a->argv, a->virtualBox, performanceCollector);
642 else if (!strcmp(a->argv[0], "query"))
643 rcExit = handleMetricsQuery(a->argc, a->argv, a->virtualBox, performanceCollector);
644 else if (!strcmp(a->argv[0], "collect"))
645 rcExit = handleMetricsCollect(a->argc, a->argv, a->virtualBox, performanceCollector);
646 else if (!strcmp(a->argv[0], "enable"))
647 rcExit = handleMetricsEnable(a->argc, a->argv, a->virtualBox, performanceCollector);
648 else if (!strcmp(a->argv[0], "disable"))
649 rcExit = handleMetricsDisable(a->argc, a->argv, a->virtualBox, performanceCollector);
650 else
651 return errorSyntax(USAGE_METRICS, "Invalid subcommand '%s'", a->argv[0]);
652
653 return rcExit;
654}
655
656#endif /* VBOX_ONLY_DOCS */
657
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