VirtualBox

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

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

FE/VBoxManage: Remove the now unused VBoxManageHelp build target and the VBOX_ONLY_DOCS #ifdef's in the code, ​bugref:9186 [scm fix]

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