From fa7e5527aa3f17b277a051e35a3cb1415ace48a3 Mon Sep 17 00:00:00 2001
From: jspringe <jspringe@wrfl.de>
Date: Tue, 17 Feb 2009 00:26:25 +0000
Subject: [PATCH] added history-count command and changed history command
 to allow for timestamp specification!

---
 sbin/hammer/cmd_history.c |   66 ++++++++++++++++++++++++++++++++++++++------
 sbin/hammer/hammer.c      |    9 +++++-
 sbin/hammer/hammer.h      |    2 +-
 3 files changed, 65 insertions(+), 12 deletions(-)

diff --git a/sbin/hammer/cmd_history.c b/sbin/hammer/cmd_history.c
index e42ccac..084995e 100644
--- a/sbin/hammer/cmd_history.c
+++ b/sbin/hammer/cmd_history.c
@@ -36,20 +36,22 @@
 
 #include "hammer.h"
 
-static void hammer_do_history(const char *path, off_t off, int len);
+static void hammer_do_history(const char *path, off_t off, int len, int count_option, hammer_tid_t start, hammer_tid_t end);
 static void dumpat(const char *path, off_t off, int len);
 static const char *timestr32(u_int32_t time32);
+static int get_cmd_history_opt(char **av, int ac, hammer_tid_t *start, hammer_tid_t *end);
 
 /*
- * history <file1> ... <fileN>
+ * history[-count] <file1> ... <fileN> [options]
  */
 void
-hammer_cmd_history(const char *offset_str, char **av, int ac)
+hammer_cmd_history(const char *offset_str, char **av, int ac, int count_option)
 {
 	off_t off;
 	int i;
 	int len;
 	char *rptr;
+	hammer_tid_t start, end;
 
 	len = 32;
 	if (*offset_str == '@') {
@@ -59,13 +61,20 @@ hammer_cmd_history(const char *offset_str, char **av, int ac)
 	} else {
 		off = -1;
 	}
-
+	ac = get_cmd_history_opt(av, ac, &start, &end);
+	/* consistency check of timestamps */
+	if (start > end)
+	{
+		fprintf(stderr, "invalid option: start-tid is bigger than end-tid\n");
+		exit(1);
+	}
 	for (i = 0; i < ac; ++i)
-		hammer_do_history(av[i], off, len);
+		hammer_do_history(av[i], off, len, count_option, start, end);
 }
 
+
 static void
-hammer_do_history(const char *path, off_t off, int len)
+hammer_do_history(const char *path, off_t off, int len, int count_option, hammer_tid_t start, hammer_tid_t end)
 {
 	struct hammer_ioc_history hist;
 	const char *status;
@@ -79,8 +88,8 @@ hammer_do_history(const char *path, off_t off, int len)
 		return;
 	}
 	bzero(&hist, sizeof(hist));
-	hist.beg_tid = HAMMER_MIN_TID;
-	hist.end_tid = HAMMER_MAX_TID;
+	hist.beg_tid = start;
+	hist.end_tid = end;
 
 	if (off >= 0) {
 		hist.head.flags |= HAMMER_IOC_HISTORY_ATKEY;
@@ -94,6 +103,13 @@ hammer_do_history(const char *path, off_t off, int len)
 		close(fd);
 		return;
 	}
+
+	if (count_option) {
+		printf("\t%d\n", hist.count);
+		close(fd);
+		return;
+	}
+
 	status = ((hist.head.flags & HAMMER_IOC_HISTORY_UNSYNCED) ?
 		 "dirty" : "clean");
 	printf("%016llx %s {\n", hist.obj_id, status);
@@ -159,6 +175,39 @@ dumpat(const char *path, off_t off, int len)
 	}
 }
 
+static int
+get_cmd_history_opt(char **av, int ac, hammer_tid_t *start, hammer_tid_t *end) {
+	int i;
+	char *ptr;
+
+	/* default start TID are MIN_TID and MAX_TID */
+	*start = HAMMER_MIN_TID;
+	*end = HAMMER_MAX_TID;
+
+	for(i = ac - 1; i >= 0; i--) {
+		if ((ptr = strchr(av[i], '=')) != NULL)
+			*ptr++ = 0;
+
+		if(ptr == NULL) {
+			/* no options left */
+			break;
+		}
+
+		if (strcmp(av[i], "start-tid") == 0) {
+			*start = strtoull(ptr, NULL, 16);
+			ac--;
+		} else if (strcmp(av[i], "end-tid") == 0) {
+			*end = strtoull(ptr, NULL, 16);
+			ac--;
+		} else {
+			fprintf(stderr, "invalid option: %s\n", av[i]);
+			exit(1);
+		}
+	}
+
+	return ac;
+}
+
 /*
  * Return a human-readable timestamp
  */
@@ -173,4 +222,3 @@ timestr32(u_int32_t time32)
 	strftime(timebuf, sizeof(timebuf), "%d-%b-%Y %H:%M:%S", tp);
 	return(timebuf);
 }
-
diff --git a/sbin/hammer/hammer.c b/sbin/hammer/hammer.c
index fc5eb5b..c98afd3 100644
--- a/sbin/hammer/hammer.c
+++ b/sbin/hammer/hammer.c
@@ -262,7 +262,12 @@ main(int ac, char **av)
 	}
 
 	if (strncmp(av[0], "history", 7) == 0) {
-		hammer_cmd_history(av[0] + 7, av + 1, ac - 1);
+		if (strcmp(av[0], "history") == 0)
+			hammer_cmd_history(av[0] + 7, av + 1, ac - 1, 0);
+		else if (strcmp(av[0], "history-count") == 0)
+			hammer_cmd_history(av[0] + 13, av + 1, ac - 1, 1);
+		else
+			usage(1);
 		exit(0);
 	}
 	if (strncmp(av[0], "reblock", 7) == 0) {
@@ -381,7 +386,7 @@ usage(int exit_code)
 		"hammer -f blkdev[:blkdev]* blockmap\n"
 		"hammer bstats [interval]\n"
 		"hammer iostats [interval]\n"
-		"hammer history[@offset[,len]] <file> ...\n"
+		"hammer history[-count][@offset[,len]] <file> ... <fileN> [options]\n"
 		"hammer -f blkdev[:blkdev]* [-r] show [offset]\n"
 #if 0
 		"hammer -f blkdev[:blkdev]* blockmap\n"
diff --git a/sbin/hammer/hammer.h b/sbin/hammer/hammer.h
index ec7d7d7..51f3ce8 100644
--- a/sbin/hammer/hammer.h
+++ b/sbin/hammer/hammer.h
@@ -83,7 +83,7 @@ void hammer_cmd_mirror_read(char **av, int ac, int streaming);
 void hammer_cmd_mirror_write(char **av, int ac);
 void hammer_cmd_mirror_copy(char **av, int ac, int streaming);
 void hammer_cmd_mirror_dump(void);
-void hammer_cmd_history(const char *offset_str, char **av, int ac);
+void hammer_cmd_history(const char *offset_str, char **av, int ac, int count_option);
 void hammer_cmd_blockmap(void);
 void hammer_cmd_reblock(char **av, int ac, int flags);
 void hammer_cmd_pseudofs_status(char **av, int ac);
-- 
1.5.6.4

