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
main(int argc,char ** argv)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
printhdr(int sig)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
dostats(ndmp_stat_t * old,ndmp_stat_t * new)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
usage(void)234 usage(void)
235 {
236 (void) fprintf(stderr, "Usage: ndmpstat [interval [count]]\n");
237 }
238