[BACK]Return to iostat.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / systat

Annotation of src/usr.bin/systat/iostat.c, Revision 1.23

1.23    ! tedu        1: /*     $OpenBSD: iostat.c,v 1.22 2004/02/15 02:45:47 tedu 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.23    ! tedu       37: static char rcsid[] = "$OpenBSD: iostat.c,v 1.22 2004/02/15 02:45:47 tedu 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.23    ! tedu       58: static int split = 0;                  /* whether to split r/w stats */
1.1       deraadt    59:
1.17      millert    60: static int barlabels(int);
                     61: static void histogram(double, int, double);
                     62: static int numlabels(int);
                     63: static int stats(int, int, int);
                     64: static void stat1(int, int);
1.1       deraadt    65:
                     66:
                     67: WINDOW *
1.18      deraadt    68: openiostat(void)
1.1       deraadt    69: {
                     70:        return (subwin(stdscr, LINES-1-5, 0, 5, 0));
                     71: }
                     72:
                     73: void
1.18      deraadt    74: closeiostat(WINDOW *w)
1.1       deraadt    75: {
                     76:        if (w == NULL)
                     77:                return;
                     78:        wclear(w);
                     79:        wrefresh(w);
                     80:        delwin(w);
                     81: }
                     82:
                     83: int
1.18      deraadt    84: initiostat(void)
1.1       deraadt    85: {
1.3       deraadt    86:        dkinit(1);
                     87:        dkreadstats();
1.9       kstailey   88:        return (1);
1.1       deraadt    89: }
                     90:
                     91: void
1.18      deraadt    92: fetchiostat(void)
1.1       deraadt    93: {
1.19      tdeval     94:        if (cur.dk_ndrive == 0)
1.1       deraadt    95:                return;
1.3       deraadt    96:        dkreadstats();
1.1       deraadt    97: }
                     98:
                     99: #define        INSET   10
                    100:
                    101: void
1.18      deraadt   102: labeliostat(void)
1.1       deraadt   103: {
                    104:        int row;
                    105:
                    106:        row = 0;
                    107:        wmove(wnd, row, 0); wclrtobot(wnd);
                    108:        mvwaddstr(wnd, row++, INSET,
                    109:            "/0   /10  /20  /30  /40  /50  /60  /70  /80  /90  /100");
                    110:        mvwaddstr(wnd, row++, 0, "cpu  user|");
                    111:        mvwaddstr(wnd, row++, 0, "     nice|");
                    112:        mvwaddstr(wnd, row++, 0, "   system|");
                    113:        mvwaddstr(wnd, row++, 0, "interrupt|");
                    114:        mvwaddstr(wnd, row++, 0, "     idle|");
                    115:        if (numbers)
                    116:                row = numlabels(row + 1);
                    117:        else
                    118:                row = barlabels(row + 1);
                    119: }
                    120:
                    121: static int
1.18      deraadt   122: numlabels(int row)
1.1       deraadt   123: {
                    124:        int i, col, regions, ndrives;
                    125:
1.19      tdeval    126:        if (cur.dk_ndrive == 0) {
1.7       kstailey  127:                mvwaddstr(wnd, row++, INSET, "No drives attached.");
                    128:                return (row);
                    129:        }
1.23    ! tedu      130: #define COLWIDTH       (split ? 30 : 17)
1.4       mickey    131: #define DRIVESPERLINE  ((wnd->_maxx - INSET) / COLWIDTH)
1.19      tdeval    132:        for (ndrives = 0, i = 0; i < cur.dk_ndrive; i++)
1.3       deraadt   133:                if (cur.dk_select[i])
1.1       deraadt   134:                        ndrives++;
                    135:        regions = howmany(ndrives, DRIVESPERLINE);
                    136:        /*
                    137:         * Deduct -regions for blank line after each scrolling region.
                    138:         */
1.4       mickey    139:        linesperregion = (wnd->_maxy - row - regions) / regions;
1.1       deraadt   140:        /*
                    141:         * Minimum region contains space for two
                    142:         * label lines and one line of statistics.
                    143:         */
                    144:        if (linesperregion < 3)
                    145:                linesperregion = 3;
1.11      deraadt   146:        col = INSET;
1.19      tdeval    147:        for (i = 0; i < cur.dk_ndrive; i++)
1.3       deraadt   148:                if (cur.dk_select[i] /*&& cur.dk_bytes[i] != 0.0*/) {
1.11      deraadt   149:                        if (col + COLWIDTH >= wnd->_maxx) {
                    150:                                col = INSET, row += linesperregion + 1;
1.4       mickey    151:                                if (row > wnd->_maxy - (linesperregion + 1))
1.1       deraadt   152:                                        break;
                    153:                        }
1.3       deraadt   154:                        mvwaddstr(wnd, row, col + 4, cur.dk_name[i]);
1.23    ! tedu      155:                        if (split)
        !           156:                                mvwaddstr(wnd, row + 1, col, " rKBps wKBps "
        !           157:                                    "rtps wtps  sec");
        !           158:                        else
        !           159:                                mvwaddstr(wnd, row + 1, col, " KBps tps  sec");
1.1       deraadt   160:                        col += COLWIDTH;
                    161:                }
                    162:        if (col)
                    163:                row += linesperregion + 1;
                    164:        return (row);
                    165: }
                    166:
                    167: static int
