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