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