1 /* 2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* 7 * BSD 3 Clause License 8 * 9 * Copyright (c) 2007, The Storage Networking Industry Association. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * - Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 17 * - Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in 19 * the documentation and/or other materials provided with the 20 * distribution. 21 * 22 * - Neither the name of The Storage Networking Industry Association (SNIA) 23 * nor the names of its contributors may be used to endorse or promote 24 * products derived from this software without specific prior written 25 * permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 28 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 31 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 #include <stdio.h> 40 #include <stdlib.h> 41 #include <stdarg.h> 42 #include <ctype.h> 43 #include <unistd.h> 44 #include <memory.h> 45 #include <string.h> 46 #include <fcntl.h> 47 #include <errno.h> 48 #include <signal.h> 49 #include <values.h> 50 #include <poll.h> 51 #include <locale.h> 52 #include <libndmp.h> 53 54 #define MAX_DEV_STAT 16 55 #define REPRINT 19 56 #define VAL(v) (new->ns_##v) 57 #define DELTA(v) (new->ns_##v - (old ? old->ns_##v : 0)) 58 #define ADJ(n) ((adj <= 0) ? n : (adj >= n) ? 1 : n - adj) 59 #define adjprintf(fmt, n, val) adj -= (n + 1) - printf(fmt, ADJ(n), val) 60 #if !defined(TEXT_DOMAIN) 61 #define TEXT_DOMAIN "SYS_TEST" 62 #endif 63 64 static int adj; /* number of excess columns */ 65 static long iter = 0; 66 static int blksize = 1024; 67 static int poll_interval = 1; 68 static ndmp_stat_t *nstat; 69 static int lines = 1; 70 71 static void dostats(ndmp_stat_t *, ndmp_stat_t *); 72 static void printhdr(int); 73 static void usage(void); 74 75 int 76 main(int argc, char **argv) 77 { 78 ndmp_stat_t *old = NULL; 79 80 (void) setlocale(LC_ALL, ""); 81 (void) textdomain(TEXT_DOMAIN); 82 83 argc--, argv++; 84 85 if (argc > 0) { 86 long interval; 87 char *endptr; 88 89 errno = 0; 90 interval = strtol(argv[0], &endptr, 10); 91 92 if (errno > 0 || *endptr != '\0' || interval <= 0 || 93 interval > MAXLONG) { 94 usage(); 95 return (1); 96 } 97 poll_interval = 1000 * interval; 98 if (poll_interval <= 0) { 99 usage(); 100 return (1); 101 } 102 iter = MAXLONG; 103 if (argc > 1) { 104 iter = strtol(argv[1], NULL, 10); 105 if (errno > 0 || *endptr != '\0' || iter <= 0) { 106 usage(); 107 return (1); 108 } 109 } 110 if (argc > 2) { 111 usage(); 112 return (1); 113 } 114 } 115 116 if (ndmp_door_status()) { 117 (void) fprintf(stdout, 118 gettext(" Error: ndmpd service not running.\n")); 119 return (1); 120 } 121 122 (void) sigset(SIGCONT, printhdr); 123 124 printhdr(0); 125 126 if ((nstat = malloc(sizeof (ndmp_stat_t))) == NULL) { 127 (void) fprintf(stdout, gettext("Out of memory")); 128 return (1); 129 } 130 131 132 if (ndmp_get_stats(nstat) != 0) { 133 free(nstat); 134 return (1); 135 } 136 137 dostats(old, nstat); 138 while (--iter > 0) { 139 (void) poll(NULL, 0, poll_interval); 140 141 free(old); 142 old = nstat; 143 if ((nstat = malloc(sizeof (ndmp_stat_t))) == NULL) { 144 (void) fprintf(stdout, gettext("Out of memory")); 145 free(old); 146 return (1); 147 } 148 if (ndmp_get_stats(nstat) != 0) { 149 free(old); 150 free(nstat); 151 return (1); 152 } 153 dostats(old, nstat); 154 } 155 156 return (0); 157 } 158 159 /* ARGSUSED */ 160 static void 161 printhdr(int sig) 162 { 163 (void) printf(" wthr ops file disk tape "); 164 (void) printf("bytes perf prcnt\n"); 165 166 (void) printf(" r w bk rs rd wr rd wr rd wr rd "); 167 (void) printf("wr bk rs dsk tpe idl\n"); 168 169 lines = REPRINT; 170 } 171 172 static void 173 dostats(ndmp_stat_t *old, ndmp_stat_t *new) 174 { 175 long long dskop = 0; 176 long long tpop = 0; 177 long dpcnt, tpcnt; 178 long ipcnt; 179 int totl; 180 long rbytes; 181 long wbytes; 182 183 adj = 0; 184 185 if (--lines == 0) 186 printhdr(0); 187 188 if (!old) { 189 (void) printf(" 0 0 0 0 0 0 0 "); 190 (void) printf("0 0 0 0 0 0 0 0 0 100\n"); 191 return; 192 } 193 194 adjprintf(" %*u", 1, VAL(trun)); 195 adjprintf(" %*u", 1, VAL(twait)); 196 adjprintf(" %*u", 2, VAL(nbk)); 197 adjprintf(" %*u", 2, VAL(nrs)); 198 adjprintf(" %*u", 4, DELTA(rfile)); 199 adjprintf(" %*u", 4, DELTA(wfile)); 200 adjprintf(" %*u", 4, (unsigned)(DELTA(rdisk) / blksize)); 201 adjprintf(" %*u", 4, (unsigned)(DELTA(wdisk) / blksize)); 202 adjprintf(" %*u", 4, (unsigned)(DELTA(rtape) / blksize)); 203 adjprintf(" %*u", 4, (unsigned)(DELTA(wtape) / blksize)); 204 205 /* Get the average throughput */ 206 rbytes = (DELTA(wtape) + DELTA(rdisk)) / 2; 207 wbytes = (DELTA(rtape) + DELTA(wdisk)) / 2; 208 rbytes /= blksize; 209 wbytes /= blksize; 210 211 adjprintf(" %*lu", 4, rbytes); 212 adjprintf(" %*lu", 4, wbytes); 213 214 adjprintf(" %*lu", 3, rbytes / poll_interval); 215 adjprintf(" %*lu", 2, wbytes / poll_interval); 216 217 dskop += DELTA(rdisk); 218 dskop += DELTA(wdisk); 219 tpop += DELTA(rtape); 220 tpop += DELTA(wtape); 221 totl = (dskop + tpop) ? (dskop + tpop) : 1; 222 223 dpcnt = (dskop * 100) / totl; 224 tpcnt = (tpop * 100) / totl; 225 ipcnt = 100 - dpcnt - tpcnt; 226 227 adjprintf(" %*lu", 4, dpcnt); 228 adjprintf(" %*lu", 3, tpcnt); 229 adjprintf(" %*lu\n", 3, ipcnt); 230 (void) fflush(stdout); 231 } 232 233 static void 234 usage(void) 235 { 236 (void) fprintf(stderr, "Usage: ndmpstat [interval [count]]\n"); 237 } 238