]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
rpcgen: Add support for generating funcs returning alloc'd typed params
authorPeter Krempa <pkrempa@redhat.com>
Sun, 19 Jun 2016 19:30:59 +0000 (21:30 +0200)
committerPeter Krempa <pkrempa@redhat.com>
Wed, 22 Jun 2016 06:15:45 +0000 (08:15 +0200)
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
src/rpc/gendispatch.pl

index 0170c0c182111b92a4cadb2fe25b00660944e796..cec6bd2fb19c63e82bef228ec8aa0fe1d6ae4ee3 100644 (file)
@@ -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 */
 
index 5564b2ee275b3f61280f4c6e6e3cafe551cf33f6..173189c81be3cd09e674cc82845cb0c30c4c3e8a 100755 (executable)
@@ -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";