Annotation of embedaddon/curl/src/tool_progress.c, revision 1.1

1.1     ! misho       1: /***************************************************************************
        !             2:  *                                  _   _ ____  _
        !             3:  *  Project                     ___| | | |  _ \| |
        !             4:  *                             / __| | | | |_) | |
        !             5:  *                            | (__| |_| |  _ <| |___
        !             6:  *                             \___|\___/|_| \_\_____|
        !             7:  *
        !             8:  * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
        !             9:  *
        !            10:  * This software is licensed as described in the file COPYING, which
        !            11:  * you should have received as part of this distribution. The terms
        !            12:  * are also available at https://curl.haxx.se/docs/copyright.html.
        !            13:  *
        !            14:  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
        !            15:  * copies of the Software, and permit persons to whom the Software is
        !            16:  * furnished to do so, under the terms of the COPYING file.
        !            17:  *
        !            18:  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
        !            19:  * KIND, either express or implied.
        !            20:  *
        !            21:  ***************************************************************************/
        !            22: #include "tool_setup.h"
        !            23: #include "tool_operate.h"
        !            24: #include "tool_progress.h"
        !            25: #include "tool_util.h"
        !            26: 
        !            27: #define ENABLE_CURLX_PRINTF
        !            28: /* use our own printf() functions */
        !            29: #include "curlx.h"
        !            30: 
        !            31: /* The point of this function would be to return a string of the input data,
        !            32:    but never longer than 5 columns (+ one zero byte).
        !            33:    Add suffix k, M, G when suitable... */
        !            34: static char *max5data(curl_off_t bytes, char *max5)
        !            35: {
        !            36: #define ONE_KILOBYTE  CURL_OFF_T_C(1024)
        !            37: #define ONE_MEGABYTE (CURL_OFF_T_C(1024) * ONE_KILOBYTE)
        !            38: #define ONE_GIGABYTE (CURL_OFF_T_C(1024) * ONE_MEGABYTE)
        !            39: #define ONE_TERABYTE (CURL_OFF_T_C(1024) * ONE_GIGABYTE)
        !            40: #define ONE_PETABYTE (CURL_OFF_T_C(1024) * ONE_TERABYTE)
        !            41: 
        !            42:   if(bytes < CURL_OFF_T_C(100000))
        !            43:     msnprintf(max5, 6, "%5" CURL_FORMAT_CURL_OFF_T, bytes);
        !            44: 
        !            45:   else if(bytes < CURL_OFF_T_C(10000) * ONE_KILOBYTE)
        !            46:     msnprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "k", bytes/ONE_KILOBYTE);
        !            47: 
        !            48:   else if(bytes < CURL_OFF_T_C(100) * ONE_MEGABYTE)
        !            49:     /* 'XX.XM' is good as long as we're less than 100 megs */
        !            50:     msnprintf(max5, 6, "%2" CURL_FORMAT_CURL_OFF_T ".%0"
        !            51:               CURL_FORMAT_CURL_OFF_T "M", bytes/ONE_MEGABYTE,
        !            52:               (bytes%ONE_MEGABYTE) / (ONE_MEGABYTE/CURL_OFF_T_C(10)) );
        !            53: 
        !            54: #if (CURL_SIZEOF_CURL_OFF_T > 4)
        !            55: 
        !            56:   else if(bytes < CURL_OFF_T_C(10000) * ONE_MEGABYTE)
        !            57:     /* 'XXXXM' is good until we're at 10000MB or above */
        !            58:     msnprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "M", bytes/ONE_MEGABYTE);
        !            59: 
        !            60:   else if(bytes < CURL_OFF_T_C(100) * ONE_GIGABYTE)
        !            61:     /* 10000 MB - 100 GB, we show it as XX.XG */
        !            62:     msnprintf(max5, 6, "%2" CURL_FORMAT_CURL_OFF_T ".%0"
        !            63:               CURL_FORMAT_CURL_OFF_T "G", bytes/ONE_GIGABYTE,
        !            64:               (bytes%ONE_GIGABYTE) / (ONE_GIGABYTE/CURL_OFF_T_C(10)) );
        !            65: 
        !            66:   else if(bytes < CURL_OFF_T_C(10000) * ONE_GIGABYTE)
        !            67:     /* up to 10000GB, display without decimal: XXXXG */
        !            68:     msnprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "G", bytes/ONE_GIGABYTE);
        !            69: 
        !            70:   else if(bytes < CURL_OFF_T_C(10000) * ONE_TERABYTE)
        !            71:     /* up to 10000TB, display without decimal: XXXXT */
        !            72:     msnprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "T", bytes/ONE_TERABYTE);
        !            73: 
        !            74:   else
        !            75:     /* up to 10000PB, display without decimal: XXXXP */
        !            76:     msnprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "P", bytes/ONE_PETABYTE);
        !            77: 
        !            78:     /* 16384 petabytes (16 exabytes) is the maximum a 64 bit unsigned number
        !            79:        can hold, but our data type is signed so 8192PB will be the maximum. */
        !            80: 
        !            81: #else
        !            82: 
        !            83:   else
        !            84:     msnprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "M", bytes/ONE_MEGABYTE);
        !            85: 
        !            86: #endif
        !            87: 
        !            88:   return max5;
        !            89: }
        !            90: 
        !            91: int xferinfo_cb(void *clientp,
        !            92:                 curl_off_t dltotal,
        !            93:                 curl_off_t dlnow,
        !            94:                 curl_off_t ultotal,
        !            95:                 curl_off_t ulnow)
        !            96: {
        !            97:   struct per_transfer *per = clientp;
        !            98:   struct OperationConfig *config = per->config;
        !            99:   per->dltotal = dltotal;
        !           100:   per->dlnow = dlnow;
        !           101:   per->ultotal = ultotal;
        !           102:   per->ulnow = ulnow;
        !           103: 
        !           104:   if(config->readbusy) {
        !           105:     config->readbusy = FALSE;
        !           106:     curl_easy_pause(per->curl, CURLPAUSE_CONT);
        !           107:   }
        !           108: 
        !           109:   return 0;
        !           110: }
        !           111: 
        !           112: /* Provide a string that is 2 + 1 + 2 + 1 + 2 = 8 letters long (plus the zero
        !           113:    byte) */
        !           114: static void time2str(char *r, curl_off_t seconds)
        !           115: {
        !           116:   curl_off_t h;
        !           117:   if(seconds <= 0) {
        !           118:     strcpy(r, "--:--:--");
        !           119:     return;
        !           120:   }
        !           121:   h = seconds / CURL_OFF_T_C(3600);
        !           122:   if(h <= CURL_OFF_T_C(99)) {
        !           123:     curl_off_t m = (seconds - (h*CURL_OFF_T_C(3600))) / CURL_OFF_T_C(60);
        !           124:     curl_off_t s = (seconds - (h*CURL_OFF_T_C(3600))) - (m*CURL_OFF_T_C(60));
        !           125:     msnprintf(r, 9, "%2" CURL_FORMAT_CURL_OFF_T ":%02" CURL_FORMAT_CURL_OFF_T
        !           126:               ":%02" CURL_FORMAT_CURL_OFF_T, h, m, s);
        !           127:   }
        !           128:   else {
        !           129:     /* this equals to more than 99 hours, switch to a more suitable output
        !           130:        format to fit within the limits. */
        !           131:     curl_off_t d = seconds / CURL_OFF_T_C(86400);
        !           132:     h = (seconds - (d*CURL_OFF_T_C(86400))) / CURL_OFF_T_C(3600);
        !           133:     if(d <= CURL_OFF_T_C(999))
        !           134:       msnprintf(r, 9, "%3" CURL_FORMAT_CURL_OFF_T
        !           135:                 "d %02" CURL_FORMAT_CURL_OFF_T "h", d, h);
        !           136:     else
        !           137:       msnprintf(r, 9, "%7" CURL_FORMAT_CURL_OFF_T "d", d);
        !           138:   }
        !           139: }
        !           140: 
        !           141: static curl_off_t all_dltotal = 0;
        !           142: static curl_off_t all_ultotal = 0;
        !           143: static curl_off_t all_dlalready = 0;
        !           144: static curl_off_t all_ulalready = 0;
        !           145: 
        !           146: curl_off_t all_xfers = 0;   /* current total */
        !           147: 
        !           148: struct speedcount {
        !           149:   curl_off_t dl;
        !           150:   curl_off_t ul;
        !           151:   struct timeval stamp;
        !           152: };
        !           153: #define SPEEDCNT 10
        !           154: static unsigned int speedindex;
        !           155: static bool indexwrapped;
        !           156: static struct speedcount speedstore[SPEEDCNT];
        !           157: 
        !           158: /*
        !           159:   |DL% UL%  Dled  Uled  Xfers  Live   Qd Total     Current  Left    Speed
        !           160:   |  6 --   9.9G     0     2     2     0  0:00:40  0:00:02  0:00:37 4087M
        !           161: */
        !           162: bool progress_meter(struct GlobalConfig *global,
        !           163:                     struct timeval *start,
        !           164:                     bool final)
        !           165: {
        !           166:   static struct timeval stamp;
        !           167:   static bool header = FALSE;
        !           168:   struct timeval now;
        !           169:   long diff;
        !           170: 
        !           171:   if(global->noprogress)
        !           172:     return FALSE;
        !           173: 
        !           174:   now = tvnow();
        !           175:   diff = tvdiff(now, stamp);
        !           176: 
        !           177:   if(!header) {
        !           178:     header = TRUE;
        !           179:     fputs("DL% UL%  Dled  Uled  Xfers  Live   Qd "
        !           180:           "Total     Current  Left    Speed\n",
        !           181:           global->errors);
        !           182:   }
        !           183:   if(final || (diff > 500)) {
        !           184:     char time_left[10];
        !           185:     char time_total[10];
        !           186:     char time_spent[10];
        !           187:     char buffer[3][6];
        !           188:     curl_off_t spent = tvdiff(now, *start)/1000;
        !           189:     char dlpercen[4]="--";
        !           190:     char ulpercen[4]="--";
        !           191:     struct per_transfer *per;
        !           192:     curl_off_t all_dlnow = 0;
        !           193:     curl_off_t all_ulnow = 0;
        !           194:     bool dlknown = TRUE;
        !           195:     bool ulknown = TRUE;
        !           196:     curl_off_t all_running = 0; /* in progress */
        !           197:     curl_off_t all_queued = 0;  /* pending */
        !           198:     curl_off_t speed = 0;
        !           199:     unsigned int i;
        !           200:     stamp = now;
        !           201: 
        !           202:     /* first add the amounts of the already completed transfers */
        !           203:     all_dlnow += all_dlalready;
        !           204:     all_ulnow += all_ulalready;
        !           205: 
        !           206:     for(per = transfers; per; per = per->next) {
        !           207:       all_dlnow += per->dlnow;
        !           208:       all_ulnow += per->ulnow;
        !           209:       if(!per->dltotal)
        !           210:         dlknown = FALSE;
        !           211:       else if(!per->dltotal_added) {
        !           212:         /* only add this amount once */
        !           213:         all_dltotal += per->dltotal;
        !           214:         per->dltotal_added = TRUE;
        !           215:       }
        !           216:       if(!per->ultotal)
        !           217:         ulknown = FALSE;
        !           218:       else if(!per->ultotal_added) {
        !           219:         /* only add this amount once */
        !           220:         all_ultotal += per->ultotal;
        !           221:         per->ultotal_added = TRUE;
        !           222:       }
        !           223:       if(!per->added)
        !           224:         all_queued++;
        !           225:       else
        !           226:         all_running++;
        !           227:     }
        !           228:     if(dlknown && all_dltotal)
        !           229:       /* TODO: handle integer overflow */
        !           230:       msnprintf(dlpercen, sizeof(dlpercen), "%3d",
        !           231:                 all_dlnow * 100 / all_dltotal);
        !           232:     if(ulknown && all_ultotal)
        !           233:       /* TODO: handle integer overflow */
        !           234:       msnprintf(ulpercen, sizeof(ulpercen), "%3d",
        !           235:                 all_ulnow * 100 / all_ultotal);
        !           236: 
        !           237:     /* get the transfer speed, the higher of the two */
        !           238: 
        !           239:     i = speedindex;
        !           240:     speedstore[i].dl = all_dlnow;
        !           241:     speedstore[i].ul = all_ulnow;
        !           242:     speedstore[i].stamp = now;
        !           243:     if(++speedindex >= SPEEDCNT) {
        !           244:       indexwrapped = TRUE;
        !           245:       speedindex = 0;
        !           246:     }
        !           247: 
        !           248:     {
        !           249:       long deltams;
        !           250:       curl_off_t dl;
        !           251:       curl_off_t ul;
        !           252:       curl_off_t dls;
        !           253:       curl_off_t uls;
        !           254:       if(indexwrapped) {
        !           255:         /* 'speedindex' is the oldest stored data */
        !           256:         deltams = tvdiff(now, speedstore[speedindex].stamp);
        !           257:         dl = all_dlnow - speedstore[speedindex].dl;
        !           258:         ul = all_ulnow - speedstore[speedindex].ul;
        !           259:       }
        !           260:       else {
        !           261:         /* since the beginning */
        !           262:         deltams = tvdiff(now, *start);
        !           263:         dl = all_dlnow;
        !           264:         ul = all_ulnow;
        !           265:       }
        !           266:       dls = (curl_off_t)((double)dl / ((double)deltams/1000.0));
        !           267:       uls = (curl_off_t)((double)ul / ((double)deltams/1000.0));
        !           268:       speed = dls > uls ? dls : uls;
        !           269:     }
        !           270: 
        !           271: 
        !           272:     if(dlknown && speed) {
        !           273:       curl_off_t est = all_dltotal / speed;
        !           274:       curl_off_t left = (all_dltotal - all_dlnow) / speed;
        !           275:       time2str(time_left, left);
        !           276:       time2str(time_total, est);
        !           277:     }
        !           278:     else {
        !           279:       time2str(time_left, 0);
        !           280:       time2str(time_total, 0);
        !           281:     }
        !           282:     time2str(time_spent, spent);
        !           283: 
        !           284:     fprintf(global->errors,
        !           285:             "\r"
        !           286:             "%-3s " /* percent downloaded */
        !           287:             "%-3s " /* percent uploaded */
        !           288:             "%s " /* Dled */
        !           289:             "%s " /* Uled */
        !           290:             "%5" CURL_FORMAT_CURL_OFF_T " " /* Xfers */
        !           291:             "%5" CURL_FORMAT_CURL_OFF_T " " /* Live */
        !           292:             "%5" CURL_FORMAT_CURL_OFF_T " " /* Queued */
        !           293:             "%s "  /* Total time */
        !           294:             "%s "  /* Current time */
        !           295:             "%s "  /* Time left */
        !           296:             "%s "  /* Speed */
        !           297:             "%5s" /* final newline */,
        !           298: 
        !           299:             dlpercen,  /* 3 letters */
        !           300:             ulpercen,  /* 3 letters */
        !           301:             max5data(all_dlnow, buffer[0]),
        !           302:             max5data(all_ulnow, buffer[1]),
        !           303:             all_xfers,
        !           304:             all_running,
        !           305:             all_queued,
        !           306:             time_total,
        !           307:             time_spent,
        !           308:             time_left,
        !           309:             max5data(speed, buffer[2]), /* speed */
        !           310:             final ? "\n" :"");
        !           311:     return TRUE;
        !           312:   }
        !           313:   return FALSE;
        !           314: }
        !           315: 
        !           316: void progress_finalize(struct per_transfer *per)
        !           317: {
        !           318:   /* get the numbers before this transfer goes away */
        !           319:   all_dlalready += per->dlnow;
        !           320:   all_ulalready += per->ulnow;
        !           321: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>