
On 09/19/2011 06:23 AM, Peter Krempa wrote:
Users of virsh complain that output of the domblkstat command is not intuitive enough. This patch adds explanation of fields returned by this command to the help section for domblkstat and the man page of virsh. Also a switch --human is added for domblkstat that prints the fields with more descriptive texts.
This patch also changes sequence of the output fields and their names back to the order and spelling established by previous versions of virsh to mantain compatibility with scripts.
s/mantain/maintain/
Example of human readable output:
virsh # domblkstat 1 vda --human Device: vda number of read operations: 3726 number of read bytes: 82815488 number of write operations: 478 number of bytes written: 4965376
For consistency, I think "bytes read" matches better with "bytes written".
IMHO this patch is worth getting into 0.9.5 as it fixes the changed output order since addition of the new api, and translates field names into those that have been used in previous versions.
Agree. So I'll help out, so you don't have to make a v8 :)
+++ b/tools/virsh.c @@ -369,6 +369,8 @@ static const char *vshDomainStateReasonToString(int state, int reason); static const char *vshDomainControlStateToString(int state); static const char *vshDomainVcpuStateToString(int state); static bool vshConnectionUsability(vshControl *ctl, virConnectPtr conn); +static virTypedParameterPtr vshFindTypedParamByName(const char *name, virTypedParameterPtr list, int count);
Long line; wrapped to keep at 80 columns.
+static char *vshGetTypedParamValue(vshControl *ctl, virTypedParameterPtr item);
static char *editWriteToTempFile (vshControl *ctl, const char *doc); static int editFile (vshControl *ctl, const char *filename); @@ -1054,16 +1056,43 @@ cleanup: */ static const vshCmdInfo info_domblkstat[] = { {"help", N_("get device block stats for a domain")}, - {"desc", N_("Get device block stats for a running domain.")}, + {"desc", N_("Get device block stats for a running domain. See man page or use --human for explanation of fields")},
Another long line.
+ +#define DOMBLKSTAT_LEGACY_PRINT(ID, VALUE) \ + if (VALUE>= 0) \ + vshPrint(ctl, "%s %s %lld\n", device, \ + human?_(domblkstat_output[ID].human):domblkstat_output[ID].legacy, \
Spacing around ?: operator.
- if (stats.wr_bytes>= 0) - vshPrint (ctl, "%s wr_bytes %lld\n", device, stats.wr_bytes); + if (virDomainBlockStats (dom, device,&stats,
No space before '(' in function call.
+ /* at first print all known values in desired order */ + for (i = 0; domblkstat_output[i].field != NULL; i++) { + if (!(par = vshFindTypedParamByName(domblkstat_output[i].field, + params, + nparams)))
Indentation.
+ if (strlen(params[i].field) == 0)
More efficient as: if (!*params[i].field)
@@ -15202,6 +15245,85 @@ vshDomainStateReasonToString(int state, int reason) return N_("unknown"); }
+static char * +vshGetTypedParamValue(vshControl *ctl, virTypedParameterPtr item) +{ + int size = 0; + char *str = NULL; + + if (!ctl || !item) + return NULL; + + switch(item->type) { + case VIR_TYPED_PARAM_INT: + size = snprintf(NULL, 0, "%d", item->value.i); + str = vshMalloc(ctl, size+1); + snprintf(str, size+1, "%d", item->value.i);
Yuck. Why not just use virAsprintf?
+++ b/tools/virsh.pod @@ -501,13 +501,31 @@ be lost once the guest stops running, but the snapshot contents still exist, and a new domain with the same name and UUID can restore the snapshot metadata with B<snapshot-create>.
-=item B<domblkstat> I<domain> I<block-device> +=item B<domblkstat> I<domain> I<block-device> [I<--human>]
Get device block stats for a running domain. A I<block-device> corresponds to a unique target name (<target dev='name'/>) or source file (<source file='name'/>) for one of the disk devices attached to I<domain> (see also B<domblklist> for listing these names).
+Use I<--human> for a more human readable output. + +Availabilty of these fields depends on hypervisor. Unsupported fields are
s/Availabilty/Availability/
+missing from the output. Other fields may appear if comunicating with a newer
s/comunicating/communicating/ ACK with my nits fixed, so I've pushed this. Here's what I squashed in: diff --git i/tools/virsh.c w/tools/virsh.c index f2bb2db..df1e10e 100644 --- i/tools/virsh.c +++ w/tools/virsh.c @@ -369,7 +369,9 @@ static const char *vshDomainStateReasonToString(int state, int reason); static const char *vshDomainControlStateToString(int state); static const char *vshDomainVcpuStateToString(int state); static bool vshConnectionUsability(vshControl *ctl, virConnectPtr conn); -static virTypedParameterPtr vshFindTypedParamByName(const char *name, virTypedParameterPtr list, int count); +static virTypedParameterPtr vshFindTypedParamByName(const char *name, + virTypedParameterPtr list, + int count); static char *vshGetTypedParamValue(vshControl *ctl, virTypedParameterPtr item); static char *editWriteToTempFile (vshControl *ctl, const char *doc); @@ -1056,7 +1058,8 @@ cleanup: */ static const vshCmdInfo info_domblkstat[] = { {"help", N_("get device block stats for a domain")}, - {"desc", N_("Get device block stats for a running domain. See man page or use --human for explanation of fields")}, + {"desc", N_("Get device block stats for a running domain. See man page or " + "use --human for explanation of fields")}, {NULL,NULL} }; @@ -1073,24 +1076,35 @@ struct _domblkstat_sequence { const char *human; /* human-friendly explanation */ }; -/* sequence of values for output to honor legacy format from previous versions */ +/* sequence of values for output to honor legacy format from previous + * versions */ static const struct _domblkstat_sequence domblkstat_output[] = { - { VIR_DOMAIN_BLOCK_STATS_READ_REQ, "rd_req", N_("number of read operations: ") }, /* 0 */ - { VIR_DOMAIN_BLOCK_STATS_READ_BYTES, "rd_bytes", N_("number of read bytes: ") }, /* 1 */ - { VIR_DOMAIN_BLOCK_STATS_WRITE_REQ, "wr_req", N_("number of write operations: ") }, /* 2 */ - { VIR_DOMAIN_BLOCK_STATS_WRITE_BYTES, "wr_bytes", N_("number of bytes written: ") }, /* 3 */ - { VIR_DOMAIN_BLOCK_STATS_ERRS, "errs", N_("error count: ") }, /* 4 */ - { VIR_DOMAIN_BLOCK_STATS_FLUSH_REQ, NULL, N_("number of flush operations: ") }, /* 5 */ - { VIR_DOMAIN_BLOCK_STATS_READ_TOTAL_TIMES, NULL, N_("total duration of reads (ns): ") }, /* 6 */ - { VIR_DOMAIN_BLOCK_STATS_WRITE_TOTAL_TIMES, NULL, N_("total duration of writes (ns): ") }, /* 7 */ - { VIR_DOMAIN_BLOCK_STATS_FLUSH_TOTAL_TIMES, NULL, N_("total duration of flushes (ns):") }, /* 8 */ + { VIR_DOMAIN_BLOCK_STATS_READ_REQ, "rd_req", + N_("number of read operations: ") }, /* 0 */ + { VIR_DOMAIN_BLOCK_STATS_READ_BYTES, "rd_bytes", + N_("number of read bytes: ") }, /* 1 */ + { VIR_DOMAIN_BLOCK_STATS_WRITE_REQ, "wr_req", + N_("number of write operations: ") }, /* 2 */ + { VIR_DOMAIN_BLOCK_STATS_WRITE_BYTES, "wr_bytes", + N_("number of bytes written: ") }, /* 3 */ + { VIR_DOMAIN_BLOCK_STATS_ERRS, "errs", + N_("error count: ") }, /* 4 */ + { VIR_DOMAIN_BLOCK_STATS_FLUSH_REQ, NULL, + N_("number of flush operations: ") }, /* 5 */ + { VIR_DOMAIN_BLOCK_STATS_READ_TOTAL_TIMES, NULL, + N_("total duration of reads (ns): ") }, /* 6 */ + { VIR_DOMAIN_BLOCK_STATS_WRITE_TOTAL_TIMES, NULL, + N_("total duration of writes (ns): ") }, /* 7 */ + { VIR_DOMAIN_BLOCK_STATS_FLUSH_TOTAL_TIMES, NULL, + N_("total duration of flushes (ns):") }, /* 8 */ { NULL, NULL, NULL } }; -#define DOMBLKSTAT_LEGACY_PRINT(ID, VALUE) \ - if (VALUE >= 0) \ - vshPrint(ctl, "%s %s %lld\n", device, \ - human?_(domblkstat_output[ID].human):domblkstat_output[ID].legacy, \ +#define DOMBLKSTAT_LEGACY_PRINT(ID, VALUE) \ + if (VALUE >= 0) \ + vshPrint(ctl, "%s %s %lld\n", device, \ + human ? _(domblkstat_output[ID].human) \ + : domblkstat_output[ID].legacy, \ VALUE); static bool @@ -1106,15 +1120,15 @@ cmdDomblkstat (vshControl *ctl, const vshCmd *cmd) int rc, nparams = 0; int i = 0; bool ret = false; - bool human = vshCommandOptBool(cmd, "human"); /* enable human readable output */ + bool human = vshCommandOptBool(cmd, "human"); /* human readable output */ - if (!vshConnectionUsability (ctl, ctl->conn)) + if (!vshConnectionUsability(ctl, ctl->conn)) return false; - if (!(dom = vshCommandOptDomain (ctl, cmd, &name))) + if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) return false; - if (vshCommandOptString (cmd, "device", &device) <= 0) + if (vshCommandOptString(cmd, "device", &device) <= 0) goto cleanup; rc = virDomainBlockStatsFlags(dom, device, NULL, &nparams, 0); @@ -1131,8 +1145,8 @@ cmdDomblkstat (vshControl *ctl, const vshCmd *cmd) virFreeError(last_error); last_error = NULL; - if (virDomainBlockStats (dom, device, &stats, - sizeof stats) == -1) { + if (virDomainBlockStats(dom, device, &stats, + sizeof stats) == -1) { vshError(ctl, _("Failed to get block stats %s %s"), name, device); goto cleanup; @@ -1166,8 +1180,8 @@ cmdDomblkstat (vshControl *ctl, const vshCmd *cmd) /* at first print all known values in desired order */ for (i = 0; domblkstat_output[i].field != NULL; i++) { if (!(par = vshFindTypedParamByName(domblkstat_output[i].field, - params, - nparams))) + params, + nparams))) continue; if (!(value = vshGetTypedParamValue(ctl, par))) @@ -1192,9 +1206,9 @@ cmdDomblkstat (vshControl *ctl, const vshCmd *cmd) VIR_FREE(value); } - /* go through the fields again, looking for fields that were not printed*/ + /* go through the fields again, for remaining fields */ for (i = 0; i < nparams; i++) { - if (strlen(params[i].field) == 0) + if (!*params[i].field) continue; if (!(value = vshGetTypedParamValue(ctl, params+i))) @@ -15248,7 +15262,7 @@ vshDomainStateReasonToString(int state, int reason) static char * vshGetTypedParamValue(vshControl *ctl, virTypedParameterPtr item) { - int size = 0; + int ret = 0; char *str = NULL; if (!ctl || !item) @@ -15256,52 +15270,36 @@ vshGetTypedParamValue(vshControl *ctl, virTypedParameterPtr item) switch(item->type) { case VIR_TYPED_PARAM_INT: - size = snprintf(NULL, 0, "%d", item->value.i); - str = vshMalloc(ctl, size+1); - snprintf(str, size+1, "%d", item->value.i); - return str; + ret = virAsprintf(&str, "%d", item->value.i); break; case VIR_TYPED_PARAM_UINT: - size = snprintf(NULL, 0, "%u", item->value.ui); - str = vshMalloc(ctl, size+1); - snprintf(str, size+1, "%u", item->value.ui); - return str; + ret = virAsprintf(&str, "%u", item->value.ui); break; case VIR_TYPED_PARAM_LLONG: - size = snprintf(NULL, 0, "%lld", item->value.l); - str = vshMalloc(ctl, size+1); - snprintf(str, size+1, "%lld", item->value.l); - return str; + ret = virAsprintf(&str, "%lld", item->value.l); break; case VIR_TYPED_PARAM_ULLONG: - size = snprintf(NULL, 0, "%llu", item->value.ul); - str = vshMalloc(ctl, size+1); - snprintf(str, size+1, "%llu", item->value.ul); - return str; + ret = virAsprintf(&str, "%llu", item->value.ul); break; case VIR_TYPED_PARAM_DOUBLE: - size = snprintf(NULL, 0, "%f", item->value.d); - str = vshMalloc(ctl, size+1); - snprintf(str, size+1, "%f", item->value.d); - return str; + ret = virAsprintf(&str, "%f", item->value.d); break; case VIR_TYPED_PARAM_BOOLEAN: - size = snprintf(NULL, 0, "%s", item->value.b ? _("yes") : _("no")); - str = vshMalloc(ctl, size+1); - snprintf(str, size+1, "%s", item->value.b ? _("yes") : _("no")); - return str; + ret = virAsprintf(&str, "%s", item->value.b ? _("yes") : _("no")); break; default: vshError(ctl, _("unimplemented block statistics parameter type")); } - return NULL; + if (ret < 0) + vshError(ctl, "%s", _("Out of memory")); + return str; } static virTypedParameterPtr diff --git i/tools/virsh.pod w/tools/virsh.pod index edf451f..6529cd6 100644 --- i/tools/virsh.pod +++ w/tools/virsh.pod @@ -510,8 +510,8 @@ also B<domblklist> for listing these names). Use I<--human> for a more human readable output. -Availabilty of these fields depends on hypervisor. Unsupported fields are -missing from the output. Other fields may appear if comunicating with a newer +Availability of these fields depends on hypervisor. Unsupported fields are +missing from the output. Other fields may appear if communicating with a newer version of libvirtd. B<Explanation of fields> (fields appear in the folowing order): -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org