VirtualBox

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

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

doc/manual,FE/VBoxManage: Convert metrics command to refentry documentation, ​bugref:9186

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette