VirtualBox

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

Last change on this file since 76553 was 76553, checked in by vboxsync, 5 years ago

scm --update-copyright-year

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

© 2023 Oracle
ContactPrivacy policyTerms of Use