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 */ 210Sstevel@tonic-gate /* 22*10265SKrishnendu.Sadhukhan@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 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" 41*10265SKrishnendu.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 49*10265SKrishnendu.Sadhukhan@Sun.COM static uint_t timestamp_fmt = NODATE; 50*10265SKrishnendu.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 * 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 * 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 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 1200Sstevel@tonic-gate usage() 1210Sstevel@tonic-gate { 1220Sstevel@tonic-gate (void) fprintf(stderr, 123*10265SKrishnendu.Sadhukhan@Sun.COM gettext("usage: rcapstat [-g] [-p | -z] [-T d|u] " 124*10265SKrishnendu.Sadhukhan@Sun.COM "[interval [count]]\n")); 1250Sstevel@tonic-gate exit(E_USAGE); 1260Sstevel@tonic-gate } 1270Sstevel@tonic-gate 1280Sstevel@tonic-gate static void 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 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 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 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 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); 3680Sstevel@tonic-gate (void) setprogname("rcapstat"); 3690Sstevel@tonic-gate 3700Sstevel@tonic-gate global = unformatted = 0; 371*10265SKrishnendu.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; 387*10265SKrishnendu.Sadhukhan@Sun.COM case 'T': 388*10265SKrishnendu.Sadhukhan@Sun.COM if (optarg) { 389*10265SKrishnendu.Sadhukhan@Sun.COM if (*optarg == 'u') 390*10265SKrishnendu.Sadhukhan@Sun.COM timestamp_fmt = UDATE; 391*10265SKrishnendu.Sadhukhan@Sun.COM else if (*optarg == 'd') 392*10265SKrishnendu.Sadhukhan@Sun.COM timestamp_fmt = DDATE; 393*10265SKrishnendu.Sadhukhan@Sun.COM else 394*10265SKrishnendu.Sadhukhan@Sun.COM usage(); 395*10265SKrishnendu.Sadhukhan@Sun.COM } else { 396*10265SKrishnendu.Sadhukhan@Sun.COM usage(); 397*10265SKrishnendu.Sadhukhan@Sun.COM } 398*10265SKrishnendu.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); 418*10265SKrishnendu.Sadhukhan@Sun.COM if (timestamp_fmt != NODATE) 419*10265SKrishnendu.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