]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
virsh: make tree listing more flexible
authorEric Blake <eblake@redhat.com>
Fri, 8 Jun 2012 21:01:08 +0000 (15:01 -0600)
committerEric Blake <eblake@redhat.com>
Mon, 11 Jun 2012 15:23:16 +0000 (09:23 -0600)
Requiring the user to pass in parallel arrays of names and parents
is annoying; it means that you can't qsort one of the arrays without
invalidating the ordering of the other.  By refactoring this function
to use callbacks, we isolate the layout to be independent of the
printing, and a future patch can exploit that to improve layout.

* tools/virsh.c (vshTreePrintInternal): Use callbacks rather than
requiring a char** array.
(vshTreeArrayLookup): New helper function.
(vshTreePrint, cmdNodeListDevices, cmdSnapshotList): Update callers.

tools/virsh.c

index 9194a5ba3e3a875a8546928b7df2e4cdc797604c..4dd1d81e3a6edf2436325fc582b72f4e20f837d4 100644 (file)
@@ -13165,10 +13165,15 @@ cmdVersion(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
 }
 
 /* Tree listing helpers.  */
+
+/* Given an index, return either the name of that device (non-NULL) or
+ * of its parent (NULL if a root).  */
+typedef const char * (*vshTreeLookup)(int devid, bool parent, void *opaque);
+
 static int
 vshTreePrintInternal(vshControl *ctl,
-                     char **devices,
-                     char **parents,
+                     vshTreeLookup lookup,
+                     void *opaque,
                      int num_devices,
                      int devid,
                      int lastdev,
@@ -13178,13 +13183,14 @@ vshTreePrintInternal(vshControl *ctl,
     int i;
     int nextlastdev = -1;
     int ret = -1;
+    const char *dev = (lookup)(devid, false, opaque);
 
     if (virBufferError(indent))
         goto cleanup;
 
     /* Print this device, with indent if not at root */
     vshPrint(ctl, "%s%s%s\n", virBufferCurrentContent(indent),
-             root ? "" : "+- ", devices[devid]);
+             root ? "" : "+- ", dev);
 
     /* Update indent to show '|' or ' ' for child devices */
     if (!root) {
@@ -13196,10 +13202,10 @@ vshTreePrintInternal(vshControl *ctl,
 
     /* Determine the index of the last child device */
     for (i = 0 ; i < num_devices ; i++) {
-        if (parents[i] &&
-            STREQ(parents[i], devices[devid])) {
+        const char *parent = (lookup)(i, true, opaque);
+
+        if (parent && STREQ(parent, dev))
             nextlastdev = i;
-        }
     }
 
     /* If there is a child device, then print another blank line */
@@ -13209,8 +13215,10 @@ vshTreePrintInternal(vshControl *ctl,
     /* Finally print all children */
     virBufferAddLit(indent, "  ");
     for (i = 0 ; i < num_devices ; i++) {
-        if (parents[i] && STREQ(parents[i], devices[devid]) &&
-            vshTreePrintInternal(ctl, devices, parents,
+        const char *parent = (lookup)(i, true, opaque);
+
+        if (parent && STREQ(parent, dev) &&
+            vshTreePrintInternal(ctl, lookup, opaque,
                                  num_devices, i, nextlastdev,
                                  false, indent) < 0)
             goto cleanup;
@@ -13230,13 +13238,13 @@ cleanup:
 }
 
 static int
-vshTreePrint(vshControl *ctl, char **devices, char **parents,
+vshTreePrint(vshControl *ctl, vshTreeLookup lookup, void *opaque,
              int num_devices, int devid)
 {
     int ret;
     virBuffer indent = VIR_BUFFER_INITIALIZER;
 
-    ret = vshTreePrintInternal(ctl, devices, parents, num_devices,
+    ret = vshTreePrintInternal(ctl, lookup, opaque, num_devices,
                                devid, devid, true, &indent);
     if (ret < 0)
         vshError(ctl, "%s", _("Failed to complete tree listing"));
@@ -13244,6 +13252,20 @@ vshTreePrint(vshControl *ctl, char **devices, char **parents,
     return ret;
 }
 
+struct vshTreeArray {
+    char **names;
+    char **parents;
+};
+
+static const char *
+vshTreeArrayLookup(int devid, bool parent, void *opaque)
+{
+    struct vshTreeArray *arrays = opaque;
+    if (parent)
+        return arrays->parents[devid];
+    return arrays->names[devid];
+}
+
 /*
  * "nodedev-list" command
  */
@@ -13293,6 +13315,7 @@ cmdNodeListDevices(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
     qsort(&devices[0], num_devices, sizeof(char*), namesorter);
     if (tree) {
         char **parents = vshMalloc(ctl, sizeof(char *) * num_devices);
+        struct vshTreeArray arrays = { devices, parents };
 
         for (i = 0; i < num_devices; i++) {
             virNodeDevicePtr dev = virNodeDeviceLookupByName(ctl->conn, devices[i]);
@@ -13306,7 +13329,8 @@ cmdNodeListDevices(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
         }
         for (i = 0 ; i < num_devices ; i++) {
             if (parents[i] == NULL &&
-                vshTreePrint(ctl, devices, parents, num_devices, i) < 0)
+                vshTreePrint(ctl, vshTreeArrayLookup, &arrays, num_devices,
+                             i) < 0)
                 ret = false;
         }
         for (i = 0 ; i < num_devices ; i++) {
@@ -16755,10 +16779,12 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd)
         }
     }
     if (tree) {
+        struct vshTreeArray arrays = { names, parents };
+
         for (i = 0 ; i < actual ; i++) {
             if ((from && ctl->useSnapshotOld) ? STREQ(names[i], from) :
                 !parents[i] &&
-                vshTreePrint(ctl, names, parents, actual, i) < 0)
+                vshTreePrint(ctl, vshTreeArrayLookup, &arrays, actual, i) < 0)
                 goto cleanup;
         }