diff options
Diffstat (limited to 'Source/CTest/Curl/progress.c')
-rw-r--r-- | Source/CTest/Curl/progress.c | 317 |
1 files changed, 171 insertions, 146 deletions
diff --git a/Source/CTest/Curl/progress.c b/Source/CTest/Curl/progress.c index 76fa18c..36be56e 100644 --- a/Source/CTest/Curl/progress.c +++ b/Source/CTest/Curl/progress.c @@ -1,16 +1,16 @@ /*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://curl.haxx.se/docs/copyright.html. - * + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is * furnished to do so, under the terms of the COPYING file. @@ -24,17 +24,8 @@ #include "setup.h" #include <string.h> - -#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__) -#if defined(__MINGW32__) -#include <winsock.h> -#endif #include <time.h> -#endif -/* 20000318 mgs - * later we use _scrsize to determine the screen width, this emx library - * function needs stdlib.h to be included */ #if defined(__EMX__) #include <stdlib.h> #endif @@ -42,46 +33,94 @@ #include <curl/curl.h> #include "urldata.h" #include "sendf.h" - #include "progress.h" #define _MPRINTF_REPLACE /* use our functions only */ #include <curl/mprintf.h> - -static void time2str(char *r, int t) +/* Provide a string that is 2 + 1 + 2 + 1 + 2 = 8 letters long (plus the zero + byte) */ +static void time2str(char *r, long t) { - int h = (t/3600); - int m = (t-(h*3600))/60; - int s = (t-(h*3600)-(m*60)); - sprintf(r,"%2d:%02d:%02d",h,m,s); + long h; + if(!t) { + strcpy(r, "--:--:--"); + return; + } + h = (t/3600); + if(h <= 99) { + long m = (t-(h*3600))/60; + long s = (t-(h*3600)-(m*60)); + snprintf(r, 9, "%2ld:%02ld:%02ld",h,m,s); + } + else { + /* this equals to more than 99 hours, switch to a more suitable output + format to fit within the limits. */ + if(h/24 <= 999) + snprintf(r, 9, "%3ldd %02ldh", h/24, h-(h/24)*24); + else + snprintf(r, 9, "%7ldd", h/24); + } } /* The point of this function would be to return a string of the input data, - but never longer than 5 columns. Add suffix k, M, G when suitable... */ -static char *max5data(double bytes, char *max5) + but never longer than 5 columns (+ one zero byte). + Add suffix k, M, G when suitable... */ +static char *max5data(curl_off_t bytes, char *max5) { #define ONE_KILOBYTE 1024 -#define ONE_MEGABYTE (1024*1024) +#define ONE_MEGABYTE (1024* ONE_KILOBYTE) +#define ONE_GIGABYTE (1024* ONE_MEGABYTE) +#define ONE_TERRABYTE ((curl_off_t)1024* ONE_GIGABYTE) +#define ONE_PETABYTE ((curl_off_t)1024* ONE_TERRABYTE) if(bytes < 100000) { - sprintf(max5, "%5d", (int)bytes); - return max5; + snprintf(max5, 6, "%5" FORMAT_OFF_T, bytes); } - if(bytes < (9999*ONE_KILOBYTE)) { - sprintf(max5, "%4dk", (int)bytes/ONE_KILOBYTE); - return max5; + else if(bytes < (10000*ONE_KILOBYTE)) { + snprintf(max5, 6, "%4" FORMAT_OFF_T "k", (curl_off_t)(bytes/ONE_KILOBYTE)); } - if(bytes < (100*ONE_MEGABYTE)) { + else if(bytes < (100*ONE_MEGABYTE)) { /* 'XX.XM' is good as long as we're less than 100 megs */ - sprintf(max5, "%4.1fM", bytes/ONE_MEGABYTE); - return max5; + snprintf(max5, 6, "%2d.%0dM", + (int)(bytes/ONE_MEGABYTE), + (int)(bytes%ONE_MEGABYTE)/(ONE_MEGABYTE/10) ); } - sprintf(max5, "%4dM", (int)bytes/ONE_MEGABYTE); +#if SIZEOF_CURL_OFF_T > 4 + else if(bytes < ( (curl_off_t)10000*ONE_MEGABYTE)) + /* 'XXXXM' is good until we're at 10000MB or above */ + snprintf(max5, 6, "%4" FORMAT_OFF_T "M", (curl_off_t)(bytes/ONE_MEGABYTE)); + + else if(bytes < (curl_off_t)100*ONE_GIGABYTE) + /* 10000 MB - 100 GB, we show it as XX.XG */ + snprintf(max5, 6, "%2d.%0dG", + (int)(bytes/ONE_GIGABYTE), + (int)(bytes%ONE_GIGABYTE)/(ONE_GIGABYTE/10) ); + + else if(bytes < (curl_off_t)10000 * ONE_GIGABYTE) + /* up to 10000GB, display without decimal: XXXXG */ + snprintf(max5, 6, "%4dG", (int)(bytes/ONE_GIGABYTE)); + + else if(bytes < (curl_off_t)10000 * ONE_TERRABYTE) + /* up to 10000TB, display without decimal: XXXXT */ + snprintf(max5, 6, "%4dT", (int)(bytes/ONE_TERRABYTE)); + else { + /* up to 10000PB, display without decimal: XXXXP */ + snprintf(max5, 6, "%4dP", (int)(bytes/ONE_PETABYTE)); + + /* 16384 petabytes (16 exabytes) is maximum a 64 bit number can hold, + but this type is signed so 8192PB will be max.*/ + } + +#else + else + snprintf(max5, 6, "%4" FORMAT_OFF_T "M", (curl_off_t)(bytes/ONE_MEGABYTE)); +#endif + return max5; } -/* +/* New proposed interface, 9th of February 2000: @@ -98,13 +137,12 @@ static char *max5data(double bytes, char *max5) void Curl_pgrsDone(struct connectdata *conn) { struct SessionHandle *data = conn->data; - if(!(data->progress.flags & PGRS_HIDE)) { - data->progress.lastshow=0; - Curl_pgrsUpdate(conn); /* the final (forced) update */ - if(!data->progress.callback) - /* only output if we don't use progress callback */ - fprintf(data->set.err, "\n"); - } + data->progress.lastshow=0; + Curl_pgrsUpdate(conn); /* the final (forced) update */ + if(!(data->progress.flags & PGRS_HIDE) && + !data->progress.callback) + /* only output if we don't use a progress callback and we're not hidden */ + fprintf(data->set.err, "\n"); } /* reset all times except redirect */ @@ -130,26 +168,26 @@ void Curl_pgrsTime(struct SessionHandle *data, timerid timer) case TIMER_NAMELOOKUP: data->progress.t_nslookup = - (double)Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle)/1000.0; + Curl_tvdiff_secs(Curl_tvnow(), data->progress.t_startsingle); break; case TIMER_CONNECT: data->progress.t_connect = - (double)Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle)/1000.0; + Curl_tvdiff_secs(Curl_tvnow(), data->progress.t_startsingle); break; case TIMER_PRETRANSFER: data->progress.t_pretransfer = - (double)Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle)/1000.0; + Curl_tvdiff_secs(Curl_tvnow(), data->progress.t_startsingle); break; case TIMER_STARTTRANSFER: data->progress.t_starttransfer = - (double)Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle)/1000.0; + Curl_tvdiff_secs(Curl_tvnow(), data->progress.t_startsingle); break; case TIMER_POSTRANSFER: /* this is the normal end-of-transfer thing */ break; case TIMER_REDIRECT: data->progress.t_redirect = - (double)Curl_tvdiff(Curl_tvnow(), data->progress.start)/1000.0; + Curl_tvdiff_secs(Curl_tvnow(), data->progress.start); break; } } @@ -160,70 +198,55 @@ void Curl_pgrsStartNow(struct SessionHandle *data) data->progress.start = Curl_tvnow(); } -void Curl_pgrsSetDownloadCounter(struct SessionHandle *data, double size) +void Curl_pgrsSetDownloadCounter(struct SessionHandle *data, curl_off_t size) { data->progress.downloaded = size; } -void Curl_pgrsSetUploadCounter(struct SessionHandle *data, double size) +void Curl_pgrsSetUploadCounter(struct SessionHandle *data, curl_off_t size) { data->progress.uploaded = size; } -void Curl_pgrsSetDownloadSize(struct SessionHandle *data, double size) +void Curl_pgrsSetDownloadSize(struct SessionHandle *data, curl_off_t size) { - if(size > 0) { - data->progress.size_dl = size; + data->progress.size_dl = size; + if(size > 0) data->progress.flags |= PGRS_DL_SIZE_KNOWN; - } + else + data->progress.flags &= ~PGRS_DL_SIZE_KNOWN; } -void Curl_pgrsSetUploadSize(struct SessionHandle *data, double size) +void Curl_pgrsSetUploadSize(struct SessionHandle *data, curl_off_t size) { - if(size > 0) { - data->progress.size_ul = size; + data->progress.size_ul = size; + if(size > 0) data->progress.flags |= PGRS_UL_SIZE_KNOWN; - } + else + data->progress.flags &= ~PGRS_UL_SIZE_KNOWN; } -/* EXAMPLE OUTPUT to follow: - - % Total % Received % Xferd Average Speed Time Curr. - Dload Upload Total Current Left Speed -100 12345 100 12345 100 12345 12345 12345 12:12:12 12:12:12 12:12:12 12345 - - */ - int Curl_pgrsUpdate(struct connectdata *conn) { struct timeval now; int result; - char max5[6][10]; - double dlpercen=0; - double ulpercen=0; - double total_percen=0; - - double total_transfer; - double total_expected_transfer; - double timespent; - + int dlpercen=0; + int ulpercen=0; + int total_percen=0; + curl_off_t total_transfer; + curl_off_t total_expected_transfer; + long timespent; struct SessionHandle *data = conn->data; - int nowindex = data->progress.speeder_c% CURR_TIME; int checkindex; - int countindex; /* amount of seconds stored in the speeder array */ - char time_left[10]; char time_total[10]; - char time_current[10]; - - double ulestimate=0; - double dlestimate=0; - - double total_estimate; - + char time_spent[10]; + long ulestimate=0; + long dlestimate=0; + long total_estimate; if(data->progress.flags & PGRS_HIDE) ; /* We do enter this function even if we don't wanna see anything, since @@ -232,32 +255,35 @@ int Curl_pgrsUpdate(struct connectdata *conn) else if(!(data->progress.flags & PGRS_HEADERS_OUT)) { if (!data->progress.callback) { if(conn->resume_from) - fprintf(data->set.err, "** Resuming transfer from byte position %d\n", + fprintf(data->set.err, + "** Resuming transfer from byte position %" FORMAT_OFF_T + "\n", conn->resume_from); fprintf(data->set.err, - " %% Total %% Received %% Xferd Average Speed Time Curr.\n" - " Dload Upload Total Current Left Speed\n"); + " %% Total %% Received %% Xferd Average Speed Time Time Time Current\n" + " Dload Upload Total Spent Left Speed\n"); } data->progress.flags |= PGRS_HEADERS_OUT; /* headers are shown */ } now = Curl_tvnow(); /* what time is it */ - /* The exact time spent so far (from the start) */ - timespent = (double)Curl_tvdiff (now, data->progress.start)/1000; - - data->progress.timespent = timespent; + /* The time spent so far (from the start) */ + data->progress.timespent = Curl_tvdiff_secs(now, data->progress.start); + timespent = (long)data->progress.timespent; /* The average download speed this far */ - data->progress.dlspeed = - data->progress.downloaded/(timespent>0.01?timespent:1); + data->progress.dlspeed = (curl_off_t) + ((double)data->progress.downloaded/ + (data->progress.timespent>0?data->progress.timespent:1)); /* The average upload speed this far */ - data->progress.ulspeed = - data->progress.uploaded/(timespent>0.01?timespent:1); + data->progress.ulspeed = (curl_off_t) + ((double)data->progress.uploaded/ + (data->progress.timespent>0?data->progress.timespent:1)); if(data->progress.lastshow == Curl_tvlong(now)) - return 0; /* never update this more than once a second if the end isn't + return 0; /* never update this more than once a second if the end isn't reached */ data->progress.lastshow = now.tv_sec; @@ -297,10 +323,21 @@ int Curl_pgrsUpdate(struct connectdata *conn) if(0 == span_ms) span_ms=1; /* at least one millisecond MUST have passed */ - /* Calculate the average speed the last 'countindex' seconds */ - data->progress.current_speed = - (data->progress.speeder[nowindex]- - data->progress.speeder[checkindex])/((double)span_ms/1000); + /* Calculate the average speed the last 'span_ms' milliseconds */ + { + curl_off_t amount = data->progress.speeder[nowindex]- + data->progress.speeder[checkindex]; + + if(amount > 0xffffffff/1000) + /* the 'amount' value is bigger than would fit in 32 bits if + multiplied with 1000, so we use the double math for this */ + data->progress.current_speed = (curl_off_t) + ((double)amount/((double)span_ms/1000.0)); + else + /* the 'amount' value is small enough to fit within 32 bits even + when multiplied with 1000 */ + data->progress.current_speed = amount*1000/span_ms; + } } else /* the first second we use the main average */ @@ -315,74 +352,70 @@ int Curl_pgrsUpdate(struct connectdata *conn) /* There's a callback set, so we call that instead of writing anything ourselves. This really is the way to go. */ result= data->set.fprogress(data->set.progress_client, - data->progress.size_dl, - data->progress.downloaded, - data->progress.size_ul, - data->progress.uploaded); + (double)data->progress.size_dl, + (double)data->progress.downloaded, + (double)data->progress.size_ul, + (double)data->progress.uploaded); if(result) failf(data, "Callback aborted"); return result; } /* Figure out the estimated time of arrival for the upload */ - if((data->progress.flags & PGRS_UL_SIZE_KNOWN) && data->progress.ulspeed){ - ulestimate = data->progress.size_ul / data->progress.ulspeed; - ulpercen = (data->progress.uploaded / data->progress.size_ul)*100; + if((data->progress.flags & PGRS_UL_SIZE_KNOWN) && + (data->progress.ulspeed>0) && + (data->progress.size_ul > 100) ) { + ulestimate = (long)(data->progress.size_ul / data->progress.ulspeed); + ulpercen = (int)(100*(data->progress.uploaded/100) / + (data->progress.size_ul/100) ); } /* ... and the download */ - if((data->progress.flags & PGRS_DL_SIZE_KNOWN) && data->progress.dlspeed) { - dlestimate = data->progress.size_dl / data->progress.dlspeed; - dlpercen = (data->progress.downloaded / data->progress.size_dl)*100; + if((data->progress.flags & PGRS_DL_SIZE_KNOWN) && + (data->progress.dlspeed>0) && + (data->progress.size_dl>100)) { + dlestimate = (long)(data->progress.size_dl / data->progress.dlspeed); + dlpercen = (int)(100*(data->progress.downloaded/100) / + (data->progress.size_dl/100)); } - + /* Now figure out which of them that is slower and use for the for total estimate! */ total_estimate = ulestimate>dlestimate?ulestimate:dlestimate; - - /* If we have a total estimate, we can display that and the expected - time left */ - if(total_estimate) { - time2str(time_left, (int)(total_estimate - data->progress.timespent)); - time2str(time_total, (int)total_estimate); - } - else { - /* otherwise we blank those times */ - strcpy(time_left, "--:--:--"); - strcpy(time_total, "--:--:--"); - } - /* The time spent so far is always known */ - time2str(time_current, (int)data->progress.timespent); + /* create the three time strings */ + time2str(time_left, total_estimate > 0?(total_estimate - timespent):0); + time2str(time_total, total_estimate); + time2str(time_spent, timespent); /* Get the total amount of data expected to get transfered */ - total_expected_transfer = + total_expected_transfer = (data->progress.flags & PGRS_UL_SIZE_KNOWN? data->progress.size_ul:data->progress.uploaded)+ (data->progress.flags & PGRS_DL_SIZE_KNOWN? data->progress.size_dl:data->progress.downloaded); - + /* We have transfered this much so far */ total_transfer = data->progress.downloaded + data->progress.uploaded; /* Get the percentage of data transfered so far */ - if(total_expected_transfer) - total_percen=(double)(total_transfer/total_expected_transfer)*100; + if(total_expected_transfer > 100) + total_percen=(int)(100*(total_transfer/100) / + (total_expected_transfer/100) ); fprintf(data->set.err, "\r%3d %s %3d %s %3d %s %s %s %s %s %s %s", - (int)total_percen, /* total % */ + total_percen, /* 3 letters */ /* total % */ max5data(total_expected_transfer, max5[2]), /* total size */ - (int)dlpercen, /* rcvd % */ + dlpercen, /* 3 letters */ /* rcvd % */ max5data(data->progress.downloaded, max5[0]), /* rcvd size */ - (int)ulpercen, /* xfer % */ + ulpercen, /* 3 letters */ /* xfer % */ max5data(data->progress.uploaded, max5[1]), /* xfer size */ - - max5data(data->progress.dlspeed, max5[3]), /* avrg dl speed */ - max5data(data->progress.ulspeed, max5[4]), /* avrg ul speed */ - time_total, /* total time */ - time_current, /* current time */ - time_left, /* time left */ + max5data(data->progress.dlspeed, max5[3]), /* avrg dl speed */ + max5data(data->progress.ulspeed, max5[4]), /* avrg ul speed */ + time_total, /* 8 letters */ /* total time */ + time_spent, /* 8 letters */ /* time spent */ + time_left, /* 8 letters */ /* time left */ max5data(data->progress.current_speed, max5[5]) /* current speed */ ); @@ -391,11 +424,3 @@ int Curl_pgrsUpdate(struct connectdata *conn) return 0; } - -/* - * local variables: - * eval: (load-file "../curl-mode.el") - * end: - * vim600: fdm=marker - * vim: et sw=2 ts=2 sts=2 tw=78 - */ |