Blob Blame History Raw
From e07158fef33e27a1e76cf9e4e04884462a876ea8 Mon Sep 17 00:00:00 2001
Message-Id: <e07158fef33e27a1e76cf9e4e04884462a876ea8@dist-git>
From: Peter Krempa <pkrempa@redhat.com>
Date: Tue, 2 Aug 2016 13:41:45 +0200
Subject: [PATCH] util: qemu: Allow for different approaches to format JSON
 arrays

For use with memory hotplug virQEMUBuildCommandLineJSONRecurse attempted
to format JSON arrays as bitmap on the command line. Make the formatter
function configurable so that it can be reused with different syntaxes
of arrays such as numbered arrays for use with disk sources.

This patch extracts the code and adds a parameter for the function that
will allow to plug in different formatters.

(cherry picked from commit b7eef33df20dc19b3c70285ee29dabd2ee7391fa)
https://bugzilla.redhat.com/show_bug.cgi?id=1134878 [JSON backing]
https://bugzilla.redhat.com/show_bug.cgi?id=1247521 [gluster multi-host]
---
 src/libvirt_private.syms    |  1 +
 src/util/virqemu.c          | 73 ++++++++++++++++++++++++++++++---------------
 src/util/virqemu.h          | 10 ++++++-
 tests/qemucommandutiltest.c |  3 +-
 4 files changed, 61 insertions(+), 26 deletions(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 70e40be..27bf269 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2194,6 +2194,7 @@ virProcessWait;
 # util/virqemu.h
 virQEMUBuildBufferEscapeComma;
 virQEMUBuildCommandLineJSON;
+virQEMUBuildCommandLineJSONArrayBitmap;
 virQEMUBuildLuksOpts;
 virQEMUBuildObjectCommandlineFromJSON;
 
diff --git a/src/util/virqemu.c b/src/util/virqemu.c
index df665ad..3cc59e7 100644
--- a/src/util/virqemu.c
+++ b/src/util/virqemu.c
@@ -36,6 +36,7 @@ VIR_LOG_INIT("util.qemu");
 struct virQEMUCommandLineJSONIteratorData {
     const char *prefix;
     virBufferPtr buf;
+    virQEMUBuildCommandLineJSONArrayFormatFunc arrayFunc;
 };
 
 
@@ -43,8 +44,41 @@ static int
 virQEMUBuildCommandLineJSONRecurse(const char *key,
                                    const virJSONValue *value,
                                    virBufferPtr buf,
+                                   virQEMUBuildCommandLineJSONArrayFormatFunc arrayFunc,
                                    bool nested);
 
+
+
+int
+virQEMUBuildCommandLineJSONArrayBitmap(const char *key,
+                                       const virJSONValue *array,
+                                       virBufferPtr buf)
+{
+    ssize_t pos = -1;
+    ssize_t end;
+    virBitmapPtr bitmap = NULL;
+
+    if (virJSONValueGetArrayAsBitmap(array, &bitmap) < 0)
+        return -1;
+
+    while ((pos = virBitmapNextSetBit(bitmap, pos)) > -1) {
+        if ((end = virBitmapNextClearBit(bitmap, pos)) < 0)
+            end = virBitmapLastSetBit(bitmap) + 1;
+
+        if (end - 1 > pos) {
+            virBufferAsprintf(buf, ",%s=%zd-%zd", key, pos, end - 1);
+            pos = end;
+        } else {
+            virBufferAsprintf(buf, ",%s=%zd", key, pos);
+        }
+    }
+
+    virBitmapFree(bitmap);
+
+    return 0;
+}
+
+
 /* internal iterator to handle nested object formatting */
 static int
 virQEMUBuildCommandLineJSONIterate(const char *key,
@@ -59,11 +93,13 @@ virQEMUBuildCommandLineJSONIterate(const char *key,
         if (virAsprintf(&tmpkey, "%s.%s", data->prefix, key) < 0)
             return -1;
 
-        ret = virQEMUBuildCommandLineJSONRecurse(tmpkey, value, data->buf, false);
+        ret = virQEMUBuildCommandLineJSONRecurse(tmpkey, value, data->buf,
+                                                 data->arrayFunc, false);
 
         VIR_FREE(tmpkey);
     } else {
-        ret = virQEMUBuildCommandLineJSONRecurse(key, value, data->buf, false);
+        ret = virQEMUBuildCommandLineJSONRecurse(key, value, data->buf,
+                                                 data->arrayFunc, false);
     }
 
     return ret;
@@ -74,13 +110,11 @@ static int
 virQEMUBuildCommandLineJSONRecurse(const char *key,
                                    const virJSONValue *value,
                                    virBufferPtr buf,
+                                   virQEMUBuildCommandLineJSONArrayFormatFunc arrayFunc,
                                    bool nested)
 {
-    struct virQEMUCommandLineJSONIteratorData data = { key, buf };
+    struct virQEMUCommandLineJSONIteratorData data = { key, buf, arrayFunc };
     virJSONValuePtr elem;
-    virBitmapPtr bitmap = NULL;
-    ssize_t pos = -1;
-    ssize_t end;
     size_t i;
 
     if (!key && value->type != VIR_JSON_TYPE_OBJECT) {
@@ -115,26 +149,15 @@ virQEMUBuildCommandLineJSONRecurse(const char *key,
             return -1;
         }
 
-        if (virJSONValueGetArrayAsBitmap(value, &bitmap) == 0) {
-            while ((pos = virBitmapNextSetBit(bitmap, pos)) > -1) {
-                if ((end = virBitmapNextClearBit(bitmap, pos)) < 0)
-                    end = virBitmapLastSetBit(bitmap) + 1;
-
-                if (end - 1 > pos) {
-                    virBufferAsprintf(buf, ",%s=%zd-%zd", key, pos, end - 1);
-                    pos = end;
-                } else {
-                    virBufferAsprintf(buf, ",%s=%zd", key, pos);
-                }
-            }
-        } else {
+        if (!arrayFunc || arrayFunc(key, value, buf) < 0) {
             /* fallback, treat the array as a non-bitmap, adding the key
              * for each member */
             for (i = 0; i < virJSONValueArraySize(value); i++) {
                 elem = virJSONValueArrayGet((virJSONValuePtr)value, i);
 
                 /* recurse to avoid duplicating code */
-                if (virQEMUBuildCommandLineJSONRecurse(key, elem, buf, true) < 0)
+                if (virQEMUBuildCommandLineJSONRecurse(key, elem, buf,
+                                                       arrayFunc, true) < 0)
                     return -1;
             }
         }
@@ -153,7 +176,6 @@ virQEMUBuildCommandLineJSONRecurse(const char *key,
         return -1;
     }
 
-    virBitmapFree(bitmap);
     return 0;
 }
 
@@ -162,6 +184,7 @@ virQEMUBuildCommandLineJSONRecurse(const char *key,
  * virQEMUBuildCommandLineJSON:
  * @value: json object containing the value
  * @buf: otuput buffer
+ * @arrayFunc: array formatter function to allow for different syntax
  *
  * Formats JSON value object into command line parameters suitable for use with
  * qemu.
@@ -170,9 +193,10 @@ virQEMUBuildCommandLineJSONRecurse(const char *key,
  */
 int
 virQEMUBuildCommandLineJSON(const virJSONValue *value,
-                            virBufferPtr buf)
+                            virBufferPtr buf,
+                            virQEMUBuildCommandLineJSONArrayFormatFunc array)
 {
-    return virQEMUBuildCommandLineJSONRecurse(NULL, value, buf, false);
+    return virQEMUBuildCommandLineJSONRecurse(NULL, value, buf, array, false);
 }
 
 
@@ -186,7 +210,8 @@ virQEMUBuildObjectCommandlineFromJSON(const char *type,
 
     virBufferAsprintf(&buf, "%s,id=%s", type, alias);
 
-    if (virQEMUBuildCommandLineJSON(props, &buf) < 0)
+    if (virQEMUBuildCommandLineJSON(props, &buf,
+                                    virQEMUBuildCommandLineJSONArrayBitmap) < 0)
         goto cleanup;
 
     if (virBufferCheckError(&buf) < 0)
diff --git a/src/util/virqemu.h b/src/util/virqemu.h
index efc6c42..801c35b 100644
--- a/src/util/virqemu.h
+++ b/src/util/virqemu.h
@@ -29,8 +29,16 @@
 # include "virjson.h"
 # include "virstorageencryption.h"
 
+typedef int (*virQEMUBuildCommandLineJSONArrayFormatFunc)(const char *key,
+                                                          const virJSONValue *array,
+                                                          virBufferPtr buf);
+int virQEMUBuildCommandLineJSONArrayBitmap(const char *key,
+                                           const virJSONValue *array,
+                                           virBufferPtr buf);
+
 int virQEMUBuildCommandLineJSON(const virJSONValue *value,
-                                virBufferPtr buf);
+                                virBufferPtr buf,
+                                virQEMUBuildCommandLineJSONArrayFormatFunc array);
 
 char *virQEMUBuildObjectCommandlineFromJSON(const char *type,
                                             const char *alias,
diff --git a/tests/qemucommandutiltest.c b/tests/qemucommandutiltest.c
index 4872ea3..a5e3153 100644
--- a/tests/qemucommandutiltest.c
+++ b/tests/qemucommandutiltest.c
@@ -51,7 +51,8 @@ testQemuCommandBuildFromJSON(const void *opaque)
         virAsprintf(&expect, ",%s", data->expectprops) < 0)
         return -1;
 
-    if (virQEMUBuildCommandLineJSON(val, &buf) < 0) {
+    if (virQEMUBuildCommandLineJSON(val, &buf,
+                                    virQEMUBuildCommandLineJSONArrayBitmap) < 0) {
         fprintf(stderr,
                 "\nvirQEMUBuildCommandlineJSON failed process JSON:\n%s\n",
                 data->props);
-- 
2.9.2