Changeset 3232 in MondoRescue for branches/3.2/mindi-busybox/libbb/progress.c


Ignore:
Timestamp:
Jan 1, 2014, 12:47:38 AM (10 years ago)
Author:
Bruno Cornec
Message:
  • Update mindi-busybox to 1.21.1
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/3.2/mindi-busybox/libbb/progress.c

    r2725 r3232  
    5353}
    5454
    55 void FAST_FUNC bb_progress_init(bb_progress_t *p)
     55void FAST_FUNC bb_progress_init(bb_progress_t *p, const char *curfile)
    5656{
     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
    5763    p->start_sec = monotonic_sec();
    58     p->lastupdate_sec = p->start_sec;
    59     p->lastsize = 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;
    6167}
    6268
     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 */
    6376void 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)
    6880{
    6981    uoff_t beg_and_transferred;
    7082    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 */
    7588
    7689    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
    130163    while (beg_and_transferred >= 100000) {
    131         i++;
    132164        beg_and_transferred >>= 10;
     165        kiloscale++;
    133166    }
    134167    /* 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;
    141175        if (since_last_update >= STALLTIME) {
    142             /* We "cut off" these seconds from elapsed time
     176            /* We "cut out" these seconds from elapsed time
    143177             * by adjusting start time */
    144178            p->start_sec += since_last_update;
     
    146180        since_last_update = 0; /* we are un-stalled now */
    147181    }
     182
    148183    elapsed -= p->start_sec; /* now it's "elapsed since start" */
    149184
    150185    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");
    152189    } 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);
    163206    }
    164207}
Note: See TracChangeset for help on using the changeset viewer.