xref: /illumos-gate/usr/src/cmd/ndmpstat/ndmpstat_main.c (revision 27fc4d460929ce333b7fc276ed26821ce9958a40)
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 		const char *errstr;
88 
89 		errno = 0;
90 		interval = strtonum(argv[0], 1, MAXLONG, &errstr);
91 
92 		if (errstr != NULL) {
93 			usage();
94 			return (1);
95 		}
96 		poll_interval = 1000 * interval;
97 		if (poll_interval <= 0) {
98 			usage();
99 			return (1);
100 		}
101 		iter = MAXLONG;
102 		if (argc > 1) {
103 			iter = strtonum(argv[1], 1, MAXLONG, &errstr);
104 			if (errstr != NULL) {
105 				usage();
106 				return (1);
107 			}
108 		}
109 		if (argc > 2) {
110 			usage();
111 			return (1);
112 		}
113 	}
114 
115 	if (ndmp_door_status()) {
116 		(void) fprintf(stdout,
117 		    gettext(" Error: ndmpd service not running.\n"));
118 		return (1);
119 	}
120 
121 	(void) sigset(SIGCONT, printhdr);
122 
123 	printhdr(0);
124 
125 	if ((nstat = malloc(sizeof (ndmp_stat_t))) == NULL) {
126 		(void) fprintf(stdout, gettext("Out of memory"));
127 		return (1);
128 	}
129 
130 
131 	if (ndmp_get_stats(nstat) != 0) {
132 		free(nstat);
133 		return (1);
134 	}
135 
136 	dostats(old, nstat);
137 	while (--iter > 0) {
138 		(void) poll(NULL, 0, poll_interval);
139 
140 		free(old);
141 		old = nstat;
142 		if ((nstat = malloc(sizeof (ndmp_stat_t))) == NULL) {
143 			(void) fprintf(stdout, gettext("Out of memory"));
144 			free(old);
145 			return (1);
146 		}
147 		if (ndmp_get_stats(nstat) != 0) {
148 			free(old);
149 			free(nstat);
150 			return (1);
151 		}
152 		dostats(old, nstat);
153 	}
154 
155 	return (0);
156 }
157 
158 /* ARGSUSED */
159 static void
160 printhdr(int sig)
161 {
162 	(void) printf(" wthr  ops    file      disk      tape      ");
163 	(void) printf("bytes   perf     prcnt\n");
164 
165 	(void) printf(" r w  bk rs  rd   wr   rd   wr   rd   wr   rd   ");
166 	(void) printf("wr  bk rs  dsk tpe idl\n");
167 
168 	lines = REPRINT;
169 }
170 
171 static void
172 dostats(ndmp_stat_t *old, ndmp_stat_t *new)
173 {
174 	long long dskop = 0;
175 	long long tpop = 0;
176 	long dpcnt, tpcnt;
177 	long ipcnt;
178 	int totl;
179 	long rbytes;
180 	long wbytes;
181 
182 	adj = 0;
183 
184 	if (--lines == 0)
185 		printhdr(0);
186 
187 	if (!old) {
188 		(void) printf(" 0 0  0  0    0    0    0    ");
189 		(void) printf("0    0    0    0    0   0  0    0   0 100\n");
190 		return;
191 	}
192 
193 	adjprintf(" %*u", 1, VAL(trun));
194 	adjprintf(" %*u", 1, VAL(twait));
195 	adjprintf(" %*u", 2, VAL(nbk));
196 	adjprintf(" %*u", 2, VAL(nrs));
197 	adjprintf(" %*u", 4, DELTA(rfile));
198 	adjprintf(" %*u", 4, DELTA(wfile));
199 	adjprintf(" %*u", 4, (unsigned)(DELTA(rdisk) / blksize));
200 	adjprintf(" %*u", 4, (unsigned)(DELTA(wdisk) / blksize));
201 	adjprintf(" %*u", 4, (unsigned)(DELTA(rtape) / blksize));
202 	adjprintf(" %*u", 4, (unsigned)(DELTA(wtape) / blksize));
203 
204 	/* Get the average throughput */
205 	rbytes = (DELTA(wtape) + DELTA(rdisk)) / 2;
206 	wbytes = (DELTA(rtape) + DELTA(wdisk)) / 2;
207 	rbytes /= blksize;
208 	wbytes /= blksize;
209 
210 	adjprintf(" %*lu", 4, rbytes);
211 	adjprintf(" %*lu", 4, wbytes);
212 
213 	adjprintf(" %*lu", 3, rbytes / poll_interval);
214 	adjprintf(" %*lu", 2, wbytes / poll_interval);
215 
216 	dskop += DELTA(rdisk);
217 	dskop += DELTA(wdisk);
218 	tpop += DELTA(rtape);
219 	tpop += DELTA(wtape);
220 	totl = (dskop + tpop) ? (dskop + tpop) : 1;
221 
222 	dpcnt = (dskop * 100) / totl;
223 	tpcnt = (tpop * 100) / totl;
224 	ipcnt = 100 - dpcnt - tpcnt;
225 
226 	adjprintf(" %*lu", 4, dpcnt);
227 	adjprintf(" %*lu", 3, tpcnt);
228 	adjprintf(" %*lu\n", 3, ipcnt);
229 	(void) fflush(stdout);
230 }
231 
232 static void
233 usage(void)
234 {
235 	(void) fprintf(stderr, "Usage: ndmpstat [interval [count]]\n");
236 }
237