[libvirt] [PATCH v4 1/2] Add VIR_TYPED_PARAM_STRING

Hu Tao hutao at cn.fujitsu.com
Wed Oct 12 09:26:34 UTC 2011


This makes string can be transported between client and server.
For compatibility,

    o new server should not send strings to old client if it
      doesn't see the flag VIR_DOMAIN_TYPED_STRING_OKAY.
    o new client that wants to be able to send/receive strings
      should always set the flag VIR_DOMAIN_TYPED_STRING_OKAY;
      if it is rejected by a old server that doesn't understand
      VIR_DOMAIN_TYPED_STRING_OKAY, then the client should have
      a second try with out flag VIR_DOMAIN_TYPED_STRING_OKAY
      to cope with an old server.

Ideas for compatibility are coming from Eric, thanks.
---
 daemon/remote.c              |   32 +++++++++++++++++++++++++++++---
 include/libvirt/libvirt.h.in |   25 ++++++++++++++++++++++++-
 src/libvirt.c                |   38 ++++++++++++++++++++++++++++++++++++++
 src/remote/remote_driver.c   |   30 ++++++++++++++++++++++++++++--
 src/remote/remote_protocol.x |    2 ++
 src/remote_protocol-structs  |    2 ++
 src/rpc/gendispatch.pl       |    2 +-
 src/util/util.c              |   15 +++++++++++++++
 src/util/util.h              |    2 ++
 9 files changed, 141 insertions(+), 7 deletions(-)

diff --git a/daemon/remote.c b/daemon/remote.c
index 550bed4..520fef2 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -672,6 +672,15 @@ remoteSerializeTypedParameters(virTypedParameterPtr params,
         case VIR_TYPED_PARAM_BOOLEAN:
             val[i].value.remote_typed_param_value_u.b = params[i].value.b;
             break;
+        case VIR_TYPED_PARAM_STRING:
+            if (params[i].value.s) {
+                val[i].value.remote_typed_param_value_u.s = strdup(params[i].value.s);
+                if (val[i].value.remote_typed_param_value_u.s == NULL) {
+                    virReportOOMError();
+                    goto cleanup;
+                }
+            }
+            break;
         default:
             virNetError(VIR_ERR_RPC, _("unknown parameter type: %d"),
                         params[i].type);
@@ -685,8 +694,11 @@ remoteSerializeTypedParameters(virTypedParameterPtr params,
 
 cleanup:
     if (val) {
-        for (i = 0; i < nparams; i++)
+        for (i = 0; i < nparams; i++) {
             VIR_FREE(val[i].field);
+            if (params[i].type == VIR_TYPED_PARAM_STRING)
+                VIR_FREE(val[i].value.remote_typed_param_value_u.s);
+        }
         VIR_FREE(val);
     }
     return rv;
@@ -699,7 +711,7 @@ remoteDeserializeTypedParameters(remote_typed_param *args_params_val,
                                  int limit,
                                  int *nparams)
 {
-    int i;
+    int i = 0;
     int rv = -1;
     virTypedParameterPtr params = NULL;
 
@@ -750,6 +762,14 @@ remoteDeserializeTypedParameters(remote_typed_param *args_params_val,
             params[i].value.b =
                 args_params_val[i].value.remote_typed_param_value_u.b;
             break;
+        case VIR_TYPED_PARAM_STRING:
+            params[i].value.s =
+                strdup(args_params_val[i].value.remote_typed_param_value_u.s);
+            if (params[i].value.s == NULL) {
+                virReportOOMError();
+                goto cleanup;
+            }
+            break;
         default:
             virNetError(VIR_ERR_INTERNAL_ERROR, _("unknown parameter type: %d"),
                         params[i].type);
@@ -760,8 +780,14 @@ remoteDeserializeTypedParameters(remote_typed_param *args_params_val,
     rv = 0;
 
 cleanup:
-    if (rv < 0)
+    if (rv < 0) {
+        int j;
+        for (j = 0; j < i; ++j) {
+            if (params[j].type == VIR_TYPED_PARAM_STRING)
+                VIR_FREE(params[j].value.s);
+        }
         VIR_FREE(params);
+    }
     return params;
 }
 
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index c991dfc..fa53147 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -208,6 +208,27 @@ typedef enum {
 } virDomainModificationImpact;
 
 /**
+ * virDomainFlags:
+ *
+ * Flags that can be used with some libvirt APIs.
+ *
+ * These enums should not confilict with those of virDomainModificationImpact.
+ */
+typedef enum {
+    VIR_DOMAIN_TYPED_STRING_OKAY = 1 << 2, /*  Usage of this flag:
+                                            *    o new server should not send strings to old client if it
+                                            *      doesn't see the flag VIR_DOMAIN_TYPED_STRING_OKAY.
+                                            *    o new client that wants to be able to send/receive strings
+                                            *      should always set the flag VIR_DOMAIN_TYPED_STRING_OKAY;
+                                            *      if it is rejected by a old server that doesn't understand
+                                            *      VIR_DOMAIN_TYPED_STRING_OKAY, then the client should have
+                                            *      a second try without flag VIR_DOMAIN_TYPED_STRING_OKAY to
+                                            *      cope with an old server.
+                                            */
+
+} virDomainFlags;
+
+/**
  * virDomainInfoPtr:
  *
  * a virDomainInfo is a structure filled by virDomainGetInfo() and extracting
@@ -489,7 +510,8 @@ typedef enum {
     VIR_TYPED_PARAM_LLONG   = 3, /* long long case */
     VIR_TYPED_PARAM_ULLONG  = 4, /* unsigned long long case */
     VIR_TYPED_PARAM_DOUBLE  = 5, /* double case */
-    VIR_TYPED_PARAM_BOOLEAN = 6  /* boolean(character) case */
+    VIR_TYPED_PARAM_BOOLEAN = 6, /* boolean(character) case */
+    VIR_TYPED_PARAM_STRING  = 7, /* string case */
 } virTypedParameterType;
 
 /**
@@ -520,6 +542,7 @@ struct _virTypedParameter {
         unsigned long long int ul;  /* type is ULLONG */
         double d;                   /* type is DOUBLE */
         char b;                     /* type is BOOLEAN */
+        char *s;                    /* type is STRING, see also VIR_DOMAIN_TYPED_STRING_OKAY */
     } value; /* parameter value */
 };
 
diff --git a/src/libvirt.c b/src/libvirt.c
index f07c720..59d6d26 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -3447,6 +3447,23 @@ error:
     return -1;
 }
 
