xref: /onnv-gate/usr/src/cmd/rcap/rcapstat/rcapstat.c (revision 13093:48f2dbca79a2)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
53247Sgjelinek  * Common Development and Distribution License (the "License").
63247Sgjelinek  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
21*13093SRoger.Faulkner@Oracle.COM 
220Sstevel@tonic-gate /*
23*13093SRoger.Faulkner@Oracle.COM  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #include <sys/types.h>
270Sstevel@tonic-gate #include <sys/stat.h>
280Sstevel@tonic-gate #include <stdlib.h>
290Sstevel@tonic-gate #include <fcntl.h>
300Sstevel@tonic-gate #include <errno.h>
310Sstevel@tonic-gate #include <stdio.h>
320Sstevel@tonic-gate #include <unistd.h>
330Sstevel@tonic-gate #include <string.h>
340Sstevel@tonic-gate #include <strings.h>
350Sstevel@tonic-gate #include <libintl.h>
360Sstevel@tonic-gate #include <locale.h>
370Sstevel@tonic-gate 
380Sstevel@tonic-gate #include "rcapd.h"
390Sstevel@tonic-gate #include "utils.h"
400Sstevel@tonic-gate #include "rcapd_stat.h"
4110265SKrishnendu.Sadhukhan@Sun.COM #include "statcommon.h"
420Sstevel@tonic-gate 
430Sstevel@tonic-gate static char mode[RC_MODE_LEN];
440Sstevel@tonic-gate static rcapd_stat_hdr_t hdr;
450Sstevel@tonic-gate static int global;
460Sstevel@tonic-gate static int unformatted;
470Sstevel@tonic-gate static time_t stat_mod = 0;
480Sstevel@tonic-gate 
4910265SKrishnendu.Sadhukhan@Sun.COM static uint_t timestamp_fmt = NODATE;
5010265SKrishnendu.Sadhukhan@Sun.COM 
510Sstevel@tonic-gate typedef struct col {
520Sstevel@tonic-gate 	rcid_t		col_id;
530Sstevel@tonic-gate 	char		col_name[LC_NAME_LEN];
540Sstevel@tonic-gate 	uint64_t	col_nproc;
550Sstevel@tonic-gate 	uint64_t	col_vmsize;
560Sstevel@tonic-gate 	uint64_t	col_rsssize;
570Sstevel@tonic-gate 	uint64_t	col_rsslimit;
580Sstevel@tonic-gate 	uint64_t	col_paged_eff;
590Sstevel@tonic-gate 	uint64_t	col_paged_eff_old;
600Sstevel@tonic-gate 	uint64_t	col_paged_eff_avg;
610Sstevel@tonic-gate 	uint64_t	col_paged_att;
620Sstevel@tonic-gate 	uint64_t	col_paged_att_old;
630Sstevel@tonic-gate 	uint64_t	col_paged_att_avg;
640Sstevel@tonic-gate 	uint64_t	col_count;
650Sstevel@tonic-gate 	int		col_fresh;
660Sstevel@tonic-gate 	struct col	*col_next;
670Sstevel@tonic-gate 	struct col	*col_prev;
680Sstevel@tonic-gate 	lcollection_stat_t	col_src_stat;
690Sstevel@tonic-gate 	lcollection_stat_t	col_old_stat;
700Sstevel@tonic-gate } col_t;
710Sstevel@tonic-gate 
720Sstevel@tonic-gate static col_t *col_head;
730Sstevel@tonic-gate static int ncol;
740Sstevel@tonic-gate 
750Sstevel@tonic-gate static col_t *
col_find(rcid_t id)760Sstevel@tonic-gate col_find(rcid_t id)
770Sstevel@tonic-gate {
780Sstevel@tonic-gate 	col_t *col;
790Sstevel@tonic-gate 	for (col = col_head; col != NULL; col = col->col_next)
803247Sgjelinek 		if (col->col_id.rcid_type == id.rcid_type &&
813247Sgjelinek 		    col->col_id.rcid_val == id.rcid_val)
820Sstevel@tonic-gate 			return (col);
830Sstevel@tonic-gate 	return (NULL);
840Sstevel@tonic-gate }
850Sstevel@tonic-gate 
860Sstevel@tonic-gate static col_t *
col_insert(rcid_t id)870Sstevel@tonic-gate col_insert(rcid_t id)
880Sstevel@tonic-gate {
890Sstevel@tonic-gate 	col_t *new_col;
900Sstevel@tonic-gate 
910Sstevel@tonic-gate 	new_col = malloc(sizeof (col_t));
920Sstevel@tonic-gate 	if (new_col == NULL) {
930Sstevel@tonic-gate 		(void) fprintf(stderr, gettext("rcapstat: malloc() failed\n"));
940Sstevel@tonic-gate 		exit(E_ERROR);
950Sstevel@tonic-gate 	}
960Sstevel@tonic-gate 	(void) memset(new_col, 0, sizeof (col_t));
970Sstevel@tonic-gate 	new_col->col_next = col_head;
980Sstevel@tonic-gate 	new_col->col_id = id;
990Sstevel@tonic-gate 	if (col_head != NULL)
1000Sstevel@tonic-gate 		col_head->col_prev = new_col;
1010Sstevel@tonic-gate 	col_head = new_col;
1020Sstevel@tonic-gate 	ncol++;
1030Sstevel@tonic-gate 	return (new_col);
1040Sstevel@tonic-gate }
1050Sstevel@tonic-gate 
1060Sstevel@tonic-gate static void
col_remove(col_t * col)1070Sstevel@tonic-gate col_remove(col_t *col)
1080Sstevel@tonic-gate {
1090Sstevel@tonic-gate 	if (col->col_prev != NULL)
1100Sstevel@tonic-gate 		col->col_prev->col_next = col->col_next;
1110Sstevel@tonic-gate 	if (col->col_next != NULL)
1120Sstevel@tonic-gate 		col->col_next->col_prev = col->col_prev;
1130Sstevel@tonic-gate 	if (col_head == col)
1140Sstevel@tonic-gate 		col_head = col->col_next;
1150Sstevel@tonic-gate 	ncol--;
1160Sstevel@tonic-gate 	free(col);
1170Sstevel@tonic-gate }
1180Sstevel@tonic-gate 
1190Sstevel@tonic-gate static void
usage()1200Sstevel@tonic-gate usage()
1210Sstevel@tonic-gate {
1220Sstevel@tonic-gate 	(void) fprintf(stderr,
12310265SKrishnendu.Sadhukhan@Sun.COM 	    gettext("usage: rcapstat [-g] [-p | -z] [-T d|u] "
12410265SKrishnendu.Sadhukhan@Sun.COM 	    "[interval [count]]\n"));
1250Sstevel@tonic-gate 	exit(E_USAGE);
1260Sstevel@tonic-gate }
1270Sstevel@tonic-gate 
1280Sstevel@tonic-gate static void
format_size(char * str,uint64_t size,int length)1290Sstevel@tonic-gate format_size(char *str, uint64_t size, int length)
1300Sstevel@tonic-gate {
1310Sstevel@tonic-gate 	char tag = 'K';
1320Sstevel@tonic-gate 	if (size >= 10000) {
1330Sstevel@tonic-gate 		size = (size + 512) / 1024;
1340Sstevel@tonic-gate 		tag = 'M';
1350Sstevel@tonic-gate 		if (size >= 10000) {
1360Sstevel@tonic-gate 			size = (size + 512) / 1024;
1370Sstevel@tonic-gate 			tag = 'G';
1380Sstevel@tonic-gate 		}
1390Sstevel@tonic-gate 	}
1400Sstevel@tonic-gate 	(void) snprintf(str, length, "%4lld%c", size, tag);
1410Sstevel@tonic-gate }
1420Sstevel@tonic-gate 
1430Sstevel@tonic-gate static int
read_stats(rcid_type_t stat_type)1443247Sgjelinek read_stats(rcid_type_t stat_type)
1450Sstevel@tonic-gate {
1460Sstevel@tonic-gate 	int fd;
1470Sstevel@tonic-gate 	int proc_fd;
1480Sstevel@tonic-gate 	char procfile[20];
1493247Sgjelinek 	uint64_t pid;
1500Sstevel@tonic-gate 	col_t *col, *col_next;
1510Sstevel@tonic-gate 	lcollection_report_t report;
1520Sstevel@tonic-gate 	struct stat st;
1530Sstevel@tonic-gate 
1540Sstevel@tonic-gate 	if ((fd = open(STAT_FILE_DEFAULT, O_RDONLY)) < 0) {
1550Sstevel@tonic-gate 		warn(gettext("rcapd is not active\n"));
1560Sstevel@tonic-gate 		return (E_ERROR);
1570Sstevel@tonic-gate 	}
1580Sstevel@tonic-gate 
1590Sstevel@tonic-gate 	if (fstat(fd, &st) == 0)
1600Sstevel@tonic-gate 		stat_mod = st.st_mtime;
1610Sstevel@tonic-gate 
1620Sstevel@tonic-gate 	if (read(fd, &hdr, sizeof (hdr)) != sizeof (hdr)) {
1630Sstevel@tonic-gate 		(void) fprintf(stderr,
1640Sstevel@tonic-gate 		    gettext("rcapstat: can't read stat file header: %s\n"),
1650Sstevel@tonic-gate 		    strerror(errno));
1660Sstevel@tonic-gate 		(void) close(fd);
1670Sstevel@tonic-gate 		return (E_ERROR);
1680Sstevel@tonic-gate 	}
1690Sstevel@tonic-gate 
1700Sstevel@tonic-gate 	/*
1710Sstevel@tonic-gate 	 * Check if rcapd is running
1720Sstevel@tonic-gate 	 */
1730Sstevel@tonic-gate 	pid = hdr.rs_pid;
1743247Sgjelinek 	(void) snprintf(procfile, 20, "/proc/%lld/psinfo", pid);
1750Sstevel@tonic-gate 	if ((proc_fd = open(procfile, O_RDONLY)) < 0) {
1760Sstevel@tonic-gate 		warn(gettext("rcapd is not active\n"));
1770Sstevel@tonic-gate 		(void) close(fd);
1780Sstevel@tonic-gate 		return (E_ERROR);
1790Sstevel@tonic-gate 	}
1800Sstevel@tonic-gate 	(void) close(proc_fd);
1810Sstevel@tonic-gate 
1820Sstevel@tonic-gate 	(void) strncpy(mode, hdr.rs_mode, RC_MODE_LEN);
1830Sstevel@tonic-gate 	for (col = col_head; col != NULL; col = col->col_next) {
1840Sstevel@tonic-gate 		col->col_fresh = 0;
1850Sstevel@tonic-gate 		col->col_paged_eff = 0;
1860Sstevel@tonic-gate 		col->col_paged_att = 0;
1870Sstevel@tonic-gate 	}
1880Sstevel@tonic-gate 
1890Sstevel@tonic-gate 	while (read(fd, &report, sizeof (report)) == sizeof (report)) {
1903247Sgjelinek 		if (report.lcol_id.rcid_type != stat_type)
1913247Sgjelinek 			continue;
1923247Sgjelinek 
1930Sstevel@tonic-gate 		col = col_find(report.lcol_id);
1940Sstevel@tonic-gate 		if (col == NULL) {
1950Sstevel@tonic-gate 			col = col_insert(report.lcol_id);
1960Sstevel@tonic-gate 			col->col_paged_eff_old = col->col_paged_eff =
1970Sstevel@tonic-gate 			    report.lcol_stat.lcols_pg_eff;
1980Sstevel@tonic-gate 			col->col_paged_att_old = col->col_paged_att =
1990Sstevel@tonic-gate 			    report.lcol_stat.lcols_pg_att;
2000Sstevel@tonic-gate 			col->col_count = 0;
2010Sstevel@tonic-gate 		}
2020Sstevel@tonic-gate 		(void) strncpy(col->col_name, report.lcol_name, LC_NAME_LEN);
2030Sstevel@tonic-gate 		col->col_vmsize = report.lcol_image_size;
2040Sstevel@tonic-gate 		col->col_rsssize = report.lcol_rss;
2050Sstevel@tonic-gate 		col->col_rsslimit = report.lcol_rss_cap;
2060Sstevel@tonic-gate 		col->col_fresh = 1;
2070Sstevel@tonic-gate 		if (report.lcol_stat.lcols_pg_eff > col->col_paged_eff_old) {
2080Sstevel@tonic-gate 			col->col_paged_eff =
2090Sstevel@tonic-gate 			    report.lcol_stat.lcols_pg_eff -
2100Sstevel@tonic-gate 			    col->col_paged_eff_old;
2110Sstevel@tonic-gate 			if (report.lcol_stat.lcols_scan_count > col->col_count)
2120Sstevel@tonic-gate 				col->col_paged_eff_avg =
2130Sstevel@tonic-gate 				    col->col_paged_eff /
2140Sstevel@tonic-gate 				    (report.lcol_stat.lcols_scan_count -
2150Sstevel@tonic-gate 				    col->col_count);
2160Sstevel@tonic-gate 		} else {
2170Sstevel@tonic-gate 			col->col_paged_eff_avg = 0;
2180Sstevel@tonic-gate 		}
2190Sstevel@tonic-gate 		if (report.lcol_stat.lcols_pg_att > col->col_paged_att_old) {
2200Sstevel@tonic-gate 			col->col_paged_att =
2210Sstevel@tonic-gate 			    report.lcol_stat.lcols_pg_att -
2220Sstevel@tonic-gate 			    col->col_paged_att_old;
2230Sstevel@tonic-gate 			if (report.lcol_stat.lcols_scan_count > col->col_count)
2240Sstevel@tonic-gate 				col->col_paged_att_avg =
2250Sstevel@tonic-gate 				    col->col_paged_att /
2260Sstevel@tonic-gate 				    (report.lcol_stat.lcols_scan_count -
2270Sstevel@tonic-gate 				    col->col_count);
2280Sstevel@tonic-gate 		} else {
2290Sstevel@tonic-gate 			col->col_paged_att_avg = 0;
2300Sstevel@tonic-gate 		}
2310Sstevel@tonic-gate 		col->col_paged_eff_old = report.lcol_stat.lcols_pg_eff;
2320Sstevel@tonic-gate 		col->col_paged_att_old = report.lcol_stat.lcols_pg_att;
2330Sstevel@tonic-gate 		col->col_nproc =
2340Sstevel@tonic-gate 		    report.lcol_stat.lcols_proc_in -
2350Sstevel@tonic-gate 		    report.lcol_stat.lcols_proc_out;
2360Sstevel@tonic-gate 		col->col_count = report.lcol_stat.lcols_scan_count;
2370Sstevel@tonic-gate 		col->col_src_stat = report.lcol_stat;
2380Sstevel@tonic-gate 	}
2390Sstevel@tonic-gate 
2400Sstevel@tonic-gate 	/*
2410Sstevel@tonic-gate 	 * Remove stale data
2420Sstevel@tonic-gate 	 */
2430Sstevel@tonic-gate 	col = col_head;
2440Sstevel@tonic-gate 	while (col != NULL) {
2450Sstevel@tonic-gate 		col_next = col->col_next;
2460Sstevel@tonic-gate 		if (col->col_fresh == 0)
2470Sstevel@tonic-gate 			col_remove(col);
2480Sstevel@tonic-gate 		col = col_next;
2490Sstevel@tonic-gate 	}
2500Sstevel@tonic-gate 	(void) close(fd);
2510Sstevel@tonic-gate 	return (E_SUCCESS);
2520Sstevel@tonic-gate }
2530Sstevel@tonic-gate 
2540Sstevel@tonic-gate /*
2550Sstevel@tonic-gate  * Print each collection's interval statistics.
2560Sstevel@tonic-gate  */
2570Sstevel@tonic-gate /*ARGSUSED*/
2580Sstevel@tonic-gate static void
print_unformatted_stats(void)2590Sstevel@tonic-gate print_unformatted_stats(void)
2600Sstevel@tonic-gate {
2610Sstevel@tonic-gate 	col_t *col;
2620Sstevel@tonic-gate 
2630Sstevel@tonic-gate #define	DELTA(field) \
2640Sstevel@tonic-gate 	(col->col_src_stat.field - col->col_old_stat.field)
2650Sstevel@tonic-gate 
2660Sstevel@tonic-gate 	col = col_head;
2670Sstevel@tonic-gate 	while (col != NULL) {
2680Sstevel@tonic-gate 		if (bcmp(&col->col_src_stat, &col->col_old_stat,
2690Sstevel@tonic-gate 		    sizeof (col->col_src_stat)) == 0) {
2700Sstevel@tonic-gate 			col = col->col_next;
2710Sstevel@tonic-gate 			continue;
2720Sstevel@tonic-gate 		}
2730Sstevel@tonic-gate 		(void) printf("%s %s status: succeeded/attempted (k): "
2740Sstevel@tonic-gate 		    "%llu/%llu, ineffective/scans/unenforced/samplings:  "
2750Sstevel@tonic-gate 		    "%llu/%llu/%llu/%llu, RSS min/max (k): %llu/%llu, cap %llu "
2760Sstevel@tonic-gate 		    "kB, processes/thpt: %llu/%llu, %llu scans over %lld ms\n",
2770Sstevel@tonic-gate 		    mode, col->col_name, DELTA(lcols_pg_eff),
2780Sstevel@tonic-gate 		    DELTA(lcols_pg_att), DELTA(lcols_scan_ineffective),
2790Sstevel@tonic-gate 		    DELTA(lcols_scan), DELTA(lcols_unenforced_cap),
2800Sstevel@tonic-gate 		    DELTA(lcols_rss_sample), col->col_src_stat.lcols_min_rss,
2810Sstevel@tonic-gate 		    col->col_src_stat.lcols_max_rss, col->col_rsslimit,
2820Sstevel@tonic-gate 		    (col->col_src_stat.lcols_proc_in -
2830Sstevel@tonic-gate 		    col->col_old_stat.lcols_proc_out), DELTA(lcols_proc_out),
2840Sstevel@tonic-gate 		    DELTA(lcols_scan_count), DELTA(lcols_scan_time_complete) /
2850Sstevel@tonic-gate 		    (NANOSEC / MILLISEC));
2860Sstevel@tonic-gate 		col->col_old_stat = col->col_src_stat;
2870Sstevel@tonic-gate 
2880Sstevel@tonic-gate 		col = col->col_next;
2890Sstevel@tonic-gate 	}
2900Sstevel@tonic-gate 
2910Sstevel@tonic-gate 	if (global)
2920Sstevel@tonic-gate 		(void) printf(gettext("physical memory utilization: %3u%%   "
2930Sstevel@tonic-gate 		    "cap enforcement threshold: %3u%%\n"), hdr.rs_pressure_cur,
2940Sstevel@tonic-gate 		    hdr.rs_pressure_cap);
2950Sstevel@tonic-gate #undef DELTA
2960Sstevel@tonic-gate }
2970Sstevel@tonic-gate 
2980Sstevel@tonic-gate static void
print_stats(rcid_type_t stat_type)2993247Sgjelinek print_stats(rcid_type_t stat_type)
3000Sstevel@tonic-gate {
3010Sstevel@tonic-gate 	col_t *col;
3020Sstevel@tonic-gate 	char size[6];
3030Sstevel@tonic-gate 	char limit[6];
3040Sstevel@tonic-gate 	char rss[6];
3053247Sgjelinek 	char nproc[6];
3060Sstevel@tonic-gate 	char paged_att[6];
3070Sstevel@tonic-gate 	char paged_eff[6];
3080Sstevel@tonic-gate 	char paged_att_avg[6];
3090Sstevel@tonic-gate 	char paged_eff_avg[6];
3100Sstevel@tonic-gate 	static int count = 0;
3110Sstevel@tonic-gate 
3120Sstevel@tonic-gate 	/*
3130Sstevel@tonic-gate 	 * Print a header once every 20 times if we're only displaying reports
3140Sstevel@tonic-gate 	 * for one collection (10 times if -g is used).  Print a header every
3150Sstevel@tonic-gate 	 * interval otherwise.
3160Sstevel@tonic-gate 	 */
3170Sstevel@tonic-gate 	if (count == 0 || ncol != 1)
3180Sstevel@tonic-gate 		(void) printf("%6s %-15s %5s %5s %5s %5s %5s %5s %5s %5s\n",
3193247Sgjelinek 		    "id", (stat_type == RCIDT_PROJECT ?  "project" : "zone"),
3203247Sgjelinek 		    "nproc", "vm", "rss", "cap",
3210Sstevel@tonic-gate 		    "at", "avgat", "pg", "avgpg");
3220Sstevel@tonic-gate 	if (++count >= 20 || (count >= 10 && global != 0) || ncol != 1)
3230Sstevel@tonic-gate 		count = 0;
3240Sstevel@tonic-gate 
3250Sstevel@tonic-gate 	for (col = col_head; col != NULL; col = col->col_next) {
3263247Sgjelinek 		if (col->col_id.rcid_type != stat_type)
3273247Sgjelinek 			continue;
3283247Sgjelinek 
3293247Sgjelinek 		if (col->col_paged_att == 0)
3304131Stn143363 			(void) strlcpy(nproc, "-", sizeof (nproc));
3313247Sgjelinek 		else
3323247Sgjelinek 			(void) snprintf(nproc, sizeof (nproc), "%lld",
3333247Sgjelinek 			    col->col_nproc);
3340Sstevel@tonic-gate 		format_size(size, col->col_vmsize, 6);
3350Sstevel@tonic-gate 		format_size(rss, col->col_rsssize, 6);
3360Sstevel@tonic-gate 		format_size(limit, col->col_rsslimit, 6);
3370Sstevel@tonic-gate 		format_size(paged_att, col->col_paged_att, 6);
3380Sstevel@tonic-gate 		format_size(paged_eff, col->col_paged_eff, 6);
3390Sstevel@tonic-gate 		format_size(paged_att_avg, col->col_paged_att_avg, 6);
3400Sstevel@tonic-gate 		format_size(paged_eff_avg, col->col_paged_eff_avg, 6);
3413247Sgjelinek 		(void) printf("%6lld %-15s %5s %5s %5s %5s %5s %5s %5s %5s\n",
3423247Sgjelinek 		    col->col_id.rcid_val, col->col_name,
3433247Sgjelinek 		    nproc,
3440Sstevel@tonic-gate 		    size, rss, limit,
3450Sstevel@tonic-gate 		    paged_att, paged_att_avg,
3460Sstevel@tonic-gate 		    paged_eff, paged_eff_avg);
3470Sstevel@tonic-gate 	}
3480Sstevel@tonic-gate 	if (global)
3490Sstevel@tonic-gate 		(void) printf(gettext("physical memory utilization: %3u%%   "
3500Sstevel@tonic-gate 		    "cap enforcement threshold: %3u%%\n"), hdr.rs_pressure_cur,
3510Sstevel@tonic-gate 		    hdr.rs_pressure_cap);
3520Sstevel@tonic-gate }
3530Sstevel@tonic-gate 
3540Sstevel@tonic-gate int
main(int argc,char * argv[])3550Sstevel@tonic-gate main(int argc, char *argv[])
3560Sstevel@tonic-gate {
3570Sstevel@tonic-gate 	int interval = 5;
3580Sstevel@tonic-gate 	int count;
3590Sstevel@tonic-gate 	int always = 1;
3600Sstevel@tonic-gate 	int opt;
3613247Sgjelinek 	int projects = 0;
3623247Sgjelinek 	int zones = 0;
3633247Sgjelinek 	/* project reporting is the default if no option is specified */
3643247Sgjelinek 	rcid_type_t stat_type = RCIDT_PROJECT;
3650Sstevel@tonic-gate 
3660Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
3670Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
368*13093SRoger.Faulkner@Oracle.COM 	(void) setpname("rcapstat");
3690Sstevel@tonic-gate 
3700Sstevel@tonic-gate 	global = unformatted = 0;
37110265SKrishnendu.Sadhukhan@Sun.COM 	while ((opt = getopt(argc, argv, "gpuzT:")) != (int)EOF) {
3720Sstevel@tonic-gate 		switch (opt) {
3730Sstevel@tonic-gate 		case 'g':
3740Sstevel@tonic-gate 			global = 1;
3750Sstevel@tonic-gate 			break;
3763247Sgjelinek 		case 'p':
3773247Sgjelinek 			projects = 1;
3783247Sgjelinek 			stat_type = RCIDT_PROJECT;
3793247Sgjelinek 			break;
3800Sstevel@tonic-gate 		case 'u':
3810Sstevel@tonic-gate 			unformatted = 1;
3820Sstevel@tonic-gate 			break;
3833247Sgjelinek 		case 'z':
3843247Sgjelinek 			stat_type = RCIDT_ZONE;
3853247Sgjelinek 			zones = 1;
3863247Sgjelinek 			break;
38710265SKrishnendu.Sadhukhan@Sun.COM 		case 'T':
38810265SKrishnendu.Sadhukhan@Sun.COM 			if (optarg) {
38910265SKrishnendu.Sadhukhan@Sun.COM 				if (*optarg == 'u')
39010265SKrishnendu.Sadhukhan@Sun.COM 					timestamp_fmt = UDATE;
39110265SKrishnendu.Sadhukhan@Sun.COM 				else if (*optarg == 'd')
39210265SKrishnendu.Sadhukhan@Sun.COM 					timestamp_fmt = DDATE;
39310265SKrishnendu.Sadhukhan@Sun.COM 				else
39410265SKrishnendu.Sadhukhan@Sun.COM 					usage();
39510265SKrishnendu.Sadhukhan@Sun.COM 			} else {
39610265SKrishnendu.Sadhukhan@Sun.COM 				usage();
39710265SKrishnendu.Sadhukhan@Sun.COM 			}
39810265SKrishnendu.Sadhukhan@Sun.COM 			break;
3990Sstevel@tonic-gate 		default:
4000Sstevel@tonic-gate 			usage();
4010Sstevel@tonic-gate 		}
4020Sstevel@tonic-gate 	}
4030Sstevel@tonic-gate 
4040Sstevel@tonic-gate 	if (argc > optind)
4050Sstevel@tonic-gate 		if ((interval = xatoi(argv[optind++])) <= 0)
4060Sstevel@tonic-gate 			die(gettext("invalid interval specified\n"));
4070Sstevel@tonic-gate 	if (argc > optind) {
4080Sstevel@tonic-gate 		if ((count = xatoi(argv[optind++])) <= 0)
4090Sstevel@tonic-gate 			die(gettext("invalid count specified\n"));
4100Sstevel@tonic-gate 		always = 0;
4110Sstevel@tonic-gate 	}
4123247Sgjelinek 	if (argc > optind || (projects > 0 && zones > 0))
4130Sstevel@tonic-gate 		usage();
4140Sstevel@tonic-gate 
4150Sstevel@tonic-gate 	while (always || count-- > 0) {
4163247Sgjelinek 		if (read_stats(stat_type) != E_SUCCESS)
4170Sstevel@tonic-gate 			return (E_ERROR);
41810265SKrishnendu.Sadhukhan@Sun.COM 		if (timestamp_fmt != NODATE)
41910265SKrishnendu.Sadhukhan@Sun.COM 			print_timestamp(timestamp_fmt);
4200Sstevel@tonic-gate 		if (!unformatted) {
4213247Sgjelinek 			print_stats(stat_type);
4223247Sgjelinek 			(void) fflush(stdout);
4230Sstevel@tonic-gate 			if (count || always)
4240Sstevel@tonic-gate 				(void) sleep(interval);
4250Sstevel@tonic-gate 		} else {
4260Sstevel@tonic-gate 			struct stat st;
4270Sstevel@tonic-gate 
4280Sstevel@tonic-gate 			print_unformatted_stats();
4293247Sgjelinek 			(void) fflush(stdout);
4300Sstevel@tonic-gate 			while (stat(STAT_FILE_DEFAULT, &st) == 0 &&
4310Sstevel@tonic-gate 			    st.st_mtime == stat_mod)
4324131Stn143363 				(void) usleep((useconds_t)(0.2 * MICROSEC));
4330Sstevel@tonic-gate 		}
4340Sstevel@tonic-gate 	}
4350Sstevel@tonic-gate 
4360Sstevel@tonic-gate 	return (E_SUCCESS);
4370Sstevel@tonic-gate }
438