WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] Rename vm-top to xentop. Make "xm top" invoke xentop. Ma

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] Rename vm-top to xentop. Make "xm top" invoke xentop. Make libxenstat a static library, and do not install it.
From: Xen patchbot -unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Tue, 23 Aug 2005 00:08:13 +0000
Delivery-date: Tue, 23 Aug 2005 08:30:50 +0000
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User josht@xxxxxxxxxx
# Node ID 173b918160e27ae385258cf8dd6dfd266974ba90
# Parent  b38cbc8f4d983652803be188a6d7f90220d80692
Rename vm-top to xentop.  Make "xm top" invoke xentop.  Make libxenstat a 
static library, and do not install it.
# HG changeset patch
# User josht@xxxxxxxxxx
# Node ID ea025493dfe39540075ee9e4e75b2146f25bdbd3
# Parent  ce557cc4fdc764ac2ce07b8d4bcae77ecf847c29
Rename vm-top to xentop.  Make "xm top" invoke xentop.  Make libxenstat a 
static library, and do not install it.

diff -r b38cbc8f4d98 -r 173b918160e2 Config.mk
--- a/Config.mk Mon Aug 15 18:25:33 2005
+++ b/Config.mk Wed Aug 17 16:50:33 2005
@@ -14,6 +14,7 @@
 CC         = $(CROSS_COMPILE)gcc
 CPP        = $(CROSS_COMPILE)gcc -E
 AR         = $(CROSS_COMPILE)ar
+RANLIB     = $(CROSS_COMPILE)ranlib
 NM         = $(CROSS_COMPILE)nm
 STRIP      = $(CROSS_COMPILE)strip
 OBJCOPY    = $(CROSS_COMPILE)objcopy
@@ -37,6 +38,4 @@
 KERNEL_REPO = http://www.kernel.org
 
 # Optional components
-XENSTAT_PERL_BINDINGS   ?= n
-XENSTAT_PYTHON_BINDINGS ?= y
-XENSTAT_VM_TOP          ?= y
+XENSTAT_XENTOP ?= y
diff -r b38cbc8f4d98 -r 173b918160e2 tools/python/xen/xm/main.py
--- a/tools/python/xen/xm/main.py       Mon Aug 15 18:25:33 2005
+++ b/tools/python/xen/xm/main.py       Wed Aug 17 16:50:33 2005
@@ -49,6 +49,7 @@
     restore <File>          create a domain from a saved state file
     save <DomId> <File>     save domain state (and config) to file
     shutdown <DomId>        shutdown a domain
+    top                     monitor system and domains in real-time
     unpause <DomId>         unpause a paused domain
 
 For a complete list of subcommands run 'xm help --long'
@@ -87,6 +88,7 @@
     dmesg   [--clear]         read or clear Xen's message buffer
     info                      get information about the xen host
     log                       print the xend log
+    top                       monitor system and domains in real-time
 
   Scheduler Commands:
     bvt <options>             set BVT scheduler parameters
@@ -452,6 +454,9 @@
     os.execvp('/usr/libexec/xen/xenconsole', cmd.split())
     console = sxp.child(info, "console")
 