+static int virDomainCheckTypedStringFlag(virTypedParameterPtr params,
+                                         int nparams,
+                                         unsigned int flags)
+{
+    if (!(flags & VIR_DOMAIN_TYPED_STRING_OKAY)) {
+        int i;
+        for (i = 0; i < nparams; i++) {
+            if (params[i].type == VIR_TYPED_PARAM_STRING) {
+                virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__);
+                virDispatchError(NULL);
+                return -1;
+            }
+        }
+    }
+    return 0;
+}
+
 /**
  * virDomainSetMemoryParameters:
  * @domain: pointer to domain object
@@ -3472,6 +3489,9 @@ virDomainSetMemoryParameters(virDomainPtr domain,
 
     virResetLastError();
 
+    if (virDomainCheckTypedStringFlag(params, nparams, flags) < 0)
+        return -1;
+
     if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
         virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
         virDispatchError(NULL);
@@ -3547,6 +3567,9 @@ virDomainGetMemoryParameters(virDomainPtr domain,
 
     virResetLastError();
 
+    if (virDomainCheckTypedStringFlag(params, *nparams, flags) < 0)
+        return -1;
+
     if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
         virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
         virDispatchError(NULL);
@@ -3598,6 +3621,9 @@ virDomainSetBlkioParameters(virDomainPtr domain,
 
     virResetLastError();
 
+    if (virDomainCheckTypedStringFlag(params, nparams, flags) < 0)
+        return -1;
+
     if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
         virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
         virDispatchError(NULL);
@@ -3657,6 +3683,9 @@ virDomainGetBlkioParameters(virDomainPtr domain,
 
     virResetLastError();
 
+    if (virDomainCheckTypedStringFlag(params, *nparams, flags) < 0)
+        return -1;
+
     if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
         virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
         virDispatchError(NULL);
@@ -6279,6 +6308,9 @@ virDomainGetSchedulerParametersFlags(virDomainPtr domain,
 
     virResetLastError();
 
+    if (virDomainCheckTypedStringFlag(params, *nparams, flags) < 0)
+        return -1;
+
     if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
         virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
         virDispatchError(NULL);
@@ -6396,6 +6428,9 @@ virDomainSetSchedulerParametersFlags(virDomainPtr domain,
 
     virResetLastError();
 
+    if (virDomainCheckTypedStringFlag(params, nparams, flags) < 0)
+        return -1;
+
     if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
         virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
         virDispatchError(NULL);
@@ -6537,6 +6572,9 @@ int virDomainBlockStatsFlags (virDomainPtr dom,
 
     virResetLastError();
 
+    if (virDomainCheckTypedStringFlag(params, *nparams, flags) < 0)
+        return -1;
+
     if (!VIR_IS_CONNECTED_DOMAIN (dom)) {
         virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
         virDispatchError(NULL);
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 4dc6974..46738d5 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -1226,8 +1226,11 @@ remoteFreeTypedParameters(remote_typed_param *args_params_val,
     if (args_params_val == NULL)
         return;
 
-    for (i = 0; i < args_params_len; i++)
+    for (i = 0; i < args_params_len; i++) {
         VIR_FREE(args_params_val[i].field);
+        if (args_params_val[i].value.type == VIR_TYPED_PARAM_STRING)
+            VIR_FREE(args_params_val[i].value.remote_typed_param_value_u.s);
+    }
 
     VIR_FREE(args_params_val);
 }
@@ -1276,6 +1279,15 @@ remoteSerializeTypedParameters(virTypedParameterPtr params,
         case VIR_TYPED_PARAM_BOOLEAN:
             val[i].value.remote_typed_param_value_u.b = params[i].value.b;
             break;
+        case VIR_TYPED_PARAM_STRING:
+            if (params[i].value.s) {
+                val[i].value.remote_typed_param_value_u.s = strdup(params[i].value.s);
+                if (val[i].value.remote_typed_param_value_u.s == NULL) {
+                    virReportOOMError();
+                    goto cleanup;
+                }
+            }
+            break;
         default:
             remoteError(VIR_ERR_RPC, _("unknown parameter type: %d"),
                 params[i].type);
@@ -1300,7 +1312,7 @@ remoteDeserializeTypedParameters(remote_typed_param *ret_params_val,
                                  virTypedParameterPtr params,
                                  int *nparams)
 {
-    int i;
+    int i = 0;
     int rv = -1;
 
     /* Check the length of the returned list carefully. */
