Changeset 3232 in MondoRescue for branches/3.2/mindi-busybox/libbb/progress.c
- Timestamp:
- Jan 1, 2014, 12:47:38 AM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/3.2/mindi-busybox/libbb/progress.c
r2725 r3232 53 53 } 54 54 55 void FAST_FUNC bb_progress_init(bb_progress_t *p )55 void FAST_FUNC bb_progress_init(bb_progress_t *p, const char *curfile) 56 56 { 57 #if ENABLE_UNICODE_SUPPORT 58 init_unicode(); 59 p->curfile = unicode_conv_to_printable_fixedwidth(/*NULL,*/ curfile, 20); 60 #else 61 p->curfile = curfile; 62 #endif 57 63 p->start_sec = monotonic_sec(); 58 p->last update_sec = p->start_sec;59 p->last size = 0;60 p-> inited = 1;64 p->last_update_sec = p->start_sec; 65 p->last_change_sec = p->start_sec; 66 p->last_size = 0; 61 67 } 62 68 69 /* File already had beg_size bytes. 70 * Then we started downloading. 71 * We downloaded "transferred" bytes so far. 72 * Download is expected to stop when total size (beg_size + transferred) 73 * will be "totalsize" bytes. 74 * If totalsize == 0, then it is unknown. 75 */ 63 76 void FAST_FUNC bb_progress_update(bb_progress_t *p, 64 const char *curfile, 65 off_t beg_range, 66 off_t transferred, 67 off_t totalsize) 77 uoff_t beg_size, 78 uoff_t transferred, 79 uoff_t totalsize) 68 80 { 69 81 uoff_t beg_and_transferred; 70 82 unsigned since_last_update, elapsed; 71 unsigned ratio; 72 int barlength, i; 73 74 /* totalsize == 0 if it is unknown */ 83 int barlength; 84 int kiloscale; 85 86 //transferred = 1234; /* use for stall detection testing */ 87 //totalsize = 0; /* use for unknown size download testing */ 75 88 76 89 elapsed = monotonic_sec(); 77 since_last_update = elapsed - p->lastupdate_sec; 78 /* Do not update on every call 79 * (we can be called on every network read!) */ 80 if (since_last_update == 0 && !totalsize) 81 return; 82 83 beg_and_transferred = beg_range + transferred; 84 ratio = 100; 85 if (beg_and_transferred < totalsize) { 86 /* Do not update on every call 87 * (we can be called on every network read!) */ 88 if (since_last_update == 0) 89 return; 90 /* long long helps to have it working even if !LFS */ 91 ratio = 100ULL * beg_and_transferred / (uoff_t)totalsize; 92 } 93 94 #if ENABLE_UNICODE_SUPPORT 95 init_unicode(); 96 /* libbb candidate? */ 97 { 98 wchar_t wbuf21[21]; 99 char *buf = xstrdup(curfile); 100 unsigned len; 101 102 /* trim to 20 wide chars max (sets wbuf21[20] to 0) 103 * also, in case mbstowcs fails, we at least 104 * dont get garbage */ 105 memset(wbuf21, 0, sizeof(wbuf21)); 106 /* convert to wide chars, no more than 20 */ 107 len = mbstowcs(wbuf21, curfile, 20); /* NB: may return -1 */ 108 /* back to multibyte; cant overflow */ 109 wcstombs(buf, wbuf21, INT_MAX); 110 len = (len > 20) ? 0 : 20 - len; 111 fprintf(stderr, "\r%s%*s%4u%% ", buf, len, "", ratio); 112 free(buf); 113 } 114 #else 115 fprintf(stderr, "\r%-20.20s%4u%% ", curfile, ratio); 116 #endif 117 118 barlength = get_tty2_width() - 49; 119 if (barlength > 0) { 120 /* god bless gcc for variable arrays :) */ 121 char buf[barlength + 1]; 122 unsigned stars = (unsigned)barlength * ratio / (unsigned)100; 123 memset(buf, ' ', barlength); 124 buf[barlength] = '\0'; 125 memset(buf, '*', stars); 126 fprintf(stderr, "|%s|", buf); 127 } 128 129 i = 0; 90 since_last_update = elapsed - p->last_update_sec; 91 p->last_update_sec = elapsed; 92 93 if (totalsize != 0 && transferred >= totalsize - beg_size) { 94 /* Last call. Do not skip this update */ 95 transferred = totalsize - beg_size; /* sanitize just in case */ 96 } 97 else if (since_last_update == 0) { 98 /* 99 * Do not update on every call 100 * (we can be called on every network read!) 101 */ 102 return; 103 } 104 105 kiloscale = 0; 106 /* 107 * Scale sizes down if they are close to overflowing. 108 * This allows calculations like (100 * transferred / totalsize) 109 * without risking overflow: we guarantee 10 highest bits to be 0. 110 * Introduced error is less than 1 / 2^12 ~= 0.025% 111 */ 112 if (ULONG_MAX > 0xffffffff || sizeof(off_t) == 4 || sizeof(off_t) != 8) { 113 /* 114 * 64-bit CPU || small off_t: in either case, 115 * >> is cheap, single-word operation. 116 * ... || strange off_t: also use this code 117 * (it is safe, just suboptimal wrt code size), 118 * because 32/64 optimized one works only for 64-bit off_t. 119 */ 120 if (totalsize >= (1 << 22)) { 121 totalsize >>= 10; 122 beg_size >>= 10; 123 transferred >>= 10; 124 kiloscale = 1; 125 } 126 } else { 127 /* 32-bit CPU and 64-bit off_t. 128 * Use a 40-bit shift, it is easier to do on 32-bit CPU. 129 */ 130 /* ONE suppresses "warning: shift count >= width of type" */ 131 #define ONE (sizeof(off_t) > 4) 132 if (totalsize >= (uoff_t)(1ULL << 54*ONE)) { 133 totalsize = (uint32_t)(totalsize >> 32*ONE) >> 8; 134 beg_size = (uint32_t)(beg_size >> 32*ONE) >> 8; 135 transferred = (uint32_t)(transferred >> 32*ONE) >> 8; 136 kiloscale = 4; 137 } 138 } 139 140 if (ENABLE_UNICODE_SUPPORT) 141 fprintf(stderr, "\r%s", p->curfile); 142 else 143 fprintf(stderr, "\r%-20.20s", p->curfile); 144 145 beg_and_transferred = beg_size + transferred; 146 147 if (totalsize != 0) { 148 unsigned ratio = 100 * beg_and_transferred / totalsize; 149 fprintf(stderr, "%4u%%", ratio); 150 151 barlength = get_tty2_width() - 49; 152 if (barlength > 0) { 153 /* god bless gcc for variable arrays :) */ 154 char buf[barlength + 1]; 155 unsigned stars = (unsigned)barlength * beg_and_transferred / totalsize; 156 memset(buf, ' ', barlength); 157 buf[barlength] = '\0'; 158 memset(buf, '*', stars); 159 fprintf(stderr, " |%s|", buf); 160 } 161 } 162 130 163 while (beg_and_transferred >= 100000) { 131 i++;132 164 beg_and_transferred >>= 10; 165 kiloscale++; 133 166 } 134 167 /* see http://en.wikipedia.org/wiki/Tera */ 135 fprintf(stderr, "%6u%c ", (unsigned)beg_and_transferred, " kMGTPEZY"[i]); 136 #define beg_and_transferred dont_use_beg_and_transferred_below 137 138 if (transferred > p->lastsize) { 139 p->lastupdate_sec = elapsed; 140 p->lastsize = transferred; 168 fprintf(stderr, "%6u%c", (unsigned)beg_and_transferred, " kMGTPEZY"[kiloscale]); 169 #define beg_and_transferred dont_use_beg_and_transferred_below() 170 171 since_last_update = elapsed - p->last_change_sec; 172 if ((unsigned)transferred != p->last_size) { 173 p->last_change_sec = elapsed; 174 p->last_size = (unsigned)transferred; 141 175 if (since_last_update >= STALLTIME) { 142 /* We "cut o ff" these seconds from elapsed time176 /* We "cut out" these seconds from elapsed time 143 177 * by adjusting start time */ 144 178 p->start_sec += since_last_update; … … 146 180 since_last_update = 0; /* we are un-stalled now */ 147 181 } 182 148 183 elapsed -= p->start_sec; /* now it's "elapsed since start" */ 149 184 150 185 if (since_last_update >= STALLTIME) { 151 fprintf(stderr, " - stalled -"); 186 fprintf(stderr, " - stalled -"); 187 } else if (!totalsize || !transferred || (int)elapsed < 0) { 188 fprintf(stderr, " --:--:-- ETA"); 152 189 } else { 153 off_t to_download = totalsize - beg_range; 154 if (!totalsize || transferred <= 0 || (int)elapsed <= 0 || transferred > to_download) { 155 fprintf(stderr, "--:--:-- ETA"); 156 } else { 157 /* to_download / (transferred/elapsed) - elapsed: */ 158 /* (long long helps to have working ETA even if !LFS) */ 159 unsigned eta = (unsigned long long)to_download*elapsed/(uoff_t)transferred - elapsed; 160 unsigned secs = eta % 3600; 161 fprintf(stderr, "%02u:%02u:%02u ETA", eta / 3600, secs / 60, secs % 60); 162 } 190 unsigned eta, secs, hours; 191 192 totalsize -= beg_size; /* now it's "total to upload" */ 193 194 /* Estimated remaining time = 195 * estimated_sec_to_dl_totalsize_bytes - elapsed_sec = 196 * totalsize / average_bytes_sec_so_far - elapsed = 197 * totalsize / (transferred/elapsed) - elapsed = 198 * totalsize * elapsed / transferred - elapsed 199 */ 200 eta = totalsize * elapsed / transferred - elapsed; 201 if (eta >= 1000*60*60) 202 eta = 1000*60*60 - 1; 203 secs = eta % 3600; 204 hours = eta / 3600; 205 fprintf(stderr, "%3u:%02u:%02u ETA", hours, secs / 60, secs % 60); 163 206 } 164 207 }
Note:
See TracChangeset
for help on using the changeset viewer.