[Sheepdog] [PATCH 2/2] shepherd: clean up treeview routines

MORITA Kazutaka morita.kazutaka at lab.ntt.co.jp
Wed Feb 10 02:25:06 CET 2010


Signed-off-by: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
---
 shepherd/shepherd.c |    3 +-
 shepherd/treeview.c |  300 +++++++++++++++++++++------------------------------
 shepherd/treeview.h |    3 +-
 3 files changed, 125 insertions(+), 181 deletions(-)

diff --git a/shepherd/shepherd.c b/shepherd/shepherd.c
index bd93168..e9489fa 100644
--- a/shepherd/shepherd.c
+++ b/shepherd/shepherd.c
@@ -537,7 +537,7 @@ static void print_vdi_tree(uint64_t oid, char *name, uint32_t tag,
 			 "[%y-%m-%d %H:%M]", &tm);
 	}
 
-	add_proc(name, buf, oid, i->parent_oid,
+	add_vdi_tree(name, buf, oid, i->parent_oid,
 		 info->highlight && (flags & FLAG_CURRENT));
 }
 
@@ -549,7 +549,6 @@ static int treeview_vdi(char *vdiname, int highlight)
 	i.highlight = highlight;
 
 	init_tree();
-	add_proc("", "root", 1, 1, 0);
 
 	parse_vdi(print_vdi_tree, &i);
 
diff --git a/shepherd/treeview.c b/shepherd/treeview.c
index bacb9c5..f9e4389 100644
--- a/shepherd/treeview.c
+++ b/shepherd/treeview.c
@@ -12,240 +12,184 @@
 #include <stdio.h>
 #include <string.h>
 #include <stdint.h>
-#include <ctype.h>
-#include <unistd.h>
-#include <getopt.h>
-#include <dirent.h>
-#include <curses.h>
 #include <term.h>
 
+#include "list.h"
+
 #ifndef MAX_DEPTH
 #define MAX_DEPTH    100
 #endif
 