@@ -1347,6 +1359,14 @@ remoteDeserializeTypedParameters(remote_typed_param *ret_params_val,
             params[i].value.b =
                 ret_params_val[i].value.remote_typed_param_value_u.b;
             break;
+        case VIR_TYPED_PARAM_STRING:
+            params[i].value.s =
+                strdup(ret_params_val[i].value.remote_typed_param_value_u.s);
+            if (params[i].value.s == NULL) {
+                virReportOOMError();
+                goto cleanup;
+            }
+            break;
         default:
             remoteError(VIR_ERR_RPC, _("unknown parameter type: %d"),
                         params[i].type);
@@ -1357,6 +1377,12 @@ remoteDeserializeTypedParameters(remote_typed_param *ret_params_val,
     rv = 0;
 
 cleanup:
+    if (rv < 0) {
+        int j;
+        for (j = 0; j < i; j++)
+            if (params[i].type == VIR_TYPED_PARAM_STRING)
+                VIR_FREE(params[i].value.s);
+    }
     return rv;
 }
 
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index f95253e..994c339 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -317,6 +317,8 @@ union remote_typed_param_value switch (int type) {
      double d;
  case VIR_TYPED_PARAM_BOOLEAN:
      int b;
+ case VIR_TYPED_PARAM_STRING:
+     remote_nonnull_string s;
 };
 
 struct remote_typed_param {
diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs
index 7894441..9257545 100644
--- a/src/remote_protocol-structs
+++ b/src/remote_protocol-structs
@@ -6,6 +6,7 @@ enum {
         VIR_TYPED_PARAM_ULLONG = 4,
         VIR_TYPED_PARAM_DOUBLE = 5,
         VIR_TYPED_PARAM_BOOLEAN = 6,
+        VIR_TYPED_PARAM_STRING = 7,
 };
 struct remote_nonnull_domain {
         remote_nonnull_string      name;
@@ -78,6 +79,7 @@ struct remote_typed_param_value {
                 uint64_t           ul;
                 double             d;
                 int                b;
+                remote_nonnull_string s;
         } remote_typed_param_value_u;
 };
 struct remote_typed_param {
diff --git a/src/rpc/gendispatch.pl b/src/rpc/gendispatch.pl
index b7ac3c8..96340c0 100755
--- a/src/rpc/gendispatch.pl
+++ b/src/rpc/gendispatch.pl
@@ -439,7 +439,7 @@ elsif ($opt_b) {
                                         "                                                   $2,\n" .
                                         "                                                   &n$1)) == NULL)\n" .
                                         "        goto cleanup;\n");
-                    push(@free_list, "    VIR_FREE(params);");
+                    push(@free_list, "    virTypedParameterFree($1, n$1);");
                 } elsif ($args_member =~ m/<\S+>;/ or $args_member =~ m/\[\S+\];/) {
                     # just make all other array types fail
                     die "unhandled type for argument value: $args_member";
diff --git a/src/util/util.c b/src/util/util.c
index 1ff287d..cb9be0a 100644
--- a/src/util/util.c
+++ b/src/util/util.c
@@ -2509,3 +2509,18 @@ or other application using the libvirt API.\n\
 
     return 0;
 }
+
+void virTypedParameterFree(virTypedParameterPtr params, int nparams)
+{
+    int i;
+
+    if (!params)
+        return;
+
+    for (i = 0; i < nparams; i++) {
+        if (params[i].type == VIR_TYPED_PARAM_STRING)
+            VIR_FREE(params[i].value.s);
+    }
+
+    VIR_FREE(params);
+}
diff --git a/src/util/util.h b/src/util/util.h
index c55e852..8e9c6fb 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -260,4 +260,6 @@ bool virIsDevMapperDevice(const char *dev_name) ATTRIBUTE_NONNULL(1);
 int virEmitXMLWarning(int fd,
                       const char *name,
                       const char *cmd) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
+
+void virTypedParameterFree(virTypedParameterPtr params, int nparams);
 #endif /* __VIR_UTIL_H__ */
-- 
1.7.3.1




More information about the libvir-list mailing list