# 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
|