File reiserfsprogs-progress.diff of Package reiserfs

From: Jeff Mahoney <jeffm@suse.com>
Subject: [PATCH] reiserprogs: add spinner and progress bar for -a mode

 This patch implements a progress bar with percentages and a plain spinner
 for when progress wants to be demonstrated but percentages aren't known.

 These are used during journal replay and for the internal tree check.

---
 fsck/check_tree.c      |    2 
 fsck/ustree.c          |    7 ++
 include/progbar.h      |   32 +++++++++++++
 lib/Makefile.am        |    2 
 lib/progbar.c          |  117 +++++++++++++++++++++++++++++++++++++++++++++++++
 reiserfscore/journal.c |   16 +++++-
 6 files changed, 172 insertions(+), 4 deletions(-)

--- a/fsck/check_tree.c	2004-09-29 15:52:20.000000000 -0400
+++ b/fsck/check_tree.c	2008-01-24 13:39:05.000000000 -0500
@@ -1124,7 +1124,7 @@ void check_fs_tree (reiserfs_filsys_t * 
 {
     before_check_fs_tree (fs);
     
-    fsck_progress ("Checking internal tree..");
+    fsck_progress ("Checking internal tree..  ");
     pass_through_tree (fs, bad_node, bad_path, fsck_mode(fs) == FSCK_AUTO ? 2 : -1);
     /* internal tree is correct (including all objects have correct
        sequences of items) */
--- a/fsck/ustree.c	2004-05-24 18:11:43.000000000 -0400
+++ b/fsck/ustree.c	2008-01-24 13:39:05.000000000 -0500
@@ -4,6 +4,7 @@
  */
 
 #include "fsck.h"
+#include "progbar.h"
 
 struct tree_balance * cur_tb = 0;
 
@@ -196,6 +197,9 @@ void pass_through_tree (reiserfs_filsys_
     int h = 0;
     unsigned long block = get_sb_root_block (fs->fs_ondisk_sb);
     int problem;
+    struct spinner spinner;
+
+    spinner_init(&spinner, fsck_progress_file(fs));
 
 
     if (block >= get_sb_block_count (fs->fs_ondisk_sb) || not_data_block (fs, block)) {
@@ -223,6 +227,8 @@ void pass_through_tree (reiserfs_filsys_
 	    }
 	    problem = 1;		
 	} else {
+
+	    spinner_touch(&spinner);
 	    path[h] = bread (fs->fs_dev, block, fs->fs_blocksize);
 	    if (path[h] == 0)
 		/* FIXME: handle case when read failed */
@@ -279,4 +285,5 @@ void pass_through_tree (reiserfs_filsys_
         block = first_child (path[h]);
         h ++;
     }
+    spinner_clear(&spinner);
 }
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ b/include/progbar.h	2008-01-24 13:39:05.000000000 -0500
@@ -0,0 +1,32 @@
+#ifndef _PROGBAR_H_
+#define _PROGBAR_H_
+
+enum {
+	E2F_FLAG_PROG_SUPPRESS = 1,
+	E2F_FLAG_PROG_BAR = 2,
+};
+
+struct progbar {
+	char units[16];
+	int progress_pos;
+	int progress_last_percent;
+	time_t progress_last_time;
+	int flags;
+	FILE *file;
+};
+
+struct spinner {
+	int count;
+	FILE *file;
+};
+
+void progbar_init(struct progbar *ctx, const char *units, FILE *fp);
+void progbar_clear(struct progbar * ctx);
+int progbar_update(struct progbar * ctx, const char *label, int curr, int max,
+                           unsigned int dpynum);
+
+void spinner_init(struct spinner *spinner, FILE *fp);
+void spinner_touch(struct spinner *spinner);
+void spinner_clear(struct spinner *spinner);
+
+#endif /* _PROGBAR_H_ */
--- a/lib/Makefile.am	2004-02-17 06:35:12.000000000 -0500
+++ b/lib/Makefile.am	2008-01-24 13:39:05.000000000 -0500
@@ -1,5 +1,5 @@
 noinst_LIBRARIES = libmisc.a
 
-libmisc_a_SOURCES = io.c misc.c 
+libmisc_a_SOURCES = io.c misc.c progbar.c
 ##reiserfs.c
 
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ b/lib/progbar.c	2008-01-24 13:39:05.000000000 -0500
@@ -0,0 +1,117 @@
+#include <stdio.h>
+#include <sys/time.h>
+#include <string.h>
+
+#include "progbar.h"
+
+static char bar[128], spaces[128];
+static const char spinner[] = "\\|/-";
+
+void progbar_init(struct progbar *ctx, const char *units, FILE *fp)
+{
+	memset(ctx, 0, sizeof (*ctx));
+	if (!bar[0])
+		memset(bar, '=', sizeof(bar)-1);
+	if (!spaces[0])
+		memset(spaces, ' ', sizeof(spaces)-1);
+	strncpy(ctx->units, units, sizeof(ctx->units));
+	ctx->file = fp;
+}
+
+
+void progbar_clear(struct progbar * ctx)
+{
+	if (!(ctx->flags & E2F_FLAG_PROG_BAR))
+		return;
+
+	fprintf(ctx->file, "\r%*s\r", 80, " ");
+	fflush(ctx->file);
+	ctx->flags &= ~E2F_FLAG_PROG_BAR;
+}
+
+int progbar_update(struct progbar * ctx, const char *label, int curr, int max,
+                           unsigned int dpynum)
+{
+	int	i;
+	unsigned int	tick;
+	struct timeval	tv;
+	int dpywidth;
+	int fixed_percent;
+	float percent = ((float) curr) / ((float) max) * 100;
+
+	if (ctx->flags & E2F_FLAG_PROG_SUPPRESS)
+		return 0;
+
+	/*
+	 * Calculate the new progress position.  If the
+	 * percentage hasn't changed, then we skip out right
+	 * away.
+	 */
+	fixed_percent = (int) ((10 * percent) + 0.5);
+	if (ctx->progress_last_percent == fixed_percent)
+		return 0;
+	ctx->progress_last_percent = fixed_percent;
+
+	/*
+	 * If we've already updated the spinner once within
+	 * the last 1/8th of a second, no point doing it
+	 * again.
+	 */
+	gettimeofday(&tv, NULL);
+	tick = (tv.tv_sec << 3) + (tv.tv_usec / (1000000 / 8));
+	if ((tick == ctx->progress_last_time) &&
+	    (fixed_percent != 0) && (fixed_percent != 1000))
+		return 0;
+	ctx->progress_last_time = tick;
+
+	/*
+	 * Advance the spinner, and note that the progress bar
+	 * will be on the screen
+	 */
+	ctx->progress_pos = (ctx->progress_pos+1) & 3;
+	ctx->flags |= E2F_FLAG_PROG_BAR;
+
+	dpywidth = 66 - strlen(label);
+	dpywidth = 8 * (dpywidth / 8);
+	if (dpynum)
+		dpywidth -= 8;
+
+	i = ((percent * dpywidth) + 50) / 100;
+	fprintf(ctx->file, "\r%s: |%s%s", label,
+	       bar + (sizeof(bar) - (i+1)),
+	       spaces + (sizeof(spaces) - (dpywidth - i + 1)));
+	if (fixed_percent == 1000)
+		fputc('|', ctx->file);
+	else
+		fputc(spinner[ctx->progress_pos & 3], ctx->file);
+	fprintf(ctx->file, " %4.1f%%  ", percent);
+	if (dpynum)
+		fprintf(ctx->file, "%u%s\r", dpynum, ctx->units);
+	else
+		fputs(" \r", ctx->file);
+
+	if (fixed_percent == 1000)
+		progbar_clear(ctx);
+	fflush(ctx->file);
+
+	return 0;
+}
+
+void
+spinner_init(struct spinner *ctx, FILE *fp)
+{
+	memset(ctx, 0, sizeof (*ctx));
+	ctx->file = fp;
+}
+
+void
+spinner_touch(struct spinner *ctx)
+{
+	fprintf(ctx->file, "%c", spinner[ctx->count++ % 4]);
+}
+
+void
+spinner_clear(struct spinner *ctx)
+{
+	fputs("", ctx->file);
+}
--- a/reiserfscore/journal.c	2008-01-24 13:39:04.000000000 -0500
+++ b/reiserfscore/journal.c	2008-01-24 13:39:05.000000000 -0500
@@ -6,6 +6,7 @@
 #define _GNU_SOURCE
 
 #include "includes.h"
+#include "progbar.h"
 
 /* compares description block with commit block. returns 0 if they differ, 1
    if they match */
@@ -799,6 +800,8 @@ int replay_journal (reiserfs_filsys_t * 
     struct reiserfs_journal_header * j_head;
     reiserfs_trans_t cur, newest, control;
     int replayed, ret;
+    struct progbar progbar;
+    int trans_count;
 
     if (!reiserfs_journal_opened (fs))
         reiserfs_panic ("replay_journal: journal is not opened");
@@ -806,7 +809,8 @@ int replay_journal (reiserfs_filsys_t * 
     if (!is_opened_rw (fs))
         reiserfs_panic ("replay_journal: fs is not opened with write perms");
 
-    reiserfs_warning (stderr, "Replaying journal..\n");
+
+    reiserfs_warning (stderr, "Replaying journal: ");
     bh = fs->fs_jh_bh;
 	
     j_head = (struct reiserfs_journal_header *)(bh->b_data);
@@ -819,12 +823,15 @@ int replay_journal (reiserfs_filsys_t * 
 	return 0;
     }
 
+    trans_count = newest.trans_id - cur.trans_id;
+
     /*  Smth strange with journal header or journal. We cannot say for sure what was the last 
 	replaied transaction, but relying on JH data is preferable. */
 
     replayed = 0;
     ret = TRANS_FOUND;
     
+    progbar_init(&progbar, " trans", stderr);
     /* Looking to the first valid not replayed transaction. */
     while (1) {
 	if (cur.mount_id == control.mount_id && 
@@ -842,6 +849,7 @@ int replay_journal (reiserfs_filsys_t * 
 	    break;
 	
 	if (!transaction_check_content(fs, &cur)) {
+	    progbar_clear(&progbar);
 	    reiserfs_warning (stderr, "Trans broken: mountid %lu, transid %lu, desc %lu, "
 		"len %lu, commit %lu, next trans offset %lu\n", cur.mount_id, cur.trans_id, 
 		cur.desc_blocknr, cur.trans_len, cur.commit_blocknr, cur.next_trans_offset);
@@ -857,10 +865,14 @@ int replay_journal (reiserfs_filsys_t * 
 	control = cur;
         replayed ++;
 
+	progbar_update(&progbar, "Replaying journal", replayed, trans_count,
+	               replayed);
+
 	ret = next_transaction (fs, &cur, newest);
     }
+    progbar_clear(&progbar);
 
-    reiserfs_warning (stderr, "Reiserfs journal '%s' in blocks [%u..%u]: %d "
+    reiserfs_warning (stderr, "\rReplaying journal: Done.\nReiserfs journal '%s' in blocks [%u..%u]: %d "
 		      "transactions replayed\n", fs->fs_j_file_name, 
 		      get_jp_journal_1st_block(sb_jp(fs->fs_ondisk_sb)),
 		      get_jp_journal_1st_block(sb_jp(fs->fs_ondisk_sb)) +
openSUSE Build Service is sponsored by