Reamove grub support.
[unleashed.git] / usr / src / cmd / avs / sdbc / sd_stats.c
blob211ce6c1d6f5845286ae1202245e0c02f0d52bb8
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <unistd.h>
30 #include <strings.h>
31 #include <curses.h>
32 #include <signal.h>
33 #include <fcntl.h>
34 #include <locale.h>
36 #include <sys/types.h>
37 #include <sys/time.h>
38 #include <sys/nsctl/sdbc_ioctl.h>
39 #include <sys/unistat/spcs_s_u.h>
40 #include <sys/nsctl/sd_bcache.h>
41 #include <sys/nsctl/sd_conf.h>
43 extern void total_display(void);
44 extern void display_cache(void);
45 extern void wrefresh_file(WINDOW *, int);
46 extern int is_dirty(void);
47 extern int dual_stats(void);
48 void checkbuf(int);
49 void setup_ranges(char *);
50 void prheading(int);
51 extern int zero_nic(void);
53 #ifdef m88k
54 #define USEC_INIT() usec_ptr = (unsigned int *)timer_init()
55 #define USEC_READ() (*usec_ptr)
56 #else /* !m88k */
57 #define USEC_INIT() USEC_START()
58 #include <sys/time.h>
59 static struct timeval Usec_time;
60 static int Usec_started = 0;
62 extern int higher(int);
63 extern int is_dirty();
64 extern int dual_stats();
65 extern void total_display();
66 extern void display_cache();
67 extern void wrefresh_file(WINDOW *, int);
68 void setup_ranges(char *);
70 void prheading(int);
71 void checkbuf(int);
72 void quit(int);
73 void leave(int);
74 #pragma does_not_return(quit, leave)
76 int sdbc_max_devices = 0;
78 static void
79 USEC_START()
81 if (!Usec_started) {
82 (void) gettimeofday(&Usec_time, NULL);
83 Usec_started = 1;
87 static unsigned int
88 USEC_READ()
90 struct timeval tv;
91 if (!Usec_started)
92 USEC_START();
94 (void) gettimeofday(&tv, NULL);
95 return (unsigned)((tv.tv_sec - Usec_time.tv_sec) * 1000000
96 + (tv.tv_usec - Usec_time.tv_usec));
98 #endif /* m88k */
100 int rev_flag = 0; /* Reverse video flag */
101 int bold_flg = 0; /* Bold flag */
102 int under_flg = 0; /* Underline flag */
103 int errflg = 0; /* Error flag */
104 int node_sw = 0; /* Per node switch */
105 int toggle_total_sw = 0;
106 int mirror_sw = 0; /* Dual copy switch */
108 int kmemfd;
109 int delay = 1; /* Display delay (seconds) */
111 time_t *usec_ptr;
112 time_t currtime = 0;
113 int lasttime = 0;
114 int Elapsed_Time = 0;
116 static char *range;
117 static int had_r_option = 0;
118 int logfd = -1; /* screen output logging */
119 extern int range_num;
120 extern int screen;
121 extern int dual_screen;
122 int *on_off;
123 int *dual_on_off;
124 int *updates_prev;
125 double *rate_prev;
126 int *samples;
127 _sd_stats_t *cs_cur;
128 _sd_stats_t *cs_prev;
129 _sd_stats_t *cs_persec;
131 typedef struct {
132 int lb, ub;
133 } range_t;
135 extern range_t ranges[];
137 #ifdef lint
139 sd_stats_lintmain(int argc, char *argv[])
140 #else
142 main(int argc, char *argv[])
143 #endif
145 spcs_s_info_t ustats;
146 struct timeval tout;
147 fd_set readfds;
148 char *errmessage, *ch;
149 int c, period, prev;
150 int count = 0, dflag = 0;
151 int fd = fileno(stdin);
153 errmessage = NULL;
155 if (strcmp(argv[0], "sd_stats") != 0)
156 errmessage = getenv("SD_STATS_USAGE");
158 if (errmessage == NULL)
159 errmessage = gettext("Usage: sd_stats [-Mz] "
160 "[-d delay_time] [-l logfile] [-r range]");
162 if (SDBC_IOCTL(SDBC_MAXFILES, &sdbc_max_devices,
163 0, 0, 0, 0, &ustats) == SPCS_S_ERROR) {
164 if (ustats) { /* if SPCS_S_ERROR */
165 spcs_s_report(ustats, stderr);
166 spcs_s_ufree(&ustats);
168 (void) fprintf(stderr, gettext("cannot get maxfiles\n"));
169 exit(1);
171 on_off = calloc(sdbc_max_devices, sizeof (int));
172 dual_on_off = calloc(sdbc_max_devices, sizeof (int));
173 updates_prev = calloc(sdbc_max_devices, sizeof (int));
174 samples = calloc(sdbc_max_devices, sizeof (int));
175 rate_prev = calloc(sdbc_max_devices, sizeof (double));
176 cs_cur = malloc(sizeof (_sd_stats_t) +
177 (sdbc_max_devices - 1) * sizeof (_sd_shared_t));
178 cs_prev = malloc(sizeof (_sd_stats_t) +
179 (sdbc_max_devices - 1) * sizeof (_sd_shared_t));
180 cs_persec = malloc(sizeof (_sd_stats_t) +
181 (sdbc_max_devices - 1) * sizeof (_sd_shared_t));
182 range = malloc(100);
184 if (!on_off || !dual_on_off || !updates_prev || !samples ||
185 !rate_prev || !cs_cur || !cs_prev || !cs_persec || !range) {
186 (void) fprintf(stderr, gettext("no free memory\n"));
187 exit(1);
190 *range = '\0';
192 while ((c = getopt(argc, argv, "DMzd:l:r:h")) != EOF) {
194 prev = c;
195 switch (c) {
197 case 'd':
198 delay = atoi(optarg);
199 ch = optarg;
200 while (*ch != '\0') {
201 if (!isdigit(*ch))
202 errflg++;
203 ch++;
205 break;
207 case 'l':
208 logfd = open(optarg, O_CREAT|O_WRONLY|O_TRUNC, 0644);
209 break;
211 case 'r':
212 ch = optarg;
213 while (*ch != '\0') {
214 if ((!isdigit(*ch)) && (*ch != ',') &&
215 (*ch != ':'))
216 errflg++;
217 ch++;
219 if (errflg)
220 break;
222 range = realloc((char *)range,
223 (strlen(range) + strlen(optarg) + 1)
224 * sizeof (char));
226 if (had_r_option)
227 (void) strcat(range, ",");
228 (void) strcat(range, optarg);
229 had_r_option = 1;
230 break;
232 case 'z':
233 if (SDBC_IOCTL(SDBC_ZAP_STATS, 0, 0, 0, 0, 0,
234 &ustats) == SPCS_S_ERROR) {
235 if (ustats) {
236 spcs_s_report(ustats, stderr);
237 spcs_s_ufree(&ustats);
241 break;
243 case 'D':
244 dflag = 1;
245 break;
247 case 'M':
248 mirror_sw = 1;
249 break;
251 case 'h':
252 case '?':
253 default :
254 errflg++;
255 break;
259 if (errflg) {
260 (void) fprintf(stderr, "%s\n", errmessage);
261 exit(1);
262 } else if (!prev) {
263 if (argc > 1) {
264 (void) fprintf(stderr, "%s\n", errmessage);
265 exit(1);
269 if (dflag) {
270 exit(is_dirty());
275 * A few curses routines to setup screen and tty interface
277 (void) initscr();
278 (void) cbreak();
279 (void) noecho();
280 (void) nonl();
281 (void) erase();
282 (void) clear();
283 (void) refresh();
285 setup_ranges(range);
288 * Set signal handle
290 (void) sigset(SIGPIPE, leave);
291 (void) sigset(SIGINT, leave);
292 (void) sigset(SIGQUIT, leave);
293 (void) signal(SIGFPE, leave);
294 (void) signal(SIGSEGV, leave);
296 USEC_INIT();
297 currtime = USEC_READ();
300 * Wait one second before reading the new values
302 (void) sleep(1);
304 /*CONSTCOND*/
305 while (1) {
307 lasttime = currtime;
308 currtime = USEC_READ();
311 * If less that 1 second, force it to one second
313 if ((period = (currtime - lasttime) / 1000000) <= 0)
314 period = 1;
317 * Calculate new per/period values for statistics
319 Elapsed_Time += period;
322 * Display new statistics
324 prheading(++count);
326 if (mirror_sw) {
327 if (dual_stats() < 0)
328 mirror_sw = 0;
329 } else if (toggle_total_sw)
330 total_display();
331 else
332 display_cache();
334 (void) move(0, 0);
335 (void) refresh();
336 if (logfd > -1) wrefresh_file(stdscr, logfd);
338 FD_ZERO(&readfds);
339 FD_SET(fd, &readfds);
340 tout.tv_sec = delay;
341 for (;;) {
342 tout.tv_usec = 0;
343 if (select(fd + 1, &readfds, (fd_set *)0, (fd_set *)0,
344 &tout) <= 0)
345 break;
346 if ((c = getch()) == EOF) {
347 (void) sleep(delay);
348 break;
350 checkbuf(c);
351 tout.tv_sec = 0;
353 (void) erase();
355 #pragma error_messages(off, E_STATEMENT_NOT_REACHED)
356 return (0);
357 #pragma error_messages(default, E_STATEMENT_NOT_REACHED)
360 void
361 checkbuf(int c)
363 spcs_s_info_t ustats;
365 switch (c) {
366 case 'b' : /* ctrl b or b -- scroll backward */
367 case 2 :
369 if (mirror_sw == 1) {
370 if (dual_screen > 0)
371 dual_screen--;
372 break;
374 if (screen > 0)
375 screen--;
376 break;
379 case 'f' : /* ctrl f or f -- scroll forward */
380 case 6 :
382 if (mirror_sw == 1) {
383 dual_screen++;
384 break;
386 screen++;
387 break;
390 case 't':
391 case 'T':
392 if (mirror_sw == 1)
393 mirror_sw = 0;
395 toggle_total_sw ^= 1;
396 break;
398 case '-':
399 case KEY_DOWN:
400 if (delay > 1) {
401 --delay;
402 } else {
403 (void) beep();
405 break;
407 case '+':
408 case KEY_UP:
409 delay++;
410 break;
412 case 'C':
413 case 0xc:
414 (void) clearok(stdscr, TRUE);
415 break;
417 case 'B':
418 if (bold_flg) {
419 bold_flg = 0;
420 (void) attroff(A_BOLD);
421 } else {
422 bold_flg = 1;
423 (void) attron(A_BOLD);
425 break;
427 case 'R':
428 if (rev_flag) {
429 rev_flag = 0;
430 (void) attroff(A_REVERSE);
431 } else {
432 rev_flag = 1;
433 (void) attron(A_REVERSE);
435 break;
437 case 'z':
438 if (SDBC_IOCTL(SDBC_ZAP_STATS, 0, 0, 0, 0, 0,
439 &ustats) == SPCS_S_ERROR) {
440 if (ustats) {
441 spcs_s_report(ustats, stderr);
442 spcs_s_ufree(&ustats);
445 break;
447 case 'm':
448 case 'M':
449 mirror_sw = mirror_sw ? 0 : 1;
450 (void) clear();
451 break;
455 void
456 prheading(int count)
458 time_t tim;
461 * Print sample count in upper left corner
463 (void) mvprintw(0, 0, "SAMPLE %-8d", count);
466 * Get time and print it in upper right corner
468 tim = time((time_t *)0);
469 (void) mvprintw(0, 79 - 10, "%-8.8s\n", &(ctime(&tim)[11]));
472 /*ARGSUSED*/
473 void
474 leave(int status)
476 (void) sigignore(SIGPIPE);
477 (void) sigignore(SIGALRM);
478 /* clear(); */
479 (void) move(LINES, 0);
480 (void) refresh();
481 if (logfd > -1) wrefresh_file(stdscr, logfd);
482 quit(0);
485 void
486 quit(int status)
488 (void) resetterm();
489 (void) endwin();
490 exit(status);
493 void
494 setup_ranges(char *range)
496 int ndx;
497 char chr1;
498 char prev_chr = '\0';
499 int got_colon = 0;
500 int after_got_colon = 0;
501 int got_comma = 0;
502 int after_got_comma = 0;
503 int number = 0;
504 int prev_num = 0;
506 if (range == NULL || (strlen(range) == 0)) {
507 ranges[range_num].lb = 0;
508 ranges[range_num].ub = sdbc_max_devices - 1;
509 return;
510 } else {
511 ndx = 0;
512 got_comma = 0;
513 got_colon = 0;
514 while ((chr1 = (range[ndx++])) != '\0') {
515 switch (chr1) {
516 case '0':
517 case '1':
518 case '2':
519 case '3':
520 case '4':
521 case '5':
522 case '6':
523 case '7':
524 case '8':
525 case '9':
526 number = number*10 + (chr1 - '0');
527 break;
528 case ':':
529 got_colon = 1;
530 break;
531 case ',':
532 got_comma = 1;
533 break;
534 default: /* ignore any unknown characters */
535 break;
536 } /* switch */
537 if (got_comma && after_got_colon) {
538 after_got_colon = 0;
539 got_comma = 0;
540 if (number >= sdbc_max_devices)
541 number = sdbc_max_devices - 1;
542 ranges[range_num].lb = prev_num;
543 ranges[range_num].ub = number;
544 if (range_num == 99) break;
545 range_num++;
546 number = 0;
547 } else if (got_colon && after_got_comma) {
548 got_colon = 0;
549 after_got_colon = 1;
550 after_got_comma = 0;
551 if (number >= sdbc_max_devices)
552 number = sdbc_max_devices - 1;
553 prev_num = number;
554 number = 0;
555 } else if (got_colon) {
556 got_colon = 0;
557 after_got_colon = 1;
558 if ((prev_chr != '\0') && (prev_chr != ':')) {
559 if (number >= sdbc_max_devices)
560 number = sdbc_max_devices - 1;
561 prev_num = number;
562 number = 0;
564 } else if (got_comma) {
565 got_comma = 0;
566 after_got_comma = 1;
567 after_got_colon = 0;
568 if (number >= sdbc_max_devices)
569 number = sdbc_max_devices -1;
570 if ((prev_chr != '\0') && (prev_chr != ',')) {
571 ranges[range_num].lb = number;
572 ranges[range_num].ub = number;
573 if (range_num == 99) break;
574 range_num++;
576 number = 0;
577 } /* if */
578 prev_chr = chr1;
579 } /* while */
580 if (number >= sdbc_max_devices)
581 number = sdbc_max_devices - 1;
582 if (after_got_colon) {
583 ranges[range_num].lb = prev_num;
584 ranges[range_num].ub = number;
585 } else {
586 if ((after_got_comma) && (prev_chr == ','))
587 range_num--;
588 else {
589 ranges[range_num].lb = number;
590 ranges[range_num].ub = number;