progress.c (3564B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * Progress Report module 8 * 9 * Usage: 10 * 11 * Call progress_init and pass it a measure of the total count. 12 * To avoid messing up the display, try not to print 13 * anything from now until you've called progress_done. 14 * 15 * In your loop, call progress_report on every iteration and pass it 16 * an increment to the current count (usually 1). 17 * Regardless of how often it is called, an adaptive 18 * algorithm calls time() on average once per second, 19 * and updates the display if the percentage changes. 20 * 21 * Call progress_status at any time to add or change a status 22 * message displayed along with the percent done. 23 * 24 * Call progress_done when finished. 25 * 26 * If the entire procedure completes before start_seconds 27 * elapses, nothing is printed at all. 28 */ 29 30 #include <appl/diag/progress.h> 31 #include <sal/appl/sal.h> 32 #include <shared/bsl.h> 33 #include <sal/appl/io.h> 34 #include <sal/core/time.h> 35 36 struct { 37 int start_seconds; 38 int disable; 39 uint32 total_count; 40 uint32 partial_count; 41 sal_time_t start_time; 42 sal_time_t check_time; 43 int printed_something; 44 int last_frac_printed; 45 int iter_per_check_time; 46 int iter_count; 47 char *status_str; 48 } progress; 49 50 #define VT100_CLEAR_TO_EOL "\033\133\113" 51 52 void 53 progress_init(uint32 total_count, int start_seconds, int disable) 54 { 55 progress.start_seconds = start_seconds; 56 progress.disable = disable; 57 progress.total_count = total_count; 58 progress.partial_count = 0; 59 progress.start_time = sal_time(); 60 progress.check_time = progress.start_time; 61 progress.printed_something = 0; 62 progress.last_frac_printed = -1; 63 progress.iter_per_check_time = 1; 64 progress.iter_count = 0; 65 progress.status_str = 0; 66 } 67 68 void 69 progress_status(char *status_str) 70 { 71 progress.status_str = status_str; 72 progress.last_frac_printed = -1; 73 } 74 75 void 76 progress_report(uint32 count_incr) 77 { 78 sal_time_t tm; 79 if (progress.disable) 80 return; 81 if ((progress.partial_count += count_incr) > progress.total_count) 82 progress.partial_count = progress.total_count; 83 if (++progress.iter_count < progress.iter_per_check_time) 84 return; 85 tm = sal_time(); 86 if (progress.check_time == tm) { 87 int old_iter = progress.iter_per_check_time; 88 /* Calling time() more than once per second; slow down */ 89 progress.iter_per_check_time = 90 progress.iter_per_check_time * 5 / 4; 91 if (progress.iter_per_check_time == old_iter) 92 progress.iter_per_check_time++; 93 } else { 94 if (tm > progress.check_time + 1) { 95 /* Calling time() less than once per second; speed up */ 96 progress.iter_per_check_time = 97 progress.iter_per_check_time * 4 / 5; 98 } 99 progress.check_time = tm; 100 if (tm > progress.start_time + progress.start_seconds) { 101 int frac; 102 if (progress.total_count >= 0x1000000) /* Don't overflow */ 103 frac = progress.partial_count / (progress.total_count / 100); 104 else 105 frac = (100 * progress.partial_count) / progress.total_count; 106 if (frac != progress.last_frac_printed) { 107 cli_out("\r[%d%% done] %s " VT100_CLEAR_TO_EOL, 108 frac, 109 progress.status_str ? progress.status_str : ""); 110 progress.printed_something = 1; 111 progress.last_frac_printed = frac; 112 } 113 } 114 } 115 progress.iter_count = 0; 116 } 117 118 void 119 progress_done(void) 120 { 121 if (progress.printed_something) 122 cli_out("\r" VT100_CLEAR_TO_EOL); 123 }