From 2faef37957629e0436308e759211209e5e823ee0 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Fri, 26 Aug 2011 19:21:23 +0100 Subject: [PATCH] resize: Use guestfish progress bar mini-library. 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 | 1 + resize/.depend | 7 ++-- resize/Makefile.am | 15 +++++++- resize/progress.ml | 49 +++++++++++++------------ resize/progress.mli | 19 ++++++++++ resize/progress_c.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 165 insertions(+), 27 deletions(-) create mode 100644 resize/progress.mli create mode 100644 resize/progress_c.c diff --git a/po/POTFILES.in b/po/POTFILES.in index 01f7a0d..43e7ffa 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -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 diff --git a/resize/.depend b/resize/.depend index 90a87cb..17bdaca 100644 --- a/resize/.depend +++ b/resize/.depend @@ -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 diff --git a/resize/Makefile.am b/resize/Makefile.am index 93a2600..c2fbc3a 100644 --- a/resize/Makefile.am +++ b/resize/Makefile.am @@ -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 diff --git a/resize/progress.ml b/resize/progress.ml index a4eff0f..0018172 100644 --- a/resize/progress.ml +++ b/resize/progress.ml @@ -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 index 0000000..31deb09 --- /dev/null +++ b/resize/progress.mli @@ -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 index 0000000..dddf787 --- /dev/null +++ b/resize/progress_c.c @@ -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 + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#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); +} -- 1.8.3.1