+def xm_top(args):
+    os.execv('/usr/sbin/xentop', ['/usr/sbin/xentop'])
+
 def xm_dmesg(args):
     
     gopts = Opts(use="""[-c|--clear]
@@ -540,6 +545,8 @@
 commands = {
     # console commands
     "console": xm_console,
+    # xenstat commands
+    "top": xm_top,
     # domain commands
     "domid": xm_domid,
     "domname": xm_domname,
diff -r b38cbc8f4d98 -r 173b918160e2 tools/xenstat/Makefile
--- a/tools/xenstat/Makefile    Mon Aug 15 18:25:33 2005
+++ b/tools/xenstat/Makefile    Wed Aug 17 16:50:33 2005
@@ -3,7 +3,7 @@
 
 SUBDIRS :=
 SUBDIRS += libxenstat
-SUBDIRS += vm-top
+SUBDIRS += xentop
 
 .PHONY: all install clean
 
diff -r b38cbc8f4d98 -r 173b918160e2 tools/xenstat/libxenstat/Makefile
--- a/tools/xenstat/libxenstat/Makefile Mon Aug 15 18:25:33 2005
+++ b/tools/xenstat/libxenstat/Makefile Wed Aug 17 16:50:33 2005
@@ -30,8 +30,9 @@
 MAJOR=0
 MINOR=0
 
-LIB=src/libxenstat.so.$(MAJOR).$(MINOR)
-LINKS=src/libxenstat.so.$(MAJOR) src/libxenstat.so
+LIB=src/libxenstat.a
+SHLIB=src/libxenstat.so.$(MAJOR).$(MINOR)
+SHLIB_LINKS=src/libxenstat.so.$(MAJOR) src/libxenstat.so
 OBJECTS=src/xenstat.o src/xen-interface.o
 SONAME_FLAGS=-Wl,-soname -Wl,libxenstat.so.$(MAJOR)
 
@@ -42,9 +43,13 @@
 CFLAGS+=-I$(LINUX_ROOT)/include/asm-xen/linux-public/
 LDFLAGS+=-Lsrc
 
-all: $(LIB) $(LINKS)
+all: $(LIB)
 
 $(LIB): $(OBJECTS)
+       $(AR) rc $@ $^
+       $(RANLIB) $@
+
+$(SHLIB): $(OBJECTS)
        $(CC) $(LDFLAGS) $(SONAME_FLAGS) -shared -o $@ $(OBJECTS)
 
 src/xenstat.o: src/xenstat.c src/xenstat.h src/xen-interface.h
@@ -59,15 +64,17 @@
 src/libxenstat.so: src/libxenstat.so.$(MAJOR)
        $(MAKE_LINK) $(<F) $@
 
-install: all
-       $(INSTALL_DATA) src/xenstat.h $(DESTDIR)$(includedir)/xenstat.h
-       $(INSTALL_PROG) $(LIB) \
-                       $(DESTDIR)$(libdir)/libxenstat.so.$(MAJOR).$(MINOR)
-       $(MAKE_LINK) libxenstat.so.$(MAJOR).$(MINOR) \
-                    $(DESTDIR)$(libdir)/libxenstat.so.$(MAJOR)
-       $(MAKE_LINK) libxenstat.so.$(MAJOR) \
-                    $(DESTDIR)$(libdir)/libxenstat.so
-       -$(LDCONFIG)
+install:
+#install: all
+#      $(INSTALL_DATA) src/xenstat.h $(DESTDIR)$(includedir)/xenstat.h
+#      $(INSTALL_PROG) $(LIB) $(DESTDIR)$(libdir)/libxenstat.a
+#      $(INSTALL_PROG) $(SHLIB) \
+#                      $(DESTDIR)$(libdir)/libxenstat.so.$(MAJOR).$(MINOR)
+#      $(MAKE_LINK) libxenstat.so.$(MAJOR).$(MINOR) \
+#                   $(DESTDIR)$(libdir)/libxenstat.so.$(MAJOR)
+#      $(MAKE_LINK) libxenstat.so.$(MAJOR) \
+#                   $(DESTDIR)$(libdir)/libxenstat.so
+#      -$(LDCONFIG)
 
 PYLIB=bindings/swig/python/_xenstat.so
 PYMOD=bindings/swig/python/xenstat.py
@@ -84,7 +91,7 @@
 # The install-bindings target installs all the language bindings
 install-bindings: install-perl-bindings install-python-bindings
 
-$(BINDINGS): $(LIB) $(LINKS) src/xenstat.h
+$(BINDINGS): $(SHLIB) $(SHLIB_LINKS) src/xenstat.h
 
 SWIG_FLAGS=-module xenstat -Isrc
 
@@ -131,4 +138,5 @@
 endif
 
 clean:
-       rm -f $(LIB) $(OBJECTS) $(LINKS) $(BINDINGS) $(BINDINGSRC)
+       rm -f $(LIB) $(SHLIB) $(SHLIB_LINKS) $(OBJECTS) \
+             $(BINDINGS) $(BINDINGSRC)
diff -r b38cbc8f4d98 -r 173b918160e2 tools/xenstat/xentop/Makefile
--- /dev/null   Mon Aug 15 18:25:33 2005
+++ b/tools/xenstat/xentop/Makefile     Wed Aug 17 16:50:33 2005
@@ -0,0 +1,43 @@
+# Copyright (C) International Business Machines Corp., 2005
+# Author: Josh Triplett <josht@xxxxxxxxxx>
+# 
+# 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; under version 2 of the License.
+#
+# 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.
+
+XEN_ROOT=../../..
+include $(XEN_ROOT)/tools/Rules.mk
+
+ifneq ($(XENSTAT_XENTOP),y)
+all install xentop:
+else
+
+INSTALL         = install
+INSTALL_PROG    = $(INSTALL) -m0755 -D
+INSTALL_DATA    = $(INSTALL) -m0644 -D
+
+prefix=/usr
+mandir=$(prefix)/share/man
+man1dir=$(mandir)/man1
+sbindir=$(prefix)/sbin
+
+CFLAGS += -DGCC_PRINTF -Wall -Werror -I$(XEN_LIBXENSTAT)
+LDFLAGS += -L$(XEN_LIBXENSTAT) -lxenstat -lcurses
+
+all: xentop
+
+xentop: xentop.o
+
+install: xentop xentop.1
+       $(INSTALL_PROG) xentop $(DESTDIR)$(sbindir)/xentop
+       $(INSTALL_DATA) xentop.1 $(DESTDIR)$(man1dir)/xentop.1
+
+endif
+
+clean:
+       rm -f xentop xentop.o
diff -r b38cbc8f4d98 -r 173b918160e2 tools/xenstat/xentop/TODO
--- /dev/null   Mon Aug 15 18:25:33 2005
+++ b/tools/xenstat/xentop/TODO Wed Aug 17 16:50:33 2005
@@ -0,0 +1,34 @@
+Display error messages on the help line after bad input at a prompt.
+Fractional delay times
+Use prompting to search for domains
+Better line editing?
+
+* Make CPU in % more accurate
+* Domain total network TX % and RX %
+
+Like Top, f feature, field select of domain columns, toggle the display of
+field by typing the letter associated with field, if displayed it shows in
+bold and the letter is Capitalized along with a leading asterisk for the
+field, if not selected for display letter is lowercase, no leading asterisk
+and field is not bolded.
+
+Like Top, ordering of domain columns, o feature Capital letter shifts left,
+lowercase letter shifts right?
+
+Color
+Full management: pause, destroy, create domains
+
+Add support for Virtual Block Devices (vbd)
+
+To think about:
+Support for one than one node display (distributed monitoring 
+from any node of all other nodes in a cluster)
+Bottom line option (Switch node, Search node [tab completion?])
+
+Capture/Logging of resource information generated during a time interval.
+-b batch mode dump snapshots to standard output (used with -n)
+-n number of iterations to dump to standard output (unlimited if not specified)
+-d monitor DomIDs as -dD1,-dD2 or -dD1,D2...
+   Monitor only domains with specified domain IDs
+-m monitor nodeIDs as -mN1,-mN2 or -mN1,N2...
+   Monitor only domains with specified node IDs
diff -r b38cbc8f4d98 -r 173b918160e2 tools/xenstat/xentop/xentop.1
--- /dev/null   Mon Aug 15 18:25:33 2005
+++ b/tools/xenstat/xentop/xentop.1     Wed Aug 17 16:50:33 2005
@@ -0,0 +1,88 @@
+.\" Copyright (C) International Business Machines  Corp., 2005
+.\" Author: Josh Triplett <josht@xxxxxxxxxx>
+.\"
+.\" 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; under version 2 of the License.
+.\"
+.\" 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+.TH xentop 1 "August 2005"
+.SH NAME
+\fBxentop\fR \- displays real-time information about a Xen system and domains
+
+.SH SYNOPSIS
+.B xentop
+[\fB\-h\fR]
+[\fB\-V\fR]
+[\fB\-d\fRSECONDS]
+[\fB\-n\fR]
+[\fB\-r\fR]
+[\fB\-v\fR]
+
+.SH DESCRIPTION
+\fBxentop\fR displays information about the Xen system and domains, in a
+continually-updating manner.  Command-line options and interactive commands
+can change the detail and format of the information displayed by \fBxentop\fR.
+
+.SH OPTIONS
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+display help and exit
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+output version information and exit
+.TP
+\fB\-d\fR, \fB\-\-delay\fR=\fISECONDS\fR
+seconds between updates (default 1)
+.TP
+\fB\-n\fR, \fB\-\-networks\fR
+output network information
+.TP
+\fB\-r\fR, \fB\-\-repeat\-header\fR
+repeat table header before each domain
+.TP
+\fB\-v\fR, \fB\-\-vcpus\fR
+output VCPU data
+
+.SH "INTERACTIVE COMMANDS"
+All interactive commands are case-insensitive.
+.TP
+.B D
+set delay between updates
+.TP
+.B N
+toggle display of network information
+.TP
+.B Q, Esc
+quit
+.TP
+.B R
+toggle table header before each domain
+.TP
+.B S
+cycle sort order
+.TP
+.B V
+toggle display of VCPU information
+.TP
+.B Arrows
+scroll domain display
+
+.SH AUTHORS
+Written by Judy Fischbach, David Hendricks, and Josh Triplett
+
+.SH "REPORTING BUGS"
+Report bugs to <dsteklof@xxxxxxxxxx>.
+
+.SH COPYRIGHT
+Copyright \(co 2005  International Business Machines  Corp
+.br
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
diff -r b38cbc8f4d98 -r 173b918160e2 tools/xenstat/xentop/xentop.c
--- /dev/null   Mon Aug 15 18:25:33 2005
+++ b/tools/xenstat/xentop/xentop.c     Wed Aug 17 16:50:33 2005
@@ -0,0 +1,876 @@
+/*
+ *  Copyright (C) International Business Machines  Corp., 2005
+ *  Author(s): Judy Fischbach <jfisch@xxxxxxxxxx>
+ *             David Hendricks <dhendrix@xxxxxxxxxx>
+ *             Josh Triplett <josht@xxxxxxxxxx>
+ *    based on code from Anthony Liguori <aliguori@xxxxxxxxxx>
+ *
+ *  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; under version 2 of the License.
+ *
+ *  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <curses.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <xenstat.h>
+
+#define XENTOP_VERSION "1.0"
+
+#define XENTOP_DISCLAIMER \
+"Copyright (C) 2005  International Business Machines  Corp\n"\
+"This is free software; see the source for copying conditions.There is NO\n"\
+"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
+#define XENTOP_BUGSTO "Report bugs to <dsteklof@xxxxxxxxxx>.\n"
+
+#define _GNU_SOURCE
+#include <getopt.h>
+
+#if !defined(__GNUC__) && !defined(__GNUG__)
+#define __attribute__(arg) /* empty */
+#endif
+
+#define KEY_ESCAPE '\x1B'
+
+/*
+ * Function prototypes
+ */
+/* Utility functions */
+static void usage(const char *);
+static void version(void);
+static void cleanup(void);
+static void fail(const char *);
+static int current_row(void);
+static int lines(void);
+static void print(const char *, ...) __attribute__((format(printf,1,2)));
+static void attr_addstr(int attr, const char *str);
+static void set_delay(char *value);
+static void set_prompt(char *new_prompt, void (*func)(char *));
+static int handle_key(int);
+static int compare(unsigned long long, unsigned long long);
+static int compare_domains(xenstat_domain **, xenstat_domain **);
+static unsigned long long tot_net_bytes( xenstat_domain *, int);
+
+/* Field functions */
+static int compare_domid(xenstat_domain *domain1, xenstat_domain *domain2);
+static void print_domid(xenstat_domain *domain);
+static int compare_state(xenstat_domain *domain1, xenstat_domain *domain2);
+static void print_state(xenstat_domain *domain);
+static int compare_cpu(xenstat_domain *domain1, xenstat_domain *domain2);
+static void print_cpu(xenstat_domain *domain);
+static int compare_cpu_pct(xenstat_domain *domain1, xenstat_domain *domain2);
+static void print_cpu_pct(xenstat_domain *domain);
+static int compare_mem(xenstat_domain *domain1, xenstat_domain *domain2);
+static void print_mem(xenstat_domain *domain);
+static void print_mem_pct(xenstat_domain *domain);
+static int compare_maxmem(xenstat_domain *domain1, xenstat_domain *domain2);
+static void print_maxmem(xenstat_domain *domain);
+static void print_max_pct(xenstat_domain *domain);
+static int compare_vcpus(xenstat_domain *domain1, xenstat_domain *domain2);
+static void print_vcpus(xenstat_domain *domain);
+static int compare_nets(xenstat_domain *domain1, xenstat_domain *domain2);
+static void print_nets(xenstat_domain *domain);
+static int compare_net_tx(xenstat_domain *domain1, xenstat_domain *domain2);
+static void print_net_tx(xenstat_domain *domain);
+static int compare_net_rx(xenstat_domain *domain1, xenstat_domain *domain2);
+static void print_net_rx(xenstat_domain *domain);
+static int compare_ssid(xenstat_domain *domain1, xenstat_domain *domain2);
+static void print_ssid(xenstat_domain *domain);
+
+/* Section printing functions */
+static void do_summary(void);
+static void do_header(void);
+static void do_bottom_line(void);
+static void do_domain(xenstat_domain *);
+static void do_vcpu(xenstat_domain *);
+static void do_network(xenstat_domain *);
+static void top(void);
+
+/* Field types */
+typedef enum field_id {
+       FIELD_DOMID,
+       FIELD_STATE,
+       FIELD_CPU,
+       FIELD_CPU_PCT,
+       FIELD_MEM,
+       FIELD_MEM_PCT,
+       FIELD_MAXMEM,
+       FIELD_MAX_PCT,
+       FIELD_VCPUS,
+       FIELD_NETS,
+       FIELD_NET_TX,
+       FIELD_NET_RX,
+       FIELD_SSID
+} field_id;
+
+typedef struct field {
+       field_id num;
+       const char *header;
+       unsigned int default_width;
+       int (*compare)(xenstat_domain *domain1, xenstat_domain *domain2);
+       void (*print)(xenstat_domain *domain);
+} field;
+
+field fields[] = {
+       { FIELD_DOMID,   "DOMID",      5, compare_domid,   print_domid   },
+       { FIELD_STATE,   "STATE",      6, compare_state,   print_state   },
+       { FIELD_CPU,     "CPU(sec)",  10, compare_cpu,     print_cpu     },
+       { FIELD_CPU_PCT, "CPU(%)",     6, compare_cpu_pct, print_cpu_pct },
+       { FIELD_MEM,     "MEM(k)",    10, compare_mem,     print_mem     },
+       { FIELD_MEM_PCT, "MEM(%)",     6, compare_mem,     print_mem_pct },
+       { FIELD_MAXMEM,  "MAXMEM(k)", 10, compare_maxmem,  print_maxmem  },
+       { FIELD_MAX_PCT, "MAXMEM(%)",  9, compare_maxmem,  print_max_pct },
+       { FIELD_VCPUS,   "VCPUS",      5, compare_vcpus,   print_vcpus   },
+       { FIELD_NETS,    "NETS",       4, compare_nets,    print_nets    },
+       { FIELD_NET_TX,  "NETTX(k)",   8, compare_net_tx,  print_net_tx  },
+       { FIELD_NET_RX,  "NETRX(k)",   8, compare_net_rx,  print_net_rx  },
+       { FIELD_SSID,    "SSID",       4, compare_ssid,    print_ssid    }
+};
+
+const unsigned int NUM_FIELDS = sizeof(fields)/sizeof(field);
+
+/* Globals */
+struct timeval curtime, oldtime;
+xenstat_handle *xhandle = NULL;
+xenstat_node *prev_node = NULL;
+xenstat_node *cur_node = NULL;
+field_id sort_field = FIELD_DOMID;
+unsigned int first_domain_index = 0;
+unsigned int delay = 1;
+int show_vcpus = 0;
+int show_networks = 0;
+int repeat_header = 0;
+#define PROMPT_VAL_LEN 80
+char *prompt = NULL;
+char prompt_val[PROMPT_VAL_LEN];
+int prompt_val_len = 0;
+void (*prompt_complete_func)(char *);
+
+/*
+ * Function definitions
+ */
+
+/* Utility functions */
+
+/* Print usage message, using given program name */
+static void usage(const char *program)
+{
+       printf("Usage: %s [OPTION]\n"
+              "Displays ongoing information about xen vm resources \n\n"
+              "-h, --help           display this help and exit\n"
+              "-V, --version        output version information and exit\n"
+              "-d, --delay=SECONDS  seconds between updates (default 1)\n"
+              "-n, --networks       output vif network data\n"
+              "-r, --repeat-header  repeat table header before each domain\n"
+              "-v, --vcpus          output vcpu data\n"
+              "\n" XENTOP_BUGSTO,
+              program);
+       return;
+}
+
+/* Print program version information */
+static void version(void)
+{
+       printf("xentop " XENTOP_VERSION "\n"
+              "Written by Judy Fischbach, David Hendricks, Josh Triplett\n"
+              "\n" XENTOP_DISCLAIMER);
+}
+
+/* Clean up any open resources */
+static void cleanup(void)
+{
+       if(!isendwin())
+               endwin();
+       if(prev_node != NULL)
+               xenstat_free_node(prev_node);
+       if(cur_node != NULL)
+               xenstat_free_node(cur_node);
+       if(xhandle != NULL)
+               xenstat_uninit(xhandle);
+}
+
+/* Display the given message and gracefully exit */
+static void fail(const char *str)
+{
+       if(!isendwin())
+               endwin();
+       fprintf(stderr, str);
+       exit(1);
+}
+
+/* Return the row containing the cursor. */
+static int current_row(void)
+{
+       int y, x;
+       getyx(stdscr, y, x);
+       return y;
+}
+
+/* Return the number of lines on the screen. */
+static int lines(void)
+{
+       int y, x;
+       getmaxyx(stdscr, y, x);
+       return y;
+}
+
+/* printf-style print function which calls printw, but only if the cursor is
+ * not on the last line. */
+static void print(const char *fmt, ...)
+{
+       va_list args;
+
+       if(current_row() < lines()-1) {
+               va_start(args, fmt);
+               vw_printw(stdscr, fmt, args);
+               va_end(args);
+       }
+}
+
+/* Print a string with the given attributes set. */
+static void attr_addstr(int attr, const char *str)
+{
+       attron(attr);
+       addstr(str);
+       attroff(attr);
+}
+
+/* Handle setting the delay from the user-supplied value in prompt_val */
+static void set_delay(char *value)
+{
+       int new_delay;
+       new_delay = atoi(prompt_val);
+       if(new_delay > 0)
+               delay = new_delay;
+}
+
+/* Enable prompting mode with the given prompt string; call the given function
+ * when a value is available. */
+static void set_prompt(char *new_prompt, void (*func)(char *))
+{
+       prompt = new_prompt;
+       prompt_val[0] = '\0';
+       prompt_val_len = 0;
+       prompt_complete_func = func;
+}
+
+/* Handle user input, return 0 if the program should quit, or 1 if not */
+static int handle_key(int ch)
+{
+       if(prompt == NULL) {
+               /* Not prompting for input; handle interactive commands */
+               switch(ch) {
+               case 'n': case 'N':
+                       show_networks ^= 1;
+                       break;
+               case 'r': case 'R':
+                       repeat_header ^= 1;
+                       break;
+               case 's': case 'S':
+                       sort_field = (sort_field + 1) % NUM_FIELDS;
+                       break;
+               case 'v': case 'V':
+                       show_vcpus ^= 1;
+                       break;
+               case KEY_DOWN:
+                       first_domain_index++;
+                       break;
+               case KEY_UP:
+                       if(first_domain_index > 0)
+                               first_domain_index--;
+                       break;
+               case 'd': case 'D':
+                       set_prompt("Delay(sec)", set_delay);
+                       break;
+               case 'q': case 'Q': case KEY_ESCAPE:
+                       return 0;
+               }
+       } else {
+               /* Prompting for input; handle line editing */
+               switch(ch) {
+               case '\r':
+                       prompt_complete_func(prompt_val);
+                       set_prompt(NULL, NULL);
+                       break;
+               case KEY_ESCAPE:
+                       set_prompt(NULL, NULL);
+                       break;
+               case KEY_BACKSPACE:
+                       if(prompt_val_len > 0)
+                               prompt_val[--prompt_val_len] = '\0';
+               default:
+                       if((prompt_val_len+1) < PROMPT_VAL_LEN
+                          && isprint(ch)) {
+                               prompt_val[prompt_val_len++] = (char)ch;
+                               prompt_val[prompt_val_len] = '\0';
+                       }
+               }
+       }
+
+       return 1;
+}
+
+/* Compares two integers, returning -1,0,1 for <,=,> */
+static int compare(unsigned long long i1, unsigned long long i2)
+{
+       if(i1 < i2)
+               return -1;
+       if(i1 > i2)
+               return 1;
+       return 0;
+}
+
+/* Comparison function for use with qsort.  Compares two domains using the
+ * current sort field. */
+static int compare_domains(xenstat_domain **domain1, xenstat_domain **domain2)
+{
+       return fields[sort_field].compare(*domain1, *domain2);
+}
+
+/* Field functions */
+
+/* Compares domain ids of two domains, returning -1,0,1 for <,=,> */
+int compare_domid(xenstat_domain *domain1, xenstat_domain *domain2)
+{
+       return compare(xenstat_domain_id(domain1), xenstat_domain_id(domain2));
+}
+
+/* Prints domain identification number */
+void print_domid(xenstat_domain *domain)
+{
+       print("%5u", xenstat_domain_id(domain));
+}
+
+struct {
+       unsigned int (*get)(xenstat_domain *);
+       char ch;
+} state_funcs[] = {
+       { xenstat_domain_dying,    'd' },
+       { xenstat_domain_shutdown, 's' },
+       { xenstat_domain_blocked,  'b' },
+       { xenstat_domain_crashed,  'c' },
+       { xenstat_domain_paused,   'p' },
+       { xenstat_domain_running,  'r' }
+};
+const unsigned int NUM_STATES = sizeof(state_funcs)/sizeof(*state_funcs);
+
+/* Compare states of two domains, returning -1,0,1 for <,=,> */
+static int compare_state(xenstat_domain *domain1, xenstat_domain *domain2)
+{
+       unsigned int i, d1s, d2s;
+       for(i = 0; i < NUM_STATES; i++) {
+               d1s = state_funcs[i].get(domain1);
+               d2s = state_funcs[i].get(domain2);
+               if(d1s && !d2s)
+                       return -1;
+               if(d2s && !d1s)
+                       return 1;
+       }
+       return 0;
+}
+
+/* Prints domain state in abbreviated letter format */
+static void print_state(xenstat_domain *domain)
+{
+       unsigned int i;
+       for(i = 0; i < NUM_STATES; i++)
+               print("%c", state_funcs[i].get(domain) ? state_funcs[i].ch
+                                                      : '-');
+}
+
+/* Compares cpu usage of two domains, returning -1,0,1 for <,=,> */
+static int compare_cpu(xenstat_domain *domain1, xenstat_domain *domain2)
+{
+       return -compare(xenstat_domain_cpu_ns(domain1),
+                       xenstat_domain_cpu_ns(domain2));
+}
+
+/* Prints domain cpu usage in seconds */
+static void print_cpu(xenstat_domain *domain)
+{
+       print("%10llu", xenstat_domain_cpu_ns(domain)/1000000000);
+}
+
+/* Computes the CPU percentage used for a specified domain */
+static double get_cpu_pct(xenstat_domain *domain)
+{
+       xenstat_domain *old_domain;
+       double us_elapsed;
+
+       /* Can't calculate CPU percentage without a previous sample. */
+       if(prev_node == NULL)
+               return 0.0;
+
+       old_domain = xenstat_node_domain(prev_node, xenstat_domain_id(domain));
+       if(old_domain == NULL)
+               return 0.0;
+
+       /* Calculate the time elapsed in microseconds */
+       us_elapsed = ((curtime.tv_sec-oldtime.tv_sec)*1000000.0
+                     +(curtime.tv_usec - oldtime.tv_usec));
+
+       /* In the following, nanoseconds must be multiplied by 1000.0 to
+        * convert to microseconds, then divided by 100.0 to get a percentage,
+        * resulting in a multiplication by 10.0 */
+       return ((xenstat_domain_cpu_ns(domain)
+                -xenstat_domain_cpu_ns(old_domain))/10.0)/us_elapsed;
+}
+
+static int compare_cpu_pct(xenstat_domain *domain1, xenstat_domain *domain2)
+{
+       return -compare(get_cpu_pct(domain1), get_cpu_pct(domain2));
+}
+
+/* Prints cpu percentage statistic */
+static void print_cpu_pct(xenstat_domain *domain)
+{
+       print("%6.1f", get_cpu_pct(domain));
+}
+
+/* Compares current memory of two domains, returning -1,0,1 for <,=,> */
+static int compare_mem(xenstat_domain *domain1, xenstat_domain *domain2)
+{
+       return -compare(xenstat_domain_cur_mem(domain1),
+                       xenstat_domain_cur_mem(domain2));
+}
+
+/* Prints current memory statistic */
+static void print_mem(xenstat_domain *domain)
+{
+       print("%10llu", xenstat_domain_cur_mem(domain)/1024);
+}
+
+/* Prints memory percentage statistic, ratio of current domain memory to total
+ * node memory */
+static void print_mem_pct(xenstat_domain *domain)
+{
+       print("%6.1f", (double)xenstat_domain_cur_mem(domain) /
+                      (double)xenstat_node_tot_mem(cur_node) * 100);
+}
+
+/* Compares maximum memory of two domains, returning -1,0,1 for <,=,> */
+static int compare_maxmem(xenstat_domain *domain1, xenstat_domain *domain2)
+{
+       return -compare(xenstat_domain_max_mem(domain1),
+                       xenstat_domain_max_mem(domain2));
+}
+
+/* Prints maximum domain memory statistic in KB */
+static void print_maxmem(xenstat_domain *domain)
+{
+       unsigned long long max_mem = xenstat_domain_max_mem(domain);
+       if(max_mem == ((unsigned long long)-1))
+               print("%10s", "no limit");
+       else
+               print("%10llu", max_mem/1024);
+}
+
+/* Prints memory percentage statistic, ratio of current domain memory to total
+ * node memory */
+static void print_max_pct(xenstat_domain *domain)
+{
+       if (xenstat_domain_max_mem(domain) == (unsigned long long)-1)
+               print("%9s", "n/a");
+       else
+               print("%9.1f", (double)xenstat_domain_max_mem(domain) /
+                              (double)xenstat_node_tot_mem(cur_node) * 100);
+}
+
+/* Compares number of virtual CPUs of two domains, returning -1,0,1 for
+ * <,=,> */
+static int compare_vcpus(xenstat_domain *domain1, xenstat_domain *domain2)
+{
+       return -compare(xenstat_domain_num_vcpus(domain1),
+                       xenstat_domain_num_vcpus(domain2));
+}
+
+/* Prints number of virtual CPUs statistic */
+static void print_vcpus(xenstat_domain *domain)
+{
+       print("%5u", xenstat_domain_num_vcpus(domain));
+}
+
+/* Compares number of virtual networks of two domains, returning -1,0,1 for
+ * <,=,> */
+static int compare_nets(xenstat_domain *domain1, xenstat_domain *domain2)
+{
+       return -compare(xenstat_domain_num_networks(domain1),
+                       xenstat_domain_num_networks(domain2));
+}
+
+/* Prints number of virtual networks statistic */
+static void print_nets(xenstat_domain *domain)
+{
+       print("%4u", xenstat_domain_num_networks(domain));
+}
+
+/* Compares number of total network tx bytes of two domains, returning -1,0,1 
for
+ * <,=,> */
+static int compare_net_tx(xenstat_domain *domain1, xenstat_domain *domain2)
+{
+       return -compare(tot_net_bytes(domain1, FALSE),
+                       tot_net_bytes(domain2, FALSE));
+}
+
+/* Prints number of total network tx bytes statistic */
+static void print_net_tx(xenstat_domain *domain)
+{
+       print("%8llu", tot_net_bytes(domain, FALSE)/1024);
+}
+
+/* Compares number of total network rx bytes of two domains, returning -1,0,1 
for
+ * <,=,> */
+static int compare_net_rx(xenstat_domain *domain1, xenstat_domain *domain2)
+{
+       return -compare(tot_net_bytes(domain1, TRUE),
+                       tot_net_bytes(domain2, TRUE));
+}
+
+/* Prints number of total network rx bytes statistic */
+static void print_net_rx(xenstat_domain *domain)
+{
+       print("%8llu", tot_net_bytes(domain, TRUE)/1024);
+}
+
+/* Gets number of total network bytes statistic, if rx true, then rx bytes
+ * otherwise tx bytes
+ */
+static unsigned long long tot_net_bytes(xenstat_domain *domain, int rx_flag)
+{
+       int i = 0;
+       xenstat_network *network;
+       unsigned num_networks = 0;
+        unsigned long long total = 0;
+
+       /* How many networks? */
+       num_networks = xenstat_domain_num_networks(domain);
+
+       /* Dump information for each network */
+       for (i=0; i < num_networks; i++) {
+               /* Next get the network information */
+               network = xenstat_domain_network(domain,i);
+                if (rx_flag) 
+                       total += xenstat_network_rbytes(network);
+                else 
+                       total += xenstat_network_tbytes(network);
+       }
+        return (total);
+}
+
+/* Compares security id (ssid) of two domains, returning -1,0,1 for <,=,> */
+static int compare_ssid(xenstat_domain *domain1, xenstat_domain *domain2)
+{
+       return compare(xenstat_domain_ssid(domain1),
+                      xenstat_domain_ssid(domain2));
+}
+
+/* Prints ssid statistic */
+static void print_ssid(xenstat_domain *domain)
+{
+       print("%4u", xenstat_domain_ssid(domain));
+}
+
+/* Section printing functions */
+/* Prints the top summary, above the domain table */
+void do_summary(void)
+{
+#define TIME_STR_LEN 9
+       const char *TIME_STR_FORMAT = "%H:%M:%S";
+       char time_str[TIME_STR_LEN];
+       unsigned run = 0, block = 0, pause = 0,
+                crash = 0, dying = 0, shutdown = 0;
+       unsigned i, num_domains = 0;
+       unsigned long long used = 0;
+       xenstat_domain *domain;
+
+       /* Print program name, current time, and number of domains */
+       strftime(time_str, TIME_STR_LEN, TIME_STR_FORMAT,
+                localtime(&curtime.tv_sec));
+       num_domains = xenstat_node_num_domains(cur_node);
+       print("xentop - %s\n", time_str);
+
+       /* Tabulate what states domains are in for summary */
+       for (i=0; i < num_domains; i++) {
+               domain = xenstat_node_domain_by_index(cur_node,i);
+               if (xenstat_domain_running(domain)) run++;
+               else if (xenstat_domain_blocked(domain)) block++;
+               else if (xenstat_domain_paused(domain)) pause++;
+               else if (xenstat_domain_shutdown(domain)) shutdown++;
+               else if (xenstat_domain_crashed(domain)) crash++;
+               else if (xenstat_domain_dying(domain)) dying++;
+       }
+
+       print("%u domains: %u running, %u blocked, %u paused, "
+             "%u crashed, %u dying, %u shutdown \n",
+             num_domains, run, block, pause, crash, dying, shutdown);
+
+       used = xenstat_node_tot_mem(cur_node)-xenstat_node_free_mem(cur_node);
+
+       /* Dump node memory and cpu information */
+       print("Mem: %lluk total, %lluk used, %lluk free    "
+             "CPUs: %u @ %lluMHz\n",
+             xenstat_node_tot_mem(cur_node)/1024, used/1024,
+             xenstat_node_free_mem(cur_node)/1024,
+             xenstat_node_num_cpus(cur_node),
+             xenstat_node_cpu_hz(cur_node)/1000000);
+}
+
+/* Display the top header for the domain table */
+void do_header(void)
+{
+       field_id i;
+
+       /* Turn on REVERSE highlight attribute for headings */
+       attron(A_REVERSE);
+       for(i = 0; i < NUM_FIELDS; i++) {
+               if(i != 0)
+                       print(" ");
+               /* The BOLD attribute is turned on for the sort column */
+               if(i == sort_field)
+                       attron(A_BOLD);
+               print("%*s", fields[i].default_width, fields[i].header);
+               if(i == sort_field)
+                       attroff(A_BOLD);
+       }
+       attroff(A_REVERSE);
+       print("\n");
+}
+
+/* Displays bottom status line or current prompt */
+void do_bottom_line(void)
+{
+       move(lines()-1, 2);
+
+       if (prompt != NULL) {
+               printw("%s: %s", prompt, prompt_val);
+       } else {
+               addch(A_REVERSE | 'D'); addstr("elay  ");
+
+               /* network */
+               addch(A_REVERSE | 'N');
+               attr_addstr(show_networks ? COLOR_PAIR(1) : 0, "etworks");
+               addstr("  ");
+
+               /* vcpus */
+               addch(A_REVERSE | 'V');
+               attr_addstr(show_vcpus ? COLOR_PAIR(1) : 0, "CPUs");
+               addstr("  ");
+
+               /* repeat */
+               addch(A_REVERSE | 'R');
+               attr_addstr(repeat_header ? COLOR_PAIR(1) : 0, "epeat header");
+               addstr("  ");
+
+               /* sort order */
+               addch(A_REVERSE | 'S'); addstr("ort order  ");
+
+               addch(A_REVERSE | 'Q'); addstr("uit  ");
+       }
+}
+
+/* Prints Domain information */
+void do_domain(xenstat_domain *domain)
+{
+       unsigned int i;
+       for(i = 0; i < NUM_FIELDS; i++) {
+               if(i != 0)
+                       print(" ");
+               if(i == sort_field)
+                       attron(A_BOLD);
+               fields[i].print(domain);
+               if(i == sort_field)
+                       attroff(A_BOLD);
+       }
+       print("\n");
+}
+
+/* Output all vcpu information */
+void do_vcpu(xenstat_domain *domain)
+{
+       int i = 0;
+       unsigned num_vcpus = 0;
+       xenstat_vcpu *vcpu;
+
+       print("VCPUs(sec): ");
+
+       num_vcpus = xenstat_domain_num_vcpus(domain);
+
+       /* for all vcpus dump out values */
+       for (i=0; i< num_vcpus; i++) {
+               vcpu = xenstat_domain_vcpu(domain,i);
+
+               if (i != 0 && (i%5)==0)
+                       print("\n        ");
+               print(" %2u: %10llus", i, xenstat_vcpu_ns(vcpu)/1000000000);
+       }
+       print("\n");
+}
+
+/* Output all network information */
+void do_network(xenstat_domain *domain)
+{
+       int i = 0;
+       xenstat_network *network;
+       unsigned num_networks = 0;
+
+       /* How many networks? */
+       num_networks = xenstat_domain_num_networks(domain);
+
+       /* Dump information for each network */
+       for (i=0; i < num_networks; i++) {
+               /* Next get the network information */
+               network = xenstat_domain_network(domain,i);
+
+               print("Net%d RX: %8llubytes %8llupkts %8lluerr %8lludrop  ",
+                     i,
+                     xenstat_network_rbytes(network),
+                     xenstat_network_rpackets(network),
+                     xenstat_network_rerrs(network),
+                     xenstat_network_rdrop(network));
+
+               print("TX: %8llubytes %8llupkts %8lluerr %8lludrop\n",
+                     xenstat_network_tbytes(network),
+                     xenstat_network_tpackets(network),
+                     xenstat_network_terrs(network),
+                     xenstat_network_tdrop(network));
+       }
+}
+
+static void top(void)
+{
+       xenstat_domain **domains;
+       unsigned int i, num_domains = 0;
+
+       /* Now get the node information */
+       if (prev_node != NULL)
+               xenstat_free_node(prev_node);
+       prev_node = cur_node;
+       cur_node = xenstat_get_node(xhandle, XENSTAT_ALL);
+       if (cur_node == NULL)
+               fail("Failed to retrieve statistics from libxenstat\n");
+
+       /* dump summary top information */
+       do_summary();
+
+       /* Count the number of domains for which to report data */
+       num_domains = xenstat_node_num_domains(cur_node);
+
+       domains = malloc(num_domains*sizeof(xenstat_domain *));
+       if(domains == NULL)
+               fail("Failed to allocate memory\n");
+
+       for (i=0; i < num_domains; i++)
+               domains[i] = xenstat_node_domain_by_index(cur_node, i);
+
+       /* Sort */
+       qsort(domains, num_domains, sizeof(xenstat_domain *),
+             (int(*)(const void *, const void *))compare_domains);
+
+       if(first_domain_index >= num_domains)
+               first_domain_index = num_domains-1;
+
+       for (i = first_domain_index; i < num_domains; i++) {
+               if(current_row() == lines()-1)
+                       break;
+               if (i == first_domain_index || repeat_header)
+                       do_header();
+               do_domain(domains[i]);
+               if (show_vcpus)
+                       do_vcpu(domains[i]);
+               if (show_networks)
+                       do_network(domains[i]);
+       }
+
+       do_bottom_line();
+}
+
+int main(int argc, char **argv)
+{
+       int opt, optind = 0;
+       int ch = ERR;
+
+       struct option lopts[] = {
+               { "help",          no_argument,       NULL, 'h' },
+               { "version",       no_argument,       NULL, 'V' },
+               { "networks",      no_argument,       NULL, 'n' },
+               { "repeat-header", no_argument,       NULL, 'r' },
+               { "vcpus",         no_argument,       NULL, 'v' },
+               { "delay",         required_argument, NULL, 'd' },
+               { 0, 0, 0, 0 },
+       };
+       const char *sopts = "hVbnvd:";
+
+       if (atexit(cleanup) != 0)
+               fail("Failed to install cleanup handler.\n");
+
+       while ((opt = getopt_long(argc, argv, sopts, lopts, &optind)) != -1) {
+               switch (opt) {
+               case 'h':
+               case '?':
+               default:
+                       usage(argv[0]);
+                       exit(0);
+               case 'V':
+                       version();
+                       exit(0);
+               case 'n':
+                       show_networks = 1;
+                       break;
+               case 'r':
+                       repeat_header = 1;
+                       break;
+               case 'v':
+                       show_vcpus = 1;
+                       break;
+               case 'd':
+                       delay = atoi(optarg);
+                       break;
+               }
+       }
+
+       /* Get xenstat handle */
+       xhandle = xenstat_init();
+       if (xhandle == NULL)
+               fail("Failed to initialize xenstat library\n");
+
+       /* Begin curses stuff */
+       initscr();
+       start_color();
+       cbreak();
+       noecho();
+       nonl();
+       keypad(stdscr, TRUE);
+       halfdelay(5);
+       use_default_colors();
+       init_pair(1, -1, COLOR_YELLOW);
+
+       do {
+               gettimeofday(&curtime, NULL);
+               if(ch != ERR || (curtime.tv_sec - oldtime.tv_sec) >= delay) {
+                       clear();
+                       top();
+                       oldtime = curtime;
+                       refresh();
+               }
+               ch = getch();
+       } while (handle_key(ch));
+
+       /* Cleanup occurs in cleanup(), so no work to do here. */
+
+       return 0;
+}
diff -r b38cbc8f4d98 -r 173b918160e2 tools/xenstat/vm-top/Makefile
--- a/tools/xenstat/vm-top/Makefile     Mon Aug 15 18:25:33 2005
+++ /dev/null   Wed Aug 17 16:50:33 2005
@@ -1,43 +0,0 @@
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Josh Triplett <josht@xxxxxxxxxx>
-# 
-# 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; under version 2 of the License.
-#
-# 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.
-
-XEN_ROOT=../../..
-include $(XEN_ROOT)/tools/Rules.mk
-
-ifneq ($(XENSTAT_VM_TOP),y)
-all install vm-top:
-else
-
-INSTALL         = install
-INSTALL_PROG    = $(INSTALL) -m0755 -D
-INSTALL_DATA    = $(INSTALL) -m0644 -D
-
-prefix=/usr
-mandir=$(prefix)/share/man
-man1dir=$(mandir)/man1
-sbindir=$(prefix)/sbin
-
-CFLAGS += -DGCC_PRINTF -Wall -Werror -I$(XEN_LIBXENSTAT)
-LDFLAGS += -L$(XEN_LIBXENSTAT) -lxenstat -lcurses
-
-all: vm-top
-
-vm-top: vm-top.o
-
-install: vm-top vm-top.1
-       $(INSTALL_PROG) vm-top $(DESTDIR)$(sbindir)/vm-top
-       $(INSTALL_DATA) vm-top.1 $(DESTDIR)$(man1dir)/vm-top.1
-
-endif
-
-clean:
-       rm -f vm-top vm-top.o
diff -r b38cbc8f4d98 -r 173b918160e2 tools/xenstat/vm-top/TODO
--- a/tools/xenstat/vm-top/TODO Mon Aug 15 18:25:33 2005
+++ /dev/null   Wed Aug 17 16:50:33 2005
@@ -1,37 +0,0 @@
-Inefficient about how it handles newlines in vm-top 
-for proc/net/dev. Fix.
-
-Display error messages on the help line after bad input at a prompt.
-Fractional delay times
-Use prompting to search for domains
-Better line editing?
-
-* Make CPU in % more accurate
-* Domain total network TX % and RX %
-
-Like Top, f feature, field select of domain columns, toggle the display of
-field by typing the letter associated with field, if displayed it shows in
-bold and the letter is Capitalized along with a leading asterisk for the
-field, if not selected for display letter is lowercase, no leading asterisk
-and field is not bolded.
-
-Like Top, ordering of domain columns, o feature Capital letter shifts left,
-lowercase letter shifts right?
-
-Color
-Full management: pause, destroy, create domains
-
-Add support for Virtual Block Devices (vbd)
-
-To think about:
-Support for one than one node display (distributed monitoring 
-from any node of all other nodes in a cluster)
-Bottom line option (Switch node, Search node [tab completion?])
-
-Capture/Logging of resource information generated during a time interval.
--b batch mode dump snapshots to standard output (used with -n)
--n number of iterations to dump to standard output (unlimited if not specified)
--d monitor DomIDs as -dD1,-dD2 or -dD1,D2...
-   Monitor only domains with specified domain IDs
--m monitor nodeIDs as -mN1,-mN2 or -mN1,N2...
-   Monitor only domains with specified node IDs
diff -r b38cbc8f4d98 -r 173b918160e2 tools/xenstat/vm-top/vm-top.1
--- a/tools/xenstat/vm-top/vm-top.1     Mon Aug 15 18:25:33 2005
+++ /dev/null   Wed Aug 17 16:50:33 2005
@@ -1,88 +0,0 @@
-.\" Copyright (C) International Business Machines  Corp., 2005
-.\" Author: Josh Triplett <josht@xxxxxxxxxx>
-.\"
-.\" 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; under version 2 of the License.
-.\"
-.\" 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-.TH vm-top 1 "August 2005"
-.SH NAME
-\fBvm-top\fR \- displays real-time information about a Xen system and domains
-
-.SH SYNOPSIS
-.B vm-top
-[\fB\-h\fR]
-[\fB\-V\fR]
-[\fB\-d\fRSECONDS]
-[\fB\-n\fR]
-[\fB\-r\fR]
-[\fB\-v\fR]
-
-.SH DESCRIPTION
-\fBvm-top\fR displays information about the Xen system and domains, in a
-continually-updating manner.  Command-line options and interactive commands
-can change the detail and format of the information displayed by \fBvm-top\fR.
-
-.SH OPTIONS
-.TP
-\fB\-h\fR, \fB\-\-help\fR
-display help and exit
-.TP
-\fB\-V\fR, \fB\-\-version\fR
-output version information and exit
-.TP
-\fB\-d\fR, \fB\-\-delay\fR=\fISECONDS\fR
-seconds between updates (default 1)
-.TP
-\fB\-n\fR, \fB\-\-networks\fR
-output network information
-.TP
-\fB\-r\fR, \fB\-\-repeat\-header\fR
-repeat table header before each domain
-.TP
-\fB\-v\fR, \fB\-\-vcpus\fR
-output VCPU data
-
-.SH "INTERACTIVE COMMANDS"
-All interactive commands are case-insensitive.
-.TP
-.B D
-set delay between updates
-.TP
-.B N
-toggle display of network information
-.TP
-.B Q, Esc
-quit
-.TP
-.B R
-toggle table header before each domain
-.TP
-.B S
-cycle sort order
-.TP
-.B V
-toggle display of VCPU information
-.TP
-.B Arrows
-scroll domain display
-
-.SH AUTHORS
-Written by Judy Fischbach, David Hendricks, and Josh Triplett
-
-.SH "REPORTING BUGS"
-Report bugs to <dsteklof@xxxxxxxxxx>.
-
-.SH COPYRIGHT
-Copyright \(co 2005  International Business Machines  Corp
-.br
-This is free software; see the source for copying conditions.  There is NO
-warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
diff -r b38cbc8f4d98 -r 173b918160e2 tools/xenstat/vm-top/vm-top.c
--- a/tools/xenstat/vm-top/vm-top.c     Mon Aug 15 18:25:33 2005
+++ /dev/null   Wed Aug 17 16:50:33 2005
@@ -1,880 +0,0 @@
-/*
- *  Copyright (C) International Business Machines  Corp., 2005
- *  Author(s): Judy Fischbach <jfisch@xxxxxxxxxx>
- *             David Hendricks <dhendrix@xxxxxxxxxx>
- *             Josh Triplett <josht@xxxxxxxxxx>
- *    based on code from Anthony Liguori <aliguori@xxxxxxxxxx>
- *
- *  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; under version 2 of the License.
- *
- *  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#include <curses.h>
-#include <ctype.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/time.h>
-#include <time.h>
-#include <unistd.h>
-
-#include <xenstat.h>
-
-#define VM_TOP_VERSION "1.0"
-
-#define VM_TOP_DISCLAIMER \
-"Copyright (C) 2005  International Business Machines  Corp\n"\
-"This is free software; see the source for copying conditions.There is NO\n"\
-"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
-#define VM_TOP_BUGSTO "Report bugs to <dsteklof@xxxxxxxxxx>.\n"
-
-#define _GNU_SOURCE
-#include <getopt.h>
-
-#if !defined(__GNUC__) && !defined(__GNUG__)
-#define __attribute__(arg) /* empty */
-#endif
-
-#define KEY_ESCAPE '\x1B'
-
-/*
- * Function prototypes
- */
-/* Utility functions */
-static void usage(const char *);
-static void version(void);
-static void cleanup(void);
-static void fail(const char *);
-static int current_row(void);
-static int lines(void);
-static void print(const char *, ...) __attribute__((format(printf,1,2)));
-static void attr_addstr(int attr, const char *str);
-static void set_delay(char *value);
-static void set_prompt(char *new_prompt, void (*func)(char *));
-static int handle_key(int);
-static int compare(unsigned long long, unsigned long long);
-static int compare_domains(xenstat_domain **, xenstat_domain **);
-static unsigned long long tot_net_bytes( xenstat_domain *, int);
-
-/* Field functions */
-static int compare_domid(xenstat_domain *domain1, xenstat_domain *domain2);
-static void print_domid(xenstat_domain *domain);
-static int compare_state(xenstat_domain *domain1, xenstat_domain *domain2);
-static void print_state(xenstat_domain *domain);
-static int compare_cpu(xenstat_domain *domain1, xenstat_domain *domain2);
-static void print_cpu(xenstat_domain *domain);
-static int compare_cpu_pct(xenstat_domain *domain1, xenstat_domain *domain2);
-static void print_cpu_pct(xenstat_domain *domain);
-static int compare_mem(xenstat_domain *domain1, xenstat_domain *domain2);
-static void print_mem(xenstat_domain *domain);
-static void print_mem_pct(xenstat_domain *domain);
-static int compare_maxmem(xenstat_domain *domain1, xenstat_domain *domain2);
-static void print_maxmem(xenstat_domain *domain);
-static void print_max_pct(xenstat_domain *domain);
-static int compare_vcpus(xenstat_domain *domain1, xenstat_domain *domain2);
-static void print_vcpus(xenstat_domain *domain);
-static int compare_nets(xenstat_domain *domain1, xenstat_domain *domain2);
-static void print_nets(xenstat_domain *domain);
-static int compare_net_tx(xenstat_domain *domain1, xenstat_domain *domain2);
-static void print_net_tx(xenstat_domain *domain);
-static int compare_net_rx(xenstat_domain *domain1, xenstat_domain *domain2);
-static void print_net_rx(xenstat_domain *domain);
-static int compare_ssid(xenstat_domain *domain1, xenstat_domain *domain2);
-static void print_ssid(xenstat_domain *domain);
-
-/* Section printing functions */
-static void do_summary(void);
-static void do_header(void);
-static void do_bottom_line(void);
-static void do_domain(xenstat_domain *);
-static void do_vcpu(xenstat_domain *);
-static void do_network(xenstat_domain *);
-static void top(void);
-
-/* Field types */
-typedef enum field_id {
-       FIELD_DOMID,
-       FIELD_STATE,
-       FIELD_CPU,
-       FIELD_CPU_PCT,
-       FIELD_MEM,
-       FIELD_MEM_PCT,
-       FIELD_MAXMEM,
-       FIELD_MAX_PCT,
-       FIELD_VCPUS,
-       FIELD_NETS,
-       FIELD_NET_TX,
-       FIELD_NET_RX,
-       FIELD_SSID
-} field_id;
-
-typedef struct field {
-       field_id num;
-       const char *header;
-       unsigned int default_width;
-       int (*compare)(xenstat_domain *domain1, xenstat_domain *domain2);
-       void (*print)(xenstat_domain *domain);
-} field;
-
-field fields[] = {
-       { FIELD_DOMID,   "DOMID",      5, compare_domid,   print_domid   },
-       { FIELD_STATE,   "STATE",      6, compare_state,   print_state   },
-       { FIELD_CPU,     "CPU(sec)",  10, compare_cpu,     print_cpu     },
-       { FIELD_CPU_PCT, "CPU(%)",     6, compare_cpu_pct, print_cpu_pct },
-       { FIELD_MEM,     "MEM(k)",    10, compare_mem,     print_mem     },
-       { FIELD_MEM_PCT, "MEM(%)",     6, compare_mem,     print_mem_pct },
-       { FIELD_MAXMEM,  "MAXMEM(k)", 10, compare_maxmem,  print_maxmem  },
-       { FIELD_MAX_PCT, "MAXMEM(%)",  9, compare_maxmem,  print_max_pct },
-       { FIELD_VCPUS,   "VCPUS",      5, compare_vcpus,   print_vcpus   },
-       { FIELD_NETS,    "NETS",       4, compare_nets,    print_nets    },
-       { FIELD_NET_TX,  "NETTX(k)",   8, compare_net_tx,  print_net_tx  },
-       { FIELD_NET_RX,  "NETRX(k)",   8, compare_net_rx,  print_net_rx  },
-       { FIELD_SSID,    "SSID",       4, compare_ssid,    print_ssid    }
-};
-
-const unsigned int NUM_FIELDS = sizeof(fields)/sizeof(field);
-
-/* Globals */
-struct timeval curtime, oldtime;
-xenstat_handle *xhandle = NULL;
-xenstat_node *prev_node = NULL;
-xenstat_node *cur_node = NULL;
-field_id sort_field = FIELD_DOMID;
-unsigned int first_domain_index = 0;
-unsigned int delay = 1;
-int show_vcpus = 0;
-int show_networks = 0;
-int repeat_header = 0;
-#define PROMPT_VAL_LEN 80
-char *prompt = NULL;
-char prompt_val[PROMPT_VAL_LEN];
-int prompt_val_len = 0;
-void (*prompt_complete_func)(char *);
-
-/*
- * Function definitions
- */
-
-/* Utility functions */
-
-/* Print usage message, using given program name */
-static void usage(const char *program)
-{
-       printf("Usage: %s [OPTION]\n"
-              "Displays ongoing information about xen vm resources \n\n"
-              "-h, --help           display this help and exit\n"
-              "-V, --version        output version information and exit\n"
-              "-d, --delay=SECONDS  seconds between updates (default 1)\n"
-              "-n, --networks       output vif network data\n"
-              "-r, --repeat-header  repeat table header before each domain\n"
-              "-v, --vcpus          output vcpu data\n"
-              "\n" VM_TOP_BUGSTO,
-              program);
-       return;
-}
-
-/* Print program version information */
-static void version(void)
-{
-       printf("vm-top " VM_TOP_VERSION "\n"
-              "Written by Judy Fischbach, David Hendricks, Josh Triplett\n"
-              "\n" VM_TOP_DISCLAIMER);
-}
-
-/* Clean up any open resources */
-static void cleanup(void)
-{
-       if(!isendwin())
-               endwin();
-       if(prev_node != NULL)
-               xenstat_free_node(prev_node);
-       if(cur_node != NULL)
-               xenstat_free_node(cur_node);
-       if(xhandle != NULL)
-               xenstat_uninit(xhandle);
-}
-
-/* Display the given message and gracefully exit */
-static void fail(const char *str)
-{
-       if(!isendwin())
-               endwin();
-       fprintf(stderr, str);
-       exit(1);
-}
-
-/* Return the row containing the cursor. */
-static int current_row(void)
-{
-       int y, x;
-       getyx(stdscr, y, x);
-       return y;
-}
-
-/* Return the number of lines on the screen. */
-static int lines(void)
-{
-       int y, x;
-       getmaxyx(stdscr, y, x);
-       return y;
-}
-
-/* printf-style print function which calls printw, but only if the cursor is
- * not on the last line. */
-static void print(const char *fmt, ...)
-{
-       va_list args;
-
-       if(current_row() < lines()-1) {
-               va_start(args, fmt);
-               vw_printw(stdscr, fmt, args);
-               va_end(args);
-       }
-}
-
-/* Print a string with the given attributes set. */
-static void attr_addstr(int attr, const char *str)
-{
-       attron(attr);
-       addstr(str);
-       attroff(attr);
-}
-
-/* Handle setting the delay from the user-supplied value in prompt_val */
-static void set_delay(char *value)
-{
-       int new_delay;
-       new_delay = atoi(prompt_val);
-       if(new_delay > 0)
-               delay = new_delay;
-}
-
-/* Enable prompting mode with the given prompt string; call the given function
- * when a value is available. */
-static void set_prompt(char *new_prompt, void (*func)(char *))
-{
-       prompt = new_prompt;
-       prompt_val[0] = '\0';
-       prompt_val_len = 0;
-       prompt_complete_func = func;
-}
-
-/* Handle user input, return 0 if the program should quit, or 1 if not */
-static int handle_key(int ch)
-{
-       if(prompt == NULL) {
-               /* Not prompting for input; handle interactive commands */
-               switch(ch) {
-               case 'n': case 'N':
-                       show_networks ^= 1;
-                       break;
-               case 'r': case 'R':
-                       repeat_header ^= 1;
-                       break;
-               case 's': case 'S':
-                       sort_field = (sort_field + 1) % NUM_FIELDS;
-                       break;
-               case 'v': case 'V':
-                       show_vcpus ^= 1;
-                       break;
-               case KEY_DOWN:
-                       first_domain_index++;
-                       break;
-               case KEY_UP:
-                       if(first_domain_index > 0)
-                               first_domain_index--;
-                       break;
-               case 'd': case 'D':
-                       set_prompt("Delay(sec)", set_delay);
-                       break;
-               case 'q': case 'Q': case KEY_ESCAPE:
-                       return 0;
-               }
-       } else {
-               /* Prompting for input; handle line editing */
-               switch(ch) {
-               case '\r':
-                       prompt_complete_func(prompt_val);
-                       set_prompt(NULL, NULL);
-                       break;
-               case KEY_ESCAPE:
-                       set_prompt(NULL, NULL);
-                       break;
-               case KEY_BACKSPACE:
-                       if(prompt_val_len > 0)
-                               prompt_val[--prompt_val_len] = '\0';
-               default:
-                       if((prompt_val_len+1) < PROMPT_VAL_LEN
-                          && isprint(ch)) {
-                               prompt_val[prompt_val_len++] = (char)ch;
-                               prompt_val[prompt_val_len] = '\0';
-                       }
-               }
-       }
-
-       return 1;
-}
-
-/* Compares two integers, returning -1,0,1 for <,=,> */
-static int compare(unsigned long long i1, unsigned long long i2)
-{
-       if(i1 < i2)
-               return -1;
-       if(i1 > i2)
-               return 1;
-       return 0;
-}
-
-/* Comparison function for use with qsort.  Compares two domains using the
- * current sort field. */
-static int compare_domains(xenstat_domain **domain1, xenstat_domain **domain2)
-{
-       return fields[sort_field].compare(*domain1, *domain2);
-}
-
-/* Field functions */
-
-/* Compares domain ids of two domains, returning -1,0,1 for <,=,> */
-int compare_domid(xenstat_domain *domain1, xenstat_domain *domain2)
-{
-       return compare(xenstat_domain_id(domain1), xenstat_domain_id(domain2));
-}
-
-/* Prints domain identification number */
-void print_domid(xenstat_domain *domain)
-{
-       print("%5u", xenstat_domain_id(domain));
-}
-
-struct {
-       unsigned int (*get)(xenstat_domain *);
-       char ch;
-} state_funcs[] = {
-       { xenstat_domain_dying,    'd' },
-       { xenstat_domain_shutdown, 's' },
-       { xenstat_domain_blocked,  'b' },
-       { xenstat_domain_crashed,  'c' },
-       { xenstat_domain_paused,   'p' },
-       { xenstat_domain_running,  'r' }
-};
-const unsigned int NUM_STATES = sizeof(state_funcs)/sizeof(*state_funcs);
-
-/* Compare states of two domains, returning -1,0,1 for <,=,> */
-static int compare_state(xenstat_domain *domain1, xenstat_domain *domain2)
-{
-       unsigned int i, d1s, d2s;
-       for(i = 0; i < NUM_STATES; i++) {
-               d1s = state_funcs[i].get(domain1);
-               d2s = state_funcs[i].get(domain2);
-               if(d1s && !d2s)
-                       return -1;
-               if(d2s && !d1s)
-                       return 1;
-       }
-       return 0;
-}
-
-/* Prints domain state in abbreviated letter format */
-static void print_state(xenstat_domain *domain)
-{
-       unsigned int i;
-       for(i = 0; i < NUM_STATES; i++)
-               print("%c", state_funcs[i].get(domain) ? state_funcs[i].ch
-                                                      : '-');
-}
-
-/* Compares cpu usage of two domains, returning -1,0,1 for <,=,> */
-static int compare_cpu(xenstat_domain *domain1, xenstat_domain *domain2)
-{
-       return -compare(xenstat_domain_cpu_ns(domain1),
-                       xenstat_domain_cpu_ns(domain2));
-}
-
-/* Prints domain cpu usage in seconds */
-static void print_cpu(xenstat_domain *domain)
-{
-       print("%10llu", xenstat_domain_cpu_ns(domain)/1000000000);
-}
-
-/* Computes the CPU percentage used for a specified domain */
-static double get_cpu_pct(xenstat_domain *domain)
-{
-       xenstat_domain *old_domain;
-       double us_elapsed;
-
-       /* Can't calculate CPU percentage without a previous sample. */
-       if(prev_node == NULL)
-               return 0.0;
-
-       old_domain = xenstat_node_domain(prev_node, xenstat_domain_id(domain));
-       if(old_domain == NULL)
-               return 0.0;
-
-       /* Calculate the time elapsed in microseconds */
-       us_elapsed = ((curtime.tv_sec-oldtime.tv_sec)*1000000.0
-                     +(curtime.tv_usec - oldtime.tv_usec));
-
-       /* In the following, nanoseconds must be multiplied by 1000.0 to
-        * convert to microseconds, then divided by 100.0 to get a percentage,
-        * resulting in a multiplication by 10.0 */
-       return ((xenstat_domain_cpu_ns(domain)
-                -xenstat_domain_cpu_ns(old_domain))/10.0)/us_elapsed;
-}
-
-static int compare_cpu_pct(xenstat_domain *domain1, xenstat_domain *domain2)
-{
-       return -compare(get_cpu_pct(domain1), get_cpu_pct(domain2));
-}
-
-/* Prints cpu percentage statistic */
-static void print_cpu_pct(xenstat_domain *domain)
-{
-       print("%6.1f", get_cpu_pct(domain));
-}
-
-/* Compares current memory of two domains, returning -1,0,1 for <,=,> */
-static int compare_mem(xenstat_domain *domain1, xenstat_domain *domain2)
-{
-       return -compare(xenstat_domain_cur_mem(domain1),
-                       xenstat_domain_cur_mem(domain2));
-}
-
-/* Prints current memory statistic */
-static void print_mem(xenstat_domain *domain)
-{
-       print("%10llu", xenstat_domain_cur_mem(domain)/1024);
-}
-
-/* Prints memory percentage statistic, ratio of current domain memory to total
- * node memory */
-static void print_mem_pct(xenstat_domain *domain)
-{
-       print("%6.1f", (double)xenstat_domain_cur_mem(domain) /
-                      (double)xenstat_node_tot_mem(cur_node) * 100);
-}
-
-/* Compares maximum memory of two domains, returning -1,0,1 for <,=,> */
-static int compare_maxmem(xenstat_domain *domain1, xenstat_domain *domain2)
-{
-       return -compare(xenstat_domain_max_mem(domain1),
-                       xenstat_domain_max_mem(domain2));
-}
-
-/* Prints maximum domain memory statistic in KB */
-static void print_maxmem(xenstat_domain *domain)
-{
-       unsigned long long max_mem = xenstat_domain_max_mem(domain);
-       if(max_mem == ((unsigned long long)-1))
-               print("%10s", "no limit");
-       else
-               print("%10llu", max_mem/1024);
-}
-
-/* Prints memory percentage statistic, ratio of current domain memory to total
- * node memory */
-static void print_max_pct(xenstat_domain *domain)
-{
-       if (xenstat_domain_max_mem(domain) == (unsigned long long)-1)
-               print("%9s", "n/a");
-       else
-               print("%9.1f", (double)xenstat_domain_max_mem(domain) /
-                              (double)xenstat_node_tot_mem(cur_node) * 100);
-}
-
-/* Compares number of virtual CPUs of two domains, returning -1,0,1 for
- * <,=,> */
-static int compare_vcpus(xenstat_domain *domain1, xenstat_domain *domain2)
-{
-       return -compare(xenstat_domain_num_vcpus(domain1),
-                       xenstat_domain_num_vcpus(domain2));
-}
-
-/* Prints number of virtual CPUs statistic */
-static void print_vcpus(xenstat_domain *domain)
-{
-       print("%5u", xenstat_domain_num_vcpus(domain));
-}
-
-/* Compares number of virtual networks of two domains, returning -1,0,1 for
- * <,=,> */
-static int compare_nets(xenstat_domain *domain1, xenstat_domain *domain2)
-{
-       return -compare(xenstat_domain_num_networks(domain1),
-                       xenstat_domain_num_networks(domain2));
-}
-
-/* Prints number of virtual networks statistic */
-static void print_nets(xenstat_domain *domain)
-{
-       print("%4u", xenstat_domain_num_networks(domain));
-}
-
-/* Compares number of total network tx bytes of two domains, returning -1,0,1 
for
- * <,=,> */
-static int compare_net_tx(xenstat_domain *domain1, xenstat_domain *domain2)
-{
-       return -compare(tot_net_bytes(domain1, FALSE),
-                       tot_net_bytes(domain2, FALSE));
-}
-
-/* Prints number of total network tx bytes statistic */
-static void print_net_tx(xenstat_domain *domain)
-{
-       print("%8llu", tot_net_bytes(domain, FALSE)/1024);
-}
-
-/* Compares number of total network rx bytes of two domains, returning -1,0,1 
for
- * <,=,> */
-static int compare_net_rx(xenstat_domain *domain1, xenstat_domain *domain2)
-{
-       return -compare(tot_net_bytes(domain1, TRUE),
-                       tot_net_bytes(domain2, TRUE));
-}
-
-/* Prints number of total network rx bytes statistic */
-static void print_net_rx(xenstat_domain *domain)
-{
-       print("%8llu", tot_net_bytes(domain, TRUE)/1024);
-}
-
-/* Gets number of total network bytes statistic, if rx true, then rx bytes
- * otherwise tx bytes
- */
-static unsigned long long tot_net_bytes(xenstat_domain *domain, int rx_flag)
-{
-       int i = 0;
-       xenstat_network *network;
-       unsigned num_networks = 0;
-        unsigned long long total = 0;
-
-       /* How many networks? */
-       num_networks = xenstat_domain_num_networks(domain);
-
-       /* Dump information for each network */
-       for (i=0; i < num_networks; i++) {
-               /* Next get the network information */
-               network = xenstat_domain_network(domain,i);
-                if (rx_flag) 
-                       total += xenstat_network_rbytes(network);
-                else 
-                       total += xenstat_network_tbytes(network);
-       }
-        return (total);
-}
-
-/* Compares security id (ssid) of two domains, returning -1,0,1 for <,=,> */
-static int compare_ssid(xenstat_domain *domain1, xenstat_domain *domain2)
-{
-       return compare(xenstat_domain_ssid(domain1),
-                      xenstat_domain_ssid(domain2));
-}
-
-/* Prints ssid statistic */
-static void print_ssid(xenstat_domain *domain)
-{
-       print("%4u", xenstat_domain_ssid(domain));
-}
-
-/* Section printing functions */
-/* Prints three line summary header */
-void do_summary(void)
-{
-#define TIME_STR_LEN 9
-       const char *TIME_STR_FORMAT = "%H:%M:%S";
-       char time_str[TIME_STR_LEN];
-       unsigned run = 0, block = 0, pause = 0,
-                crash = 0, dying = 0, shutdown = 0;
-       unsigned i, num_domains = 0;
-       unsigned long long used = 0;
-       xenstat_domain *domain;
-
-       /* Print program name, current time, and number of domains */
-       strftime(time_str, TIME_STR_LEN, TIME_STR_FORMAT,
-                localtime(&curtime.tv_sec));
-       num_domains = xenstat_node_num_domains(cur_node);
-       print("vm-top - %s\n", time_str);
-
-       /* Tabulate what states domains are in for summary */
-       for (i=0; i < num_domains; i++) {
-               domain = xenstat_node_domain_by_index(cur_node,i);
-               if (xenstat_domain_running(domain)) run++;
-               else if (xenstat_domain_blocked(domain)) block++;
-               else if (xenstat_domain_paused(domain)) pause++;
-               else if (xenstat_domain_shutdown(domain)) shutdown++;
-               else if (xenstat_domain_crashed(domain)) crash++;
-               else if (xenstat_domain_dying(domain)) dying++;
-       }
-
-       print("%u domains: %u running, %u blocked, %u paused, "
-             "%u crashed, %u dying, %u shutdown \n",
-             num_domains, run, block, pause, crash, dying, shutdown);
-
-       used = xenstat_node_tot_mem(cur_node)-xenstat_node_free_mem(cur_node);
-
-       /* Dump node memory and cpu information */
-       print("Mem: %lluk total, %lluk used, %lluk free    "
-             "CPUs: %u @ %lluMHz\n",
-             xenstat_node_tot_mem(cur_node)/1024, used/1024,
-             xenstat_node_free_mem(cur_node)/1024,
-             xenstat_node_num_cpus(cur_node),
-             xenstat_node_cpu_hz(cur_node)/1000000);
-}
-
-/* Display top portion of vm-top */
-void do_header(void)
-{
-       field_id i;
-
-       /* Turn on REVERSE highlight attribute for headings */
-       attron(A_REVERSE);
-       for(i = 0; i < NUM_FIELDS; i++) {
-               if(i != 0)
-                       print(" ");
-               /* The BOLD attribute is turned on for the sort column */
-               if(i == sort_field)
-                       attron(A_BOLD);
-               print("%*s", fields[i].default_width, fields[i].header);
-               if(i == sort_field)
-                       attroff(A_BOLD);
-       }
-       attroff(A_REVERSE);
-       print("\n");
-}
-
-/* Displays bottom portion of vm-top, interactive options
- * N toggles network information display, V toggles CPU information
- * display, S toggles sort order of information (ascending/descending),
- * R toggles whether header is repeated for each domain
- */
-void do_bottom_line(void)
-{
-       move(lines()-1, 2);
-
-       if (prompt != NULL) {
-               printw("%s: %s", prompt, prompt_val);
-       } else {
-               addch(A_REVERSE | 'D'); addstr("elay  ");
-
-               /* network */
-               addch(A_REVERSE | 'N');
-               attr_addstr(show_networks ? COLOR_PAIR(1) : 0, "etworks");
-               addstr("  ");
-
-               /* vcpus */
-               addch(A_REVERSE | 'V');
-               attr_addstr(show_vcpus ? COLOR_PAIR(1) : 0, "CPUs");
-               addstr("  ");
-
-               /* repeat */
-               addch(A_REVERSE | 'R');
-               attr_addstr(repeat_header ? COLOR_PAIR(1) : 0, "epeat header");
-               addstr("  ");
-
-               /* sort order */
-               addch(A_REVERSE | 'S'); addstr("ort order  ");
-
-               addch(A_REVERSE | 'Q'); addstr("uit  ");
-       }
-}
-
-/* Prints Domain information */
-void do_domain(xenstat_domain *domain)
-{
-       unsigned int i;
-       for(i = 0; i < NUM_FIELDS; i++) {
-               if(i != 0)
-                       print(" ");
-               if(i == sort_field)
-                       attron(A_BOLD);
-               fields[i].print(domain);
-               if(i == sort_field)
-                       attroff(A_BOLD);
-       }
-       print("\n");
-}
-
-/* Output all vcpu information */
-void do_vcpu(xenstat_domain *domain)
-{
-       int i = 0;
-       unsigned num_vcpus = 0;
-       xenstat_vcpu *vcpu;
-
-       print("VCPUs(sec): ");
-
-       num_vcpus = xenstat_domain_num_vcpus(domain);
-
-       /* for all vcpus dump out values */
-       for (i=0; i< num_vcpus; i++) {
-               vcpu = xenstat_domain_vcpu(domain,i);
-
-               if (i != 0 && (i%5)==0)
-                       print("\n        ");
-               print(" %2u: %10llus", i, xenstat_vcpu_ns(vcpu)/1000000000);
-       }
-       print("\n");
-}
-
-/* Output all network information */
-void do_network(xenstat_domain *domain)
-{
-       int i = 0;
-       xenstat_network *network;
-       unsigned num_networks = 0;
-
-       /* How many networks? */
-       num_networks = xenstat_domain_num_networks(domain);
-
-       /* Dump information for each network */
-       for (i=0; i < num_networks; i++) {
-               /* Next get the network information */
-               network = xenstat_domain_network(domain,i);
-
-               print("Net%d RX: %8llubytes %8llupkts %8lluerr %8lludrop  ",
-                     i,
-                     xenstat_network_rbytes(network),
-                     xenstat_network_rpackets(network),
-                     xenstat_network_rerrs(network),
-                     xenstat_network_rdrop(network));
-
-               print("TX: %8llubytes %8llupkts %8lluerr %8lludrop\n",
-                     xenstat_network_tbytes(network),
-                     xenstat_network_tpackets(network),
-                     xenstat_network_terrs(network),
-                     xenstat_network_tdrop(network));
-       }
-}
-
-static void top(void)
-{
-       xenstat_domain **domains;
-       unsigned int i, num_domains = 0;
-
-       /* Now get the node information */
-       if (prev_node != NULL)
-               xenstat_free_node(prev_node);
-       prev_node = cur_node;
-       cur_node = xenstat_get_node(xhandle, XENSTAT_ALL);
-       if (cur_node == NULL)
-               fail("Failed to retrieve statistics from libxenstat\n");
-
-       /* dump summary top information */
-       do_summary();
-
-       /* Count the number of domains for which to report data */
-       num_domains = xenstat_node_num_domains(cur_node);
-
-       domains = malloc(num_domains*sizeof(xenstat_domain *));
-       if(domains == NULL)
-               fail("Failed to allocate memory\n");
-
-       for (i=0; i < num_domains; i++)
-               domains[i] = xenstat_node_domain_by_index(cur_node, i);
-
-       /* Sort */
-       qsort(domains, num_domains, sizeof(xenstat_domain *),
-             (int(*)(const void *, const void *))compare_domains);
-
-       if(first_domain_index >= num_domains)
-               first_domain_index = num_domains-1;
-
-       for (i = first_domain_index; i < num_domains; i++) {
-               if(current_row() == lines()-1)
-                       break;
-               if (i == first_domain_index || repeat_header)
-                       do_header();
-               do_domain(domains[i]);
-               if (show_vcpus)
-                       do_vcpu(domains[i]);
-               if (show_networks)
-                       do_network(domains[i]);
-       }
-
-       do_bottom_line();
-}
-
-int main(int argc, char **argv)
-{
-       int opt, optind = 0;
-       int ch = ERR;
-
-       struct option lopts[] = {
-               { "help",          no_argument,       NULL, 'h' },
-               { "version",       no_argument,       NULL, 'V' },
-               { "networks",      no_argument,       NULL, 'n' },
-               { "repeat-header", no_argument,       NULL, 'r' },
-               { "vcpus",         no_argument,       NULL, 'v' },
-               { "delay",         required_argument, NULL, 'd' },
-               { 0, 0, 0, 0 },
-       };
-       const char *sopts = "hVbnvd:";
-
-       if (atexit(cleanup) != 0)
-               fail("Failed to install cleanup handler.\n");
-
-       while ((opt = getopt_long(argc, argv, sopts, lopts, &optind)) != -1) {
-               switch (opt) {
-               case 'h':
-               case '?':
-               default:
-                       usage(argv[0]);
-                       exit(0);
-               case 'V':
-                       version();
-                       exit(0);
-               case 'n':
-                       show_networks = 1;
-                       break;
-               case 'r':
-                       repeat_header = 1;
-                       break;
-               case 'v':
-                       show_vcpus = 1;
-                       break;
-               case 'd':
-                       delay = atoi(optarg);
-                       break;
-               }
-       }
-
-       /* Get xenstat handle */
-       xhandle = xenstat_init();
-       if (xhandle == NULL)
-               fail("Failed to initialize xenstat library\n");
-
-       /* Begin curses stuff */
-       initscr();
-       start_color();
-       cbreak();
-       noecho();
-       nonl();
-       keypad(stdscr, TRUE);
-       halfdelay(5);
-       use_default_colors();
-       init_pair(1, -1, COLOR_YELLOW);
-
-       do {
-               gettimeofday(&curtime, NULL);
-               if(ch != ERR || (curtime.tv_sec - oldtime.tv_sec) >= delay) {
-                       clear();
-                       top();
-                       oldtime = curtime;
-                       refresh();
-               }
-               ch = getch();
-       } while (handle_key(ch));
-
-       /* Cleanup occurs in cleanup(), so no work to do here. */
-
-       return 0;
-}

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] Rename vm-top to xentop. Make "xm top" invoke xentop. Make libxenstat a static library, and do not install it., Xen patchbot -unstable <=