提交 ef981053 编写于 作者: E Eric Blake

virsh: remove limits on tree listing

I am not a fan of fixed-width buffers.  All it takes is a
linear chain of more than 100 snapshots to mess up 'virsh
snapshot-list --tree'.  Now that virBuffer is more powerful,
we might as well exploit its power.

* tools/virsh.c (cmdNodeListDevicesPrint): Simplify to use a
virBuffer instead of fixed-width prefix, factor guts, and rename...
(vshTreePrint, vshTreePrintInternal): ...along with new helper.
(cmdNodeListDevices, cmdSnapshotList): Update callers.
上级 9202f2c2
...@@ -13164,60 +13164,34 @@ cmdVersion(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) ...@@ -13164,60 +13164,34 @@ cmdVersion(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
return true; return true;
} }
/* /* Tree listing helpers. */
* "nodedev-list" command static int
*/ vshTreePrintInternal(vshControl *ctl,
static const vshCmdInfo info_node_list_devices[] = { char **devices,
{"help", N_("enumerate devices on this host")}, char **parents,
{"desc", ""}, int num_devices,
{NULL, NULL} int devid,
}; int lastdev,
bool root,
static const vshCmdOptDef opts_node_list_devices[] = { virBufferPtr indent)
{"tree", VSH_OT_BOOL, 0, N_("list devices in a tree")},
{"cap", VSH_OT_STRING, VSH_OFLAG_NONE, N_("capability name")},
{NULL, 0, 0, NULL}
};
#define MAX_DEPTH 100
#define INDENT_SIZE 4
#define INDENT_BUFLEN ((MAX_DEPTH * INDENT_SIZE) + 1)
static void
cmdNodeListDevicesPrint(vshControl *ctl,
char **devices,
char **parents,
int num_devices,
int devid,
int lastdev,
unsigned int depth,
unsigned int indentIdx,
char *indentBuf)
{ {
int i; int i;
int nextlastdev = -1; int nextlastdev = -1;
int ret = -1;
/* Prepare indent for this device, but not if at root */ if (virBufferError(indent))
if (depth && depth < MAX_DEPTH) { goto cleanup;
indentBuf[indentIdx] = '+';
indentBuf[indentIdx+1] = '-';
indentBuf[indentIdx+2] = ' ';
indentBuf[indentIdx+3] = '\0';
}
/* Print this device */
vshPrint(ctl, "%s", indentBuf);
vshPrint(ctl, "%s\n", devices[devid]);
/* Print this device, with indent if not at root */
vshPrint(ctl, "%s%s%s\n", virBufferCurrentContent(indent),
root ? "" : "+- ", devices[devid]);
/* Update indent to show '|' or ' ' for child devices */ /* Update indent to show '|' or ' ' for child devices */
if (depth && depth < MAX_DEPTH) { if (!root) {
if (devid == lastdev) virBufferAddChar(indent, devid == lastdev ? ' ' : '|');
indentBuf[indentIdx] = ' '; virBufferAddChar(indent, ' ');
else if (virBufferError(indent))
indentBuf[indentIdx] = '|'; goto cleanup;
indentBuf[indentIdx+1] = ' ';
indentIdx+=2;
} }
/* Determine the index of the last child device */ /* Determine the index of the last child device */
...@@ -13229,43 +13203,70 @@ cmdNodeListDevicesPrint(vshControl *ctl, ...@@ -13229,43 +13203,70 @@ cmdNodeListDevicesPrint(vshControl *ctl,
} }
/* If there is a child device, then print another blank line */ /* If there is a child device, then print another blank line */
if (nextlastdev != -1) { if (nextlastdev != -1)
vshPrint(ctl, "%s", indentBuf); vshPrint(ctl, "%s |\n", virBufferCurrentContent(indent));
vshPrint(ctl, " |\n");
}
/* Finally print all children */ /* Finally print all children */
if (depth < MAX_DEPTH) virBufferAddLit(indent, " ");
indentBuf[indentIdx] = ' ';
for (i = 0 ; i < num_devices ; i++) { for (i = 0 ; i < num_devices ; i++) {
if (depth < MAX_DEPTH) { if (parents[i] && STREQ(parents[i], devices[devid]) &&
indentBuf[indentIdx] = ' '; vshTreePrintInternal(ctl, devices, parents,
indentBuf[indentIdx+1] = ' '; num_devices, i, nextlastdev,
} false, indent) < 0)
if (parents[i] && goto cleanup;
STREQ(parents[i], devices[devid]))
cmdNodeListDevicesPrint(ctl, devices, parents,
num_devices, i, nextlastdev,
depth + 1, indentIdx + 2, indentBuf);
if (depth < MAX_DEPTH)
indentBuf[indentIdx] = '\0';
} }
virBufferTrim(indent, " ", -1);
/* If there was no child device, and we're the last in /* If there was no child device, and we're the last in
* a list of devices, then print another blank line */ * a list of devices, then print another blank line */
if (nextlastdev == -1 && devid == lastdev) { if (nextlastdev == -1 && devid == lastdev)
vshPrint(ctl, "%s", indentBuf); vshPrint(ctl, "%s\n", virBufferCurrentContent(indent));
vshPrint(ctl, "\n");
} if (!root)
virBufferTrim(indent, NULL, 2);
ret = 0;
cleanup:
return ret;
}
static int
vshTreePrint(vshControl *ctl, char **devices, char **parents,
int num_devices, int devid)
{
int ret;
virBuffer indent = VIR_BUFFER_INITIALIZER;
ret = vshTreePrintInternal(ctl, devices, parents, num_devices,
devid, devid, true, &indent);
if (ret < 0)
vshError(ctl, "%s", _("Failed to complete tree listing"));
virBufferFreeAndReset(&indent);
return ret;
} }
/*
* "nodedev-list" command
*/
static const vshCmdInfo info_node_list_devices[] = {
{"help", N_("enumerate devices on this host")},
{"desc", ""},
{NULL, NULL}
};
static const vshCmdOptDef opts_node_list_devices[] = {
{"tree", VSH_OT_BOOL, 0, N_("list devices in a tree")},
{"cap", VSH_OT_STRING, VSH_OFLAG_NONE, N_("capability name")},
{NULL, 0, 0, NULL}
};
static bool static bool
cmdNodeListDevices (vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) cmdNodeListDevices(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
{ {
const char *cap = NULL; const char *cap = NULL;
char **devices; char **devices;
int num_devices, i; int num_devices, i;
bool tree = vshCommandOptBool(cmd, "tree"); bool tree = vshCommandOptBool(cmd, "tree");
bool ret = true;
if (!vshConnectionUsability(ctl, ctl->conn)) if (!vshConnectionUsability(ctl, ctl->conn))
return false; return false;
...@@ -13291,8 +13292,8 @@ cmdNodeListDevices (vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) ...@@ -13291,8 +13292,8 @@ cmdNodeListDevices (vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
} }
qsort(&devices[0], num_devices, sizeof(char*), namesorter); qsort(&devices[0], num_devices, sizeof(char*), namesorter);
if (tree) { if (tree) {
char indentBuf[INDENT_BUFLEN];
char **parents = vshMalloc(ctl, sizeof(char *) * num_devices); char **parents = vshMalloc(ctl, sizeof(char *) * num_devices);
for (i = 0; i < num_devices; i++) { for (i = 0; i < num_devices; i++) {
virNodeDevicePtr dev = virNodeDeviceLookupByName(ctl->conn, devices[i]); virNodeDevicePtr dev = virNodeDeviceLookupByName(ctl->conn, devices[i]);
if (dev && STRNEQ(devices[i], "computer")) { if (dev && STRNEQ(devices[i], "computer")) {
...@@ -13304,17 +13305,9 @@ cmdNodeListDevices (vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) ...@@ -13304,17 +13305,9 @@ cmdNodeListDevices (vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
virNodeDeviceFree(dev); virNodeDeviceFree(dev);
} }
for (i = 0 ; i < num_devices ; i++) { for (i = 0 ; i < num_devices ; i++) {
memset(indentBuf, '\0', sizeof(indentBuf)); if (parents[i] == NULL &&
if (parents[i] == NULL) vshTreePrint(ctl, devices, parents, num_devices, i) < 0)
cmdNodeListDevicesPrint(ctl, ret = false;
devices,
parents,
num_devices,
i,
i,
0,
0,
indentBuf);
} }
for (i = 0 ; i < num_devices ; i++) { for (i = 0 ; i < num_devices ; i++) {
VIR_FREE(devices[i]); VIR_FREE(devices[i]);
...@@ -13328,7 +13321,7 @@ cmdNodeListDevices (vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) ...@@ -13328,7 +13321,7 @@ cmdNodeListDevices (vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
} }
} }
VIR_FREE(devices); VIR_FREE(devices);
return true; return ret;
} }
/* /*
...@@ -16762,20 +16755,11 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd) ...@@ -16762,20 +16755,11 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd)
} }
} }
if (tree) { if (tree) {
char indentBuf[INDENT_BUFLEN];
for (i = 0 ; i < actual ; i++) { for (i = 0 ; i < actual ; i++) {
memset(indentBuf, '\0', sizeof(indentBuf));
if ((from && ctl->useSnapshotOld) ? STREQ(names[i], from) : if ((from && ctl->useSnapshotOld) ? STREQ(names[i], from) :
!parents[i]) !parents[i] &&
cmdNodeListDevicesPrint(ctl, vshTreePrint(ctl, names, parents, actual, i) < 0)
names, goto cleanup;
parents,
actual,
i,
i,
0,
0,
indentBuf);
} }
ret = true; ret = true;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册