-typedef struct _proc {
+struct vdi_tree {
+	char name[1024];
 	char label[256];
-	char tag[256];
 	uint64_t oid;
+	uint64_t poid;
 	int highlight;
-	struct _child *children;
-	struct _proc *parent;
-	struct _proc *next;
-} PROC;
-
-typedef struct _child {
-	PROC *child;
-	struct _child *next;
-} CHILD;
-
-static struct {
-	const char *empty_2;	/*    */
-	const char *branch_2;	/* |- */
-	const char *vert_2;	/* |  */
-	const char *last_2;	/* `- */
-	const char *single_3;	/* --- */
-	const char *first_3;	/* -+- */
-} sym_ascii = {
-"  ", "|-", "| ", "`-", "---", "-+-"}
-
-, *sym = &sym_ascii;
-
-static PROC *list = NULL;
-static int width[MAX_DEPTH], more[MAX_DEPTH];
-static int trunc = 1;
-static int output_width = 132;
-static int cur_x = 1;
-static char last_char = 0;
-
-static void out_char(char c)
+	struct list_head children;
+	struct list_head siblings;
+};
+
+static int *width, *more;
+static struct vdi_tree *root;
+
+static struct vdi_tree *find_vdi(struct vdi_tree *parent, uint64_t oid,
+				 char *name)
 {
-	cur_x += (c & 0xc0) != 0x80;	/* only count first UTF-8 char */
-	if (cur_x <= output_width || !trunc)
-		putchar(c);
-	if (cur_x == output_width + 1 && trunc && ((c & 0xc0) != 0x80)) {
-		if (last_char || (c & 0x80))
-			putchar('+');
-		else {
-			last_char = c;
-			cur_x--;
-			return;
-		}
+	struct vdi_tree *vdi, *ret;
+
+	list_for_each_entry(vdi, &parent->children, siblings) {
+		if (vdi->oid == oid && !strcmp(vdi->name, name))
+			return vdi;
+
+		ret = find_vdi(vdi, oid, name);
+		if (ret)
+			return ret;
 	}
+	return NULL;
 }
 
-static void out_string(const char *str)
+static struct vdi_tree *new_vdi(char *name, char *label, uint64_t oid,
+			   uint64_t poid, int highlight)
 {
-	while (*str)
-		out_char(*str++);
-}
+	struct vdi_tree *vdi;
 
-static void out_newline(void)
-{
-	if (last_char && cur_x == output_width)
-		putchar(last_char);
-	last_char = 0;
-	putchar('\n');
-	cur_x = 1;
+	vdi = malloc(sizeof(struct vdi_tree));
+	if (!vdi) {
+		fprintf(stderr, "malloc\n");
+		return NULL;
+	}
+	strcpy(vdi->name, name);
+	strcpy(vdi->label, label);
+	vdi->oid = oid;
+	vdi->poid = poid;
+	vdi->highlight = highlight;
+	INIT_LIST_HEAD(&vdi->children);
+	return vdi;
 }
 
 void init_tree(void)
 {
-	list = NULL;
+	root = new_vdi("", "", 0, 0, 0);
 }
 
-static PROC *find_proc(uint64_t oid, const char *name)
+void add_vdi_tree(char *name, char *label, uint64_t oid, uint64_t poid,
+		  int highlight)
 {
-	PROC *walk;
+	struct vdi_tree *vdi, *parent;
 
-	for (walk = list; walk; walk = walk->next)
-		if (walk->oid == oid && (name == NULL || !strcmp(walk->label, name)))
-			break;
-	return walk;
-}
+	vdi = new_vdi(name, label, oid, poid, highlight);
+	if (!vdi)
+		return;
 
-static PROC *new_proc(const char *label, const char *tag, uint64_t oid)
-{
-	PROC *new;
+	parent = find_vdi(root, poid, name);
+	if (!parent)
+		parent = root;
 
-	if (!(new = malloc(sizeof(PROC)))) {
-		perror("malloc");
-		exit(1);
-	}
-	strcpy(new->label, label);
-	strcpy(new->tag, tag);
-	new->oid = oid;
-	new->highlight = 0;
-	new->children = NULL;
-	new->parent = NULL;
-	new->next = list;
-	return list = new;
+	list_add_tail(&vdi->siblings, &parent->children);
 }
 
-static void del_child(PROC * parent, PROC * child)
+static void compaction(struct vdi_tree *parent)
 {
-	CHILD *new, **walk;
+	struct vdi_tree *vdi, *e, *new_parent;
 
-	for (walk = &parent->children; *walk; walk = &(*walk)->next) {
-		if ((*walk)->child->oid == child->oid) {
-			*walk = (*walk)->next;
-			break;
+	list_for_each_entry_safe(vdi, e, &parent->children, siblings) {
+		new_parent = find_vdi(root, vdi->poid, vdi->name);
+		if (new_parent && parent != new_parent) {
+			list_del(&vdi->siblings);
+			list_add_tail(&vdi->siblings, &new_parent->children);
 		}
+
+		compaction(vdi);
 	}
 }
 
-static void add_child(PROC * parent, PROC * child)
+static int get_depth(struct vdi_tree *parent)
 {
-	CHILD *new, **walk;
+	struct vdi_tree *vdi;
+	int max_depth = 0, depth;
 
-	if (!(new = malloc(sizeof(CHILD)))) {
-		perror("malloc");
-		exit(1);
+	list_for_each_entry(vdi, &parent->children, siblings) {
+		depth = get_depth(vdi);
+		if (max_depth < depth)
+			max_depth = depth;
 	}
-	new->child = child;
-	for (walk = &parent->children; *walk; walk = &(*walk)->next) ;
-	new->next = *walk;
-	*walk = new;
+	return max_depth + 1;
 }
 
-void add_proc(const char *label, const char *tag, uint64_t oid, uint64_t poid, int highlight)
+static void spaces(int n)
 {
-	PROC *this, *parent, *root = NULL;
-	const CHILD *walk;
-
-	if (!(this = find_proc(oid, label)))
-		this = new_proc(label, tag, oid);
-	else {
-		strcpy(this->label, label);
-		strcpy(this->tag, tag);
-	}
-	this->highlight = highlight;
-	if (oid == poid) {
-		poid = 0;
-		return;
-	}
-	if (!(parent = find_proc(poid, label))) {
-		root = find_proc(1, NULL);
-		parent = new_proc("", label, poid);
-		add_child(root, parent);
-	}
+	while (n--)
+		putchar(' ');
+}
 
-	add_child(parent, this);
-	this->parent = parent;
+static void indent(int level, int first, int last)
+{
+	int lvl;
 
-	for (walk = find_proc(1, NULL)->children; walk; walk = walk->next) {
-		if (walk->child->oid == oid) {
-			add_child(this, walk->child->children->child);
-			del_child(find_proc(1, NULL), walk->child);
-			break;
+	if (first)
+		printf(last ? "---" : "-+-");
+	else {
+		for (lvl = 0; lvl < level - 1; lvl++) {
+			spaces(width[lvl] + 1);
+			printf(more[lvl + 1] ? "| " : "  ");
 		}
+
+		spaces(width[level - 1] + 1);
+		printf(last ? "`-" : "|-");
 	}
 }
 
-static void _dump_tree(PROC * current, int level, int leaf, int last)
+static void _dump_tree(struct vdi_tree *current, int level, int first, int last)
 {
-	CHILD *walk, *next;
-	int lvl, i, add, offset, tag_len, first;
-	const char *tmp, *here;
+	char *tmp;
+	struct vdi_tree *vdi;
+
+	indent(level, first, last);
 
-	if (!current)
-		return;
-	if (level >= MAX_DEPTH - 1) {
-		fprintf(stderr, "Internal error: MAX_DEPTH not big enough.\n");
-		exit(1);
-	}
-	if (!leaf)
-		for (lvl = 0; lvl < level; lvl++) {
-			for (i = width[lvl] + 1; i; i--)
-				out_char(' ');
-			out_string(lvl ==
-				   level -
-				   1 ? last ? sym->
-				   last_2 : sym->branch_2 : more[lvl +
-								 1] ? sym->
-				   vert_2 : sym->empty_2);
-		}
-	add = 0;
 	if (current->highlight && (tmp = tgetstr("md", NULL)))
 		tputs(tmp, 1, putchar);
-	tag_len = 0;
-	for (here = current->tag; *here; here++) {
-		out_char(*here);
-		tag_len++;
-	}
-	offset = cur_x;
+
+	printf(current->label);
+
 	if (current->highlight && (tmp = tgetstr("me", NULL)))
 		tputs(tmp, 1, putchar);
-	if (!current->children) {
-		out_newline();
-	} else {
-		more[level] = !last;
-		width[level] = tag_len + cur_x - offset + add;
-		if (cur_x >= output_width && trunc) {
-			out_string(sym->first_3);
-			out_string("+");
-			out_newline();
-		} else {
-			first = 1;
-			for (walk = current->children; walk; walk = next) {
-				next = walk->next;
-				if (first) {
-					out_string(next ? sym->
-						   first_3 : sym->single_3);
-					first = 0;
-				}
-				_dump_tree(walk->child, level + 1,
-					   walk == current->children, !next);
-			}
-		}
+
+	if (list_empty(&current->children)) {
+		putchar('\n');
+		return;
+	}
+
+	more[level] = !last;
+	width[level] = strlen(current->label);
+
+	list_for_each_entry(vdi, &current->children, siblings) {
+		_dump_tree(vdi, level + 1,
+			   &vdi->siblings == current->children.next,
+			   vdi->siblings.next == &current->children);
 	}
 }
 
 void dump_tree(void)
 {
-	const CHILD *walk;
+	struct vdi_tree *vdi;
+	int depth;
 
-	sym = &sym_ascii;
+	compaction(root);
 
-	for (walk = find_proc(1, NULL)->children; walk; walk = walk->next)
-		_dump_tree(walk->child, 0, 1, 1);
+	depth = get_depth(root);
+
+	width = malloc(sizeof(int) * depth);
+	more = malloc(sizeof(int) * depth);
+	if (!width || !more) {
+		fprintf(stderr, "out of memory\n");
+		return;
+	}
+
+	list_for_each_entry(vdi, &root->children, siblings) {
+		printf(vdi->name);
+		more[0] = 0;
+		width[0] = strlen(vdi->name);
+		_dump_tree(vdi, 1, 1, 1);
+	}
 }
diff --git a/shepherd/treeview.h b/shepherd/treeview.h
index 3d9f504..c3905a6 100644
--- a/shepherd/treeview.h
+++ b/shepherd/treeview.h
@@ -12,7 +12,8 @@
 #define __TREEVIEW__
 
 void init_tree(void);
-void add_proc(const char *label, const char *tag, uint64_t pid, uint64_t ppid, int highlight);
+void add_vdi_tree(const char *label, const char *tag, uint64_t pid,
+		  uint64_t ppid, int highlight);
 void dump_tree(void);
 
 #endif
-- 
1.5.6.5




More information about the sheepdog mailing list