[PATCH 1/7] rpcgen: Add support for generating funcs returning alloc'd typed params

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Since it's rather tedious to write the dispatchers for functions that
return an array of typed parameters (which are rather common) let's add
some rpcgen code to generate them.
---
 src/remote/remote_protocol.x |  5 +++++
 src/rpc/gendispatch.pl       | 45 +++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 49 insertions(+), 1 deletion(-)

diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index 0170c0c..cec6bd2 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -414,6 +414,11 @@ struct remote_domain_disk_error {
  * insert@<offset> comment to indicate the offset in the parameter list of
  * the function to be called.
  *
+ * For cases where the API allocates memory and fills the arguments (mostly
+ * typed parameters) a similar comment indicates the type and offset
+ * of the variable to be filled with the count of returned elements.
+ * alloc@<offset>@unsigned int@<count offset>
+ *
  * Dynamic opaque and remote_nonnull_string arrays can be annotated with an
  * optional typecast */

diff --git a/src/rpc/gendispatch.pl b/src/rpc/gendispatch.pl
index 5564b2e..173189c 100755
--- a/src/rpc/gendispatch.pl
+++ b/src/rpc/gendispatch.pl
@@ -862,6 +862,25 @@ elsif ($mode eq "server") {
                     $single_ret_var = $2;
                     $single_ret_by_ref = 0;
                     $single_ret_check = " == NULL";
+                } elsif ($ret_member =~ m/^remote_typed_param (\S+)<(\S+)>;\s*\/\*\s*alloc@(\d+)@([^@]+)@(\d+)\s*\*\//) {
+                    push(@vars_list, "virTypedParameterPtr $1 = NULL");
+                    push(@vars_list, "$4 $1_len = 0");
+
+                    $single_ret_by_ref = 1;
+                    $single_ret_var = undef;
+
+                    splice(@args_list, int($3), 0, "&$1");
+                    splice(@args_list, int($5), 0, "&$1_len");
+
+                    push(@ret_list, "if (virTypedParamsSerialize($1, $1_len,\n" .
+                                    "                                (virTypedParameterRemotePtr *) &ret->$1.$1_val,\n" .
+                                    "                                &ret->$1.$1_len,\n" .
+                                    "                                VIR_TYPED_PARAM_STRING_OKAY) < 0)\n" .
+                                    "        goto cleanup;\n");
+
+                    push(@free_list, "    virTypedParamsFree($1, $1_len);");
+                    push(@free_list_on_error, "virTypedParamsRemoteFree((virTypedParameterRemotePtr) ret->params.params_val,\n" .
+                                              "                                 ret->params.params_len);\n");
                 } elsif ($ret_member =~ m/^(\/)?\*/) {
                     # ignore comments
                 } else {
@@ -1422,6 +1441,7 @@ elsif ($mode eq "client") {
         my $modern_ret_as_list = 0;
         my $modern_ret_struct_name = "undefined";
         my $modern_ret_var_type = "undefined";
+        my @custom_error_cleanup = ();

         if ($rettype ne "void" and
             scalar(@{$call->{ret_members}}) > 1) {
@@ -1519,6 +1539,23 @@ elsif ($mode eq "client") {
                         $single_ret_var = "vir${type_name}Ptr rv = NULL";
                         $single_ret_type = "vir${type_name}Ptr";
                     }
+                } elsif ($ret_member =~ m/^remote_typed_param (\S+)<(\S+)>;\s*\/\*\s*alloc@(\d+)@([^@]+)@(\d+)\s*\*\//) {
+                    # handle self allocating arrays of typed parameters
+                    splice(@args_list, int($3), 0, ("virTypedParameterPtr *$1"));
+                    splice(@args_list, int($5), 0, ("$4 *n$1"));
+                    push(@vars_list, "virTypedParameterPtr ret_params = NULL");
+                    push(@vars_list, "int ret_nparams = 0");
+                    # virTypedParamsDeserialize allocates the array if @params is null
+                    push(@ret_list2, "if (virTypedParamsDeserialize((virTypedParameterRemotePtr) ret.$1.$1_val,\n" .
+                                     "                                  ret.$1.$1_len,\n" .
+                                     "                                  $2,\n" .
+                                     "                                  &ret_params,\n" .
+                                     "                                  &ret_nparams) < 0)\n" .
+                                     "        goto cleanup;\n");
+                    push(@ret_list2, "*$1 = ret_params;");
+                    push(@ret_list2, "*n$1 = ret_nparams;");
+                    push(@custom_error_cleanup, "virTypedParamsFree(ret_params, ret_nparams);\n");
+                    $single_ret_cleanup = 1;
                 } elsif ($ret_member =~ m/^remote_typed_param (\S+)<(\S+)>;\s*\/\*\s*insert@(\d+)\s*\*\//) {
                     splice(@args_list, int($3), 0, ("virTypedParameterPtr $1"));
                     push(@ret_list2, "if (virTypedParamsDeserialize((virTypedParameterRemotePtr) ret.$1.$1_val,\n" .
@@ -1530,7 +1567,7 @@ elsif ($mode eq "client") {
                     $single_ret_cleanup = 1;
                 } elsif ($ret_member =~ m/^remote_typed_param (\S+)<\S+>;/) {
                     # error out on unannotated arrays
-                    die "remote_typed_param array without insert@<offset> annotation: $ret_member";
+                    die "remote_typed_param array without insert@... or alloc@... annotation: $ret_member";
                 } elsif ($ret_member =~ m/^int (\S+);/) {
                     my $arg_name = $1;

@@ -1876,6 +1913,12 @@ elsif ($mode eq "client") {
         if ($single_ret_as_list or $single_ret_cleanup or $modern_ret_as_list) {
             print "\n";
             print "cleanup:\n";
+            if (@custom_error_cleanup) {
+                print "    if (rv != 0) {\n";
+                print "        ";
+                print join("\n        ", @custom_error_cleanup);
+                print "    }\n";
+            }
             if ($modern_ret_as_list) {
                 print "    if (tmp_results) {\n";
                 print "        for (i = 0; i < ret.$single_ret_list_name.${single_ret_list_name}_len; i++)\n";
-- 
2.8.3

--
libvir-list mailing list
libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list



[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]