resize: Use guestfish progress bar mini-library.
authorRichard W.M. Jones <rjones@redhat.com>
Fri, 26 Aug 2011 18:21:23 +0000 (19:21 +0100)
committerRichard W.M. Jones <rjones@redhat.com>
Fri, 26 Aug 2011 20:55:04 +0000 (21:55 +0100)
There are two benefits:

 - the progress bars look better
 - there is a reasonably accurate estimate of how long each operation
   will take

po/POTFILES.in
resize/.depend
resize/Makefile.am
resize/progress.ml
resize/progress.mli [new file with mode: 0644]
resize/progress_c.c [new file with mode: 0644]

index 01f7a0d..43e7ffa 100644 (file)
@@ -134,6 +134,7 @@ regressions/test-launch-race.pl
 regressions/test-lvm-mapping.pl
 regressions/test-noexec-stack.pl
 rescue/virt-rescue.c
+resize/progress_c.c
 ruby/ext/guestfs/_guestfs.c
 src/actions.c
 src/appliance.c
index 90a87cb..17bdaca 100644 (file)
@@ -1,6 +1,7 @@
-progress.cmo: utils.cmo ../ocaml/guestfs.cmi
-progress.cmx: utils.cmx ../ocaml/guestfs.cmx
-resize.cmo: utils.cmo progress.cmo ../ocaml/guestfs.cmi
+progress.cmi: ../ocaml/guestfs.cmi
+progress.cmo: utils.cmo ../ocaml/guestfs.cmi progress.cmi
+progress.cmx: utils.cmx ../ocaml/guestfs.cmx progress.cmi
+resize.cmo: utils.cmo progress.cmi ../ocaml/guestfs.cmi
 resize.cmx: utils.cmx progress.cmx ../ocaml/guestfs.cmx
 utils.cmo: ../ocaml/guestfs.cmi
 utils.cmx: ../ocaml/guestfs.cmx
index 93a2600..c2fbc3a 100644 (file)
@@ -29,12 +29,16 @@ if HAVE_OCAML_PCRE
 
 # Alphabetical order.
 SOURCES = \
+       progress_c.c \
+       progress.mli \
        progress.ml \
        resize.ml \
        utils.ml
 
 # Note this list must be in dependency order.
 OBJECTS = \
+       ../fish/guestfish-progress.o \
+       progress_c.o \
        utils.cmx \
        progress.cmx \
        resize.cmx
@@ -50,7 +54,8 @@ OCAMLCFLAGS = -g -warn-error CDEFLMPSUVYZX $(OCAMLPACKAGES)
 OCAMLOPTFLAGS = $(OCAMLCFLAGS)
 
 virt-resize: $(OBJECTS)
-       $(OCAMLFIND) ocamlopt $(OCAMLOPTFLAGS) mlguestfs.cmxa -linkpkg $^ -o $@
+       $(OCAMLFIND) ocamlopt $(OCAMLOPTFLAGS) \
+         mlguestfs.cmxa -linkpkg $^ -cclib -lncurses -o $@
 
 .mli.cmi:
        $(OCAMLFIND) ocamlc $(OCAMLCFLAGS) -c $< -o $@
@@ -59,6 +64,14 @@ virt-resize: $(OBJECTS)
 .ml.cmx:
        $(OCAMLFIND) ocamlopt $(OCAMLCFLAGS) -c $< -o $@
 
+# automake will decide we don't need C support in this file.  Really
+# we do, so we have to provide it ourselves.
+
+DEFAULT_INCLUDES = -I. -I$(top_builddir) -I$(shell $(OCAMLC) -where) -I../fish
+
+.c.o:
+       $(CC) $(CFLAGS) $(PROF_CFLAGS) $(DEFAULT_INCLUDES) -c $< -o $@
+
 # Manual pages and HTML files for the website.
 
 man_MANS = virt-resize.1
index a4eff0f..0018172 100644 (file)
@@ -22,28 +22,31 @@ open Utils
 
 module G = Guestfs
 
