VirtualBox

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

Last change on this file since 108699 was 108003, checked in by vboxsync, 3 months ago

Parfait: fixed the warning "Change of signedness on implicit conversion" in VBoxManage part of the code

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