1.18      deraadt   168: barlabels(int row)
1.1       deraadt   169: {
                    170:        int i;
                    171:
1.19      tdeval    172:        if (cur.dk_ndrive == 0) {
1.7       kstailey  173:                mvwaddstr(wnd, row++, INSET, "No drives attached.");
                    174:                return (row);
                    175:        }
1.1       deraadt   176:        mvwaddstr(wnd, row++, INSET,
1.3       deraadt   177:            "/0   /10  /20  /30  /40  /50  /60  /70  /80  /90  /100");
                    178:        linesperregion = 2 + secs;
1.1       deraadt   179:        for (i = 0; i < dk_ndrive; i++)
1.3       deraadt   180:                if (cur.dk_select[i] /*&& cur.dk_bytes[i] != 0.0*/) {
1.4       mickey    181:                        if (row > wnd->_maxy - linesperregion)
1.1       deraadt   182:                                break;
1.23    ! tedu      183:                        if (split) {
        !           184:                                mvwprintw(wnd, row++, 0, "%4.4s rKps|",
        !           185:                                    cur.dk_name[i]);
        !           186:                                mvwaddstr(wnd, row++, 0, "     wKps|");
        !           187:                                mvwaddstr(wnd, row++, 0, "     rtps|");
        !           188:                                mvwaddstr(wnd, row++, 0, "     wtps|");
        !           189:                        } else {
        !           190:                                mvwprintw(wnd, row++, 0, "%4.4s  Kps|",
        !           191:                                    cur.dk_name[i]);
        !           192:                                mvwaddstr(wnd, row++, 0, "      tps|");
        !           193:                        }
1.3       deraadt   194:                        if (secs)
                    195:                                mvwaddstr(wnd, row++, 0, "     msec|");
1.1       deraadt   196:                }
                    197:        return (row);
                    198: }
                    199:
                    200:
                    201: void
1.18      deraadt   202: showiostat(void)
1.1       deraadt   203: {
1.13      mpech     204:        int i, row, col;
1.1       deraadt   205:
1.3       deraadt   206:        dkswap();
                    207:
1.1       deraadt   208:        etime = 0;
1.18      deraadt   209:        for (i = 0; i < CPUSTATES; i++) {
1.3       deraadt   210:                etime += cur.cp_time[i];
1.1       deraadt   211:        }
                    212:        if (etime == 0.0)
                    213:                etime = 1.0;
                    214:        etime /= (float) hz;
                    215:        row = 1;
                    216:
                    217:        /*
                    218:         * Interrupt CPU state not calculated yet.
1.16      deraadt   219:         */
1.1       deraadt   220:        for (i = 0; i < CPUSTATES; i++)
                    221:                stat1(row++, i);
1.7       kstailey  222:
1.19      tdeval    223:        if (last.dk_ndrive != cur.dk_ndrive)
                    224:                labeliostat();
                    225:
                    226:        if (cur.dk_ndrive == 0)
1.7       kstailey  227:                return;
                    228:
1.1       deraadt   229:        if (!numbers) {
                    230:                row += 2;
1.19      tdeval    231:                for (i = 0; i < cur.dk_ndrive; i++)
1.3       deraadt   232:                        if (cur.dk_select[i] /*&& cur.dk_bytes[i] != 0.0*/) {
1.4       mickey    233:                                if (row > wnd->_maxy - linesperregion)
1.1       deraadt   234:                                        break;
                    235:                                row = stats(row, INSET, i);
                    236:                        }
                    237:                return;
                    238:        }
1.11      deraadt   239:        col = INSET;
1.1       deraadt   240:        wmove(wnd, row + linesperregion, 0);
                    241:        wdeleteln(wnd);
                    242:        wmove(wnd, row + 3, 0);
                    243:        winsertln(wnd);
1.19      tdeval    244:        for (i = 0; i < cur.dk_ndrive; i++)
1.3       deraadt   245:                if (cur.dk_select[i] /*&& cur.dk_bytes[i] != 0.0*/) {
1.4       mickey    246:                        if (col + COLWIDTH >= wnd->_maxx) {
1.11      deraadt   247:                                col = INSET, row += linesperregion + 1;
1.4       mickey    248:                                if (row > wnd->_maxy - (linesperregion + 1))
1.1       deraadt   249:                                        break;
                    250:                                wmove(wnd, row + linesperregion, 0);
                    251:                                wdeleteln(wnd);
                    252:                                wmove(wnd, row + 3, 0);
                    253:                                winsertln(wnd);
                    254:                        }
                    255:                        (void) stats(row + 3, col, i);
                    256:                        col += COLWIDTH;
                    257:                }
                    258: }
                    259:
                    260: static int
