1269 lines
26 KiB
C
1269 lines
26 KiB
C
/* @(#)sysmeter.c 1.1 88/02/26 3.2 NFSSRC */
|
|
|
|
#include <stdio.h>
|
|
#include <errno.h>
|
|
#include <netdb.h>
|
|
#include <signal.h>
|
|
#include <string.h>
|
|
#include <sys/param.h>
|
|
#include <sys/socket.h>
|
|
#include <rpc/rpc.h>
|
|
#include <rpc/pmap_clnt.h>
|
|
#include <rpcsvc/rstat.h>
|
|
#include <arpa/inet.h>
|
|
|
|
#include <gl/gl.h>
|
|
#include <gl/device.h>
|
|
|
|
|
|
#ifndef FSCALE
|
|
#define FSCALE (1<<8)
|
|
#endif
|
|
#define MAXSTEP 5 /* five step function in slide */
|
|
#define CHAR_SIZE 9 /* width per char. */
|
|
#define SLIDER_SIZE 8 /* half of slider height */
|
|
#define H_GAP1 2 /* gap between lower horizontal line and lower chars. */
|
|
#define H_GAP2 4 /* gap between top h. line and top chars. */
|
|
#define V_GAP 2 /* gap between right vertical line and next char. */
|
|
#define PER_INT 1 /* pixls per interval */
|
|
#define MIN_PIC 1 /* min. appearance on each view */
|
|
#define MIN_INT_WID (40/PER_INT)
|
|
|
|
#define S1X1 (CHAR_SIZE)
|
|
#define S1Y1 (2*SLIDER_SIZE)
|
|
#define S1X2 (S1X1+2*SLIDER_SIZE)
|
|
#define S1Y2 (S1Y1+2*SLIDER_SIZE)
|
|
#define S2X1 (S1X2+CHAR_SIZE*5)
|
|
#define S2Y1 (S1Y1+SLIDER_SIZE-CHAR_SIZE/2)
|
|
#define S2X2 (S2X1+CHAR_SIZE)
|
|
#define S2Y2 (S1Y2-SLIDER_SIZE+CHAR_SIZE/2)
|
|
#define S3X1 (S1X1)
|
|
#define S3Y1 (0)
|
|
#define S3X2 (CHAR_SIZE*14)
|
|
#define S3Y2 (2*SLIDER_SIZE-CHAR_SIZE-2)
|
|
|
|
#define SLDXL S3X1
|
|
#define SLDXH S3X2
|
|
|
|
|
|
#define M_ALLOC 100 /* num. of structure once allocated */
|
|
|
|
#define ADJMAX(val, max, indx)\
|
|
while (max <= val) max *= 2; \
|
|
if ( val > items[indx].cmax ) { \
|
|
val = items[indx].cmax; \
|
|
}
|
|
|
|
char hostnm[MAXHOSTNAMELEN];
|
|
|
|
|
|
int g_size = 40;
|
|
int tot_elapse;
|
|
Colorindex backgnd_color = 15,
|
|
chartback_color = 12,
|
|
avg_color = 1,
|
|
text_color = 4,
|
|
changeback_color = 10;
|
|
|
|
#define P_CPU 0
|
|
#define P_PAGE 1
|
|
#define P_SWAP 2
|
|
#define P_INTR 3
|
|
#define P_DISK 4
|
|
#define P_CNTXT 5
|
|
#define P_LOAD 6
|
|
#define P_PKTS 7
|
|
#define P_IPKTS 8
|
|
#define P_OPKTS 9
|
|
#define P_COLLS 10
|
|
#define P_ERRS 11
|
|
#define MAXITEMS 12
|
|
|
|
#define P_DISP_AVG 50
|
|
#define P_PARAM 51
|
|
#define P_STYLE 52
|
|
#define P_EXIT 53
|
|
|
|
/* the latter 4 items must be number n+1 */
|
|
const char menu[] =
|
|
"Sysmeter %t|cpu|page|swap|intr|disk|contxt|load|pkts|inpkts|outpkts|colls|errs %l|Display average %x51|Change params %x52|Change style %x53|Exit %x54";
|
|
struct disp_fac {
|
|
short onoff;
|
|
short cmax;
|
|
short minmax;
|
|
short maxmax;
|
|
char *name;
|
|
int adj;
|
|
int x1;
|
|
int y1;
|
|
int x2;
|
|
int y2;
|
|
} items[MAXITEMS] = {
|
|
{0, 100, 100, 100, "cpu", 0},
|
|
{0, 16, 4, 8192, "page", 0},
|
|
{0, 4, 4, 8192, "swap", 0},
|
|
{0, 64, 4, 8192, "intr", 0},
|
|
{0, 32, 4, 8192, "disk", 0},
|
|
{0, 64, 4, 8192, "cntxt", 0},
|
|
{0, 4, 4, 8192, "load", 0},
|
|
{0, 32, 4, 8192, "pkts", 0},
|
|
{0, 32, 4, 8192, "inpkts", 0},
|
|
{0, 32, 4, 8192, "outpkts", 0},
|
|
{0, 4, 4, 8192, "colls", 0},
|
|
{0, 4, 4, 8192, "errs", 0},
|
|
};
|
|
|
|
enum { SAMPLE, AVERAGE, WINDOW } chg_state = SAMPLE;
|
|
|
|
struct entry *avail_h, *used_h, *used_t;
|
|
struct entry {
|
|
struct entry *f_link;
|
|
struct entry *b_link;
|
|
int data[MAXITEMS];
|
|
int avg[MAXITEMS];
|
|
int intv;
|
|
};
|
|
|
|
int total_item;
|
|
int smp_intv = 2, avg_intv = 20;
|
|
int meter = 0, f_row, row, x_coord = -1, y_coord = -1;
|
|
int f_duration = 120, duration;
|
|
char v_chg = 0, vflag;
|
|
int vers, Debug = 0;
|
|
int wid;
|
|
int item_len, item_high;
|
|
int in_interrupt, need_avg, fancy_title =1;
|
|
int x_size, y_size;
|
|
int rx_size, ry_size;
|
|
int menu1, accum;
|
|
int acc_s, acc_a, acc_w;
|
|
int step_val[MAXSTEP] = { 1, 5, 30, 60, 300 };
|
|
int step_rng[MAXSTEP] = { 20, 8, 8, 10, 21};
|
|
int sld_max, sld_maxp;
|
|
char buf[80];
|
|
char buf2[80];
|
|
int sig_timer;
|
|
void get_perfdata();
|
|
int set_unit();
|
|
|
|
|
|
CLIENT *Client;
|
|
struct hostent *hp;
|
|
struct timeval retry_timeout, total_timeout;
|
|
struct sockaddr_in server_addr;
|
|
int sock = RPC_ANYSOCK;
|
|
struct statstime stats_info;
|
|
|
|
main(argc, argv)
|
|
char **argv;
|
|
{
|
|
short val;
|
|
int tval, dev, x1, y1;
|
|
|
|
(void) gethostname(hostnm, sizeof(hostnm));
|
|
|
|
while (argc > 1) {
|
|
if (argv[1][0] != '-') {
|
|
if ( vflag ) {
|
|
seton(argv[1]);
|
|
}
|
|
else
|
|
usage();
|
|
}
|
|
else {
|
|
vflag = 0;
|
|
switch(argv[1][1]) {
|
|
case 's':
|
|
if ( argc < 3 || argv[2][0] == '-' )
|
|
usage();
|
|
smp_intv = atoi(argv[2]);
|
|
if ( smp_intv < 1)
|
|
smp_intv = 2;
|
|
argc--;
|
|
argv++;
|
|
break;
|
|
case 'a':
|
|
if ( argc < 3 || argv[2][0] == '-' )
|
|
usage();
|
|
avg_intv = atoi(argv[2]);
|
|
need_avg = 1;
|
|
argc--;
|
|
argv++;
|
|
break;
|
|
case 'r':
|
|
if ( argc < 3 || argv[2][0] == '-' )
|
|
usage();
|
|
f_row = atoi(argv[2]);
|
|
argc--;
|
|
argv++;
|
|
break;
|
|
case 'g':
|
|
if ( argc < 3 || argv[2][0] == '-' )
|
|
usage();
|
|
g_size = atoi(argv[2]);
|
|
argc--;
|
|
argv++;
|
|
break;
|
|
case 'h':
|
|
if ( argc < 3 || argv[2][0] == '-' )
|
|
usage();
|
|
strcpy(hostnm, argv[2]);
|
|
argc--;
|
|
argv++;
|
|
break;
|
|
case 'v':
|
|
vflag++;
|
|
break;
|
|
case 'x':
|
|
if ( argc < 3 || argv[2][0] == '-' )
|
|
usage();
|
|
x_coord = atoi(argv[2]);
|
|
argc--;
|
|
argv++;
|
|
break;
|
|
case 'y':
|
|
if ( argc < 3 || argv[2][0] == '-' )
|
|
usage();
|
|
y_coord = atoi(argv[2]);
|
|
argc--;
|
|
argv++;
|
|
break;
|
|
case 'd':
|
|
if ( argc < 3 || argv[2][0] == '-' )
|
|
usage();
|
|
f_duration = atoi(argv[2]);
|
|
argc--;
|
|
argv++;
|
|
break;
|
|
case 'm':
|
|
meter = 1;
|
|
break;
|
|
case 'D':
|
|
Debug = 1;
|
|
break;
|
|
case 'i':
|
|
if ( argc < 3 || argv[2][0] == '-' )
|
|
usage();
|
|
(void) sscanf(argv[2], "%hu,%hu,%hu,%hu,%hu",
|
|
&backgnd_color,
|
|
&chartback_color,
|
|
&avg_color,
|
|
&text_color,
|
|
&changeback_color);
|
|
argc--;
|
|
argv++;
|
|
break;
|
|
default:
|
|
usage();
|
|
}
|
|
}
|
|
argv++;
|
|
argc--;
|
|
}
|
|
|
|
if ( !total_item ) {
|
|
items[0].onoff = 1;
|
|
total_item++;
|
|
}
|
|
row = f_row;
|
|
if ( row == 0 )
|
|
row = (total_item + 1)/2;
|
|
|
|
rndup_dur();
|
|
|
|
perf_setup();
|
|
|
|
qdevice(RIGHTMOUSE);
|
|
qdevice(LEFTMOUSE);
|
|
qdevice(REDRAW);
|
|
menu1 = defpup((char *)menu);
|
|
for (tval = 0; tval < MAXITEMS; tval++) {
|
|
setpup(menu1, tval+1, items[tval].onoff ? PUP_CHECK: PUP_BOX);
|
|
}
|
|
|
|
for ( ; ; ) {
|
|
errno = 0;
|
|
dev = qread(&val);
|
|
if ( dev != REDRAW && val != 1 )
|
|
continue;
|
|
in_interrupt = 1;
|
|
switch(dev) {
|
|
case RIGHTMOUSE:
|
|
tval = dopup(menu1);
|
|
menu_op(tval);
|
|
break;
|
|
|
|
case LEFTMOUSE:
|
|
if ( v_chg ) {
|
|
x1 = getvaluator(MOUSEX) - x_coord;
|
|
y1 = getvaluator(MOUSEY) - y_coord;
|
|
left_func(x1, y1);
|
|
}
|
|
break;
|
|
|
|
case REDRAW:
|
|
re_start();
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
in_interrupt = 0;
|
|
}
|
|
}
|
|
|
|
|
|
left_func(x, y)
|
|
int x, y;
|
|
{
|
|
int i;
|
|
int t_x, t_y;
|
|
|
|
getsize((long *)&t_x, (long *)&t_y);
|
|
x = x*x_size/t_x;
|
|
y = y*y_size/t_y;
|
|
|
|
if ( x >= S1X1 && x <= S1X2 && y <= S1Y2 && y >= S1Y1 ) {
|
|
switch (chg_state) {
|
|
case SAMPLE:
|
|
if (accum >= 1)
|
|
acc_s = accum;
|
|
chg_state = AVERAGE;
|
|
accum = acc_a;
|
|
break;
|
|
case AVERAGE:
|
|
if (accum > smp_intv)
|
|
acc_a = accum;
|
|
chg_state = WINDOW;
|
|
accum = acc_w;
|
|
break;
|
|
case WINDOW:
|
|
if (accum > smp_intv)
|
|
acc_w = accum;
|
|
chg_state = SAMPLE;
|
|
accum = acc_s;
|
|
break;
|
|
}
|
|
draw_chg();
|
|
draw_chg();
|
|
return;
|
|
}
|
|
else if ( x >= S2X1 && x <= S2X2 && y <= S2Y2 && y >= S2Y1 ) {
|
|
if (acc_s < 1) {
|
|
#ifdef DEBUG
|
|
abort();
|
|
#endif
|
|
acc_s = 1;
|
|
}
|
|
smp_intv = acc_s;
|
|
avg_intv = acc_a;
|
|
f_duration = acc_w;
|
|
acc_s = acc_a = acc_w = 0;
|
|
switch (chg_state) {
|
|
case SAMPLE:
|
|
if (accum >= 1)
|
|
smp_intv = accum;
|
|
break;
|
|
case AVERAGE:
|
|
if (accum > smp_intv)
|
|
avg_intv = accum;
|
|
break;
|
|
case WINDOW:
|
|
if (accum > smp_intv)
|
|
f_duration = accum;
|
|
else
|
|
return;
|
|
break;
|
|
}
|
|
v_chg = 0;
|
|
accum = 0;
|
|
re_start();
|
|
} else {
|
|
for ( ; getbutton(LEFTMOUSE); ) {
|
|
x = getvaluator(MOUSEX) - x_coord;
|
|
y = getvaluator(MOUSEY) - y_coord;
|
|
x = x*x_size/t_x;
|
|
y = y*y_size/t_y;
|
|
if (x >= S3X1 && x <= S3X2 && y <= S3Y2 && y >= S3Y1 ) {
|
|
x = (x-SLDXL)*sld_maxp/(SLDXH - SLDXL);
|
|
accum = 0;
|
|
for ( i = 0; i < MAXSTEP; i++ ) {
|
|
if ( x > step_rng[i] ) {
|
|
accum +=
|
|
step_val[i]*step_rng[i];
|
|
x -= step_rng[i];
|
|
continue;
|
|
}
|
|
accum += step_val[i]*x;
|
|
break;
|
|
}
|
|
draw_slide(accum);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
menu_op(val)
|
|
int val;
|
|
{
|
|
val--;
|
|
if (v_chg && val != P_EXIT && val != P_PARAM)
|
|
return;
|
|
|
|
switch(val) {
|
|
case P_CPU:
|
|
case P_PAGE:
|
|
case P_SWAP:
|
|
case P_INTR:
|
|
case P_DISK:
|
|
case P_CNTXT:
|
|
case P_LOAD:
|
|
case P_PKTS:
|
|
case P_IPKTS:
|
|
case P_OPKTS:
|
|
case P_COLLS:
|
|
case P_ERRS:
|
|
if ( items[val].onoff ) {
|
|
items[val].onoff = 0;
|
|
total_item--;
|
|
setpup(menu1, val+1, PUP_BOX);
|
|
} else {
|
|
items[val].onoff = 1;
|
|
total_item++;
|
|
setpup(menu1, val+1, PUP_CHECK);
|
|
}
|
|
if ( total_item == 0 ) {
|
|
items[P_CPU].onoff = 1;
|
|
total_item = 1;
|
|
setpup(menu1, P_CPU+1, PUP_CHECK);
|
|
}
|
|
re_start();
|
|
break;
|
|
|
|
case P_DISP_AVG:
|
|
need_avg = !need_avg;
|
|
re_start();
|
|
break;
|
|
|
|
case P_PARAM:
|
|
if (v_chg) {
|
|
v_chg = 0;
|
|
re_start();
|
|
} else {
|
|
v_chg = 1;
|
|
acc_s = smp_intv;
|
|
acc_a = avg_intv;
|
|
acc_w = duration;
|
|
switch (chg_state) {
|
|
case SAMPLE:
|
|
accum = smp_intv;
|
|
break;
|
|
case AVERAGE:
|
|
accum = avg_intv;
|
|
break;
|
|
case WINDOW:
|
|
accum = duration;
|
|
break;
|
|
default:
|
|
#ifdef DEBUG
|
|
abort();
|
|
#endif
|
|
break;
|
|
}
|
|
if (acc_s < 1) {
|
|
#ifdef DEBUG
|
|
abort();
|
|
#endif
|
|
accum = 1;
|
|
}
|
|
re_draw(1);
|
|
re_draw(1);
|
|
draw_chg();
|
|
draw_chg();
|
|
}
|
|
break;
|
|
|
|
case P_STYLE:
|
|
meter = !meter;
|
|
re_start();
|
|
break;
|
|
|
|
case P_EXIT:
|
|
winclose(wid);
|
|
exit(1);
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
retitle(void)
|
|
{
|
|
char title[MAXHOSTNAMELEN + 50];
|
|
|
|
if (fancy_title) {
|
|
if ( meter ) {
|
|
if ( need_avg )
|
|
sprintf(title, "%s (samp=%ds,avg=%ds)",
|
|
hostnm, smp_intv, avg_intv);
|
|
else
|
|
sprintf(title,
|
|
"%s (samp=%ds)", hostnm, smp_intv);
|
|
} else if ( need_avg )
|
|
sprintf(title, "%s (samp=%ds,avg=%ds,win=%ds)",
|
|
hostnm, smp_intv, avg_intv, duration);
|
|
else
|
|
sprintf(title, "%s (samp=%ds,win=%ds)",
|
|
hostnm, smp_intv, duration);
|
|
} else
|
|
sprintf(title, "%s", hostnm);
|
|
|
|
wintitle(title);
|
|
}
|
|
|
|
re_start()
|
|
{
|
|
rndup_dur();
|
|
|
|
item_high = g_size + CHAR_SIZE + H_GAP1 + H_GAP2 + MIN_PIC;
|
|
if ( meter ) {
|
|
item_len = g_size + CHAR_SIZE*4+V_GAP;
|
|
} else {
|
|
item_len = (duration/smp_intv) *
|
|
PER_INT+PER_INT-1+4*CHAR_SIZE+V_GAP;
|
|
}
|
|
|
|
row = howmanyrow();
|
|
x_size = item_len*((total_item+row-1)/row)+CHAR_SIZE;
|
|
y_size = row*item_high + CHAR_SIZE;
|
|
getorigin((long *)&x_coord, (long *)&y_coord);
|
|
|
|
resize();
|
|
getsize((long *)&rx_size,(long *)&ry_size);
|
|
|
|
retitle ();
|
|
|
|
draw_backg();
|
|
draw_backg();
|
|
re_draw(1);
|
|
re_draw(1);
|
|
|
|
if ( v_chg ) {
|
|
draw_chg();
|
|
draw_chg();
|
|
}
|
|
(void) signal(SIGALRM, get_perfdata);
|
|
alarm(smp_intv);
|
|
}
|
|
|
|
|
|
|
|
seton(item)
|
|
char *item;
|
|
{
|
|
int i;
|
|
|
|
if (!strcmp(item, "all")) {
|
|
for ( i = 0; i < MAXITEMS; i++ ) {
|
|
items[i].onoff = 1;
|
|
total_item++;
|
|
}
|
|
return;
|
|
} else
|
|
for ( i = 0; i < MAXITEMS; i++ )
|
|
if ( !strcmp(item, items[i].name) ) {
|
|
items[i].onoff = 1;
|
|
total_item++;
|
|
return;
|
|
}
|
|
usage();
|
|
}
|
|
|
|
usage()
|
|
{
|
|
fprintf(stderr, "Usage: sysmeter [-s sample-interval]\n");
|
|
fprintf(stderr, " [-a averaging-interval]\n");
|
|
fprintf(stderr, " [-h hostname]\n");
|
|
fprintf(stderr, " [-r row]\n");
|
|
fprintf(stderr, " [-d duration-in-seconds]\n");
|
|
fprintf(stderr, " [-D debugging-version]\n");
|
|
fprintf(stderr, " [-x xcoord] [-y ycoord]\n");
|
|
fprintf(stderr, " [-g height]\n");
|
|
fprintf(stderr, " [-m]\n");
|
|
fprintf(stderr, " [-i 1stof5colorindex]\n");
|
|
fprintf(stderr, " [-v value value ...]\n");
|
|
fprintf(stderr, "value can be: cpu page swap intr disk cntxt load pkts inpkts outpkts colls errs\n");
|
|
exit(1);
|
|
}
|
|
|
|
perf_setup()
|
|
{
|
|
int i;
|
|
|
|
vers = RSTATVERS_TIME;
|
|
if ((hp = gethostbyname(hostnm)) == NULL) {
|
|
fprintf(stderr, "sysmeter: unknown host %s\n", hostnm);
|
|
exit(1);
|
|
}
|
|
bcopy(hp->h_addr, (caddr_t)&server_addr.sin_addr, hp->h_length);
|
|
server_addr.sin_family = AF_INET;
|
|
server_addr.sin_port = 0; /* use pmapper */
|
|
if (Debug) printf("Got the host named %s (%s)\n",
|
|
hostnm, inet_ntoa(server_addr.sin_addr));
|
|
retry_timeout.tv_sec = 5;
|
|
retry_timeout.tv_usec = 0;
|
|
|
|
if ((Client = clntudp_create(&server_addr, RSTATPROG, vers, retry_timeout,
|
|
&sock)) == NULL) {
|
|
fprintf(stderr, "sysmeter: cannot contact %s%s\n",
|
|
hostnm, clnt_spcreateerror(""));
|
|
exit(1);
|
|
}
|
|
if (Debug) printf("UDP RPC connection created\n");
|
|
Client->cl_auth = authunix_create_default();
|
|
|
|
total_timeout.tv_sec = 20;
|
|
total_timeout.tv_usec = 0;
|
|
|
|
for ( i = 0; i < MAXSTEP; i++ ) {
|
|
sld_maxp += step_rng[i];
|
|
sld_max += step_val[i]*step_rng[i];
|
|
}
|
|
|
|
/* open window, get window size and allocate memory */
|
|
create_window();
|
|
|
|
get_perfdata();
|
|
}
|
|
|
|
|
|
/* all coordination supposed to aligned with pixels, otherwise, you
|
|
can't determine the window size */
|
|
create_window()
|
|
{
|
|
item_high = g_size+CHAR_SIZE+H_GAP1+H_GAP2 + MIN_PIC;
|
|
if ( meter ) {
|
|
item_len = g_size + CHAR_SIZE*4+V_GAP;
|
|
}
|
|
else {
|
|
item_len = (duration/smp_intv)*PER_INT+PER_INT-1+4*CHAR_SIZE+V_GAP;
|
|
}
|
|
#ifdef DEBUG
|
|
foreground();
|
|
#endif
|
|
if ( x_coord >= 0 && y_coord >= 0 ) {
|
|
if ( row > total_item )
|
|
row = total_item;
|
|
x_size = item_len*((total_item+row-1)/row) + CHAR_SIZE;
|
|
y_size = row*item_high + CHAR_SIZE;
|
|
|
|
if ( x_coord + x_size > XMAXSCREEN )
|
|
x_coord = XMAXSCREEN - x_size;
|
|
if ( y_coord + y_size + 2*CHAR_SIZE > YMAXSCREEN )
|
|
y_coord = YMAXSCREEN - y_size - 2*CHAR_SIZE;
|
|
prefposition(x_coord, x_coord + x_size, y_coord, y_coord + y_size);
|
|
wid = winopen("sysmeter");
|
|
winconstraints();;
|
|
}
|
|
else {
|
|
wid = winopen("sysmeter");
|
|
getorigin((long *)&x_coord, (long *)&y_coord);
|
|
f_row = row = howmanyrow();
|
|
x_size = item_len*((total_item+row-1)/row) + CHAR_SIZE;
|
|
y_size = row*item_high + CHAR_SIZE;
|
|
resize();
|
|
}
|
|
doublebuffer();
|
|
gconfig();
|
|
getsize((long *)&rx_size, (long *)&ry_size);
|
|
|
|
retitle ();
|
|
draw_backg();
|
|
draw_backg();
|
|
}
|
|
|
|
|
|
resize()
|
|
{
|
|
register float t_x, t_y;
|
|
|
|
if ( x_size >= rx_size ) {
|
|
t_x = x_size/rx_size;
|
|
}
|
|
else {
|
|
t_x = rx_size/x_size;
|
|
}
|
|
if ( y_size >= ry_size ) {
|
|
t_y = y_size/ry_size;
|
|
}
|
|
else {
|
|
t_y = ry_size/y_size;
|
|
}
|
|
if ( t_x >= t_y ) {
|
|
if ( ry_size < y_size )
|
|
ry_size = y_size;
|
|
if ( ry_size*x_size/y_size - 1 > XMAXSCREEN )
|
|
return;
|
|
if ( rx_size != ry_size*x_size/y_size )
|
|
winposition(x_coord, x_coord+ry_size*x_size/y_size-1,
|
|
y_coord, y_coord+ry_size-1);
|
|
}
|
|
else {
|
|
if ( rx_size < x_size )
|
|
rx_size = x_size;
|
|
if ( rx_size*y_size/x_size -1 > YMAXSCREEN )
|
|
return;
|
|
if ( ry_size != rx_size*y_size/x_size )
|
|
winposition(x_coord, x_coord+rx_size-1, y_coord,
|
|
y_coord+rx_size*y_size/x_size-1);
|
|
}
|
|
}
|
|
|
|
/* given an arbitrary shape of window, figure out best arrangement */
|
|
int
|
|
howmanyrow()
|
|
{
|
|
register int i, j, col;
|
|
float prev_ratio, r_ratio, tmp_ratio;
|
|
float f1, f2;
|
|
|
|
getsize((long *)&rx_size, (long *)&ry_size);
|
|
prev_ratio = -1;
|
|
f1 = rx_size;
|
|
f2 = ry_size;
|
|
r_ratio = f2/f1;
|
|
|
|
for ( i = 1; i <= total_item; i++ ) {
|
|
col = (total_item + i - 1)/i;
|
|
if ( (i*col - total_item) > (col-1) )
|
|
continue;
|
|
x_size = item_len*col + CHAR_SIZE;
|
|
y_size = i*item_high + CHAR_SIZE;
|
|
f1 = x_size;
|
|
f2 = y_size;
|
|
tmp_ratio = f2/f1;
|
|
if ( tmp_ratio >= r_ratio ) {
|
|
if ( prev_ratio < 0 )
|
|
return(i);
|
|
if ( tmp_ratio - r_ratio > r_ratio - prev_ratio )
|
|
return (j);
|
|
else
|
|
return (i);
|
|
}
|
|
prev_ratio = tmp_ratio;
|
|
j = i;
|
|
}
|
|
return (total_item);
|
|
}
|
|
|
|
|
|
draw_backg()
|
|
{
|
|
int x1, x2, y1, y2;
|
|
int i, j, c_row, row_item;
|
|
float xx, yy;
|
|
|
|
reshapeviewport();
|
|
xx = x_size;
|
|
yy = y_size;
|
|
ortho2(0.0, xx, 0.0, yy);
|
|
color(backgnd_color);
|
|
clear();
|
|
getsize((long *)&rx_size, (long *)&ry_size);
|
|
|
|
row_item = 0;
|
|
c_row = 0;
|
|
for ( j = i = 0; i < total_item; i++) {
|
|
for ( ; !(items[j].onoff); j++);
|
|
|
|
x1 = item_len*row_item + 4*CHAR_SIZE + V_GAP;
|
|
y1 = (row-c_row-1)*item_high + CHAR_SIZE + H_GAP1 + H_GAP2;
|
|
y2 = y1 + g_size + MIN_PIC;
|
|
|
|
if ( meter ) {
|
|
x2 = x1 + g_size;
|
|
|
|
color(text_color);
|
|
move2i(x1, y2);
|
|
draw2i(x1, y1);
|
|
draw2i(x2, y1);
|
|
move2i(x1, y2);
|
|
draw2i(x1 + g_size/8, y2);
|
|
move2i(x1, y1 + g_size*3/4 + MIN_PIC);
|
|
draw2i(x1 + g_size/8, y1 + g_size*3/4 + MIN_PIC);
|
|
move2i(x1, y1 + g_size/2 + MIN_PIC);
|
|
draw2i(x1 + g_size/8, y1 + g_size/2 + MIN_PIC);
|
|
move2i(x1, y1 + g_size/4 + MIN_PIC);
|
|
draw2i(x1 + g_size/8, y1 + g_size/4 + MIN_PIC);
|
|
}
|
|
else {
|
|
x2 = (row_item + 1)*item_len;
|
|
|
|
color(chartback_color);
|
|
rectfi(x1, y1, x2, y2);
|
|
}
|
|
|
|
items[j].x1 = x1;
|
|
items[j].x2 = x2;
|
|
items[j].y1 = y1;
|
|
items[j].y2 = y2;
|
|
|
|
strcpy(buf, items[j].name);
|
|
|
|
color(text_color);
|
|
cmov2i(x1 + V_GAP, y1 - H_GAP1 - CHAR_SIZE*x_size/rx_size);
|
|
charstr(buf);
|
|
|
|
cmov2i(x1 - V_GAP - 4*CHAR_SIZE*x_size/rx_size,
|
|
y2 - CHAR_SIZE*x_size/rx_size);
|
|
sprintf(buf, "%4d", items[j].cmax);
|
|
charstr(buf);
|
|
|
|
cmov2i(x1 - V_GAP - CHAR_SIZE*x_size/rx_size, y1);
|
|
charstr("0");
|
|
|
|
row_item++;
|
|
if ( row_item >= (total_item+row-1)/row ) {
|
|
row_item = 0;
|
|
c_row++;
|
|
}
|
|
j++;
|
|
}
|
|
swapbuffers();
|
|
getorigin((long *)&x_coord, (long *)&y_coord);
|
|
}
|
|
|
|
|
|
|
|
void
|
|
get_perfdata()
|
|
{
|
|
enum clnt_stat err;
|
|
|
|
sig_timer++;
|
|
err = clnt_call(Client, RSTATPROC_STATS, xdr_void, 0, xdr_statstime,
|
|
&stats_info, total_timeout);
|
|
if ( err != RPC_SUCCESS ) {
|
|
fprintf(stderr, "sysmeter: can't get stats: %s\n",
|
|
clnt_sperrno(err));
|
|
winclose(wid);
|
|
exit(1);
|
|
}
|
|
|
|
insert_new();
|
|
|
|
(void) signal(SIGALRM, get_perfdata);
|
|
alarm(smp_intv);
|
|
}
|
|
|
|
insert_new()
|
|
{
|
|
static struct statstime prev_v;
|
|
static int first = 1;
|
|
register int i;
|
|
register struct entry *mem;
|
|
int temp, totcpu;
|
|
|
|
if ( in_interrupt )
|
|
return;
|
|
|
|
if ( avail_h == 0 )
|
|
release_used();
|
|
|
|
if ( avail_h == 0 ) {
|
|
mem = (struct entry *)malloc(M_ALLOC*sizeof(struct entry));
|
|
if ( mem == NULL ) {
|
|
fprintf(stderr, "Out of memory\n");
|
|
winclose(wid);
|
|
exit(1);
|
|
}
|
|
for ( i = 0; i < M_ALLOC; i++, mem++)
|
|
insert_avail(mem);
|
|
}
|
|
|
|
if (first) {
|
|
prev_v = stats_info;
|
|
first = 0;
|
|
return;
|
|
}
|
|
|
|
mem = avail_h;
|
|
if ( avail_h->f_link )
|
|
avail_h->f_link->b_link = 0;
|
|
avail_h = avail_h->f_link;
|
|
|
|
mem->intv = smp_intv;
|
|
temp = stats_info.cp_time[CP_USER] - prev_v.cp_time[CP_USER] +
|
|
stats_info.cp_time[CP_NICE] - prev_v.cp_time[CP_NICE] +
|
|
stats_info.cp_time[CP_SYS] - prev_v.cp_time[CP_SYS];
|
|
totcpu = temp + stats_info.cp_time[CP_IDLE] - prev_v.cp_time[CP_IDLE];
|
|
if (totcpu)
|
|
mem->data[P_CPU] = temp*100/totcpu;
|
|
else
|
|
mem->data[P_CPU] = 0;
|
|
mem->data[P_PAGE] = (stats_info.v_pgpgin - prev_v.v_pgpgin +
|
|
stats_info.v_pgpgout - prev_v.v_pgpgout + smp_intv/2) /
|
|
smp_intv;
|
|
mem->data[P_SWAP] = (stats_info.v_pswpin - prev_v.v_pswpin +
|
|
stats_info.v_pswpout - prev_v.v_pswpout + smp_intv/2) /
|
|
smp_intv;
|
|
mem->data[P_INTR] = (stats_info.v_intr - prev_v.v_intr + smp_intv/2) /
|
|
smp_intv;
|
|
mem->data[P_DISK] =
|
|
(stats_info.dk_xfer[0] - prev_v.dk_xfer[0] +
|
|
stats_info.dk_xfer[1] - prev_v.dk_xfer[1] +
|
|
stats_info.dk_xfer[2] - prev_v.dk_xfer[2] +
|
|
stats_info.dk_xfer[3] - prev_v.dk_xfer[3] + smp_intv/2) /
|
|
smp_intv;
|
|
mem->data[P_CNTXT] = (stats_info.v_swtch - prev_v.v_swtch + smp_intv/2) /
|
|
smp_intv;
|
|
mem->data[P_LOAD] = stats_info.avenrun[0]/FSCALE;
|
|
mem->data[P_PKTS] = (stats_info.if_ipackets - prev_v.if_ipackets +
|
|
stats_info.if_opackets - prev_v.if_opackets + smp_intv/2) /
|
|
smp_intv;
|
|
mem->data[P_IPKTS] = (stats_info.if_ipackets - prev_v.if_ipackets +
|
|
smp_intv/2) / smp_intv;
|
|
mem->data[P_OPKTS] = (stats_info.if_opackets - prev_v.if_opackets +
|
|
smp_intv/2) / smp_intv;
|
|
mem->data[P_COLLS] = (stats_info.if_collisions - prev_v.if_collisions +
|
|
smp_intv/2) / smp_intv;
|
|
mem->data[P_ERRS] = (stats_info.if_ierrors - prev_v.if_ierrors +
|
|
stats_info.if_oerrors - prev_v.if_oerrors + smp_intv/2) /
|
|
smp_intv;
|
|
for ( i = 0; i < MAXITEMS; i++ )
|
|
if ( mem->data[i] < 0 )
|
|
mem->data[i] = 0;
|
|
|
|
if ( used_h ) {
|
|
used_h->b_link = mem;
|
|
mem->f_link = used_h;
|
|
mem->b_link = 0;
|
|
used_h = mem;
|
|
}
|
|
else {
|
|
used_t = used_h = mem;
|
|
mem->f_link = mem->b_link = 0;
|
|
}
|
|
|
|
set_avgval();
|
|
|
|
tot_elapse += smp_intv;
|
|
prev_v = stats_info;
|
|
|
|
re_draw(0);
|
|
}
|
|
|
|
|
|
re_draw(force)
|
|
int force;
|
|
{
|
|
register struct entry *ent;
|
|
int new_max, c_col, i, j;
|
|
int c_val, ini_draw;
|
|
int x_pos, y_pos;
|
|
long draw[4][2];
|
|
|
|
if ( used_h == 0 )
|
|
return;
|
|
if ( !force && v_chg )
|
|
return;
|
|
c_col = 0;
|
|
for ( i = 0; i < MAXITEMS; i++) {
|
|
if ( !items[i].onoff ) continue;
|
|
ini_draw = c_val = 0;
|
|
new_max = items[i].cmax/2;
|
|
|
|
x_pos = items[i].x1;
|
|
y_pos = items[i].y1;
|
|
if ( meter ) {
|
|
color(backgnd_color);
|
|
rectfi(x_pos+g_size/3, y_pos, x_pos+g_size-g_size/3+g_size/8,
|
|
y_pos+g_size+MIN_PIC);
|
|
}
|
|
else {
|
|
color(chartback_color);
|
|
rectfi(x_pos, y_pos, items[i].x2, items[i].y2);
|
|
}
|
|
if ( meter ) {
|
|
if ( need_avg ) {
|
|
c_val = used_h->avg[i];
|
|
ADJMAX(c_val, new_max, i);
|
|
color(avg_color);
|
|
rectfi(x_pos+g_size/3+g_size/8, y_pos,
|
|
x_pos+g_size-g_size/3+g_size/8,
|
|
y_pos+MIN_PIC+g_size*c_val/items[i].cmax);
|
|
}
|
|
c_val = used_h->data[i];
|
|
ADJMAX(c_val, new_max, i);
|
|
color(chartback_color);
|
|
rectfi(x_pos+g_size/3, y_pos, x_pos+g_size-g_size/3,
|
|
y_pos+MIN_PIC+g_size*c_val/items[i].cmax);
|
|
move2i(x_pos+g_size/3, y_pos);
|
|
color(text_color);
|
|
draw2i(x_pos+g_size-g_size/3+g_size/8, y_pos);
|
|
|
|
goto adjust_max;
|
|
}
|
|
|
|
if ( need_avg && used_h->f_link) {
|
|
color(avg_color);
|
|
j = duration/smp_intv;
|
|
c_val = used_h->avg[i];
|
|
ADJMAX(c_val, new_max, i);
|
|
draw[0][0] = x_pos + j*PER_INT;
|
|
draw[0][1] = y_pos + MIN_PIC + g_size*c_val/items[i].cmax;
|
|
draw[3][0] = draw[0][0];
|
|
draw[2][1] = draw[3][1] = y_pos;
|
|
ent = used_h->f_link;
|
|
j--;
|
|
for ( ; j >= 0; j-- ) {
|
|
c_val = ent->avg[i];
|
|
ADJMAX(c_val, new_max, i);
|
|
|
|
draw[2][0] = draw[1][0] = x_pos + j*PER_INT;
|
|
draw[1][1] = y_pos+MIN_PIC+g_size*c_val/items[i].cmax;
|
|
polf2i(4, draw);
|
|
draw[0][0] = draw[1][0];
|
|
draw[0][1] = draw[1][1];
|
|
draw[3][0] = draw[2][0];
|
|
if ( !(ent = ent->f_link ) )
|
|
break;
|
|
}
|
|
}
|
|
|
|
color(BLACK);
|
|
ent = used_h;
|
|
ini_draw = c_val = 0;
|
|
for ( j = duration/smp_intv; j; j-- ) {
|
|
if ( !ent )
|
|
break;
|
|
c_val = ent->data[i];
|
|
ent = ent->f_link;
|
|
|
|
/* now draw one sample */
|
|
ADJMAX(c_val, new_max, i);
|
|
if ( ini_draw )
|
|
draw2i(x_pos + j*PER_INT,
|
|
y_pos + MIN_PIC + g_size*c_val/items[i].cmax);
|
|
else {
|
|
ini_draw = 1;
|
|
move2i(x_pos + j*PER_INT,
|
|
y_pos + MIN_PIC + g_size*c_val/items[i].cmax);
|
|
}
|
|
}
|
|
|
|
adjust_max:
|
|
if ( new_max > items[i].maxmax )
|
|
new_max = items[i].maxmax;
|
|
if ( new_max < items[i].minmax )
|
|
new_max = items[i].minmax;
|
|
if ( i != P_CPU && ((new_max != items[i].cmax) ||
|
|
items[i].adj) ) {
|
|
if ( items[i].cmax == new_max )
|
|
items[i].adj = 0;
|
|
else
|
|
items[i].adj = 1;
|
|
items[i].cmax = new_max;
|
|
x_pos = items[i].x1 - V_GAP - 4*CHAR_SIZE*x_size/rx_size;
|
|
y_pos = items[i].y2 - CHAR_SIZE*x_size/rx_size;
|
|
color(backgnd_color);
|
|
rectfi(x_pos, y_pos, x_pos + 4*CHAR_SIZE*x_size/rx_size,
|
|
y_pos + CHAR_SIZE*x_size/rx_size + H_GAP2);
|
|
color(text_color);
|
|
sprintf(buf, "%4d", items[i].cmax);
|
|
cmov2i(x_pos, y_pos);
|
|
charstr(buf);
|
|
}
|
|
|
|
if ( ++c_col >= (total_item+row-1)/row ) {
|
|
c_col = 0;
|
|
}
|
|
}
|
|
swapbuffers();
|
|
}
|
|
|
|
|
|
draw_chg()
|
|
{
|
|
long i, arrow[3][2];
|
|
float xx, yy;
|
|
|
|
color(changeback_color);
|
|
rectfi(0, 0, 15*CHAR_SIZE, 4*SLIDER_SIZE);
|
|
color(text_color);
|
|
arcfi(CHAR_SIZE+SLIDER_SIZE, 3*SLIDER_SIZE, SLIDER_SIZE-1, 450, 1350);
|
|
arcfi(CHAR_SIZE+SLIDER_SIZE, 3*SLIDER_SIZE, SLIDER_SIZE-1, 1650, 2550);
|
|
arcfi(CHAR_SIZE+SLIDER_SIZE, 3*SLIDER_SIZE, SLIDER_SIZE-1, 2850, 3750);
|
|
color(changeback_color);
|
|
circfi(CHAR_SIZE+SLIDER_SIZE, 3*SLIDER_SIZE, SLIDER_SIZE-3);
|
|
color(text_color);
|
|
for ( i = 0; i < 3; i++ ) {
|
|
pushmatrix();
|
|
xx = CHAR_SIZE+SLIDER_SIZE;
|
|
yy = 3*SLIDER_SIZE;
|
|
translate(xx, yy, 0.0);
|
|
arrow[0][0] = 0;
|
|
arrow[0][1] = -2;
|
|
arrow[1][0] = 2;
|
|
arrow[1][1] = 0;
|
|
arrow[2][0] = -2;
|
|
arrow[2][1] = 0;
|
|
rotate(i*1200+450, 'Z');
|
|
xx = SLIDER_SIZE-2;
|
|
translate(xx, 0.0, 0.0);
|
|
polf2i(3, arrow);
|
|
popmatrix();
|
|
}
|
|
cmov2i(S1X2+CHAR_SIZE, 3*SLIDER_SIZE-CHAR_SIZE/2);
|
|
switch (chg_state) {
|
|
case SAMPLE:
|
|
strcpy(buf, "Sample");
|
|
break;
|
|
case AVERAGE:
|
|
strcpy(buf, "Average");
|
|
break;
|
|
case WINDOW:
|
|
strcpy(buf, "Window");
|
|
break;
|
|
}
|
|
charstr(buf);
|
|
recti(S2X1, S2Y1, S2X2, S2Y2);
|
|
cmov2i(S2X1+2, S2Y1+1);
|
|
charstr("ok");
|
|
|
|
cmov2i(CHAR_SIZE, 2*SLIDER_SIZE-CHAR_SIZE+1);
|
|
charstr("0");
|
|
sprintf(buf, "%d", sld_max);
|
|
cmov2i(14*CHAR_SIZE-strlen(buf)*CHAR_SIZE*x_size/rx_size,
|
|
2*SLIDER_SIZE-CHAR_SIZE+1);
|
|
charstr(buf);
|
|
|
|
rectfi(SLDXL, 2*SLIDER_SIZE-CHAR_SIZE-2, SLDXH,
|
|
2*SLIDER_SIZE-CHAR_SIZE);
|
|
draw_slide(accum);
|
|
}
|
|
|
|
|
|
draw_slide(val)
|
|
int val;
|
|
{
|
|
register int i, cur_val, tot_p;
|
|
long trian[3][2];
|
|
float x_lo, y_lo;
|
|
|
|
color(changeback_color);
|
|
rectfi(0, 0, 15*CHAR_SIZE, 2*SLIDER_SIZE-CHAR_SIZE-2);
|
|
color(chartback_color);
|
|
rectfi(3*CHAR_SIZE, 2*SLIDER_SIZE-CHAR_SIZE+1, CHAR_SIZE*10, 2*SLIDER_SIZE);
|
|
color(text_color);
|
|
cur_val = val/60;
|
|
sprintf(buf, "%3d", cur_val);
|
|
strcat(buf, "m");
|
|
cur_val = val - cur_val*60;
|
|
sprintf(buf2, "%2d", cur_val);
|
|
strcat(buf, buf2);
|
|
strcat(buf, "s");
|
|
cmov2i(3*CHAR_SIZE, 2*SLIDER_SIZE-CHAR_SIZE+1);
|
|
charstr(buf);
|
|
|
|
cur_val = tot_p = 0;
|
|
for ( i = 0; i < MAXSTEP; i++ ) {
|
|
if ( val > cur_val + step_val[i]*step_rng[i] ) {
|
|
cur_val += step_val[i]*step_rng[i];
|
|
tot_p += step_rng[i];
|
|
continue;
|
|
}
|
|
tot_p += ((val - cur_val + step_val[i] - 1)/step_val[i]);
|
|
break;
|
|
}
|
|
x_lo = (SLDXH-SLDXL)*tot_p;
|
|
x_lo = x_lo/sld_maxp + SLDXL;
|
|
y_lo = 2*SLIDER_SIZE-CHAR_SIZE-2;
|
|
pushmatrix();
|
|
translate(x_lo, y_lo, 0.0);
|
|
trian[0][0] = 0;
|
|
trian[0][1] = 0;
|
|
trian[1][0] = -2;
|
|
trian[1][1] = -5;
|
|
trian[2][0] = 2;
|
|
trian[2][1] = -5;
|
|
polf2i(3, trian);
|
|
popmatrix();
|
|
swapbuffers();
|
|
}
|
|
|
|
|
|
/*
|
|
* Compute averag value from '*used_h', averaging over 'avg_intv'.
|
|
*/
|
|
int
|
|
set_avgval()
|
|
{
|
|
int i;
|
|
register tot_s;
|
|
register float c_val;
|
|
register struct entry *ent;
|
|
|
|
for ( i = 0; i < MAXITEMS; i++ ) {
|
|
ent = used_h;
|
|
c_val = 0;
|
|
tot_s = 0;
|
|
for ( ; ; ) {
|
|
if ( tot_s + ent->intv > avg_intv )
|
|
c_val = (c_val*tot_s+ent->data[i]*(avg_intv-tot_s))/avg_intv;
|
|
else
|
|
c_val = (c_val*tot_s+ent->data[i]*ent->intv)/(tot_s+ent->intv);
|
|
tot_s += ent->intv;
|
|
if ( tot_s >= avg_intv || !(ent = ent->f_link) ) {
|
|
used_h->avg[i] = c_val;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
insert_avail(m)
|
|
struct entry *m;
|
|
{
|
|
if ( avail_h ) {
|
|
m->f_link = avail_h;
|
|
avail_h->b_link = m;
|
|
m->b_link = 0;
|
|
avail_h = m;
|
|
}
|
|
else {
|
|
avail_h = m;
|
|
avail_h->f_link = avail_h->b_link = 0;
|
|
}
|
|
}
|
|
|
|
release_used()
|
|
{
|
|
register int tm;
|
|
register struct entry *i, *next;
|
|
|
|
tm = duration + avg_intv;
|
|
if ( used_h == 0 || tot_elapse < tm )
|
|
return;
|
|
|
|
for ( i = used_t; tot_elapse > tm; i = next ) {
|
|
next = i->b_link;
|
|
tot_elapse -= i->intv;
|
|
i->b_link->f_link = 0;
|
|
used_t = i->b_link;
|
|
insert_avail(i);
|
|
}
|
|
}
|
|
|
|
rndup_dur()
|
|
{
|
|
|
|
duration = (f_duration + smp_intv - 1) / smp_intv * smp_intv;
|
|
|
|
if (duration/smp_intv < MIN_INT_WID)
|
|
duration = MIN_INT_WID * smp_intv;
|
|
}
|