Annotation of src/usr.bin/systat/iostat.c, Revision 1.21
1.21 ! millert 1: /* $OpenBSD: iostat.c,v 1.20 2003/02/02 18:20:41 henning Exp $ */
1.3 deraadt 2: /* $NetBSD: iostat.c,v 1.5 1996/05/10 23:16:35 thorpej Exp $ */
1.1 deraadt 3:
4: /*
5: * Copyright (c) 1980, 1992, 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
1.21 ! millert 16: * 3. Neither the name of the University nor the names of its contributors
1.1 deraadt 17: * may be used to endorse or promote products derived from this software
18: * without specific prior written permission.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30: * SUCH DAMAGE.
31: */
32:
33: #ifndef lint
34: #if 0
35: static char sccsid[] = "@(#)iostat.c 8.1 (Berkeley) 6/6/93";
36: #endif
1.21 ! millert 37: static char rcsid[] = "$OpenBSD: iostat.c,v 1.20 2003/02/02 18:20:41 henning Exp $";
1.12 heko 38: #endif /* not lint */
1.1 deraadt 39:
40: #include <sys/param.h>
41: #include <sys/dkstat.h>
42: #include <sys/buf.h>
1.3 deraadt 43: #include <sys/time.h>
1.1 deraadt 44:
45: #include <string.h>
46: #include <stdlib.h>
47: #include <paths.h>
48: #include "systat.h"
49: #include "extern.h"
50:
1.3 deraadt 51: #include "dkstats.h"
1.19 tdeval 52: extern struct _disk cur, last;
1.1 deraadt 53:
54: static int linesperregion;
55: static double etime;
56: static int numbers = 0; /* default display bar graphs */
1.3 deraadt 57: static int secs = 0; /* default seconds shown */
1.1 deraadt 58:
1.17 millert 59: static int barlabels(int);
60: static void histogram(double, int, double);
61: static int numlabels(int);
62: static int stats(int, int, int);
63: static void stat1(int, int);
1.1 deraadt 64:
65:
66: WINDOW *
1.18 deraadt 67: openiostat(void)
1.1 deraadt 68: {
69: return (subwin(stdscr, LINES-1-5, 0, 5, 0));
70: }
71:
72: void
1.18 deraadt 73: closeiostat(WINDOW *w)
1.1 deraadt 74: {
75: if (w == NULL)
76: return;
77: wclear(w);
78: wrefresh(w);
79: delwin(w);
80: }
81:
82: int
1.18 deraadt 83: initiostat(void)
1.1 deraadt 84: {
1.3 deraadt 85: dkinit(1);
86: dkreadstats();
1.9 kstailey 87: return (1);
1.1 deraadt 88: }
89:
90: void
1.18 deraadt 91: fetchiostat(void)
1.1 deraadt 92: {
1.19 tdeval 93: if (cur.dk_ndrive == 0)
1.1 deraadt 94: return;
1.3 deraadt 95: dkreadstats();
1.1 deraadt 96: }
97:
98: #define INSET 10
99:
100: void
1.18 deraadt 101: labeliostat(void)
1.1 deraadt 102: {
103: int row;
104:
105: row = 0;
106: wmove(wnd, row, 0); wclrtobot(wnd);
107: mvwaddstr(wnd, row++, INSET,
108: "/0 /10 /20 /30 /40 /50 /60 /70 /80 /90 /100");
109: mvwaddstr(wnd, row++, 0, "cpu user|");
110: mvwaddstr(wnd, row++, 0, " nice|");
111: mvwaddstr(wnd, row++, 0, " system|");
112: mvwaddstr(wnd, row++, 0, "interrupt|");
113: mvwaddstr(wnd, row++, 0, " idle|");
114: if (numbers)
115: row = numlabels(row + 1);
116: else
117: row = barlabels(row + 1);
118: }
119:
120: static int
1.18 deraadt 121: numlabels(int row)
1.1 deraadt 122: {
123: int i, col, regions, ndrives;
124:
1.19 tdeval 125: if (cur.dk_ndrive == 0) {
1.7 kstailey 126: mvwaddstr(wnd, row++, INSET, "No drives attached.");
127: return (row);
128: }
1.11 deraadt 129: #define COLWIDTH 17
1.4 mickey 130: #define DRIVESPERLINE ((wnd->_maxx - INSET) / COLWIDTH)
1.19 tdeval 131: for (ndrives = 0, i = 0; i < cur.dk_ndrive; i++)
1.3 deraadt 132: if (cur.dk_select[i])
1.1 deraadt 133: ndrives++;
134: regions = howmany(ndrives, DRIVESPERLINE);
135: /*
136: * Deduct -regions for blank line after each scrolling region.
137: */
1.4 mickey 138: linesperregion = (wnd->_maxy - row - regions) / regions;
1.1 deraadt 139: /*
140: * Minimum region contains space for two
141: * label lines and one line of statistics.
142: */
143: if (linesperregion < 3)
144: linesperregion = 3;
1.11 deraadt 145: col = INSET;
1.19 tdeval 146: for (i = 0; i < cur.dk_ndrive; i++)
1.3 deraadt 147: if (cur.dk_select[i] /*&& cur.dk_bytes[i] != 0.0*/) {
1.11 deraadt 148: if (col + COLWIDTH >= wnd->_maxx) {
149: col = INSET, row += linesperregion + 1;
1.4 mickey 150: if (row > wnd->_maxy - (linesperregion + 1))
1.1 deraadt 151: break;
152: }
1.3 deraadt 153: mvwaddstr(wnd, row, col + 4, cur.dk_name[i]);
1.11 deraadt 154: mvwaddstr(wnd, row + 1, col, " KBps tps sec");
1.1 deraadt 155: col += COLWIDTH;
156: }
157: if (col)
158: row += linesperregion + 1;
159: return (row);
160: }
161:
162: static int
1.18 deraadt 163: barlabels(int row)
1.1 deraadt 164: {
165: int i;
166:
1.19 tdeval 167: if (cur.dk_ndrive == 0) {
1.7 kstailey 168: mvwaddstr(wnd, row++, INSET, "No drives attached.");
169: return (row);
170: }
1.1 deraadt 171: mvwaddstr(wnd, row++, INSET,
1.3 deraadt 172: "/0 /10 /20 /30 /40 /50 /60 /70 /80 /90 /100");
173: linesperregion = 2 + secs;
1.1 deraadt 174: for (i = 0; i < dk_ndrive; i++)
1.3 deraadt 175: if (cur.dk_select[i] /*&& cur.dk_bytes[i] != 0.0*/) {
1.4 mickey 176: if (row > wnd->_maxy - linesperregion)
1.1 deraadt 177: break;
1.6 maja 178: mvwprintw(wnd, row++, 0, "%4.4s Kps|", cur.dk_name[i]);
1.1 deraadt 179: mvwaddstr(wnd, row++, 0, " tps|");
1.3 deraadt 180: if (secs)
181: mvwaddstr(wnd, row++, 0, " msec|");
1.1 deraadt 182: }
183: return (row);
184: }
185:
186:
187: void
1.18 deraadt 188: showiostat(void)
1.1 deraadt 189: {
1.13 mpech 190: int i, row, col;
1.1 deraadt 191:
1.3 deraadt 192: dkswap();
193:
1.1 deraadt 194: etime = 0;
1.18 deraadt 195: for (i = 0; i < CPUSTATES; i++) {
1.3 deraadt 196: etime += cur.cp_time[i];
1.1 deraadt 197: }
198: if (etime == 0.0)
199: etime = 1.0;
200: etime /= (float) hz;
201: row = 1;
202:
203: /*
204: * Interrupt CPU state not calculated yet.
1.16 deraadt 205: */
1.1 deraadt 206: for (i = 0; i < CPUSTATES; i++)
207: stat1(row++, i);
1.7 kstailey 208:
1.19 tdeval 209: if (last.dk_ndrive != cur.dk_ndrive)
210: labeliostat();
211:
212: if (cur.dk_ndrive == 0)
1.7 kstailey 213: return;
214:
1.1 deraadt 215: if (!numbers) {
216: row += 2;
1.19 tdeval 217: for (i = 0; i < cur.dk_ndrive; i++)
1.3 deraadt 218: if (cur.dk_select[i] /*&& cur.dk_bytes[i] != 0.0*/) {
1.4 mickey 219: if (row > wnd->_maxy - linesperregion)
1.1 deraadt 220: break;
221: row = stats(row, INSET, i);
222: }
223: return;
224: }
1.11 deraadt 225: col = INSET;
1.1 deraadt 226: wmove(wnd, row + linesperregion, 0);
227: wdeleteln(wnd);
228: wmove(wnd, row + 3, 0);
229: winsertln(wnd);
1.19 tdeval 230: for (i = 0; i < cur.dk_ndrive; i++)
1.3 deraadt 231: if (cur.dk_select[i] /*&& cur.dk_bytes[i] != 0.0*/) {
1.4 mickey 232: if (col + COLWIDTH >= wnd->_maxx) {
1.11 deraadt 233: col = INSET, row += linesperregion + 1;
1.4 mickey 234: if (row > wnd->_maxy - (linesperregion + 1))
1.1 deraadt 235: break;
236: wmove(wnd, row + linesperregion, 0);
237: wdeleteln(wnd);
238: wmove(wnd, row + 3, 0);
239: winsertln(wnd);
240: }
241: (void) stats(row + 3, col, i);
242: col += COLWIDTH;
243: }
244: }
245:
246: static int
1.18 deraadt 247: stats(int row, int col, int dn)
1.1 deraadt 248: {
1.3 deraadt 249: double atime, words;
250:
251: /* time busy in disk activity */
252: atime = (double)cur.dk_time[dn].tv_sec +
253: ((double)cur.dk_time[dn].tv_usec / (double)1000000);
1.1 deraadt 254:
1.3 deraadt 255: words = cur.dk_bytes[dn] / 1024.0; /* # of K transferred */
1.1 deraadt 256: if (numbers) {
1.11 deraadt 257: mvwprintw(wnd, row, col, "%5.0f%4.0f%5.1f",
1.3 deraadt 258: words / etime, cur.dk_xfer[dn] / etime, atime / etime);
1.1 deraadt 259: return (row);
260: }
261: wmove(wnd, row++, col);
1.3 deraadt 262: histogram(words / etime, 50, 0.5);
1.1 deraadt 263: wmove(wnd, row++, col);
1.3 deraadt 264: histogram(cur.dk_xfer[dn] / etime, 50, 0.5);
265: if (secs) {
1.1 deraadt 266: wmove(wnd, row++, col);
1.3 deraadt 267: atime *= 1000; /* In milliseconds */
268: histogram(atime / etime, 50, 0.5);
1.1 deraadt 269: }
270: return (row);
271: }
272:
273: static void
1.18 deraadt 274: stat1(int row, int o)
1.1 deraadt 275: {
1.13 mpech 276: int i;
1.1 deraadt 277: double time;
278:
279: time = 0;
280: for (i = 0; i < CPUSTATES; i++)
1.3 deraadt 281: time += cur.cp_time[i];
1.1 deraadt 282: if (time == 0.0)
283: time = 1.0;
284: wmove(wnd, row, INSET);
285: #define CPUSCALE 0.5
1.3 deraadt 286: histogram(100.0 * cur.cp_time[o] / time, 50, CPUSCALE);
1.1 deraadt 287: }
288:
289: static void
1.18 deraadt 290: histogram(double val, int colwidth, double scale)
1.1 deraadt 291: {
1.20 henning 292: int v = (int)(val * scale + 0.5);
293: int factor = 1;
294: int y, x;
295:
296: while (v > colwidth) {
297: v = (v + 5) / 10;
298: factor *= 10;
1.1 deraadt 299: }
1.20 henning 300: getyx(wnd, y, x);
1.1 deraadt 301: wclrtoeol(wnd);
1.20 henning 302: whline(wnd, 'X', v);
303: if (factor != 1)
304: mvwprintw(wnd, y, x + colwidth + 1, "* %d ", factor);
1.1 deraadt 305: }
306:
307: int
1.18 deraadt 308: cmdiostat(char *cmd, char *args)
1.1 deraadt 309: {
310:
1.3 deraadt 311: if (prefix(cmd, "secs"))
312: secs = !secs;
1.1 deraadt 313: else if (prefix(cmd, "numbers"))
314: numbers = 1;
315: else if (prefix(cmd, "bars"))
316: numbers = 0;
317: else if (!dkcmd(cmd, args))
318: return (0);
319: wclear(wnd);
320: labeliostat();
321: refresh();
322: return (1);
323: }