VirtualBox

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

Last change on this file since 93318 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

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