+type progress_bar
+external progress_bar_init : unit -> progress_bar
+  = "virt_resize_progress_bar_init"
+external progress_bar_reset : progress_bar -> unit
+  = "virt_resize_progress_bar_reset"
+external progress_bar_set : progress_bar -> int64 -> int64 -> unit
+  = "virt_resize_progress_bar_set"
+
+(* Initialize the C mini library. *)
+let bar = progress_bar_init ()
+
+(* Reset the progress bar before every libguestfs function. *)
+let enter_callback g event evh buf array =
+  if event = G.EVENT_ENTER then
+    progress_bar_reset bar
+
+(* A progress event: move the progress bar. *)
+let progress_callback g event evh buf array =
+  if event = G.EVENT_PROGRESS && Array.length array >= 4 then (
+    let position = array.(2)
+    and total = array.(3) in
+
+    progress_bar_set bar position total
+  )
+
 let set_up_progress_bar (g : Guestfs.guestfs) =
-  let progress_callback g event evh buf array =
-    if event = G.EVENT_PROGRESS && Array.length array >= 4 then (
-      (*let proc_nr = array.(0)
-      and serial = array.(1)*)
-      let position = array.(2)
-      and total = array.(3) in
-
-      let ratio =
-        if total <> 0L then Int64.to_float position /. Int64.to_float total
-        else 0. in
-      let ratio =
-        if ratio < 0. then 0. else if ratio > 1. then 1. else ratio in
-
-      let dots = int_of_float (ratio *. 72.) in
-
-      print_string "[";
-      for i = 0 to dots-1 do print_char '#' done;
-      for i = dots to 71 do print_char '-' done;
-      print_string "]\r";
-      if ratio = 1. then print_string "\n";
-      flush stdout
-    )
-  in
+  ignore (g#set_event_callback enter_callback [G.EVENT_ENTER]);
   ignore (g#set_event_callback progress_callback [G.EVENT_PROGRESS])
diff --git a/resize/progress.mli b/resize/progress.mli
new file mode 100644 (file)
index 0000000..31deb09
--- /dev/null
@@ -0,0 +1,19 @@
+(* virt-resize
+ * Copyright (C) 2010-2011 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *)
+
+val set_up_progress_bar : Guestfs.guestfs -> unit
diff --git a/resize/progress_c.c b/resize/progress_c.c
new file mode 100644 (file)
index 0000000..dddf787
--- /dev/null
@@ -0,0 +1,101 @@
+/* virt-resize - interface to progress bar mini library
+ * Copyright (C) 2011 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <locale.h>
+
+#include <caml/alloc.h>
+#include <caml/custom.h>
+#include <caml/fail.h>
+#include <caml/memory.h>
+#include <caml/mlvalues.h>
+
+#include "progress.h"
+
+#define Bar_val(v) (*((struct progress_bar **)Data_custom_val(v)))
+
+static void
+progress_bar_finalize (value barv)
+{
+  struct progress_bar *bar = Bar_val (barv);
+
+  if (bar)
+    progress_bar_free (bar);
+}
+
+static struct custom_operations progress_bar_custom_operations = {
+  (char *) "progress_bar_custom_operations",
+  progress_bar_finalize,
+  custom_compare_default,
+  custom_hash_default,
+  custom_serialize_default,
+  custom_deserialize_default
+};
+
+value
+virt_resize_progress_bar_init (value unitv)
+{
+  CAMLparam1 (unitv);
+  CAMLlocal1 (barv);
+  struct progress_bar *bar;
+
+  /* XXX Have to do this to get nl_langinfo to work properly.  However
+   * we should really only call this from main.
+   */
+  setlocale (LC_ALL, "");
+
+  bar = progress_bar_init (0);
+  if (bar == NULL)
+    caml_raise_out_of_memory ();
+
+  barv = caml_alloc_custom (&progress_bar_custom_operations,
+                            sizeof (struct progress_bar *), 0, 1);
+  Bar_val (barv) = bar;
+
+  CAMLreturn (barv);
+}
+
+value
+virt_resize_progress_bar_reset (value barv)
+{
+  CAMLparam1 (barv);
+  struct progress_bar *bar = Bar_val (barv);
+
+  progress_bar_reset (bar);
+
+  CAMLreturn (Val_unit);
+}
+
+value
+virt_resize_progress_bar_set (value barv,
+                              value positionv, value totalv)
+{
+  CAMLparam3 (barv, positionv, totalv);
+  struct progress_bar *bar = Bar_val (barv);
+  uint64_t position = Int64_val (positionv);
+  uint64_t total = Int64_val (totalv);
+
+  progress_bar_set (bar, position, total);
+
+  CAMLreturn (Val_unit);
+}