ia64/xen-unstable

changeset 6337:173b918160e2

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@us.ibm.com
# 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.
author josht@us.ibm.com
date Wed Aug 17 16:50:33 2005 +0000 (2005-08-17)
parents b38cbc8f4d98
children 59a6a0350158
files Config.mk tools/python/xen/xm/main.py tools/xenstat/Makefile tools/xenstat/libxenstat/Makefile tools/xenstat/xentop/Makefile tools/xenstat/xentop/TODO tools/xenstat/xentop/xentop.1 tools/xenstat/xentop/xentop.c
line diff
     1.1 --- a/Config.mk	Mon Aug 15 18:25:33 2005 +0000
     1.2 +++ b/Config.mk	Wed Aug 17 16:50:33 2005 +0000
     1.3 @@ -14,6 +14,7 @@ LD         = $(CROSS_COMPILE)ld
     1.4  CC         = $(CROSS_COMPILE)gcc
     1.5  CPP        = $(CROSS_COMPILE)gcc -E
     1.6  AR         = $(CROSS_COMPILE)ar
     1.7 +RANLIB     = $(CROSS_COMPILE)ranlib
     1.8  NM         = $(CROSS_COMPILE)nm
     1.9  STRIP      = $(CROSS_COMPILE)strip
    1.10  OBJCOPY    = $(CROSS_COMPILE)objcopy
    1.11 @@ -37,6 +38,4 @@ CFLAGS += $(foreach i, $(EXTRA_INCLUDES)
    1.12  KERNEL_REPO = http://www.kernel.org
    1.13  
    1.14  # Optional components
    1.15 -XENSTAT_PERL_BINDINGS   ?= n
    1.16 -XENSTAT_PYTHON_BINDINGS ?= y
    1.17 -XENSTAT_VM_TOP          ?= y
    1.18 +XENSTAT_XENTOP ?= y
     2.1 --- a/tools/python/xen/xm/main.py	Mon Aug 15 18:25:33 2005 +0000
     2.2 +++ b/tools/python/xen/xm/main.py	Wed Aug 17 16:50:33 2005 +0000
     2.3 @@ -49,6 +49,7 @@ xm common subcommands:
     2.4      restore <File>          create a domain from a saved state file
     2.5      save <DomId> <File>     save domain state (and config) to file
     2.6      shutdown <DomId>        shutdown a domain
     2.7 +    top                     monitor system and domains in real-time
     2.8      unpause <DomId>         unpause a paused domain
     2.9  
    2.10  For a complete list of subcommands run 'xm help --long'
    2.11 @@ -87,6 +88,7 @@ xm full list of subcommands:
    2.12      dmesg   [--clear]         read or clear Xen's message buffer
    2.13      info                      get information about the xen host
    2.14      log                       print the xend log
    2.15 +    top                       monitor system and domains in real-time
    2.16  
    2.17    Scheduler Commands:
    2.18      bvt <options>             set BVT scheduler parameters
    2.19 @@ -452,6 +454,9 @@ def xm_console(args):
    2.20      os.execvp('/usr/libexec/xen/xenconsole', cmd.split())
    2.21      console = sxp.child(info, "console")
    2.22  
    2.23 +def xm_top(args):
    2.24 +    os.execv('/usr/sbin/xentop', ['/usr/sbin/xentop'])
    2.25 +
    2.26  def xm_dmesg(args):
    2.27      
    2.28      gopts = Opts(use="""[-c|--clear]
    2.29 @@ -540,6 +545,8 @@ def xm_block_destroy(args):
    2.30  commands = {
    2.31      # console commands
    2.32      "console": xm_console,
    2.33 +    # xenstat commands
    2.34 +    "top": xm_top,
    2.35      # domain commands
    2.36      "domid": xm_domid,
    2.37      "domname": xm_domname,
     3.1 --- a/tools/xenstat/Makefile	Mon Aug 15 18:25:33 2005 +0000
     3.2 +++ b/tools/xenstat/Makefile	Wed Aug 17 16:50:33 2005 +0000
     3.3 @@ -3,7 +3,7 @@ include $(XEN_ROOT)/tools/Rules.mk
     3.4  
     3.5  SUBDIRS :=
     3.6  SUBDIRS += libxenstat
     3.7 -SUBDIRS += vm-top
     3.8 +SUBDIRS += xentop
     3.9  
    3.10  .PHONY: all install clean
    3.11  
     4.1 --- a/tools/xenstat/libxenstat/Makefile	Mon Aug 15 18:25:33 2005 +0000
     4.2 +++ b/tools/xenstat/libxenstat/Makefile	Wed Aug 17 16:50:33 2005 +0000
     4.3 @@ -30,8 +30,9 @@ MAKE_LINK=ln -sf
     4.4  MAJOR=0
     4.5  MINOR=0
     4.6  
     4.7 -LIB=src/libxenstat.so.$(MAJOR).$(MINOR)
     4.8 -LINKS=src/libxenstat.so.$(MAJOR) src/libxenstat.so
     4.9 +LIB=src/libxenstat.a
    4.10 +SHLIB=src/libxenstat.so.$(MAJOR).$(MINOR)
    4.11 +SHLIB_LINKS=src/libxenstat.so.$(MAJOR) src/libxenstat.so
    4.12  OBJECTS=src/xenstat.o src/xen-interface.o
    4.13  SONAME_FLAGS=-Wl,-soname -Wl,libxenstat.so.$(MAJOR)
    4.14  
    4.15 @@ -42,9 +43,13 @@ CFLAGS+=-I$(XEN_ROOT)/xen/include/public
    4.16  CFLAGS+=-I$(LINUX_ROOT)/include/asm-xen/linux-public/
    4.17  LDFLAGS+=-Lsrc
    4.18  
    4.19 -all: $(LIB) $(LINKS)
    4.20 +all: $(LIB)
    4.21  
    4.22  $(LIB): $(OBJECTS)
    4.23 +	$(AR) rc $@ $^
    4.24 +	$(RANLIB) $@
    4.25 +
    4.26 +$(SHLIB): $(OBJECTS)
    4.27  	$(CC) $(LDFLAGS) $(SONAME_FLAGS) -shared -o $@ $(OBJECTS)
    4.28  
    4.29  src/xenstat.o: src/xenstat.c src/xenstat.h src/xen-interface.h
    4.30 @@ -59,15 +64,17 @@ src/libxenstat.so.$(MAJOR): $(LIB)
    4.31  src/libxenstat.so: src/libxenstat.so.$(MAJOR)
    4.32  	$(MAKE_LINK) $(<F) $@
    4.33  
    4.34 -install: all
    4.35 -	$(INSTALL_DATA) src/xenstat.h $(DESTDIR)$(includedir)/xenstat.h
    4.36 -	$(INSTALL_PROG) $(LIB) \
    4.37 -	                $(DESTDIR)$(libdir)/libxenstat.so.$(MAJOR).$(MINOR)
    4.38 -	$(MAKE_LINK) libxenstat.so.$(MAJOR).$(MINOR) \
    4.39 -	             $(DESTDIR)$(libdir)/libxenstat.so.$(MAJOR)
    4.40 -	$(MAKE_LINK) libxenstat.so.$(MAJOR) \
    4.41 -	             $(DESTDIR)$(libdir)/libxenstat.so
    4.42 -	-$(LDCONFIG)
    4.43 +install:
    4.44 +#install: all
    4.45 +#	$(INSTALL_DATA) src/xenstat.h $(DESTDIR)$(includedir)/xenstat.h
    4.46 +#	$(INSTALL_PROG) $(LIB) $(DESTDIR)$(libdir)/libxenstat.a
    4.47 +#	$(INSTALL_PROG) $(SHLIB) \
    4.48 +#	                $(DESTDIR)$(libdir)/libxenstat.so.$(MAJOR).$(MINOR)
    4.49 +#	$(MAKE_LINK) libxenstat.so.$(MAJOR).$(MINOR) \
    4.50 +#	             $(DESTDIR)$(libdir)/libxenstat.so.$(MAJOR)
    4.51 +#	$(MAKE_LINK) libxenstat.so.$(MAJOR) \
    4.52 +#	             $(DESTDIR)$(libdir)/libxenstat.so
    4.53 +#	-$(LDCONFIG)
    4.54  
    4.55  PYLIB=bindings/swig/python/_xenstat.so
    4.56  PYMOD=bindings/swig/python/xenstat.py
    4.57 @@ -84,7 +91,7 @@ all-bindings: perl-bindings python-bindi
    4.58  # The install-bindings target installs all the language bindings
    4.59  install-bindings: install-perl-bindings install-python-bindings
    4.60  
    4.61 -$(BINDINGS): $(LIB) $(LINKS) src/xenstat.h
    4.62 +$(BINDINGS): $(SHLIB) $(SHLIB_LINKS) src/xenstat.h
    4.63  
    4.64  SWIG_FLAGS=-module xenstat -Isrc
    4.65  
    4.66 @@ -131,4 +138,5 @@ install: install-perl-bindings
    4.67  endif
    4.68  
    4.69  clean:
    4.70 -	rm -f $(LIB) $(OBJECTS) $(LINKS) $(BINDINGS) $(BINDINGSRC)
    4.71 +	rm -f $(LIB) $(SHLIB) $(SHLIB_LINKS) $(OBJECTS) \
    4.72 +	      $(BINDINGS) $(BINDINGSRC)
     5.1 --- a/tools/xenstat/vm-top/Makefile	Mon Aug 15 18:25:33 2005 +0000
     5.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.3 @@ -1,43 +0,0 @@
     5.4 -# Copyright (C) International Business Machines Corp., 2005
     5.5 -# Author: Josh Triplett <josht@us.ibm.com>
     5.6 -# 
     5.7 -# This program is free software; you can redistribute it and/or modify
     5.8 -# it under the terms of the GNU General Public License as published by
     5.9 -# the Free Software Foundation; under version 2 of the License.
    5.10 -#
    5.11 -# This program is distributed in the hope that it will be useful,
    5.12 -# but WITHOUT ANY WARRANTY; without even the implied warranty of
    5.13 -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    5.14 -# GNU General Public License for more details.
    5.15 -
    5.16 -XEN_ROOT=../../..
    5.17 -include $(XEN_ROOT)/tools/Rules.mk
    5.18 -
    5.19 -ifneq ($(XENSTAT_VM_TOP),y)
    5.20 -all install vm-top:
    5.21 -else
    5.22 -
    5.23 -INSTALL         = install
    5.24 -INSTALL_PROG    = $(INSTALL) -m0755 -D
    5.25 -INSTALL_DATA    = $(INSTALL) -m0644 -D
    5.26 -
    5.27 -prefix=/usr
    5.28 -mandir=$(prefix)/share/man
    5.29 -man1dir=$(mandir)/man1
    5.30 -sbindir=$(prefix)/sbin
    5.31 -
    5.32 -CFLAGS += -DGCC_PRINTF -Wall -Werror -I$(XEN_LIBXENSTAT)
    5.33 -LDFLAGS += -L$(XEN_LIBXENSTAT) -lxenstat -lcurses
    5.34 -
    5.35 -all: vm-top
    5.36 -
    5.37 -vm-top: vm-top.o
    5.38 -
    5.39 -install: vm-top vm-top.1
    5.40 -	$(INSTALL_PROG) vm-top $(DESTDIR)$(sbindir)/vm-top
    5.41 -	$(INSTALL_DATA) vm-top.1 $(DESTDIR)$(man1dir)/vm-top.1
    5.42 -
    5.43 -endif
    5.44 -
    5.45 -clean:
    5.46 -	rm -f vm-top vm-top.o
     6.1 --- a/tools/xenstat/vm-top/TODO	Mon Aug 15 18:25:33 2005 +0000
     6.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.3 @@ -1,37 +0,0 @@
     6.4 -Inefficient about how it handles newlines in vm-top 
     6.5 -for proc/net/dev. Fix.
     6.6 -
     6.7 -Display error messages on the help line after bad input at a prompt.
     6.8 -Fractional delay times
     6.9 -Use prompting to search for domains
    6.10 -Better line editing?
    6.11 -
    6.12 -* Make CPU in % more accurate
    6.13 -* Domain total network TX % and RX %
    6.14 -
    6.15 -Like Top, f feature, field select of domain columns, toggle the display of
    6.16 -field by typing the letter associated with field, if displayed it shows in
    6.17 -bold and the letter is Capitalized along with a leading asterisk for the
    6.18 -field, if not selected for display letter is lowercase, no leading asterisk
    6.19 -and field is not bolded.
    6.20 -
    6.21 -Like Top, ordering of domain columns, o feature Capital letter shifts left,
    6.22 -lowercase letter shifts right?
    6.23 -
    6.24 -Color
    6.25 -Full management: pause, destroy, create domains
    6.26 -
    6.27 -Add support for Virtual Block Devices (vbd)
    6.28 -
    6.29 -To think about:
    6.30 -Support for one than one node display (distributed monitoring 
    6.31 -from any node of all other nodes in a cluster)
    6.32 -Bottom line option (Switch node, Search node [tab completion?])
    6.33 -
    6.34 -Capture/Logging of resource information generated during a time interval.
    6.35 --b batch mode dump snapshots to standard output (used with -n)
    6.36 --n number of iterations to dump to standard output (unlimited if not specified)
    6.37 --d monitor DomIDs as -dD1,-dD2 or -dD1,D2...
    6.38 -   Monitor only domains with specified domain IDs
    6.39 --m monitor nodeIDs as -mN1,-mN2 or -mN1,N2...
    6.40 -   Monitor only domains with specified node IDs
     7.1 --- a/tools/xenstat/vm-top/vm-top.1	Mon Aug 15 18:25:33 2005 +0000
     7.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.3 @@ -1,88 +0,0 @@
     7.4 -.\" Copyright (C) International Business Machines  Corp., 2005
     7.5 -.\" Author: Josh Triplett <josht@us.ibm.com>
     7.6 -.\"
     7.7 -.\" This program is free software; you can redistribute it and/or modify
     7.8 -.\" it under the terms of the GNU General Public License as published by
     7.9 -.\" the Free Software Foundation; under version 2 of the License.
    7.10 -.\"
    7.11 -.\" This program is distributed in the hope that it will be useful,
    7.12 -.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
    7.13 -.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    7.14 -.\" GNU General Public License for more details.
    7.15 -.\"
    7.16 -.\" You should have received a copy of the GNU General Public License
    7.17 -.\" along with this program; if not, write to the Free Software
    7.18 -.\" Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    7.19 -.TH vm-top 1 "August 2005"
    7.20 -.SH NAME
    7.21 -\fBvm-top\fR \- displays real-time information about a Xen system and domains
    7.22 -
    7.23 -.SH SYNOPSIS
    7.24 -.B vm-top
    7.25 -[\fB\-h\fR]
    7.26 -[\fB\-V\fR]
    7.27 -[\fB\-d\fRSECONDS]
    7.28 -[\fB\-n\fR]
    7.29 -[\fB\-r\fR]
    7.30 -[\fB\-v\fR]
    7.31 -
    7.32 -.SH DESCRIPTION
    7.33 -\fBvm-top\fR displays information about the Xen system and domains, in a
    7.34 -continually-updating manner.  Command-line options and interactive commands
    7.35 -can change the detail and format of the information displayed by \fBvm-top\fR.
    7.36 -
    7.37 -.SH OPTIONS
    7.38 -.TP
    7.39 -\fB\-h\fR, \fB\-\-help\fR
    7.40 -display help and exit
    7.41 -.TP
    7.42 -\fB\-V\fR, \fB\-\-version\fR
    7.43 -output version information and exit
    7.44 -.TP
    7.45 -\fB\-d\fR, \fB\-\-delay\fR=\fISECONDS\fR
    7.46 -seconds between updates (default 1)
    7.47 -.TP
    7.48 -\fB\-n\fR, \fB\-\-networks\fR
    7.49 -output network information
    7.50 -.TP
    7.51 -\fB\-r\fR, \fB\-\-repeat\-header\fR
    7.52 -repeat table header before each domain
    7.53 -.TP
    7.54 -\fB\-v\fR, \fB\-\-vcpus\fR
    7.55 -output VCPU data
    7.56 -
    7.57 -.SH "INTERACTIVE COMMANDS"
    7.58 -All interactive commands are case-insensitive.
    7.59 -.TP
    7.60 -.B D
    7.61 -set delay between updates
    7.62 -.TP
    7.63 -.B N
    7.64 -toggle display of network information
    7.65 -.TP
    7.66 -.B Q, Esc
    7.67 -quit
    7.68 -.TP
    7.69 -.B R
    7.70 -toggle table header before each domain
    7.71 -.TP
    7.72 -.B S
    7.73 -cycle sort order
    7.74 -.TP
    7.75 -.B V
    7.76 -toggle display of VCPU information
    7.77 -.TP
    7.78 -.B Arrows
    7.79 -scroll domain display
    7.80 -
    7.81 -.SH AUTHORS
    7.82 -Written by Judy Fischbach, David Hendricks, and Josh Triplett
    7.83 -
    7.84 -.SH "REPORTING BUGS"
    7.85 -Report bugs to <dsteklof@us.ibm.com>.
    7.86 -
    7.87 -.SH COPYRIGHT
    7.88 -Copyright \(co 2005  International Business Machines  Corp
    7.89 -.br
    7.90 -This is free software; see the source for copying conditions.  There is NO
    7.91 -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     8.1 --- a/tools/xenstat/vm-top/vm-top.c	Mon Aug 15 18:25:33 2005 +0000
     8.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.3 @@ -1,880 +0,0 @@
     8.4 -/*
     8.5 - *  Copyright (C) International Business Machines  Corp., 2005
     8.6 - *  Author(s): Judy Fischbach <jfisch@us.ibm.com>
     8.7 - *             David Hendricks <dhendrix@us.ibm.com>
     8.8 - *             Josh Triplett <josht@us.ibm.com>
     8.9 - *    based on code from Anthony Liguori <aliguori@us.ibm.com>
    8.10 - *
    8.11 - *  This program is free software; you can redistribute it and/or modify
    8.12 - *  it under the terms of the GNU General Public License as published by
    8.13 - *  the Free Software Foundation; under version 2 of the License.
    8.14 - *
    8.15 - *  This program is distributed in the hope that it will be useful,
    8.16 - *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    8.17 - *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    8.18 - *  GNU General Public License for more details.
    8.19 - *
    8.20 - *  You should have received a copy of the GNU General Public License
    8.21 - *  along with this program; if not, write to the Free Software
    8.22 - *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    8.23 - */
    8.24 -#include <curses.h>
    8.25 -#include <ctype.h>
    8.26 -#include <errno.h>
    8.27 -#include <stdio.h>
    8.28 -#include <stdlib.h>
    8.29 -#include <string.h>
    8.30 -#include <sys/time.h>
    8.31 -#include <time.h>
    8.32 -#include <unistd.h>
    8.33 -
    8.34 -#include <xenstat.h>
    8.35 -
    8.36 -#define VM_TOP_VERSION "1.0"
    8.37 -
    8.38 -#define VM_TOP_DISCLAIMER \
    8.39 -"Copyright (C) 2005  International Business Machines  Corp\n"\
    8.40 -"This is free software; see the source for copying conditions.There is NO\n"\
    8.41 -"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
    8.42 -#define VM_TOP_BUGSTO "Report bugs to <dsteklof@us.ibm.com>.\n"
    8.43 -
    8.44 -#define _GNU_SOURCE
    8.45 -#include <getopt.h>
    8.46 -
    8.47 -#if !defined(__GNUC__) && !defined(__GNUG__)
    8.48 -#define __attribute__(arg) /* empty */
    8.49 -#endif
    8.50 -
    8.51 -#define KEY_ESCAPE '\x1B'
    8.52 -
    8.53 -/*
    8.54 - * Function prototypes
    8.55 - */
    8.56 -/* Utility functions */
    8.57 -static void usage(const char *);
    8.58 -static void version(void);
    8.59 -static void cleanup(void);
    8.60 -static void fail(const char *);
    8.61 -static int current_row(void);
    8.62 -static int lines(void);
    8.63 -static void print(const char *, ...) __attribute__((format(printf,1,2)));
    8.64 -static void attr_addstr(int attr, const char *str);
    8.65 -static void set_delay(char *value);
    8.66 -static void set_prompt(char *new_prompt, void (*func)(char *));
    8.67 -static int handle_key(int);
    8.68 -static int compare(unsigned long long, unsigned long long);
    8.69 -static int compare_domains(xenstat_domain **, xenstat_domain **);
    8.70 -static unsigned long long tot_net_bytes( xenstat_domain *, int);
    8.71 -
    8.72 -/* Field functions */
    8.73 -static int compare_domid(xenstat_domain *domain1, xenstat_domain *domain2);
    8.74 -static void print_domid(xenstat_domain *domain);
    8.75 -static int compare_state(xenstat_domain *domain1, xenstat_domain *domain2);
    8.76 -static void print_state(xenstat_domain *domain);
    8.77 -static int compare_cpu(xenstat_domain *domain1, xenstat_domain *domain2);
    8.78 -static void print_cpu(xenstat_domain *domain);
    8.79 -static int compare_cpu_pct(xenstat_domain *domain1, xenstat_domain *domain2);
    8.80 -static void print_cpu_pct(xenstat_domain *domain);
    8.81 -static int compare_mem(xenstat_domain *domain1, xenstat_domain *domain2);
    8.82 -static void print_mem(xenstat_domain *domain);
    8.83 -static void print_mem_pct(xenstat_domain *domain);
    8.84 -static int compare_maxmem(xenstat_domain *domain1, xenstat_domain *domain2);
    8.85 -static void print_maxmem(xenstat_domain *domain);
    8.86 -static void print_max_pct(xenstat_domain *domain);
    8.87 -static int compare_vcpus(xenstat_domain *domain1, xenstat_domain *domain2);
    8.88 -static void print_vcpus(xenstat_domain *domain);
    8.89 -static int compare_nets(xenstat_domain *domain1, xenstat_domain *domain2);
    8.90 -static void print_nets(xenstat_domain *domain);
    8.91 -static int compare_net_tx(xenstat_domain *domain1, xenstat_domain *domain2);
    8.92 -static void print_net_tx(xenstat_domain *domain);
    8.93 -static int compare_net_rx(xenstat_domain *domain1, xenstat_domain *domain2);
    8.94 -static void print_net_rx(xenstat_domain *domain);
    8.95 -static int compare_ssid(xenstat_domain *domain1, xenstat_domain *domain2);
    8.96 -static void print_ssid(xenstat_domain *domain);
    8.97 -
    8.98 -/* Section printing functions */
    8.99 -static void do_summary(void);
   8.100 -static void do_header(void);
   8.101 -static void do_bottom_line(void);
   8.102 -static void do_domain(xenstat_domain *);
   8.103 -static void do_vcpu(xenstat_domain *);
   8.104 -static void do_network(xenstat_domain *);
   8.105 -static void top(void);
   8.106 -
   8.107 -/* Field types */
   8.108 -typedef enum field_id {
   8.109 -	FIELD_DOMID,
   8.110 -	FIELD_STATE,
   8.111 -	FIELD_CPU,
   8.112 -	FIELD_CPU_PCT,
   8.113 -	FIELD_MEM,
   8.114 -	FIELD_MEM_PCT,
   8.115 -	FIELD_MAXMEM,
   8.116 -	FIELD_MAX_PCT,
   8.117 -	FIELD_VCPUS,
   8.118 -	FIELD_NETS,
   8.119 -	FIELD_NET_TX,
   8.120 -	FIELD_NET_RX,
   8.121 -	FIELD_SSID
   8.122 -} field_id;
   8.123 -
   8.124 -typedef struct field {
   8.125 -	field_id num;
   8.126 -	const char *header;
   8.127 -	unsigned int default_width;
   8.128 -	int (*compare)(xenstat_domain *domain1, xenstat_domain *domain2);
   8.129 -	void (*print)(xenstat_domain *domain);
   8.130 -} field;
   8.131 -
   8.132 -field fields[] = {
   8.133 -	{ FIELD_DOMID,   "DOMID",      5, compare_domid,   print_domid   },
   8.134 -	{ FIELD_STATE,   "STATE",      6, compare_state,   print_state   },
   8.135 -	{ FIELD_CPU,     "CPU(sec)",  10, compare_cpu,     print_cpu     },
   8.136 -	{ FIELD_CPU_PCT, "CPU(%)",     6, compare_cpu_pct, print_cpu_pct },
   8.137 -	{ FIELD_MEM,     "MEM(k)",    10, compare_mem,     print_mem     },
   8.138 -	{ FIELD_MEM_PCT, "MEM(%)",     6, compare_mem,     print_mem_pct },
   8.139 -	{ FIELD_MAXMEM,  "MAXMEM(k)", 10, compare_maxmem,  print_maxmem  },
   8.140 -	{ FIELD_MAX_PCT, "MAXMEM(%)",  9, compare_maxmem,  print_max_pct },
   8.141 -	{ FIELD_VCPUS,   "VCPUS",      5, compare_vcpus,   print_vcpus   },
   8.142 -	{ FIELD_NETS,    "NETS",       4, compare_nets,    print_nets    },
   8.143 -	{ FIELD_NET_TX,  "NETTX(k)",   8, compare_net_tx,  print_net_tx  },
   8.144 -	{ FIELD_NET_RX,  "NETRX(k)",   8, compare_net_rx,  print_net_rx  },
   8.145 -	{ FIELD_SSID,    "SSID",       4, compare_ssid,    print_ssid    }
   8.146 -};
   8.147 -
   8.148 -const unsigned int NUM_FIELDS = sizeof(fields)/sizeof(field);
   8.149 -
   8.150 -/* Globals */
   8.151 -struct timeval curtime, oldtime;
   8.152 -xenstat_handle *xhandle = NULL;
   8.153 -xenstat_node *prev_node = NULL;
   8.154 -xenstat_node *cur_node = NULL;
   8.155 -field_id sort_field = FIELD_DOMID;
   8.156 -unsigned int first_domain_index = 0;
   8.157 -unsigned int delay = 1;
   8.158 -int show_vcpus = 0;
   8.159 -int show_networks = 0;
   8.160 -int repeat_header = 0;
   8.161 -#define PROMPT_VAL_LEN 80
   8.162 -char *prompt = NULL;
   8.163 -char prompt_val[PROMPT_VAL_LEN];
   8.164 -int prompt_val_len = 0;
   8.165 -void (*prompt_complete_func)(char *);
   8.166 -
   8.167 -/*
   8.168 - * Function definitions
   8.169 - */
   8.170 -
   8.171 -/* Utility functions */
   8.172 -
   8.173 -/* Print usage message, using given program name */
   8.174 -static void usage(const char *program)
   8.175 -{
   8.176 -	printf("Usage: %s [OPTION]\n"
   8.177 -	       "Displays ongoing information about xen vm resources \n\n"
   8.178 -	       "-h, --help           display this help and exit\n"
   8.179 -	       "-V, --version        output version information and exit\n"
   8.180 -	       "-d, --delay=SECONDS  seconds between updates (default 1)\n"
   8.181 -	       "-n, --networks       output vif network data\n"
   8.182 -	       "-r, --repeat-header  repeat table header before each domain\n"
   8.183 -	       "-v, --vcpus          output vcpu data\n"
   8.184 -	       "\n" VM_TOP_BUGSTO,
   8.185 -	       program);
   8.186 -	return;
   8.187 -}
   8.188 -
   8.189 -/* Print program version information */
   8.190 -static void version(void)
   8.191 -{
   8.192 -	printf("vm-top " VM_TOP_VERSION "\n"
   8.193 -	       "Written by Judy Fischbach, David Hendricks, Josh Triplett\n"
   8.194 -	       "\n" VM_TOP_DISCLAIMER);
   8.195 -}
   8.196 -
   8.197 -/* Clean up any open resources */
   8.198 -static void cleanup(void)
   8.199 -{
   8.200 -	if(!isendwin())
   8.201 -		endwin();
   8.202 -	if(prev_node != NULL)
   8.203 -		xenstat_free_node(prev_node);
   8.204 -	if(cur_node != NULL)
   8.205 -		xenstat_free_node(cur_node);
   8.206 -	if(xhandle != NULL)
   8.207 -		xenstat_uninit(xhandle);
   8.208 -}
   8.209 -
   8.210 -/* Display the given message and gracefully exit */
   8.211 -static void fail(const char *str)
   8.212 -{
   8.213 -	if(!isendwin())
   8.214 -		endwin();
   8.215 -	fprintf(stderr, str);
   8.216 -	exit(1);
   8.217 -}
   8.218 -
   8.219 -/* Return the row containing the cursor. */
   8.220 -static int current_row(void)
   8.221 -{
   8.222 -	int y, x;
   8.223 -	getyx(stdscr, y, x);
   8.224 -	return y;
   8.225 -}
   8.226 -
   8.227 -/* Return the number of lines on the screen. */
   8.228 -static int lines(void)
   8.229 -{
   8.230 -	int y, x;
   8.231 -	getmaxyx(stdscr, y, x);
   8.232 -	return y;
   8.233 -}
   8.234 -
   8.235 -/* printf-style print function which calls printw, but only if the cursor is
   8.236 - * not on the last line. */
   8.237 -static void print(const char *fmt, ...)
   8.238 -{
   8.239 -	va_list args;
   8.240 -
   8.241 -	if(current_row() < lines()-1) {
   8.242 -		va_start(args, fmt);
   8.243 -		vw_printw(stdscr, fmt, args);
   8.244 -		va_end(args);
   8.245 -	}
   8.246 -}
   8.247 -
   8.248 -/* Print a string with the given attributes set. */
   8.249 -static void attr_addstr(int attr, const char *str)
   8.250 -{
   8.251 -	attron(attr);
   8.252 -	addstr(str);
   8.253 -	attroff(attr);
   8.254 -}
   8.255 -
   8.256 -/* Handle setting the delay from the user-supplied value in prompt_val */
   8.257 -static void set_delay(char *value)
   8.258 -{
   8.259 -	int new_delay;
   8.260 -	new_delay = atoi(prompt_val);
   8.261 -	if(new_delay > 0)
   8.262 -		delay = new_delay;
   8.263 -}
   8.264 -
   8.265 -/* Enable prompting mode with the given prompt string; call the given function
   8.266 - * when a value is available. */
   8.267 -static void set_prompt(char *new_prompt, void (*func)(char *))
   8.268 -{
   8.269 -	prompt = new_prompt;
   8.270 -	prompt_val[0] = '\0';
   8.271 -	prompt_val_len = 0;
   8.272 -	prompt_complete_func = func;
   8.273 -}
   8.274 -
   8.275 -/* Handle user input, return 0 if the program should quit, or 1 if not */
   8.276 -static int handle_key(int ch)
   8.277 -{
   8.278 -	if(prompt == NULL) {
   8.279 -		/* Not prompting for input; handle interactive commands */
   8.280 -		switch(ch) {
   8.281 -		case 'n': case 'N':
   8.282 -			show_networks ^= 1;
   8.283 -			break;
   8.284 -		case 'r': case 'R':
   8.285 -			repeat_header ^= 1;
   8.286 -			break;
   8.287 -		case 's': case 'S':
   8.288 -			sort_field = (sort_field + 1) % NUM_FIELDS;
   8.289 -			break;
   8.290 -		case 'v': case 'V':
   8.291 -			show_vcpus ^= 1;
   8.292 -			break;
   8.293 -		case KEY_DOWN:
   8.294 -			first_domain_index++;
   8.295 -			break;
   8.296 -		case KEY_UP:
   8.297 -			if(first_domain_index > 0)
   8.298 -				first_domain_index--;
   8.299 -			break;
   8.300 -		case 'd': case 'D':
   8.301 -			set_prompt("Delay(sec)", set_delay);
   8.302 -			break;
   8.303 -		case 'q': case 'Q': case KEY_ESCAPE:
   8.304 -			return 0;
   8.305 -		}
   8.306 -	} else {
   8.307 -		/* Prompting for input; handle line editing */
   8.308 -		switch(ch) {
   8.309 -		case '\r':
   8.310 -			prompt_complete_func(prompt_val);
   8.311 -			set_prompt(NULL, NULL);
   8.312 -			break;
   8.313 -		case KEY_ESCAPE:
   8.314 -			set_prompt(NULL, NULL);
   8.315 -			break;
   8.316 -		case KEY_BACKSPACE:
   8.317 -			if(prompt_val_len > 0)
   8.318 -				prompt_val[--prompt_val_len] = '\0';
   8.319 -		default:
   8.320 -			if((prompt_val_len+1) < PROMPT_VAL_LEN
   8.321 -			   && isprint(ch)) {
   8.322 -				prompt_val[prompt_val_len++] = (char)ch;
   8.323 -				prompt_val[prompt_val_len] = '\0';
   8.324 -			}
   8.325 -		}
   8.326 -	}
   8.327 -
   8.328 -	return 1;
   8.329 -}
   8.330 -
   8.331 -/* Compares two integers, returning -1,0,1 for <,=,> */
   8.332 -static int compare(unsigned long long i1, unsigned long long i2)
   8.333 -{
   8.334 -	if(i1 < i2)
   8.335 -		return -1;
   8.336 -	if(i1 > i2)
   8.337 -		return 1;
   8.338 -	return 0;
   8.339 -}
   8.340 -
   8.341 -/* Comparison function for use with qsort.  Compares two domains using the
   8.342 - * current sort field. */
   8.343 -static int compare_domains(xenstat_domain **domain1, xenstat_domain **domain2)
   8.344 -{
   8.345 -	return fields[sort_field].compare(*domain1, *domain2);
   8.346 -}
   8.347 -
   8.348 -/* Field functions */
   8.349 -
   8.350 -/* Compares domain ids of two domains, returning -1,0,1 for <,=,> */
   8.351 -int compare_domid(xenstat_domain *domain1, xenstat_domain *domain2)
   8.352 -{
   8.353 -	return compare(xenstat_domain_id(domain1), xenstat_domain_id(domain2));
   8.354 -}
   8.355 -
   8.356 -/* Prints domain identification number */
   8.357 -void print_domid(xenstat_domain *domain)
   8.358 -{
   8.359 -	print("%5u", xenstat_domain_id(domain));
   8.360 -}
   8.361 -
   8.362 -struct {
   8.363 -	unsigned int (*get)(xenstat_domain *);
   8.364 -	char ch;
   8.365 -} state_funcs[] = {
   8.366 -	{ xenstat_domain_dying,    'd' },
   8.367 -	{ xenstat_domain_shutdown, 's' },
   8.368 -	{ xenstat_domain_blocked,  'b' },
   8.369 -	{ xenstat_domain_crashed,  'c' },
   8.370 -	{ xenstat_domain_paused,   'p' },
   8.371 -	{ xenstat_domain_running,  'r' }
   8.372 -};
   8.373 -const unsigned int NUM_STATES = sizeof(state_funcs)/sizeof(*state_funcs);
   8.374 -
   8.375 -/* Compare states of two domains, returning -1,0,1 for <,=,> */
   8.376 -static int compare_state(xenstat_domain *domain1, xenstat_domain *domain2)
   8.377 -{
   8.378 -	unsigned int i, d1s, d2s;
   8.379 -	for(i = 0; i < NUM_STATES; i++) {
   8.380 -		d1s = state_funcs[i].get(domain1);
   8.381 -		d2s = state_funcs[i].get(domain2);
   8.382 -		if(d1s && !d2s)
   8.383 -			return -1;
   8.384 -		if(d2s && !d1s)
   8.385 -			return 1;
   8.386 -	}
   8.387 -	return 0;
   8.388 -}
   8.389 -
   8.390 -/* Prints domain state in abbreviated letter format */
   8.391 -static void print_state(xenstat_domain *domain)
   8.392 -{
   8.393 -	unsigned int i;
   8.394 -	for(i = 0; i < NUM_STATES; i++)
   8.395 -		print("%c", state_funcs[i].get(domain) ? state_funcs[i].ch
   8.396 -		                                       : '-');
   8.397 -}
   8.398 -
   8.399 -/* Compares cpu usage of two domains, returning -1,0,1 for <,=,> */
   8.400 -static int compare_cpu(xenstat_domain *domain1, xenstat_domain *domain2)
   8.401 -{
   8.402 -	return -compare(xenstat_domain_cpu_ns(domain1),
   8.403 -			xenstat_domain_cpu_ns(domain2));
   8.404 -}
   8.405 -
   8.406 -/* Prints domain cpu usage in seconds */
   8.407 -static void print_cpu(xenstat_domain *domain)
   8.408 -{
   8.409 -	print("%10llu", xenstat_domain_cpu_ns(domain)/1000000000);
   8.410 -}
   8.411 -
   8.412 -/* Computes the CPU percentage used for a specified domain */
   8.413 -static double get_cpu_pct(xenstat_domain *domain)
   8.414 -{
   8.415 -	xenstat_domain *old_domain;
   8.416 -	double us_elapsed;
   8.417 -
   8.418 -	/* Can't calculate CPU percentage without a previous sample. */
   8.419 -	if(prev_node == NULL)
   8.420 -		return 0.0;
   8.421 -
   8.422 -	old_domain = xenstat_node_domain(prev_node, xenstat_domain_id(domain));
   8.423 -	if(old_domain == NULL)
   8.424 -		return 0.0;
   8.425 -
   8.426 -	/* Calculate the time elapsed in microseconds */
   8.427 -	us_elapsed = ((curtime.tv_sec-oldtime.tv_sec)*1000000.0
   8.428 -		      +(curtime.tv_usec - oldtime.tv_usec));
   8.429 -
   8.430 -	/* In the following, nanoseconds must be multiplied by 1000.0 to
   8.431 -	 * convert to microseconds, then divided by 100.0 to get a percentage,
   8.432 -	 * resulting in a multiplication by 10.0 */
   8.433 -	return ((xenstat_domain_cpu_ns(domain)
   8.434 -		 -xenstat_domain_cpu_ns(old_domain))/10.0)/us_elapsed;
   8.435 -}
   8.436 -
   8.437 -static int compare_cpu_pct(xenstat_domain *domain1, xenstat_domain *domain2)
   8.438 -{
   8.439 -	return -compare(get_cpu_pct(domain1), get_cpu_pct(domain2));
   8.440 -}
   8.441 -
   8.442 -/* Prints cpu percentage statistic */
   8.443 -static void print_cpu_pct(xenstat_domain *domain)
   8.444 -{
   8.445 -	print("%6.1f", get_cpu_pct(domain));
   8.446 -}
   8.447 -
   8.448 -/* Compares current memory of two domains, returning -1,0,1 for <,=,> */
   8.449 -static int compare_mem(xenstat_domain *domain1, xenstat_domain *domain2)
   8.450 -{
   8.451 -	return -compare(xenstat_domain_cur_mem(domain1),
   8.452 -	                xenstat_domain_cur_mem(domain2));
   8.453 -}
   8.454 -
   8.455 -/* Prints current memory statistic */
   8.456 -static void print_mem(xenstat_domain *domain)
   8.457 -{
   8.458 -	print("%10llu", xenstat_domain_cur_mem(domain)/1024);
   8.459 -}
   8.460 -
   8.461 -/* Prints memory percentage statistic, ratio of current domain memory to total
   8.462 - * node memory */
   8.463 -static void print_mem_pct(xenstat_domain *domain)
   8.464 -{
   8.465 -	print("%6.1f", (double)xenstat_domain_cur_mem(domain) /
   8.466 -	               (double)xenstat_node_tot_mem(cur_node) * 100);
   8.467 -}
   8.468 -
   8.469 -/* Compares maximum memory of two domains, returning -1,0,1 for <,=,> */
   8.470 -static int compare_maxmem(xenstat_domain *domain1, xenstat_domain *domain2)
   8.471 -{
   8.472 -	return -compare(xenstat_domain_max_mem(domain1),
   8.473 -	                xenstat_domain_max_mem(domain2));
   8.474 -}
   8.475 -
   8.476 -/* Prints maximum domain memory statistic in KB */
   8.477 -static void print_maxmem(xenstat_domain *domain)
   8.478 -{
   8.479 -	unsigned long long max_mem = xenstat_domain_max_mem(domain);
   8.480 -	if(max_mem == ((unsigned long long)-1))
   8.481 -		print("%10s", "no limit");
   8.482 -	else
   8.483 -		print("%10llu", max_mem/1024);
   8.484 -}
   8.485 -
   8.486 -/* Prints memory percentage statistic, ratio of current domain memory to total
   8.487 - * node memory */
   8.488 -static void print_max_pct(xenstat_domain *domain)
   8.489 -{
   8.490 -	if (xenstat_domain_max_mem(domain) == (unsigned long long)-1)
   8.491 -		print("%9s", "n/a");
   8.492 -	else
   8.493 -		print("%9.1f", (double)xenstat_domain_max_mem(domain) /
   8.494 -		               (double)xenstat_node_tot_mem(cur_node) * 100);
   8.495 -}
   8.496 -
   8.497 -/* Compares number of virtual CPUs of two domains, returning -1,0,1 for
   8.498 - * <,=,> */
   8.499 -static int compare_vcpus(xenstat_domain *domain1, xenstat_domain *domain2)
   8.500 -{
   8.501 -	return -compare(xenstat_domain_num_vcpus(domain1),
   8.502 -	                xenstat_domain_num_vcpus(domain2));
   8.503 -}
   8.504 -
   8.505 -/* Prints number of virtual CPUs statistic */
   8.506 -static void print_vcpus(xenstat_domain *domain)
   8.507 -{
   8.508 -	print("%5u", xenstat_domain_num_vcpus(domain));
   8.509 -}
   8.510 -
   8.511 -/* Compares number of virtual networks of two domains, returning -1,0,1 for
   8.512 - * <,=,> */
   8.513 -static int compare_nets(xenstat_domain *domain1, xenstat_domain *domain2)
   8.514 -{
   8.515 -	return -compare(xenstat_domain_num_networks(domain1),
   8.516 -	                xenstat_domain_num_networks(domain2));
   8.517 -}
   8.518 -
   8.519 -/* Prints number of virtual networks statistic */
   8.520 -static void print_nets(xenstat_domain *domain)
   8.521 -{
   8.522 -	print("%4u", xenstat_domain_num_networks(domain));
   8.523 -}
   8.524 -
   8.525 -/* Compares number of total network tx bytes of two domains, returning -1,0,1 for
   8.526 - * <,=,> */
   8.527 -static int compare_net_tx(xenstat_domain *domain1, xenstat_domain *domain2)
   8.528 -{
   8.529 -	return -compare(tot_net_bytes(domain1, FALSE),
   8.530 -	                tot_net_bytes(domain2, FALSE));
   8.531 -}
   8.532 -
   8.533 -/* Prints number of total network tx bytes statistic */
   8.534 -static void print_net_tx(xenstat_domain *domain)
   8.535 -{
   8.536 -	print("%8llu", tot_net_bytes(domain, FALSE)/1024);
   8.537 -}
   8.538 -
   8.539 -/* Compares number of total network rx bytes of two domains, returning -1,0,1 for
   8.540 - * <,=,> */
   8.541 -static int compare_net_rx(xenstat_domain *domain1, xenstat_domain *domain2)
   8.542 -{
   8.543 -	return -compare(tot_net_bytes(domain1, TRUE),
   8.544 -	                tot_net_bytes(domain2, TRUE));
   8.545 -}
   8.546 -
   8.547 -/* Prints number of total network rx bytes statistic */
   8.548 -static void print_net_rx(xenstat_domain *domain)
   8.549 -{
   8.550 -	print("%8llu", tot_net_bytes(domain, TRUE)/1024);
   8.551 -}
   8.552 -
   8.553 -/* Gets number of total network bytes statistic, if rx true, then rx bytes
   8.554 - * otherwise tx bytes
   8.555 - */
   8.556 -static unsigned long long tot_net_bytes(xenstat_domain *domain, int rx_flag)
   8.557 -{
   8.558 -	int i = 0;
   8.559 -	xenstat_network *network;
   8.560 -	unsigned num_networks = 0;
   8.561 -        unsigned long long total = 0;
   8.562 -
   8.563 -	/* How many networks? */
   8.564 -	num_networks = xenstat_domain_num_networks(domain);
   8.565 -
   8.566 -	/* Dump information for each network */
   8.567 -	for (i=0; i < num_networks; i++) {
   8.568 -		/* Next get the network information */
   8.569 -		network = xenstat_domain_network(domain,i);
   8.570 -                if (rx_flag) 
   8.571 -			total += xenstat_network_rbytes(network);
   8.572 -                else 
   8.573 -			total += xenstat_network_tbytes(network);
   8.574 -	}
   8.575 -        return (total);
   8.576 -}
   8.577 -
   8.578 -/* Compares security id (ssid) of two domains, returning -1,0,1 for <,=,> */
   8.579 -static int compare_ssid(xenstat_domain *domain1, xenstat_domain *domain2)
   8.580 -{
   8.581 -	return compare(xenstat_domain_ssid(domain1),
   8.582 -		       xenstat_domain_ssid(domain2));
   8.583 -}
   8.584 -
   8.585 -/* Prints ssid statistic */
   8.586 -static void print_ssid(xenstat_domain *domain)
   8.587 -{
   8.588 -	print("%4u", xenstat_domain_ssid(domain));
   8.589 -}
   8.590 -
   8.591 -/* Section printing functions */
   8.592 -/* Prints three line summary header */
   8.593 -void do_summary(void)
   8.594 -{
   8.595 -#define TIME_STR_LEN 9
   8.596 -	const char *TIME_STR_FORMAT = "%H:%M:%S";
   8.597 -	char time_str[TIME_STR_LEN];
   8.598 -	unsigned run = 0, block = 0, pause = 0,
   8.599 -	         crash = 0, dying = 0, shutdown = 0;
   8.600 -	unsigned i, num_domains = 0;
   8.601 -	unsigned long long used = 0;
   8.602 -	xenstat_domain *domain;
   8.603 -
   8.604 -	/* Print program name, current time, and number of domains */
   8.605 -	strftime(time_str, TIME_STR_LEN, TIME_STR_FORMAT,
   8.606 -	         localtime(&curtime.tv_sec));
   8.607 -	num_domains = xenstat_node_num_domains(cur_node);
   8.608 -	print("vm-top - %s\n", time_str);
   8.609 -
   8.610 -	/* Tabulate what states domains are in for summary */
   8.611 -	for (i=0; i < num_domains; i++) {
   8.612 -		domain = xenstat_node_domain_by_index(cur_node,i);
   8.613 -		if (xenstat_domain_running(domain)) run++;
   8.614 -		else if (xenstat_domain_blocked(domain)) block++;
   8.615 -		else if (xenstat_domain_paused(domain)) pause++;
   8.616 -		else if (xenstat_domain_shutdown(domain)) shutdown++;
   8.617 -		else if (xenstat_domain_crashed(domain)) crash++;
   8.618 -		else if (xenstat_domain_dying(domain)) dying++;
   8.619 -	}
   8.620 -
   8.621 -	print("%u domains: %u running, %u blocked, %u paused, "
   8.622 -	      "%u crashed, %u dying, %u shutdown \n",
   8.623 -	      num_domains, run, block, pause, crash, dying, shutdown);
   8.624 -
   8.625 -	used = xenstat_node_tot_mem(cur_node)-xenstat_node_free_mem(cur_node);
   8.626 -
   8.627 -	/* Dump node memory and cpu information */
   8.628 -	print("Mem: %lluk total, %lluk used, %lluk free    "
   8.629 -	      "CPUs: %u @ %lluMHz\n",
   8.630 -	      xenstat_node_tot_mem(cur_node)/1024, used/1024,
   8.631 -	      xenstat_node_free_mem(cur_node)/1024,
   8.632 -	      xenstat_node_num_cpus(cur_node),
   8.633 -	      xenstat_node_cpu_hz(cur_node)/1000000);
   8.634 -}
   8.635 -
   8.636 -/* Display top portion of vm-top */
   8.637 -void do_header(void)
   8.638 -{
   8.639 -	field_id i;
   8.640 -
   8.641 -	/* Turn on REVERSE highlight attribute for headings */
   8.642 -	attron(A_REVERSE);
   8.643 -	for(i = 0; i < NUM_FIELDS; i++) {
   8.644 -		if(i != 0)
   8.645 -			print(" ");
   8.646 -		/* The BOLD attribute is turned on for the sort column */
   8.647 -		if(i == sort_field)
   8.648 -			attron(A_BOLD);
   8.649 -		print("%*s", fields[i].default_width, fields[i].header);
   8.650 -		if(i == sort_field)
   8.651 -			attroff(A_BOLD);
   8.652 -	}
   8.653 -	attroff(A_REVERSE);
   8.654 -	print("\n");
   8.655 -}
   8.656 -
   8.657 -/* Displays bottom portion of vm-top, interactive options
   8.658 - * N toggles network information display, V toggles CPU information
   8.659 - * display, S toggles sort order of information (ascending/descending),
   8.660 - * R toggles whether header is repeated for each domain
   8.661 - */
   8.662 -void do_bottom_line(void)
   8.663 -{
   8.664 -	move(lines()-1, 2);
   8.665 -
   8.666 -	if (prompt != NULL) {
   8.667 -		printw("%s: %s", prompt, prompt_val);
   8.668 -	} else {
   8.669 -		addch(A_REVERSE | 'D'); addstr("elay  ");
   8.670 -
   8.671 -		/* network */
   8.672 -		addch(A_REVERSE | 'N');
   8.673 -		attr_addstr(show_networks ? COLOR_PAIR(1) : 0, "etworks");
   8.674 -		addstr("  ");
   8.675 -
   8.676 -		/* vcpus */
   8.677 -		addch(A_REVERSE | 'V');
   8.678 -		attr_addstr(show_vcpus ? COLOR_PAIR(1) : 0, "CPUs");
   8.679 -		addstr("  ");
   8.680 -
   8.681 -		/* repeat */
   8.682 -		addch(A_REVERSE | 'R');
   8.683 -		attr_addstr(repeat_header ? COLOR_PAIR(1) : 0, "epeat header");
   8.684 -		addstr("  ");
   8.685 -
   8.686 -		/* sort order */
   8.687 -		addch(A_REVERSE | 'S'); addstr("ort order  ");
   8.688 -
   8.689 -		addch(A_REVERSE | 'Q'); addstr("uit  ");
   8.690 -	}
   8.691 -}
   8.692 -
   8.693 -/* Prints Domain information */
   8.694 -void do_domain(xenstat_domain *domain)
   8.695 -{
   8.696 -	unsigned int i;
   8.697 -	for(i = 0; i < NUM_FIELDS; i++) {
   8.698 -		if(i != 0)
   8.699 -			print(" ");
   8.700 -		if(i == sort_field)
   8.701 -			attron(A_BOLD);
   8.702 -		fields[i].print(domain);
   8.703 -		if(i == sort_field)
   8.704 -			attroff(A_BOLD);
   8.705 -	}
   8.706 -	print("\n");
   8.707 -}
   8.708 -
   8.709 -/* Output all vcpu information */
   8.710 -void do_vcpu(xenstat_domain *domain)
   8.711 -{
   8.712 -	int i = 0;
   8.713 -	unsigned num_vcpus = 0;
   8.714 -	xenstat_vcpu *vcpu;
   8.715 -
   8.716 -	print("VCPUs(sec): ");
   8.717 -
   8.718 -	num_vcpus = xenstat_domain_num_vcpus(domain);
   8.719 -
   8.720 -	/* for all vcpus dump out values */
   8.721 -	for (i=0; i< num_vcpus; i++) {
   8.722 -		vcpu = xenstat_domain_vcpu(domain,i);
   8.723 -
   8.724 -		if (i != 0 && (i%5)==0)
   8.725 -			print("\n        ");
   8.726 -		print(" %2u: %10llus", i, xenstat_vcpu_ns(vcpu)/1000000000);
   8.727 -	}
   8.728 -	print("\n");
   8.729 -}
   8.730 -
   8.731 -/* Output all network information */
   8.732 -void do_network(xenstat_domain *domain)
   8.733 -{
   8.734 -	int i = 0;
   8.735 -	xenstat_network *network;
   8.736 -	unsigned num_networks = 0;
   8.737 -
   8.738 -	/* How many networks? */
   8.739 -	num_networks = xenstat_domain_num_networks(domain);
   8.740 -
   8.741 -	/* Dump information for each network */
   8.742 -	for (i=0; i < num_networks; i++) {
   8.743 -		/* Next get the network information */
   8.744 -		network = xenstat_domain_network(domain,i);
   8.745 -
   8.746 -		print("Net%d RX: %8llubytes %8llupkts %8lluerr %8lludrop  ",
   8.747 -		      i,
   8.748 -		      xenstat_network_rbytes(network),
   8.749 -		      xenstat_network_rpackets(network),
   8.750 -		      xenstat_network_rerrs(network),
   8.751 -		      xenstat_network_rdrop(network));
   8.752 -
   8.753 -		print("TX: %8llubytes %8llupkts %8lluerr %8lludrop\n",
   8.754 -		      xenstat_network_tbytes(network),
   8.755 -		      xenstat_network_tpackets(network),
   8.756 -		      xenstat_network_terrs(network),
   8.757 -		      xenstat_network_tdrop(network));
   8.758 -	}
   8.759 -}
   8.760 -
   8.761 -static void top(void)
   8.762 -{
   8.763 -	xenstat_domain **domains;
   8.764 -	unsigned int i, num_domains = 0;
   8.765 -
   8.766 -	/* Now get the node information */
   8.767 -	if (prev_node != NULL)
   8.768 -		xenstat_free_node(prev_node);
   8.769 -	prev_node = cur_node;
   8.770 -	cur_node = xenstat_get_node(xhandle, XENSTAT_ALL);
   8.771 -	if (cur_node == NULL)
   8.772 -		fail("Failed to retrieve statistics from libxenstat\n");
   8.773 -
   8.774 -	/* dump summary top information */
   8.775 -	do_summary();
   8.776 -
   8.777 -	/* Count the number of domains for which to report data */
   8.778 -	num_domains = xenstat_node_num_domains(cur_node);
   8.779 -
   8.780 -	domains = malloc(num_domains*sizeof(xenstat_domain *));
   8.781 -	if(domains == NULL)
   8.782 -		fail("Failed to allocate memory\n");
   8.783 -
   8.784 -	for (i=0; i < num_domains; i++)
   8.785 -		domains[i] = xenstat_node_domain_by_index(cur_node, i);
   8.786 -
   8.787 -	/* Sort */
   8.788 -	qsort(domains, num_domains, sizeof(xenstat_domain *),
   8.789 -	      (int(*)(const void *, const void *))compare_domains);
   8.790 -
   8.791 -	if(first_domain_index >= num_domains)
   8.792 -		first_domain_index = num_domains-1;
   8.793 -
   8.794 -	for (i = first_domain_index; i < num_domains; i++) {
   8.795 -		if(current_row() == lines()-1)
   8.796 -			break;
   8.797 -		if (i == first_domain_index || repeat_header)
   8.798 -			do_header();
   8.799 -		do_domain(domains[i]);
   8.800 -		if (show_vcpus)
   8.801 -			do_vcpu(domains[i]);
   8.802 -		if (show_networks)
   8.803 -			do_network(domains[i]);
   8.804 -	}
   8.805 -
   8.806 -	do_bottom_line();
   8.807 -}
   8.808 -
   8.809 -int main(int argc, char **argv)
   8.810 -{
   8.811 -	int opt, optind = 0;
   8.812 -	int ch = ERR;
   8.813 -
   8.814 -	struct option lopts[] = {
   8.815 -		{ "help",          no_argument,       NULL, 'h' },
   8.816 -		{ "version",       no_argument,       NULL, 'V' },
   8.817 -		{ "networks",      no_argument,       NULL, 'n' },
   8.818 -		{ "repeat-header", no_argument,       NULL, 'r' },
   8.819 -		{ "vcpus",         no_argument,       NULL, 'v' },
   8.820 -		{ "delay",         required_argument, NULL, 'd' },
   8.821 -		{ 0, 0, 0, 0 },
   8.822 -	};
   8.823 -	const char *sopts = "hVbnvd:";
   8.824 -
   8.825 -	if (atexit(cleanup) != 0)
   8.826 -		fail("Failed to install cleanup handler.\n");
   8.827 -
   8.828 -	while ((opt = getopt_long(argc, argv, sopts, lopts, &optind)) != -1) {
   8.829 -		switch (opt) {
   8.830 -		case 'h':
   8.831 -		case '?':
   8.832 -		default:
   8.833 -			usage(argv[0]);
   8.834 -			exit(0);
   8.835 -		case 'V':
   8.836 -			version();
   8.837 -			exit(0);
   8.838 -		case 'n':
   8.839 -			show_networks = 1;
   8.840 -			break;
   8.841 -		case 'r':
   8.842 -			repeat_header = 1;
   8.843 -			break;
   8.844 -		case 'v':
   8.845 -			show_vcpus = 1;
   8.846 -			break;
   8.847 -		case 'd':
   8.848 -			delay = atoi(optarg);
   8.849 -			break;
   8.850 -		}
   8.851 -	}
   8.852 -
   8.853 -	/* Get xenstat handle */
   8.854 -	xhandle = xenstat_init();
   8.855 -	if (xhandle == NULL)
   8.856 -		fail("Failed to initialize xenstat library\n");
   8.857 -
   8.858 -	/* Begin curses stuff */
   8.859 -	initscr();
   8.860 -	start_color();
   8.861 -	cbreak();
   8.862 -	noecho();
   8.863 -	nonl();
   8.864 -	keypad(stdscr, TRUE);
   8.865 -	halfdelay(5);
   8.866 -	use_default_colors();
   8.867 -	init_pair(1, -1, COLOR_YELLOW);
   8.868 -
   8.869 -	do {
   8.870 -		gettimeofday(&curtime, NULL);
   8.871 -		if(ch != ERR || (curtime.tv_sec - oldtime.tv_sec) >= delay) {
   8.872 -			clear();
   8.873 -			top();
   8.874 -			oldtime = curtime;
   8.875 -			refresh();
   8.876 -		}
   8.877 -		ch = getch();
   8.878 -	} while (handle_key(ch));
   8.879 -
   8.880 -	/* Cleanup occurs in cleanup(), so no work to do here. */
   8.881 -
   8.882 -	return 0;
   8.883 -}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/tools/xenstat/xentop/Makefile	Wed Aug 17 16:50:33 2005 +0000
     9.3 @@ -0,0 +1,43 @@
     9.4 +# Copyright (C) International Business Machines Corp., 2005
     9.5 +# Author: Josh Triplett <josht@us.ibm.com>
     9.6 +# 
     9.7 +# This program is free software; you can redistribute it and/or modify
     9.8 +# it under the terms of the GNU General Public License as published by
     9.9 +# the Free Software Foundation; under version 2 of the License.
    9.10 +#
    9.11 +# This program is distributed in the hope that it will be useful,
    9.12 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
    9.13 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    9.14 +# GNU General Public License for more details.
    9.15 +
    9.16 +XEN_ROOT=../../..
    9.17 +include $(XEN_ROOT)/tools/Rules.mk
    9.18 +
    9.19 +ifneq ($(XENSTAT_XENTOP),y)
    9.20 +all install xentop:
    9.21 +else
    9.22 +
    9.23 +INSTALL         = install
    9.24 +INSTALL_PROG    = $(INSTALL) -m0755 -D
    9.25 +INSTALL_DATA    = $(INSTALL) -m0644 -D
    9.26 +
    9.27 +prefix=/usr
    9.28 +mandir=$(prefix)/share/man
    9.29 +man1dir=$(mandir)/man1
    9.30 +sbindir=$(prefix)/sbin
    9.31 +
    9.32 +CFLAGS += -DGCC_PRINTF -Wall -Werror -I$(XEN_LIBXENSTAT)
    9.33 +LDFLAGS += -L$(XEN_LIBXENSTAT) -lxenstat -lcurses
    9.34 +
    9.35 +all: xentop
    9.36 +
    9.37 +xentop: xentop.o
    9.38 +
    9.39 +install: xentop xentop.1
    9.40 +	$(INSTALL_PROG) xentop $(DESTDIR)$(sbindir)/xentop
    9.41 +	$(INSTALL_DATA) xentop.1 $(DESTDIR)$(man1dir)/xentop.1
    9.42 +
    9.43 +endif
    9.44 +
    9.45 +clean:
    9.46 +	rm -f xentop xentop.o
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/tools/xenstat/xentop/TODO	Wed Aug 17 16:50:33 2005 +0000
    10.3 @@ -0,0 +1,34 @@
    10.4 +Display error messages on the help line after bad input at a prompt.
    10.5 +Fractional delay times
    10.6 +Use prompting to search for domains
    10.7 +Better line editing?
    10.8 +
    10.9 +* Make CPU in % more accurate
   10.10 +* Domain total network TX % and RX %
   10.11 +
   10.12 +Like Top, f feature, field select of domain columns, toggle the display of
   10.13 +field by typing the letter associated with field, if displayed it shows in
   10.14 +bold and the letter is Capitalized along with a leading asterisk for the
   10.15 +field, if not selected for display letter is lowercase, no leading asterisk
   10.16 +and field is not bolded.
   10.17 +
   10.18 +Like Top, ordering of domain columns, o feature Capital letter shifts left,
   10.19 +lowercase letter shifts right?
   10.20 +
   10.21 +Color
   10.22 +Full management: pause, destroy, create domains
   10.23 +
   10.24 +Add support for Virtual Block Devices (vbd)
   10.25 +
   10.26 +To think about:
   10.27 +Support for one than one node display (distributed monitoring 
   10.28 +from any node of all other nodes in a cluster)
   10.29 +Bottom line option (Switch node, Search node [tab completion?])
   10.30 +
   10.31 +Capture/Logging of resource information generated during a time interval.
   10.32 +-b batch mode dump snapshots to standard output (used with -n)
   10.33 +-n number of iterations to dump to standard output (unlimited if not specified)
   10.34 +-d monitor DomIDs as -dD1,-dD2 or -dD1,D2...
   10.35 +   Monitor only domains with specified domain IDs
   10.36 +-m monitor nodeIDs as -mN1,-mN2 or -mN1,N2...
   10.37 +   Monitor only domains with specified node IDs
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/tools/xenstat/xentop/xentop.1	Wed Aug 17 16:50:33 2005 +0000
    11.3 @@ -0,0 +1,88 @@
    11.4 +.\" Copyright (C) International Business Machines  Corp., 2005
    11.5 +.\" Author: Josh Triplett <josht@us.ibm.com>
    11.6 +.\"
    11.7 +.\" This program is free software; you can redistribute it and/or modify
    11.8 +.\" it under the terms of the GNU General Public License as published by
    11.9 +.\" the Free Software Foundation; under version 2 of the License.
   11.10 +.\"
   11.11 +.\" This program is distributed in the hope that it will be useful,
   11.12 +.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
   11.13 +.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   11.14 +.\" GNU General Public License for more details.
   11.15 +.\"
   11.16 +.\" You should have received a copy of the GNU General Public License
   11.17 +.\" along with this program; if not, write to the Free Software
   11.18 +.\" Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   11.19 +.TH xentop 1 "August 2005"
   11.20 +.SH NAME
   11.21 +\fBxentop\fR \- displays real-time information about a Xen system and domains
   11.22 +
   11.23 +.SH SYNOPSIS
   11.24 +.B xentop
   11.25 +[\fB\-h\fR]
   11.26 +[\fB\-V\fR]
   11.27 +[\fB\-d\fRSECONDS]
   11.28 +[\fB\-n\fR]
   11.29 +[\fB\-r\fR]
   11.30 +[\fB\-v\fR]
   11.31 +
   11.32 +.SH DESCRIPTION
   11.33 +\fBxentop\fR displays information about the Xen system and domains, in a
   11.34 +continually-updating manner.  Command-line options and interactive commands
   11.35 +can change the detail and format of the information displayed by \fBxentop\fR.
   11.36 +
   11.37 +.SH OPTIONS
   11.38 +.TP
   11.39 +\fB\-h\fR, \fB\-\-help\fR
   11.40 +display help and exit
   11.41 +.TP
   11.42 +\fB\-V\fR, \fB\-\-version\fR
   11.43 +output version information and exit
   11.44 +.TP
   11.45 +\fB\-d\fR, \fB\-\-delay\fR=\fISECONDS\fR
   11.46 +seconds between updates (default 1)
   11.47 +.TP
   11.48 +\fB\-n\fR, \fB\-\-networks\fR
   11.49 +output network information
   11.50 +.TP
   11.51 +\fB\-r\fR, \fB\-\-repeat\-header\fR
   11.52 +repeat table header before each domain
   11.53 +.TP
   11.54 +\fB\-v\fR, \fB\-\-vcpus\fR
   11.55 +output VCPU data
   11.56 +
   11.57 +.SH "INTERACTIVE COMMANDS"
   11.58 +All interactive commands are case-insensitive.
   11.59 +.TP
   11.60 +.B D
   11.61 +set delay between updates
   11.62 +.TP
   11.63 +.B N
   11.64 +toggle display of network information
   11.65 +.TP
   11.66 +.B Q, Esc
   11.67 +quit
   11.68 +.TP
   11.69 +.B R
   11.70 +toggle table header before each domain
   11.71 +.TP
   11.72 +.B S
   11.73 +cycle sort order
   11.74 +.TP
   11.75 +.B V
   11.76 +toggle display of VCPU information
   11.77 +.TP
   11.78 +.B Arrows
   11.79 +scroll domain display
   11.80 +
   11.81 +.SH AUTHORS
   11.82 +Written by Judy Fischbach, David Hendricks, and Josh Triplett
   11.83 +
   11.84 +.SH "REPORTING BUGS"
   11.85 +Report bugs to <dsteklof@us.ibm.com>.
   11.86 +
   11.87 +.SH COPYRIGHT
   11.88 +Copyright \(co 2005  International Business Machines  Corp
   11.89 +.br
   11.90 +This is free software; see the source for copying conditions.  There is NO
   11.91 +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/tools/xenstat/xentop/xentop.c	Wed Aug 17 16:50:33 2005 +0000
    12.3 @@ -0,0 +1,876 @@
    12.4 +/*
    12.5 + *  Copyright (C) International Business Machines  Corp., 2005
    12.6 + *  Author(s): Judy Fischbach <jfisch@us.ibm.com>
    12.7 + *             David Hendricks <dhendrix@us.ibm.com>
    12.8 + *             Josh Triplett <josht@us.ibm.com>
    12.9 + *    based on code from Anthony Liguori <aliguori@us.ibm.com>
   12.10 + *
   12.11 + *  This program is free software; you can redistribute it and/or modify
   12.12 + *  it under the terms of the GNU General Public License as published by
   12.13 + *  the Free Software Foundation; under version 2 of the License.
   12.14 + *
   12.15 + *  This program is distributed in the hope that it will be useful,
   12.16 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   12.17 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12.18 + *  GNU General Public License for more details.
   12.19 + *
   12.20 + *  You should have received a copy of the GNU General Public License
   12.21 + *  along with this program; if not, write to the Free Software
   12.22 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   12.23 + */
   12.24 +#include <curses.h>
   12.25 +#include <ctype.h>
   12.26 +#include <errno.h>
   12.27 +#include <stdio.h>
   12.28 +#include <stdlib.h>
   12.29 +#include <string.h>
   12.30 +#include <sys/time.h>
   12.31 +#include <time.h>
   12.32 +#include <unistd.h>
   12.33 +
   12.34 +#include <xenstat.h>
   12.35 +
   12.36 +#define XENTOP_VERSION "1.0"
   12.37 +
   12.38 +#define XENTOP_DISCLAIMER \
   12.39 +"Copyright (C) 2005  International Business Machines  Corp\n"\
   12.40 +"This is free software; see the source for copying conditions.There is NO\n"\
   12.41 +"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
   12.42 +#define XENTOP_BUGSTO "Report bugs to <dsteklof@us.ibm.com>.\n"
   12.43 +
   12.44 +#define _GNU_SOURCE
   12.45 +#include <getopt.h>
   12.46 +
   12.47 +#if !defined(__GNUC__) && !defined(__GNUG__)
   12.48 +#define __attribute__(arg) /* empty */
   12.49 +#endif
   12.50 +
   12.51 +#define KEY_ESCAPE '\x1B'
   12.52 +
   12.53 +/*
   12.54 + * Function prototypes
   12.55 + */
   12.56 +/* Utility functions */
   12.57 +static void usage(const char *);
   12.58 +static void version(void);
   12.59 +static void cleanup(void);
   12.60 +static void fail(const char *);
   12.61 +static int current_row(void);
   12.62 +static int lines(void);
   12.63 +static void print(const char *, ...) __attribute__((format(printf,1,2)));
   12.64 +static void attr_addstr(int attr, const char *str);
   12.65 +static void set_delay(char *value);
   12.66 +static void set_prompt(char *new_prompt, void (*func)(char *));
   12.67 +static int handle_key(int);
   12.68 +static int compare(unsigned long long, unsigned long long);
   12.69 +static int compare_domains(xenstat_domain **, xenstat_domain **);
   12.70 +static unsigned long long tot_net_bytes( xenstat_domain *, int);
   12.71 +
   12.72 +/* Field functions */
   12.73 +static int compare_domid(xenstat_domain *domain1, xenstat_domain *domain2);
   12.74 +static void print_domid(xenstat_domain *domain);
   12.75 +static int compare_state(xenstat_domain *domain1, xenstat_domain *domain2);
   12.76 +static void print_state(xenstat_domain *domain);
   12.77 +static int compare_cpu(xenstat_domain *domain1, xenstat_domain *domain2);
   12.78 +static void print_cpu(xenstat_domain *domain);
   12.79 +static int compare_cpu_pct(xenstat_domain *domain1, xenstat_domain *domain2);
   12.80 +static void print_cpu_pct(xenstat_domain *domain);
   12.81 +static int compare_mem(xenstat_domain *domain1, xenstat_domain *domain2);
   12.82 +static void print_mem(xenstat_domain *domain);
   12.83 +static void print_mem_pct(xenstat_domain *domain);
   12.84 +static int compare_maxmem(xenstat_domain *domain1, xenstat_domain *domain2);
   12.85 +static void print_maxmem(xenstat_domain *domain);
   12.86 +static void print_max_pct(xenstat_domain *domain);
   12.87 +static int compare_vcpus(xenstat_domain *domain1, xenstat_domain *domain2);
   12.88 +static void print_vcpus(xenstat_domain *domain);
   12.89 +static int compare_nets(xenstat_domain *domain1, xenstat_domain *domain2);
   12.90 +static void print_nets(xenstat_domain *domain);
   12.91 +static int compare_net_tx(xenstat_domain *domain1, xenstat_domain *domain2);
   12.92 +static void print_net_tx(xenstat_domain *domain);
   12.93 +static int compare_net_rx(xenstat_domain *domain1, xenstat_domain *domain2);
   12.94 +static void print_net_rx(xenstat_domain *domain);
   12.95 +static int compare_ssid(xenstat_domain *domain1, xenstat_domain *domain2);
   12.96 +static void print_ssid(xenstat_domain *domain);
   12.97 +
   12.98 +/* Section printing functions */
   12.99 +static void do_summary(void);
  12.100 +static void do_header(void);
  12.101 +static void do_bottom_line(void);
  12.102 +static void do_domain(xenstat_domain *);
  12.103 +static void do_vcpu(xenstat_domain *);
  12.104 +static void do_network(xenstat_domain *);
  12.105 +static void top(void);
  12.106 +
  12.107 +/* Field types */
  12.108 +typedef enum field_id {
  12.109 +	FIELD_DOMID,
  12.110 +	FIELD_STATE,
  12.111 +	FIELD_CPU,
  12.112 +	FIELD_CPU_PCT,
  12.113 +	FIELD_MEM,
  12.114 +	FIELD_MEM_PCT,
  12.115 +	FIELD_MAXMEM,
  12.116 +	FIELD_MAX_PCT,
  12.117 +	FIELD_VCPUS,
  12.118 +	FIELD_NETS,
  12.119 +	FIELD_NET_TX,
  12.120 +	FIELD_NET_RX,
  12.121 +	FIELD_SSID
  12.122 +} field_id;
  12.123 +
  12.124 +typedef struct field {
  12.125 +	field_id num;
  12.126 +	const char *header;
  12.127 +	unsigned int default_width;
  12.128 +	int (*compare)(xenstat_domain *domain1, xenstat_domain *domain2);
  12.129 +	void (*print)(xenstat_domain *domain);
  12.130 +} field;
  12.131 +
  12.132 +field fields[] = {
  12.133 +	{ FIELD_DOMID,   "DOMID",      5, compare_domid,   print_domid   },
  12.134 +	{ FIELD_STATE,   "STATE",      6, compare_state,   print_state   },
  12.135 +	{ FIELD_CPU,     "CPU(sec)",  10, compare_cpu,     print_cpu     },
  12.136 +	{ FIELD_CPU_PCT, "CPU(%)",     6, compare_cpu_pct, print_cpu_pct },
  12.137 +	{ FIELD_MEM,     "MEM(k)",    10, compare_mem,     print_mem     },
  12.138 +	{ FIELD_MEM_PCT, "MEM(%)",     6, compare_mem,     print_mem_pct },
  12.139 +	{ FIELD_MAXMEM,  "MAXMEM(k)", 10, compare_maxmem,  print_maxmem  },
  12.140 +	{ FIELD_MAX_PCT, "MAXMEM(%)",  9, compare_maxmem,  print_max_pct },
  12.141 +	{ FIELD_VCPUS,   "VCPUS",      5, compare_vcpus,   print_vcpus   },
  12.142 +	{ FIELD_NETS,    "NETS",       4, compare_nets,    print_nets    },
  12.143 +	{ FIELD_NET_TX,  "NETTX(k)",   8, compare_net_tx,  print_net_tx  },
  12.144 +	{ FIELD_NET_RX,  "NETRX(k)",   8, compare_net_rx,  print_net_rx  },
  12.145 +	{ FIELD_SSID,    "SSID",       4, compare_ssid,    print_ssid    }
  12.146 +};
  12.147 +
  12.148 +const unsigned int NUM_FIELDS = sizeof(fields)/sizeof(field);
  12.149 +
  12.150 +/* Globals */
  12.151 +struct timeval curtime, oldtime;
  12.152 +xenstat_handle *xhandle = NULL;
  12.153 +xenstat_node *prev_node = NULL;
  12.154 +xenstat_node *cur_node = NULL;
  12.155 +field_id sort_field = FIELD_DOMID;
  12.156 +unsigned int first_domain_index = 0;
  12.157 +unsigned int delay = 1;
  12.158 +int show_vcpus = 0;
  12.159 +int show_networks = 0;
  12.160 +int repeat_header = 0;
  12.161 +#define PROMPT_VAL_LEN 80
  12.162 +char *prompt = NULL;
  12.163 +char prompt_val[PROMPT_VAL_LEN];
  12.164 +int prompt_val_len = 0;
  12.165 +void (*prompt_complete_func)(char *);
  12.166 +
  12.167 +/*
  12.168 + * Function definitions
  12.169 + */
  12.170 +
  12.171 +/* Utility functions */
  12.172 +
  12.173 +/* Print usage message, using given program name */
  12.174 +static void usage(const char *program)
  12.175 +{
  12.176 +	printf("Usage: %s [OPTION]\n"
  12.177 +	       "Displays ongoing information about xen vm resources \n\n"
  12.178 +	       "-h, --help           display this help and exit\n"
  12.179 +	       "-V, --version        output version information and exit\n"
  12.180 +	       "-d, --delay=SECONDS  seconds between updates (default 1)\n"
  12.181 +	       "-n, --networks       output vif network data\n"
  12.182 +	       "-r, --repeat-header  repeat table header before each domain\n"
  12.183 +	       "-v, --vcpus          output vcpu data\n"
  12.184 +	       "\n" XENTOP_BUGSTO,
  12.185 +	       program);
  12.186 +	return;
  12.187 +}
  12.188 +
  12.189 +/* Print program version information */
  12.190 +static void version(void)
  12.191 +{
  12.192 +	printf("xentop " XENTOP_VERSION "\n"
  12.193 +	       "Written by Judy Fischbach, David Hendricks, Josh Triplett\n"
  12.194 +	       "\n" XENTOP_DISCLAIMER);
  12.195 +}
  12.196 +
  12.197 +/* Clean up any open resources */
  12.198 +static void cleanup(void)
  12.199 +{
  12.200 +	if(!isendwin())
  12.201 +		endwin();
  12.202 +	if(prev_node != NULL)
  12.203 +		xenstat_free_node(prev_node);
  12.204 +	if(cur_node != NULL)
  12.205 +		xenstat_free_node(cur_node);
  12.206 +	if(xhandle != NULL)
  12.207 +		xenstat_uninit(xhandle);
  12.208 +}
  12.209 +
  12.210 +/* Display the given message and gracefully exit */
  12.211 +static void fail(const char *str)
  12.212 +{
  12.213 +	if(!isendwin())
  12.214 +		endwin();
  12.215 +	fprintf(stderr, str);
  12.216 +	exit(1);
  12.217 +}
  12.218 +
  12.219 +/* Return the row containing the cursor. */
  12.220 +static int current_row(void)
  12.221 +{
  12.222 +	int y, x;
  12.223 +	getyx(stdscr, y, x);
  12.224 +	return y;
  12.225 +}
  12.226 +
  12.227 +/* Return the number of lines on the screen. */
  12.228 +static int lines(void)
  12.229 +{
  12.230 +	int y, x;
  12.231 +	getmaxyx(stdscr, y, x);
  12.232 +	return y;
  12.233 +}
  12.234 +
  12.235 +/* printf-style print function which calls printw, but only if the cursor is
  12.236 + * not on the last line. */
  12.237 +static void print(const char *fmt, ...)
  12.238 +{
  12.239 +	va_list args;
  12.240 +
  12.241 +	if(current_row() < lines()-1) {
  12.242 +		va_start(args, fmt);
  12.243 +		vw_printw(stdscr, fmt, args);
  12.244 +		va_end(args);
  12.245 +	}
  12.246 +}
  12.247 +
  12.248 +/* Print a string with the given attributes set. */
  12.249 +static void attr_addstr(int attr, const char *str)
  12.250 +{
  12.251 +	attron(attr);
  12.252 +	addstr(str);
  12.253 +	attroff(attr);
  12.254 +}
  12.255 +
  12.256 +/* Handle setting the delay from the user-supplied value in prompt_val */
  12.257 +static void set_delay(char *value)
  12.258 +{
  12.259 +	int new_delay;
  12.260 +	new_delay = atoi(prompt_val);
  12.261 +	if(new_delay > 0)
  12.262 +		delay = new_delay;
  12.263 +}
  12.264 +
  12.265 +/* Enable prompting mode with the given prompt string; call the given function
  12.266 + * when a value is available. */
  12.267 +static void set_prompt(char *new_prompt, void (*func)(char *))
  12.268 +{
  12.269 +	prompt = new_prompt;
  12.270 +	prompt_val[0] = '\0';
  12.271 +	prompt_val_len = 0;
  12.272 +	prompt_complete_func = func;
  12.273 +}
  12.274 +
  12.275 +/* Handle user input, return 0 if the program should quit, or 1 if not */
  12.276 +static int handle_key(int ch)
  12.277 +{
  12.278 +	if(prompt == NULL) {
  12.279 +		/* Not prompting for input; handle interactive commands */
  12.280 +		switch(ch) {
  12.281 +		case 'n': case 'N':
  12.282 +			show_networks ^= 1;
  12.283 +			break;
  12.284 +		case 'r': case 'R':
  12.285 +			repeat_header ^= 1;
  12.286 +			break;
  12.287 +		case 's': case 'S':
  12.288 +			sort_field = (sort_field + 1) % NUM_FIELDS;
  12.289 +			break;
  12.290 +		case 'v': case 'V':
  12.291 +			show_vcpus ^= 1;
  12.292 +			break;
  12.293 +		case KEY_DOWN:
  12.294 +			first_domain_index++;
  12.295 +			break;
  12.296 +		case KEY_UP:
  12.297 +			if(first_domain_index > 0)
  12.298 +				first_domain_index--;
  12.299 +			break;
  12.300 +		case 'd': case 'D':
  12.301 +			set_prompt("Delay(sec)", set_delay);
  12.302 +			break;
  12.303 +		case 'q': case 'Q': case KEY_ESCAPE:
  12.304 +			return 0;
  12.305 +		}
  12.306 +	} else {
  12.307 +		/* Prompting for input; handle line editing */
  12.308 +		switch(ch) {
  12.309 +		case '\r':
  12.310 +			prompt_complete_func(prompt_val);
  12.311 +			set_prompt(NULL, NULL);
  12.312 +			break;
  12.313 +		case KEY_ESCAPE:
  12.314 +			set_prompt(NULL, NULL);
  12.315 +			break;
  12.316 +		case KEY_BACKSPACE:
  12.317 +			if(prompt_val_len > 0)
  12.318 +				prompt_val[--prompt_val_len] = '\0';
  12.319 +		default:
  12.320 +			if((prompt_val_len+1) < PROMPT_VAL_LEN
  12.321 +			   && isprint(ch)) {
  12.322 +				prompt_val[prompt_val_len++] = (char)ch;
  12.323 +				prompt_val[prompt_val_len] = '\0';
  12.324 +			}
  12.325 +		}
  12.326 +	}
  12.327 +
  12.328 +	return 1;
  12.329 +}
  12.330 +
  12.331 +/* Compares two integers, returning -1,0,1 for <,=,> */
  12.332 +static int compare(unsigned long long i1, unsigned long long i2)
  12.333 +{
  12.334 +	if(i1 < i2)
  12.335 +		return -1;
  12.336 +	if(i1 > i2)
  12.337 +		return 1;
  12.338 +	return 0;
  12.339 +}
  12.340 +
  12.341 +/* Comparison function for use with qsort.  Compares two domains using the
  12.342 + * current sort field. */
  12.343 +static int compare_domains(xenstat_domain **domain1, xenstat_domain **domain2)
  12.344 +{
  12.345 +	return fields[sort_field].compare(*domain1, *domain2);
  12.346 +}
  12.347 +
  12.348 +/* Field functions */
  12.349 +
  12.350 +/* Compares domain ids of two domains, returning -1,0,1 for <,=,> */
  12.351 +int compare_domid(xenstat_domain *domain1, xenstat_domain *domain2)
  12.352 +{
  12.353 +	return compare(xenstat_domain_id(domain1), xenstat_domain_id(domain2));
  12.354 +}
  12.355 +
  12.356 +/* Prints domain identification number */
  12.357 +void print_domid(xenstat_domain *domain)
  12.358 +{
  12.359 +	print("%5u", xenstat_domain_id(domain));
  12.360 +}
  12.361 +
  12.362 +struct {
  12.363 +	unsigned int (*get)(xenstat_domain *);
  12.364 +	char ch;
  12.365 +} state_funcs[] = {
  12.366 +	{ xenstat_domain_dying,    'd' },
  12.367 +	{ xenstat_domain_shutdown, 's' },
  12.368 +	{ xenstat_domain_blocked,  'b' },
  12.369 +	{ xenstat_domain_crashed,  'c' },
  12.370 +	{ xenstat_domain_paused,   'p' },
  12.371 +	{ xenstat_domain_running,  'r' }
  12.372 +};
  12.373 +const unsigned int NUM_STATES = sizeof(state_funcs)/sizeof(*state_funcs);
  12.374 +
  12.375 +/* Compare states of two domains, returning -1,0,1 for <,=,> */
  12.376 +static int compare_state(xenstat_domain *domain1, xenstat_domain *domain2)
  12.377 +{
  12.378 +	unsigned int i, d1s, d2s;
  12.379 +	for(i = 0; i < NUM_STATES; i++) {
  12.380 +		d1s = state_funcs[i].get(domain1);
  12.381 +		d2s = state_funcs[i].get(domain2);
  12.382 +		if(d1s && !d2s)
  12.383 +			return -1;
  12.384 +		if(d2s && !d1s)
  12.385 +			return 1;
  12.386 +	}
  12.387 +	return 0;
  12.388 +}
  12.389 +
  12.390 +/* Prints domain state in abbreviated letter format */
  12.391 +static void print_state(xenstat_domain *domain)
  12.392 +{
  12.393 +	unsigned int i;
  12.394 +	for(i = 0; i < NUM_STATES; i++)
  12.395 +		print("%c", state_funcs[i].get(domain) ? state_funcs[i].ch
  12.396 +		                                       : '-');
  12.397 +}
  12.398 +
  12.399 +/* Compares cpu usage of two domains, returning -1,0,1 for <,=,> */
  12.400 +static int compare_cpu(xenstat_domain *domain1, xenstat_domain *domain2)
  12.401 +{
  12.402 +	return -compare(xenstat_domain_cpu_ns(domain1),
  12.403 +			xenstat_domain_cpu_ns(domain2));
  12.404 +}
  12.405 +
  12.406 +/* Prints domain cpu usage in seconds */
  12.407 +static void print_cpu(xenstat_domain *domain)
  12.408 +{
  12.409 +	print("%10llu", xenstat_domain_cpu_ns(domain)/1000000000);
  12.410 +}
  12.411 +
  12.412 +/* Computes the CPU percentage used for a specified domain */
  12.413 +static double get_cpu_pct(xenstat_domain *domain)
  12.414 +{
  12.415 +	xenstat_domain *old_domain;
  12.416 +	double us_elapsed;
  12.417 +
  12.418 +	/* Can't calculate CPU percentage without a previous sample. */
  12.419 +	if(prev_node == NULL)
  12.420 +		return 0.0;
  12.421 +
  12.422 +	old_domain = xenstat_node_domain(prev_node, xenstat_domain_id(domain));
  12.423 +	if(old_domain == NULL)
  12.424 +		return 0.0;
  12.425 +
  12.426 +	/* Calculate the time elapsed in microseconds */
  12.427 +	us_elapsed = ((curtime.tv_sec-oldtime.tv_sec)*1000000.0
  12.428 +		      +(curtime.tv_usec - oldtime.tv_usec));
  12.429 +
  12.430 +	/* In the following, nanoseconds must be multiplied by 1000.0 to
  12.431 +	 * convert to microseconds, then divided by 100.0 to get a percentage,
  12.432 +	 * resulting in a multiplication by 10.0 */
  12.433 +	return ((xenstat_domain_cpu_ns(domain)
  12.434 +		 -xenstat_domain_cpu_ns(old_domain))/10.0)/us_elapsed;
  12.435 +}
  12.436 +
  12.437 +static int compare_cpu_pct(xenstat_domain *domain1, xenstat_domain *domain2)
  12.438 +{
  12.439 +	return -compare(get_cpu_pct(domain1), get_cpu_pct(domain2));
  12.440 +}
  12.441 +
  12.442 +/* Prints cpu percentage statistic */
  12.443 +static void print_cpu_pct(xenstat_domain *domain)
  12.444 +{
  12.445 +	print("%6.1f", get_cpu_pct(domain));
  12.446 +}
  12.447 +
  12.448 +/* Compares current memory of two domains, returning -1,0,1 for <,=,> */
  12.449 +static int compare_mem(xenstat_domain *domain1, xenstat_domain *domain2)
  12.450 +{
  12.451 +	return -compare(xenstat_domain_cur_mem(domain1),
  12.452 +	                xenstat_domain_cur_mem(domain2));
  12.453 +}
  12.454 +
  12.455 +/* Prints current memory statistic */
  12.456 +static void print_mem(xenstat_domain *domain)
  12.457 +{
  12.458 +	print("%10llu", xenstat_domain_cur_mem(domain)/1024);
  12.459 +}
  12.460 +
  12.461 +/* Prints memory percentage statistic, ratio of current domain memory to total
  12.462 + * node memory */
  12.463 +static void print_mem_pct(xenstat_domain *domain)
  12.464 +{
  12.465 +	print("%6.1f", (double)xenstat_domain_cur_mem(domain) /
  12.466 +	               (double)xenstat_node_tot_mem(cur_node) * 100);
  12.467 +}
  12.468 +
  12.469 +/* Compares maximum memory of two domains, returning -1,0,1 for <,=,> */
  12.470 +static int compare_maxmem(xenstat_domain *domain1, xenstat_domain *domain2)
  12.471 +{
  12.472 +	return -compare(xenstat_domain_max_mem(domain1),
  12.473 +	                xenstat_domain_max_mem(domain2));
  12.474 +}
  12.475 +
  12.476 +/* Prints maximum domain memory statistic in KB */
  12.477 +static void print_maxmem(xenstat_domain *domain)
  12.478 +{
  12.479 +	unsigned long long max_mem = xenstat_domain_max_mem(domain);
  12.480 +	if(max_mem == ((unsigned long long)-1))
  12.481 +		print("%10s", "no limit");
  12.482 +	else
  12.483 +		print("%10llu", max_mem/1024);
  12.484 +}
  12.485 +
  12.486 +/* Prints memory percentage statistic, ratio of current domain memory to total
  12.487 + * node memory */
  12.488 +static void print_max_pct(xenstat_domain *domain)
  12.489 +{
  12.490 +	if (xenstat_domain_max_mem(domain) == (unsigned long long)-1)
  12.491 +		print("%9s", "n/a");
  12.492 +	else
  12.493 +		print("%9.1f", (double)xenstat_domain_max_mem(domain) /
  12.494 +		               (double)xenstat_node_tot_mem(cur_node) * 100);
  12.495 +}
  12.496 +
  12.497 +/* Compares number of virtual CPUs of two domains, returning -1,0,1 for
  12.498 + * <,=,> */
  12.499 +static int compare_vcpus(xenstat_domain *domain1, xenstat_domain *domain2)
  12.500 +{
  12.501 +	return -compare(xenstat_domain_num_vcpus(domain1),
  12.502 +	                xenstat_domain_num_vcpus(domain2));
  12.503 +}
  12.504 +
  12.505 +/* Prints number of virtual CPUs statistic */
  12.506 +static void print_vcpus(xenstat_domain *domain)
  12.507 +{
  12.508 +	print("%5u", xenstat_domain_num_vcpus(domain));
  12.509 +}
  12.510 +
  12.511 +/* Compares number of virtual networks of two domains, returning -1,0,1 for
  12.512 + * <,=,> */
  12.513 +static int compare_nets(xenstat_domain *domain1, xenstat_domain *domain2)
  12.514 +{
  12.515 +	return -compare(xenstat_domain_num_networks(domain1),
  12.516 +	                xenstat_domain_num_networks(domain2));
  12.517 +}
  12.518 +
  12.519 +/* Prints number of virtual networks statistic */
  12.520 +static void print_nets(xenstat_domain *domain)
  12.521 +{
  12.522 +	print("%4u", xenstat_domain_num_networks(domain));
  12.523 +}
  12.524 +
  12.525 +/* Compares number of total network tx bytes of two domains, returning -1,0,1 for
  12.526 + * <,=,> */
  12.527 +static int compare_net_tx(xenstat_domain *domain1, xenstat_domain *domain2)
  12.528 +{
  12.529 +	return -compare(tot_net_bytes(domain1, FALSE),
  12.530 +	                tot_net_bytes(domain2, FALSE));
  12.531 +}
  12.532 +
  12.533 +/* Prints number of total network tx bytes statistic */
  12.534 +static void print_net_tx(xenstat_domain *domain)
  12.535 +{
  12.536 +	print("%8llu", tot_net_bytes(domain, FALSE)/1024);
  12.537 +}
  12.538 +
  12.539 +/* Compares number of total network rx bytes of two domains, returning -1,0,1 for
  12.540 + * <,=,> */
  12.541 +static int compare_net_rx(xenstat_domain *domain1, xenstat_domain *domain2)
  12.542 +{
  12.543 +	return -compare(tot_net_bytes(domain1, TRUE),
  12.544 +	                tot_net_bytes(domain2, TRUE));
  12.545 +}
  12.546 +
  12.547 +/* Prints number of total network rx bytes statistic */
  12.548 +static void print_net_rx(xenstat_domain *domain)
  12.549 +{
  12.550 +	print("%8llu", tot_net_bytes(domain, TRUE)/1024);
  12.551 +}
  12.552 +
  12.553 +/* Gets number of total network bytes statistic, if rx true, then rx bytes
  12.554 + * otherwise tx bytes
  12.555 + */
  12.556 +static unsigned long long tot_net_bytes(xenstat_domain *domain, int rx_flag)
  12.557 +{
  12.558 +	int i = 0;
  12.559 +	xenstat_network *network;
  12.560 +	unsigned num_networks = 0;
  12.561 +        unsigned long long total = 0;
  12.562 +
  12.563 +	/* How many networks? */
  12.564 +	num_networks = xenstat_domain_num_networks(domain);
  12.565 +
  12.566 +	/* Dump information for each network */
  12.567 +	for (i=0; i < num_networks; i++) {
  12.568 +		/* Next get the network information */
  12.569 +		network = xenstat_domain_network(domain,i);
  12.570 +                if (rx_flag) 
  12.571 +			total += xenstat_network_rbytes(network);
  12.572 +                else 
  12.573 +			total += xenstat_network_tbytes(network);
  12.574 +	}
  12.575 +        return (total);
  12.576 +}
  12.577 +
  12.578 +/* Compares security id (ssid) of two domains, returning -1,0,1 for <,=,> */
  12.579 +static int compare_ssid(xenstat_domain *domain1, xenstat_domain *domain2)
  12.580 +{
  12.581 +	return compare(xenstat_domain_ssid(domain1),
  12.582 +		       xenstat_domain_ssid(domain2));
  12.583 +}
  12.584 +
  12.585 +/* Prints ssid statistic */
  12.586 +static void print_ssid(xenstat_domain *domain)
  12.587 +{
  12.588 +	print("%4u", xenstat_domain_ssid(domain));
  12.589 +}
  12.590 +
  12.591 +/* Section printing functions */
  12.592 +/* Prints the top summary, above the domain table */
  12.593 +void do_summary(void)
  12.594 +{
  12.595 +#define TIME_STR_LEN 9
  12.596 +	const char *TIME_STR_FORMAT = "%H:%M:%S";
  12.597 +	char time_str[TIME_STR_LEN];
  12.598 +	unsigned run = 0, block = 0, pause = 0,
  12.599 +	         crash = 0, dying = 0, shutdown = 0;
  12.600 +	unsigned i, num_domains = 0;
  12.601 +	unsigned long long used = 0;
  12.602 +	xenstat_domain *domain;
  12.603 +
  12.604 +	/* Print program name, current time, and number of domains */
  12.605 +	strftime(time_str, TIME_STR_LEN, TIME_STR_FORMAT,
  12.606 +	         localtime(&curtime.tv_sec));
  12.607 +	num_domains = xenstat_node_num_domains(cur_node);
  12.608 +	print("xentop - %s\n", time_str);
  12.609 +
  12.610 +	/* Tabulate what states domains are in for summary */
  12.611 +	for (i=0; i < num_domains; i++) {
  12.612 +		domain = xenstat_node_domain_by_index(cur_node,i);
  12.613 +		if (xenstat_domain_running(domain)) run++;
  12.614 +		else if (xenstat_domain_blocked(domain)) block++;
  12.615 +		else if (xenstat_domain_paused(domain)) pause++;
  12.616 +		else if (xenstat_domain_shutdown(domain)) shutdown++;
  12.617 +		else if (xenstat_domain_crashed(domain)) crash++;
  12.618 +		else if (xenstat_domain_dying(domain)) dying++;
  12.619 +	}
  12.620 +
  12.621 +	print("%u domains: %u running, %u blocked, %u paused, "
  12.622 +	      "%u crashed, %u dying, %u shutdown \n",
  12.623 +	      num_domains, run, block, pause, crash, dying, shutdown);
  12.624 +
  12.625 +	used = xenstat_node_tot_mem(cur_node)-xenstat_node_free_mem(cur_node);
  12.626 +
  12.627 +	/* Dump node memory and cpu information */
  12.628 +	print("Mem: %lluk total, %lluk used, %lluk free    "
  12.629 +	      "CPUs: %u @ %lluMHz\n",
  12.630 +	      xenstat_node_tot_mem(cur_node)/1024, used/1024,
  12.631 +	      xenstat_node_free_mem(cur_node)/1024,
  12.632 +	      xenstat_node_num_cpus(cur_node),
  12.633 +	      xenstat_node_cpu_hz(cur_node)/1000000);
  12.634 +}
  12.635 +
  12.636 +/* Display the top header for the domain table */
  12.637 +void do_header(void)
  12.638 +{
  12.639 +	field_id i;
  12.640 +
  12.641 +	/* Turn on REVERSE highlight attribute for headings */
  12.642 +	attron(A_REVERSE);
  12.643 +	for(i = 0; i < NUM_FIELDS; i++) {
  12.644 +		if(i != 0)
  12.645 +			print(" ");
  12.646 +		/* The BOLD attribute is turned on for the sort column */
  12.647 +		if(i == sort_field)
  12.648 +			attron(A_BOLD);
  12.649 +		print("%*s", fields[i].default_width, fields[i].header);
  12.650 +		if(i == sort_field)
  12.651 +			attroff(A_BOLD);
  12.652 +	}
  12.653 +	attroff(A_REVERSE);
  12.654 +	print("\n");
  12.655 +}
  12.656 +
  12.657 +/* Displays bottom status line or current prompt */
  12.658 +void do_bottom_line(void)
  12.659 +{
  12.660 +	move(lines()-1, 2);
  12.661 +
  12.662 +	if (prompt != NULL) {
  12.663 +		printw("%s: %s", prompt, prompt_val);
  12.664 +	} else {
  12.665 +		addch(A_REVERSE | 'D'); addstr("elay  ");
  12.666 +
  12.667 +		/* network */
  12.668 +		addch(A_REVERSE | 'N');
  12.669 +		attr_addstr(show_networks ? COLOR_PAIR(1) : 0, "etworks");
  12.670 +		addstr("  ");
  12.671 +
  12.672 +		/* vcpus */
  12.673 +		addch(A_REVERSE | 'V');
  12.674 +		attr_addstr(show_vcpus ? COLOR_PAIR(1) : 0, "CPUs");
  12.675 +		addstr("  ");
  12.676 +
  12.677 +		/* repeat */
  12.678 +		addch(A_REVERSE | 'R');
  12.679 +		attr_addstr(repeat_header ? COLOR_PAIR(1) : 0, "epeat header");
  12.680 +		addstr("  ");
  12.681 +
  12.682 +		/* sort order */
  12.683 +		addch(A_REVERSE | 'S'); addstr("ort order  ");
  12.684 +
  12.685 +		addch(A_REVERSE | 'Q'); addstr("uit  ");
  12.686 +	}
  12.687 +}
  12.688 +
  12.689 +/* Prints Domain information */
  12.690 +void do_domain(xenstat_domain *domain)
  12.691 +{
  12.692 +	unsigned int i;
  12.693 +	for(i = 0; i < NUM_FIELDS; i++) {
  12.694 +		if(i != 0)
  12.695 +			print(" ");
  12.696 +		if(i == sort_field)
  12.697 +			attron(A_BOLD);
  12.698 +		fields[i].print(domain);
  12.699 +		if(i == sort_field)
  12.700 +			attroff(A_BOLD);
  12.701 +	}
  12.702 +	print("\n");
  12.703 +}
  12.704 +
  12.705 +/* Output all vcpu information */
  12.706 +void do_vcpu(xenstat_domain *domain)
  12.707 +{
  12.708 +	int i = 0;
  12.709 +	unsigned num_vcpus = 0;
  12.710 +	xenstat_vcpu *vcpu;
  12.711 +
  12.712 +	print("VCPUs(sec): ");
  12.713 +
  12.714 +	num_vcpus = xenstat_domain_num_vcpus(domain);
  12.715 +
  12.716 +	/* for all vcpus dump out values */
  12.717 +	for (i=0; i< num_vcpus; i++) {
  12.718 +		vcpu = xenstat_domain_vcpu(domain,i);
  12.719 +
  12.720 +		if (i != 0 && (i%5)==0)
  12.721 +			print("\n        ");
  12.722 +		print(" %2u: %10llus", i, xenstat_vcpu_ns(vcpu)/1000000000);
  12.723 +	}
  12.724 +	print("\n");
  12.725 +}
  12.726 +
  12.727 +/* Output all network information */
  12.728 +void do_network(xenstat_domain *domain)
  12.729 +{
  12.730 +	int i = 0;
  12.731 +	xenstat_network *network;
  12.732 +	unsigned num_networks = 0;
  12.733 +
  12.734 +	/* How many networks? */
  12.735 +	num_networks = xenstat_domain_num_networks(domain);
  12.736 +
  12.737 +	/* Dump information for each network */
  12.738 +	for (i=0; i < num_networks; i++) {
  12.739 +		/* Next get the network information */
  12.740 +		network = xenstat_domain_network(domain,i);
  12.741 +
  12.742 +		print("Net%d RX: %8llubytes %8llupkts %8lluerr %8lludrop  ",
  12.743 +		      i,
  12.744 +		      xenstat_network_rbytes(network),
  12.745 +		      xenstat_network_rpackets(network),
  12.746 +		      xenstat_network_rerrs(network),
  12.747 +		      xenstat_network_rdrop(network));
  12.748 +
  12.749 +		print("TX: %8llubytes %8llupkts %8lluerr %8lludrop\n",
  12.750 +		      xenstat_network_tbytes(network),
  12.751 +		      xenstat_network_tpackets(network),
  12.752 +		      xenstat_network_terrs(network),
  12.753 +		      xenstat_network_tdrop(network));
  12.754 +	}
  12.755 +}
  12.756 +
  12.757 +static void top(void)
  12.758 +{
  12.759 +	xenstat_domain **domains;
  12.760 +	unsigned int i, num_domains = 0;
  12.761 +
  12.762 +	/* Now get the node information */
  12.763 +	if (prev_node != NULL)
  12.764 +		xenstat_free_node(prev_node);
  12.765 +	prev_node = cur_node;
  12.766 +	cur_node = xenstat_get_node(xhandle, XENSTAT_ALL);
  12.767 +	if (cur_node == NULL)
  12.768 +		fail("Failed to retrieve statistics from libxenstat\n");
  12.769 +
  12.770 +	/* dump summary top information */
  12.771 +	do_summary();
  12.772 +
  12.773 +	/* Count the number of domains for which to report data */
  12.774 +	num_domains = xenstat_node_num_domains(cur_node);
  12.775 +
  12.776 +	domains = malloc(num_domains*sizeof(xenstat_domain *));
  12.777 +	if(domains == NULL)
  12.778 +		fail("Failed to allocate memory\n");
  12.779 +
  12.780 +	for (i=0; i < num_domains; i++)
  12.781 +		domains[i] = xenstat_node_domain_by_index(cur_node, i);
  12.782 +
  12.783 +	/* Sort */
  12.784 +	qsort(domains, num_domains, sizeof(xenstat_domain *),
  12.785 +	      (int(*)(const void *, const void *))compare_domains);
  12.786 +
  12.787 +	if(first_domain_index >= num_domains)
  12.788 +		first_domain_index = num_domains-1;
  12.789 +
  12.790 +	for (i = first_domain_index; i < num_domains; i++) {
  12.791 +		if(current_row() == lines()-1)
  12.792 +			break;
  12.793 +		if (i == first_domain_index || repeat_header)
  12.794 +			do_header();
  12.795 +		do_domain(domains[i]);
  12.796 +		if (show_vcpus)
  12.797 +			do_vcpu(domains[i]);
  12.798 +		if (show_networks)
  12.799 +			do_network(domains[i]);
  12.800 +	}
  12.801 +
  12.802 +	do_bottom_line();
  12.803 +}
  12.804 +
  12.805 +int main(int argc, char **argv)
  12.806 +{
  12.807 +	int opt, optind = 0;
  12.808 +	int ch = ERR;
  12.809 +
  12.810 +	struct option lopts[] = {
  12.811 +		{ "help",          no_argument,       NULL, 'h' },
  12.812 +		{ "version",       no_argument,       NULL, 'V' },
  12.813 +		{ "networks",      no_argument,       NULL, 'n' },
  12.814 +		{ "repeat-header", no_argument,       NULL, 'r' },
  12.815 +		{ "vcpus",         no_argument,       NULL, 'v' },
  12.816 +		{ "delay",         required_argument, NULL, 'd' },
  12.817 +		{ 0, 0, 0, 0 },
  12.818 +	};
  12.819 +	const char *sopts = "hVbnvd:";
  12.820 +
  12.821 +	if (atexit(cleanup) != 0)
  12.822 +		fail("Failed to install cleanup handler.\n");
  12.823 +
  12.824 +	while ((opt = getopt_long(argc, argv, sopts, lopts, &optind)) != -1) {
  12.825 +		switch (opt) {
  12.826 +		case 'h':
  12.827 +		case '?':
  12.828 +		default:
  12.829 +			usage(argv[0]);
  12.830 +			exit(0);
  12.831 +		case 'V':
  12.832 +			version();
  12.833 +			exit(0);
  12.834 +		case 'n':
  12.835 +			show_networks = 1;
  12.836 +			break;
  12.837 +		case 'r':
  12.838 +			repeat_header = 1;
  12.839 +			break;
  12.840 +		case 'v':
  12.841 +			show_vcpus = 1;
  12.842 +			break;
  12.843 +		case 'd':
  12.844 +			delay = atoi(optarg);
  12.845 +			break;
  12.846 +		}
  12.847 +	}
  12.848 +
  12.849 +	/* Get xenstat handle */
  12.850 +	xhandle = xenstat_init();
  12.851 +	if (xhandle == NULL)
  12.852 +		fail("Failed to initialize xenstat library\n");
  12.853 +
  12.854 +	/* Begin curses stuff */
  12.855 +	initscr();
  12.856 +	start_color();
  12.857 +	cbreak();
  12.858 +	noecho();
  12.859 +	nonl();
  12.860 +	keypad(stdscr, TRUE);
  12.861 +	halfdelay(5);
  12.862 +	use_default_colors();
  12.863 +	init_pair(1, -1, COLOR_YELLOW);
  12.864 +
  12.865 +	do {
  12.866 +		gettimeofday(&curtime, NULL);
  12.867 +		if(ch != ERR || (curtime.tv_sec - oldtime.tv_sec) >= delay) {
  12.868 +			clear();
  12.869 +			top();
  12.870 +			oldtime = curtime;
  12.871 +			refresh();
  12.872 +		}
  12.873 +		ch = getch();
  12.874 +	} while (handle_key(ch));
  12.875 +
  12.876 +	/* Cleanup occurs in cleanup(), so no work to do here. */
  12.877 +
  12.878 +	return 0;
  12.879 +}