protocol: Send progress_hint in header.
authorRichard W.M. Jones <rjones@redhat.com>
Wed, 1 Dec 2010 13:28:26 +0000 (13:28 +0000)
committerRichard W.M. Jones <rjones@redhat.com>
Wed, 1 Dec 2010 13:35:32 +0000 (13:35 +0000)
For actions that have FileIn arguments, count the size of all
the input files and send that in the progress_hint field of the
request header.

generator/generator_c.ml
src/guestfs-internal.h
src/proto.c

index 449f748..d8b13a5 100644 (file)
@@ -577,6 +577,9 @@ and generate_client_actions () =
 #include <stdint.h>
 #include <string.h>
 #include <inttypes.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 
 #include \"guestfs.h\"
 #include \"guestfs-internal.h\"
@@ -960,10 +963,34 @@ check_state (guestfs_h *g, const char *caller)
        | RStructList (_, typ) ->
            pr "  struct guestfs_%s_list *ret_v;\n" typ
       );
+
+      let has_filein =
+        List.exists (function FileIn _ -> true | _ -> false) args in
+      if has_filein then (
+        pr "  uint64_t progress_hint = 0;\n";
+        pr "  struct stat progress_stat;\n";
+      ) else
+        pr "  const uint64_t progress_hint = 0;\n";
+
       pr "\n";
       check_null_strings shortname style;
       reject_unknown_optargs shortname style;
       trace_call shortname style;
+
+      (* Calculate the total size of all FileIn arguments to pass
+       * as a progress bar hint.
+       *)
+      List.iter (
+        function
+        | FileIn n ->
+            pr "  if (stat (%s, &progress_stat) == 0 &&\n" n;
+            pr "      S_ISREG (progress_stat.st_mode))\n";
+            pr "    progress_hint += progress_stat.st_size;\n";
+            pr "\n";
+        | _ -> ()
+      ) args;
+
+      (* Check we are in the right state for sending a request. *)
       pr "  if (check_state (g, \"%s\") == -1) {\n" shortname;
       trace_return_error ~indent:4 style;
       pr "    return %s;\n" error_code;
@@ -974,8 +1001,9 @@ check_state (guestfs_h *g, const char *caller)
       (* Send the main header and arguments. *)
       (match args with
        | [] ->
-           pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
-             (String.uppercase shortname)
+           pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, progress_hint,\n"
+             (String.uppercase shortname);
+           pr "                           NULL, NULL);\n"
        | args ->
            List.iter (
              function
@@ -1006,7 +1034,7 @@ check_state (guestfs_h *g, const char *caller)
                  pr "  args.%s.%s_len = %s_size;\n" n n n
              | Pointer _ -> assert false
            ) args;
-           pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
+           pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, progress_hint,\n"
              (String.uppercase shortname);
            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
              name;
index d12e345..e4e198b 100644 (file)
@@ -250,7 +250,7 @@ extern void guestfs___print_timestamped_message (guestfs_h *g, const char *fs, .
 extern void guestfs___free_inspect_info (guestfs_h *g);
 extern int guestfs___set_busy (guestfs_h *g);
 extern int guestfs___end_busy (guestfs_h *g);
-extern int guestfs___send (guestfs_h *g, int proc_nr, xdrproc_t xdrp, char *args);
+extern int guestfs___send (guestfs_h *g, int proc_nr, uint64_t progress_hint, xdrproc_t xdrp, char *args);
 extern int guestfs___recv (guestfs_h *g, const char *fn, struct guestfs_message_header *hdr, struct guestfs_message_error *err, xdrproc_t xdrp, char *ret);
 extern int guestfs___send_file (guestfs_h *g, const char *filename);
 extern int guestfs___recv_file (guestfs_h *g, const char *filename);
index 5c22e3d..a2a5a15 100644 (file)
@@ -627,7 +627,8 @@ guestfs___accept_from_daemon (guestfs_h *g)
 }
 
 int
-guestfs___send (guestfs_h *g, int proc_nr, xdrproc_t xdrp, char *args)
+guestfs___send (guestfs_h *g, int proc_nr, uint64_t progress_hint,
+                xdrproc_t xdrp, char *args)
 {
   struct guestfs_message_header hdr;
   XDR xdr;
@@ -658,7 +659,7 @@ guestfs___send (guestfs_h *g, int proc_nr, xdrproc_t xdrp, char *args)
   hdr.direction = GUESTFS_DIRECTION_CALL;
   hdr.serial = serial;
   hdr.status = GUESTFS_STATUS_OK;
-  hdr.progress_hint = 0;
+  hdr.progress_hint = progress_hint;
   hdr.optargs_bitmask = 0;
 
   if (!xdr_guestfs_message_header (&xdr, &hdr)) {