direct-io.hg

view tools/xenstat/xentop/xentop.c @ 7477:5a7baecb1c70

Fix an issue for passing arguement from control panel to deivce model
for some arguemnt like 'localtime', 'isa', device model need an argument
"-localtime", instead of "-localtime 1"
Signed-off-by: Xiaofeng Ling <xiaofeng.ling@intel.com>
author kaf24@firebug.cl.cam.ac.uk
date Sun Oct 23 16:51:47 2005 +0100 (2005-10-23)
parents 37050ba0e35c
children a793b7a53605
line source
1 /*
2 * Copyright (C) International Business Machines Corp., 2005
3 * Author(s): Judy Fischbach <jfisch@us.ibm.com>
4 * David Hendricks <dhendrix@us.ibm.com>
5 * Josh Triplett <josht@us.ibm.com>
6 * based on code from Anthony Liguori <aliguori@us.ibm.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; under version 2 of the License.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21 #include <curses.h>
22 #include <ctype.h>
23 #include <errno.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <sys/time.h>
28 #include <time.h>
29 #include <unistd.h>
31 #include <xenstat.h>
33 #define XENTOP_VERSION "1.0"
35 #define XENTOP_DISCLAIMER \
36 "Copyright (C) 2005 International Business Machines Corp\n"\
37 "This is free software; see the source for copying conditions.There is NO\n"\
38 "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
39 #define XENTOP_BUGSTO "Report bugs to <dsteklof@us.ibm.com>.\n"
41 #define _GNU_SOURCE
42 #include <getopt.h>
44 #if !defined(__GNUC__) && !defined(__GNUG__)
45 #define __attribute__(arg) /* empty */
46 #endif
48 #define KEY_ESCAPE '\x1B'
50 /*
51 * Function prototypes
52 */
53 /* Utility functions */
54 static void usage(const char *);
55 static void version(void);
56 static void cleanup(void);
57 static void fail(const char *);
58 static int current_row(void);
59 static int lines(void);
60 static void print(const char *, ...) __attribute__((format(printf,1,2)));
61 static void attr_addstr(int attr, const char *str);
62 static void set_delay(char *value);
63 static void set_prompt(char *new_prompt, void (*func)(char *));
64 static int handle_key(int);
65 static int compare(unsigned long long, unsigned long long);
66 static int compare_domains(xenstat_domain **, xenstat_domain **);
67 static unsigned long long tot_net_bytes( xenstat_domain *, int);
69 /* Field functions */
70 static int compare_domid(xenstat_domain *domain1, xenstat_domain *domain2);
71 static void print_domid(xenstat_domain *domain);
72 static int compare_state(xenstat_domain *domain1, xenstat_domain *domain2);
73 static void print_state(xenstat_domain *domain);
74 static int compare_cpu(xenstat_domain *domain1, xenstat_domain *domain2);
75 static void print_cpu(xenstat_domain *domain);
76 static int compare_cpu_pct(xenstat_domain *domain1, xenstat_domain *domain2);
77 static void print_cpu_pct(xenstat_domain *domain);
78 static int compare_mem(xenstat_domain *domain1, xenstat_domain *domain2);
79 static void print_mem(xenstat_domain *domain);
80 static void print_mem_pct(xenstat_domain *domain);
81 static int compare_maxmem(xenstat_domain *domain1, xenstat_domain *domain2);
82 static void print_maxmem(xenstat_domain *domain);
83 static void print_max_pct(xenstat_domain *domain);
84 static int compare_vcpus(xenstat_domain *domain1, xenstat_domain *domain2);
85 static void print_vcpus(xenstat_domain *domain);
86 static int compare_nets(xenstat_domain *domain1, xenstat_domain *domain2);
87 static void print_nets(xenstat_domain *domain);
88 static int compare_net_tx(xenstat_domain *domain1, xenstat_domain *domain2);
89 static void print_net_tx(xenstat_domain *domain);
90 static int compare_net_rx(xenstat_domain *domain1, xenstat_domain *domain2);
91 static void print_net_rx(xenstat_domain *domain);
92 static int compare_ssid(xenstat_domain *domain1, xenstat_domain *domain2);
93 static void print_ssid(xenstat_domain *domain);
95 /* Section printing functions */
96 static void do_summary(void);
97 static void do_header(void);
98 static void do_bottom_line(void);
99 static void do_domain(xenstat_domain *);
100 static void do_vcpu(xenstat_domain *);
101 static void do_network(xenstat_domain *);
102 static void top(void);
104 /* Field types */
105 typedef enum field_id {
106 FIELD_DOMID,
107 FIELD_STATE,
108 FIELD_CPU,
109 FIELD_CPU_PCT,
110 FIELD_MEM,
111 FIELD_MEM_PCT,
112 FIELD_MAXMEM,
113 FIELD_MAX_PCT,
114 FIELD_VCPUS,
115 FIELD_NETS,
116 FIELD_NET_TX,
117 FIELD_NET_RX,
118 FIELD_SSID
119 } field_id;
121 typedef struct field {
122 field_id num;
123 const char *header;
124 unsigned int default_width;
125 int (*compare)(xenstat_domain *domain1, xenstat_domain *domain2);
126 void (*print)(xenstat_domain *domain);
127 } field;
129 field fields[] = {
130 { FIELD_DOMID, "DOMID", 5, compare_domid, print_domid },
131 { FIELD_STATE, "STATE", 6, compare_state, print_state },
132 { FIELD_CPU, "CPU(sec)", 10, compare_cpu, print_cpu },
133 { FIELD_CPU_PCT, "CPU(%)", 6, compare_cpu_pct, print_cpu_pct },
134 { FIELD_MEM, "MEM(k)", 10, compare_mem, print_mem },
135 { FIELD_MEM_PCT, "MEM(%)", 6, compare_mem, print_mem_pct },
136 { FIELD_MAXMEM, "MAXMEM(k)", 10, compare_maxmem, print_maxmem },
137 { FIELD_MAX_PCT, "MAXMEM(%)", 9, compare_maxmem, print_max_pct },
138 { FIELD_VCPUS, "VCPUS", 5, compare_vcpus, print_vcpus },
139 { FIELD_NETS, "NETS", 4, compare_nets, print_nets },
140 { FIELD_NET_TX, "NETTX(k)", 8, compare_net_tx, print_net_tx },
141 { FIELD_NET_RX, "NETRX(k)", 8, compare_net_rx, print_net_rx },
142 { FIELD_SSID, "SSID", 4, compare_ssid, print_ssid }
143 };
145 const unsigned int NUM_FIELDS = sizeof(fields)/sizeof(field);
147 /* Globals */
148 struct timeval curtime, oldtime;
149 xenstat_handle *xhandle = NULL;
150 xenstat_node *prev_node = NULL;
151 xenstat_node *cur_node = NULL;
152 field_id sort_field = FIELD_DOMID;
153 unsigned int first_domain_index = 0;
154 unsigned int delay = 3;
155 int show_vcpus = 0;
156 int show_networks = 0;
157 int repeat_header = 0;
158 #define PROMPT_VAL_LEN 80
159 char *prompt = NULL;
160 char prompt_val[PROMPT_VAL_LEN];
161 int prompt_val_len = 0;
162 void (*prompt_complete_func)(char *);
164 /*
165 * Function definitions
166 */
168 /* Utility functions */
170 /* Print usage message, using given program name */
171 static void usage(const char *program)
172 {
173 printf("Usage: %s [OPTION]\n"
174 "Displays ongoing information about xen vm resources \n\n"
175 "-h, --help display this help and exit\n"
176 "-V, --version output version information and exit\n"
177 "-d, --delay=SECONDS seconds between updates (default 3)\n"
178 "-n, --networks output vif network data\n"
179 "-r, --repeat-header repeat table header before each domain\n"
180 "-v, --vcpus output vcpu data\n"
181 "\n" XENTOP_BUGSTO,
182 program);
183 return;
184 }
186 /* Print program version information */
187 static void version(void)
188 {
189 printf("xentop " XENTOP_VERSION "\n"
190 "Written by Judy Fischbach, David Hendricks, Josh Triplett\n"
191 "\n" XENTOP_DISCLAIMER);
192 }
194 /* Clean up any open resources */
195 static void cleanup(void)
196 {
197 if(!isendwin())
198 endwin();
199 if(prev_node != NULL)
200 xenstat_free_node(prev_node);
201 if(cur_node != NULL)
202 xenstat_free_node(cur_node);
203 if(xhandle != NULL)
204 xenstat_uninit(xhandle);
205 }
207 /* Display the given message and gracefully exit */
208 static void fail(const char *str)
209 {
210 if(!isendwin())
211 endwin();
212 fprintf(stderr, str);
213 exit(1);
214 }
216 /* Return the row containing the cursor. */
217 static int current_row(void)
218 {
219 int y, x;
220 getyx(stdscr, y, x);
221 return y;
222 }
224 /* Return the number of lines on the screen. */
225 static int lines(void)
226 {
227 int y, x;
228 getmaxyx(stdscr, y, x);
229 return y;
230 }
232 /* printf-style print function which calls printw, but only if the cursor is
233 * not on the last line. */
234 static void print(const char *fmt, ...)
235 {
236 va_list args;
238 if(current_row() < lines()-1) {
239 va_start(args, fmt);
240 vw_printw(stdscr, fmt, args);
241 va_end(args);
242 }
243 }
245 /* Print a string with the given attributes set. */
246 static void attr_addstr(int attr, const char *str)
247 {
248 attron(attr);
249 addstr(str);
250 attroff(attr);
251 }
253 /* Handle setting the delay from the user-supplied value in prompt_val */
254 static void set_delay(char *value)
255 {
256 int new_delay;
257 new_delay = atoi(value);
258 if(new_delay > 0)
259 delay = new_delay;
260 }
262 /* Enable prompting mode with the given prompt string; call the given function
263 * when a value is available. */
264 static void set_prompt(char *new_prompt, void (*func)(char *))
265 {
266 prompt = new_prompt;
267 prompt_val[0] = '\0';
268 prompt_val_len = 0;
269 prompt_complete_func = func;
270 }
272 /* Handle user input, return 0 if the program should quit, or 1 if not */
273 static int handle_key(int ch)
274 {
275 if(prompt == NULL) {
276 /* Not prompting for input; handle interactive commands */
277 switch(ch) {
278 case 'n': case 'N':
279 show_networks ^= 1;
280 break;
281 case 'r': case 'R':
282 repeat_header ^= 1;
283 break;
284 case 's': case 'S':
285 sort_field = (sort_field + 1) % NUM_FIELDS;
286 break;
287 case 'v': case 'V':
288 show_vcpus ^= 1;
289 break;
290 case KEY_DOWN:
291 first_domain_index++;
292 break;
293 case KEY_UP:
294 if(first_domain_index > 0)
295 first_domain_index--;
296 break;
297 case 'd': case 'D':
298 set_prompt("Delay(sec)", set_delay);
299 break;
300 case 'q': case 'Q': case KEY_ESCAPE:
301 return 0;
302 }
303 } else {
304 /* Prompting for input; handle line editing */
305 switch(ch) {
306 case '\r':
307 prompt_complete_func(prompt_val);
308 set_prompt(NULL, NULL);
309 break;
310 case KEY_ESCAPE:
311 set_prompt(NULL, NULL);
312 break;
313 case KEY_BACKSPACE:
314 if(prompt_val_len > 0)
315 prompt_val[--prompt_val_len] = '\0';
316 default:
317 if((prompt_val_len+1) < PROMPT_VAL_LEN
318 && isprint(ch)) {
319 prompt_val[prompt_val_len++] = (char)ch;
320 prompt_val[prompt_val_len] = '\0';
321 }
322 }
323 }
325 return 1;
326 }
328 /* Compares two integers, returning -1,0,1 for <,=,> */
329 static int compare(unsigned long long i1, unsigned long long i2)
330 {
331 if(i1 < i2)
332 return -1;
333 if(i1 > i2)
334 return 1;
335 return 0;
336 }
338 /* Comparison function for use with qsort. Compares two domains using the
339 * current sort field. */
340 static int compare_domains(xenstat_domain **domain1, xenstat_domain **domain2)
341 {
342 return fields[sort_field].compare(*domain1, *domain2);
343 }
345 /* Field functions */
347 /* Compares domain ids of two domains, returning -1,0,1 for <,=,> */
348 int compare_domid(xenstat_domain *domain1, xenstat_domain *domain2)
349 {
350 return compare(xenstat_domain_id(domain1), xenstat_domain_id(domain2));
351 }
353 /* Prints domain identification number */
354 void print_domid(xenstat_domain *domain)
355 {
356 print("%5u", xenstat_domain_id(domain));
357 }
359 struct {
360 unsigned int (*get)(xenstat_domain *);
361 char ch;
362 } state_funcs[] = {
363 { xenstat_domain_dying, 'd' },
364 { xenstat_domain_shutdown, 's' },
365 { xenstat_domain_blocked, 'b' },
366 { xenstat_domain_crashed, 'c' },
367 { xenstat_domain_paused, 'p' },
368 { xenstat_domain_running, 'r' }
369 };
370 const unsigned int NUM_STATES = sizeof(state_funcs)/sizeof(*state_funcs);
372 /* Compare states of two domains, returning -1,0,1 for <,=,> */
373 static int compare_state(xenstat_domain *domain1, xenstat_domain *domain2)
374 {
375 unsigned int i, d1s, d2s;
376 for(i = 0; i < NUM_STATES; i++) {
377 d1s = state_funcs[i].get(domain1);
378 d2s = state_funcs[i].get(domain2);
379 if(d1s && !d2s)
380 return -1;
381 if(d2s && !d1s)
382 return 1;
383 }
384 return 0;
385 }
387 /* Prints domain state in abbreviated letter format */
388 static void print_state(xenstat_domain *domain)
389 {
390 unsigned int i;
391 for(i = 0; i < NUM_STATES; i++)
392 print("%c", state_funcs[i].get(domain) ? state_funcs[i].ch
393 : '-');
394 }
396 /* Compares cpu usage of two domains, returning -1,0,1 for <,=,> */
397 static int compare_cpu(xenstat_domain *domain1, xenstat_domain *domain2)
398 {
399 return -compare(xenstat_domain_cpu_ns(domain1),
400 xenstat_domain_cpu_ns(domain2));
401 }
403 /* Prints domain cpu usage in seconds */
404 static void print_cpu(xenstat_domain *domain)
405 {
406 print("%10llu", xenstat_domain_cpu_ns(domain)/1000000000);
407 }
409 /* Computes the CPU percentage used for a specified domain */
410 static double get_cpu_pct(xenstat_domain *domain)
411 {
412 xenstat_domain *old_domain;
413 double us_elapsed;
415 /* Can't calculate CPU percentage without a previous sample. */
416 if(prev_node == NULL)
417 return 0.0;
419 old_domain = xenstat_node_domain(prev_node, xenstat_domain_id(domain));
420 if(old_domain == NULL)
421 return 0.0;
423 /* Calculate the time elapsed in microseconds */
424 us_elapsed = ((curtime.tv_sec-oldtime.tv_sec)*1000000.0
425 +(curtime.tv_usec - oldtime.tv_usec));
427 /* In the following, nanoseconds must be multiplied by 1000.0 to
428 * convert to microseconds, then divided by 100.0 to get a percentage,
429 * resulting in a multiplication by 10.0 */
430 return ((xenstat_domain_cpu_ns(domain)
431 -xenstat_domain_cpu_ns(old_domain))/10.0)/us_elapsed;
432 }
434 static int compare_cpu_pct(xenstat_domain *domain1, xenstat_domain *domain2)
435 {
436 return -compare(get_cpu_pct(domain1), get_cpu_pct(domain2));
437 }
439 /* Prints cpu percentage statistic */
440 static void print_cpu_pct(xenstat_domain *domain)
441 {
442 print("%6.1f", get_cpu_pct(domain));
443 }
445 /* Compares current memory of two domains, returning -1,0,1 for <,=,> */
446 static int compare_mem(xenstat_domain *domain1, xenstat_domain *domain2)
447 {
448 return -compare(xenstat_domain_cur_mem(domain1),
449 xenstat_domain_cur_mem(domain2));
450 }
452 /* Prints current memory statistic */
453 static void print_mem(xenstat_domain *domain)
454 {
455 print("%10llu", xenstat_domain_cur_mem(domain)/1024);
456 }
458 /* Prints memory percentage statistic, ratio of current domain memory to total
459 * node memory */
460 static void print_mem_pct(xenstat_domain *domain)
461 {
462 print("%6.1f", (double)xenstat_domain_cur_mem(domain) /
463 (double)xenstat_node_tot_mem(cur_node) * 100);
464 }
466 /* Compares maximum memory of two domains, returning -1,0,1 for <,=,> */
467 static int compare_maxmem(xenstat_domain *domain1, xenstat_domain *domain2)
468 {
469 return -compare(xenstat_domain_max_mem(domain1),
470 xenstat_domain_max_mem(domain2));
471 }
473 /* Prints maximum domain memory statistic in KB */
474 static void print_maxmem(xenstat_domain *domain)
475 {
476 unsigned long long max_mem = xenstat_domain_max_mem(domain);
477 if(max_mem == ((unsigned long long)-1))
478 print("%10s", "no limit");
479 else
480 print("%10llu", max_mem/1024);
481 }
483 /* Prints memory percentage statistic, ratio of current domain memory to total
484 * node memory */
485 static void print_max_pct(xenstat_domain *domain)
486 {
487 if (xenstat_domain_max_mem(domain) == (unsigned long long)-1)
488 print("%9s", "n/a");
489 else
490 print("%9.1f", (double)xenstat_domain_max_mem(domain) /
491 (double)xenstat_node_tot_mem(cur_node) * 100);
492 }
494 /* Compares number of virtual CPUs of two domains, returning -1,0,1 for
495 * <,=,> */
496 static int compare_vcpus(xenstat_domain *domain1, xenstat_domain *domain2)
497 {
498 return -compare(xenstat_domain_num_vcpus(domain1),
499 xenstat_domain_num_vcpus(domain2));
500 }
502 /* Prints number of virtual CPUs statistic */
503 static void print_vcpus(xenstat_domain *domain)
504 {
505 print("%5u", xenstat_domain_num_vcpus(domain));
506 }
508 /* Compares number of virtual networks of two domains, returning -1,0,1 for
509 * <,=,> */
510 static int compare_nets(xenstat_domain *domain1, xenstat_domain *domain2)
511 {
512 return -compare(xenstat_domain_num_networks(domain1),
513 xenstat_domain_num_networks(domain2));
514 }
516 /* Prints number of virtual networks statistic */
517 static void print_nets(xenstat_domain *domain)
518 {
519 print("%4u", xenstat_domain_num_networks(domain));
520 }
522 /* Compares number of total network tx bytes of two domains, returning -1,0,1
523 * for <,=,> */
524 static int compare_net_tx(xenstat_domain *domain1, xenstat_domain *domain2)
525 {
526 return -compare(tot_net_bytes(domain1, FALSE),
527 tot_net_bytes(domain2, FALSE));
528 }
530 /* Prints number of total network tx bytes statistic */
531 static void print_net_tx(xenstat_domain *domain)
532 {
533 print("%8llu", tot_net_bytes(domain, FALSE)/1024);
534 }
536 /* Compares number of total network rx bytes of two domains, returning -1,0,1
537 * for <,=,> */
538 static int compare_net_rx(xenstat_domain *domain1, xenstat_domain *domain2)
539 {
540 return -compare(tot_net_bytes(domain1, TRUE),
541 tot_net_bytes(domain2, TRUE));
542 }
544 /* Prints number of total network rx bytes statistic */
545 static void print_net_rx(xenstat_domain *domain)
546 {
547 print("%8llu", tot_net_bytes(domain, TRUE)/1024);
548 }
550 /* Gets number of total network bytes statistic, if rx true, then rx bytes
551 * otherwise tx bytes
552 */
553 static unsigned long long tot_net_bytes(xenstat_domain *domain, int rx_flag)
554 {
555 int i = 0;
556 xenstat_network *network;
557 unsigned num_networks = 0;
558 unsigned long long total = 0;
560 /* How many networks? */
561 num_networks = xenstat_domain_num_networks(domain);
563 /* Dump information for each network */
564 for (i=0; i < num_networks; i++) {
565 /* Next get the network information */
566 network = xenstat_domain_network(domain,i);
567 if (rx_flag)
568 total += xenstat_network_rbytes(network);
569 else
570 total += xenstat_network_tbytes(network);
571 }
573 return total;
574 }
576 /* Compares security id (ssid) of two domains, returning -1,0,1 for <,=,> */
577 static int compare_ssid(xenstat_domain *domain1, xenstat_domain *domain2)
578 {
579 return compare(xenstat_domain_ssid(domain1),
580 xenstat_domain_ssid(domain2));
581 }
583 /* Prints ssid statistic */
584 static void print_ssid(xenstat_domain *domain)
585 {
586 print("%4u", xenstat_domain_ssid(domain));
587 }
589 /* Section printing functions */
590 /* Prints the top summary, above the domain table */
591 void do_summary(void)
592 {
593 #define TIME_STR_LEN 9
594 const char *TIME_STR_FORMAT = "%H:%M:%S";
595 char time_str[TIME_STR_LEN];
596 const char *ver_str;
597 unsigned run = 0, block = 0, pause = 0,
598 crash = 0, dying = 0, shutdown = 0;
599 unsigned i, num_domains = 0;
600 unsigned long long used = 0;
601 xenstat_domain *domain;
603 /* Print program name, current time, and number of domains */
604 strftime(time_str, TIME_STR_LEN, TIME_STR_FORMAT,
605 localtime(&curtime.tv_sec));
606 num_domains = xenstat_node_num_domains(cur_node);
607 ver_str = xenstat_node_xen_version(cur_node);
608 print("xentop - %s Xen %s\n", time_str, ver_str);
610 /* Tabulate what states domains are in for summary */
611 for (i=0; i < num_domains; i++) {
612 domain = xenstat_node_domain_by_index(cur_node,i);
613 if (xenstat_domain_running(domain)) run++;
614 else if (xenstat_domain_blocked(domain)) block++;
615 else if (xenstat_domain_paused(domain)) pause++;
616 else if (xenstat_domain_shutdown(domain)) shutdown++;
617 else if (xenstat_domain_crashed(domain)) crash++;
618 else if (xenstat_domain_dying(domain)) dying++;
619 }
621 print("%u domains: %u running, %u blocked, %u paused, "
622 "%u crashed, %u dying, %u shutdown \n",
623 num_domains, run, block, pause, crash, dying, shutdown);
625 used = xenstat_node_tot_mem(cur_node)-xenstat_node_free_mem(cur_node);
627 /* Dump node memory and cpu information */
628 print("Mem: %lluk total, %lluk used, %lluk free "
629 "CPUs: %u @ %lluMHz\n",
630 xenstat_node_tot_mem(cur_node)/1024, used/1024,
631 xenstat_node_free_mem(cur_node)/1024,
632 xenstat_node_num_cpus(cur_node),
633 xenstat_node_cpu_hz(cur_node)/1000000);
634 }
636 /* Display the top header for the domain table */
637 void do_header(void)
638 {
639 field_id i;
641 /* Turn on REVERSE highlight attribute for headings */
642 attron(A_REVERSE);
643 for(i = 0; i < NUM_FIELDS; i++) {
644 if(i != 0)
645 print(" ");
646 /* The BOLD attribute is turned on for the sort column */
647 if(i == sort_field)
648 attron(A_BOLD);
649 print("%*s", fields[i].default_width, fields[i].header);
650 if(i == sort_field)
651 attroff(A_BOLD);
652 }
653 attroff(A_REVERSE);
654 print("\n");
655 }
657 /* Displays bottom status line or current prompt */
658 void do_bottom_line(void)
659 {
660 move(lines()-1, 2);
662 if (prompt != NULL) {
663 printw("%s: %s", prompt, prompt_val);
664 } else {
665 addch(A_REVERSE | 'D'); addstr("elay ");
667 /* network */
668 addch(A_REVERSE | 'N');
669 attr_addstr(show_networks ? COLOR_PAIR(1) : 0, "etworks");
670 addstr(" ");
672 /* vcpus */
673 addch(A_REVERSE | 'V');
674 attr_addstr(show_vcpus ? COLOR_PAIR(1) : 0, "CPUs");
675 addstr(" ");
677 /* repeat */
678 addch(A_REVERSE | 'R');
679 attr_addstr(repeat_header ? COLOR_PAIR(1) : 0, "epeat header");
680 addstr(" ");
682 /* sort order */
683 addch(A_REVERSE | 'S'); addstr("ort order ");
685 addch(A_REVERSE | 'Q'); addstr("uit ");
686 }
687 }
689 /* Prints Domain information */
690 void do_domain(xenstat_domain *domain)
691 {
692 unsigned int i;
693 for(i = 0; i < NUM_FIELDS; i++) {
694 if(i != 0)
695 print(" ");
696 if(i == sort_field)
697 attron(A_BOLD);
698 fields[i].print(domain);
699 if(i == sort_field)
700 attroff(A_BOLD);
701 }
702 print("\n");
703 }
705 /* Output all vcpu information */
706 void do_vcpu(xenstat_domain *domain)
707 {
708 int i = 0;
709 unsigned num_vcpus = 0;
710 xenstat_vcpu *vcpu;
712 print("VCPUs(sec): ");
714 num_vcpus = xenstat_domain_num_vcpus(domain);
716 /* for all online vcpus dump out values */
717 for (i=0; i< num_vcpus; i++) {
718 vcpu = xenstat_domain_vcpu(domain,i);
720 if (xenstat_vcpu_online(vcpu) > 0) {
721 if (i != 0 && (i%5)==0)
722 print("\n ");
723 print(" %2u: %10llus", i,
724 xenstat_vcpu_ns(vcpu)/1000000000);
725 }
726 }
727 print("\n");
728 }
730 /* Output all network information */
731 void do_network(xenstat_domain *domain)
732 {
733 int i = 0;
734 xenstat_network *network;
735 unsigned num_networks = 0;
737 /* How many networks? */
738 num_networks = xenstat_domain_num_networks(domain);
740 /* Dump information for each network */
741 for (i=0; i < num_networks; i++) {
742 /* Next get the network information */
743 network = xenstat_domain_network(domain,i);
745 print("Net%d RX: %8llubytes %8llupkts %8lluerr %8lludrop ",
746 i,
747 xenstat_network_rbytes(network),
748 xenstat_network_rpackets(network),
749 xenstat_network_rerrs(network),
750 xenstat_network_rdrop(network));
752 print("TX: %8llubytes %8llupkts %8lluerr %8lludrop\n",
753 xenstat_network_tbytes(network),
754 xenstat_network_tpackets(network),
755 xenstat_network_terrs(network),
756 xenstat_network_tdrop(network));
757 }
758 }
760 static void top(void)
761 {
762 xenstat_domain **domains;
763 unsigned int i, num_domains = 0;
765 /* Now get the node information */
766 if (prev_node != NULL)
767 xenstat_free_node(prev_node);
768 prev_node = cur_node;
769 cur_node = xenstat_get_node(xhandle, XENSTAT_ALL);
770 if (cur_node == NULL)
771 fail("Failed to retrieve statistics from libxenstat\n");
773 /* dump summary top information */
774 do_summary();
776 /* Count the number of domains for which to report data */
777 num_domains = xenstat_node_num_domains(cur_node);
779 domains = malloc(num_domains*sizeof(xenstat_domain *));
780 if(domains == NULL)
781 fail("Failed to allocate memory\n");
783 for (i=0; i < num_domains; i++)
784 domains[i] = xenstat_node_domain_by_index(cur_node, i);
786 /* Sort */
787 qsort(domains, num_domains, sizeof(xenstat_domain *),
788 (int(*)(const void *, const void *))compare_domains);
790 if(first_domain_index >= num_domains)
791 first_domain_index = num_domains-1;
793 for (i = first_domain_index; i < num_domains; i++) {
794 if(current_row() == lines()-1)
795 break;
796 if (i == first_domain_index || repeat_header)
797 do_header();
798 do_domain(domains[i]);
799 if (show_vcpus)
800 do_vcpu(domains[i]);
801 if (show_networks)
802 do_network(domains[i]);
803 }
805 do_bottom_line();
806 }
808 int main(int argc, char **argv)
809 {
810 int opt, optind = 0;
811 int ch = ERR;
813 struct option lopts[] = {
814 { "help", no_argument, NULL, 'h' },
815 { "version", no_argument, NULL, 'V' },
816 { "networks", no_argument, NULL, 'n' },
817 { "repeat-header", no_argument, NULL, 'r' },
818 { "vcpus", no_argument, NULL, 'v' },
819 { "delay", required_argument, NULL, 'd' },
820 { 0, 0, 0, 0 },
821 };
822 const char *sopts = "hVbnvd:";
824 if (atexit(cleanup) != 0)
825 fail("Failed to install cleanup handler.\n");
827 while ((opt = getopt_long(argc, argv, sopts, lopts, &optind)) != -1) {
828 switch (opt) {
829 case 'h':
830 case '?':
831 default:
832 usage(argv[0]);
833 exit(0);
834 case 'V':
835 version();
836 exit(0);
837 case 'n':
838 show_networks = 1;
839 break;
840 case 'r':
841 repeat_header = 1;
842 break;
843 case 'v':
844 show_vcpus = 1;
845 break;
846 case 'd':
847 delay = atoi(optarg);
848 break;
849 }
850 }
852 /* Get xenstat handle */
853 xhandle = xenstat_init();
854 if (xhandle == NULL)
855 fail("Failed to initialize xenstat library\n");
857 /* Begin curses stuff */
858 initscr();
859 start_color();
860 cbreak();
861 noecho();
862 nonl();
863 keypad(stdscr, TRUE);
864 halfdelay(5);
865 use_default_colors();
866 init_pair(1, -1, COLOR_YELLOW);
868 do {
869 gettimeofday(&curtime, NULL);
870 if(ch != ERR || (curtime.tv_sec - oldtime.tv_sec) >= delay) {
871 clear();
872 top();
873 oldtime = curtime;
874 refresh();
875 }
876 ch = getch();
877 } while (handle_key(ch));
879 /* Cleanup occurs in cleanup(), so no work to do here. */
881 return 0;
882 }