1.18      deraadt   261: stats(int row, int col, int dn)
1.1       deraadt   262: {
1.23    ! tedu      263:        double atime, rwords, wwords;
1.3       deraadt   264:
                    265:        /* time busy in disk activity */
                    266:        atime = (double)cur.dk_time[dn].tv_sec +
                    267:                ((double)cur.dk_time[dn].tv_usec / (double)1000000);
1.1       deraadt   268:
1.23    ! tedu      269:        rwords = cur.dk_rbytes[dn] / 1024.0;    /* # of K read */
        !           270:        wwords = cur.dk_wbytes[dn] / 1024.0;    /* # of K written */
1.1       deraadt   271:        if (numbers) {
1.23    ! tedu      272:                if (split)
        !           273:                        mvwprintw(wnd, row, col, "%6.0f%6.0f%5.0f%5.0f%5.1f",
        !           274:                            rwords / etime, wwords / etime, cur.dk_rxfer[dn] /
        !           275:                            etime, cur.dk_wxfer[dn] / etime, atime / etime);
        !           276:                else
        !           277:                        mvwprintw(wnd, row, col, "%5.0f%4.0f%5.1f",
        !           278:                            (rwords + wwords) / etime,
        !           279:                            (cur.dk_rxfer[dn] + cur.dk_wxfer[dn]) / etime,
        !           280:                            atime / etime);
1.1       deraadt   281:                return (row);
                    282:        }
1.23    ! tedu      283:        if (split) {
        !           284:                wmove(wnd, row++, col);
        !           285:                histogram(rwords / etime, 50, 0.5);
        !           286:                wmove(wnd, row++, col);
        !           287:                histogram(wwords / etime, 50, 0.5);
        !           288:                wmove(wnd, row++, col);
        !           289:                histogram(cur.dk_rxfer[dn] / etime, 50, 0.5);
        !           290:                wmove(wnd, row++, col);
        !           291:                histogram(cur.dk_wxfer[dn] / etime, 50, 0.5);
        !           292:        } else {
        !           293:                wmove(wnd, row++, col);
        !           294:                histogram((rwords + wwords) / etime, 50, 0.5);
        !           295:                wmove(wnd, row++, col);
        !           296:                histogram((cur.dk_rxfer[dn] + cur.dk_wxfer[dn]) / etime, 50,
        !           297:                    0.5);
        !           298:        }
1.3       deraadt   299:        if (secs) {
1.1       deraadt   300:                wmove(wnd, row++, col);
1.3       deraadt   301:                atime *= 1000;  /* In milliseconds */
                    302:                histogram(atime / etime, 50, 0.5);
1.1       deraadt   303:        }
                    304:        return (row);
                    305: }
                    306:
                    307: static void
1.18      deraadt   308: stat1(int row, int o)
1.1       deraadt   309: {
1.13      mpech     310:        int i;
1.1       deraadt   311:        double time;
                    312:
                    313:        time = 0;
                    314:        for (i = 0; i < CPUSTATES; i++)
1.3       deraadt   315:                time += cur.cp_time[i];
1.1       deraadt   316:        if (time == 0.0)
                    317:                time = 1.0;
                    318:        wmove(wnd, row, INSET);
                    319: #define CPUSCALE       0.5
1.3       deraadt   320:        histogram(100.0 * cur.cp_time[o] / time, 50, CPUSCALE);
1.1       deraadt   321: }
                    322:
                    323: static void
1.18      deraadt   324: histogram(double val, int colwidth, double scale)
1.1       deraadt   325: {
1.20      henning   326:        int v = (int)(val * scale + 0.5);
                    327:        int factor = 1;
                    328:        int y, x;
                    329:
                    330:        while (v > colwidth) {
                    331:                v = (v + 5) / 10;
                    332:                factor *= 10;
1.1       deraadt   333:        }
1.20      henning   334:        getyx(wnd, y, x);
1.1       deraadt   335:        wclrtoeol(wnd);
1.20      henning   336:        whline(wnd, 'X', v);
                    337:        if (factor != 1)
                    338:                mvwprintw(wnd, y, x + colwidth + 1, "* %d ", factor);
1.1       deraadt   339: }
                    340:
                    341: int
1.18      deraadt   342: cmdiostat(char *cmd, char *args)
1.1       deraadt   343: {
                    344:
1.3       deraadt   345:        if (prefix(cmd, "secs"))
                    346:                secs = !secs;
1.1       deraadt   347:        else if (prefix(cmd, "numbers"))
                    348:                numbers = 1;
                    349:        else if (prefix(cmd, "bars"))
                    350:                numbers = 0;
1.23    ! tedu      351:        else if (prefix(cmd, "split"))
        !           352:                split = ~split;
1.1       deraadt   353:        else if (!dkcmd(cmd, args))
                    354:                return (0);
                    355:        wclear(wnd);
                    356:        labeliostat();
                    357:        refresh();
                    358:        return (1);
                    359: }