aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/progress.c261
-rw-r--r--lib/progress.h26
2 files changed, 277 insertions, 10 deletions
diff --git a/lib/progress.c b/lib/progress.c
index dc1073a01..a54be86d6 100644
--- a/lib/progress.c
+++ b/lib/progress.c
@@ -53,13 +53,261 @@
#include "progress.h"
-/* --- start of progress routines --- */
+void time2str(char *r, int t)
+{
+ int h = (t/3600);
+ int m = (t-(h*3600))/60;
+ int s = (t-(h*3600)-(m*60));
+ sprintf(r,"%d:%02d:%02d",h,m,s);
+}
+
+/* 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... */
+char *max5data(double bytes, char *max5)
+{
+ if(bytes < 100000) {
+ sprintf(max5, "%5d", (int)bytes);
+ return max5;
+ }
+ if(bytes < (9999*1024)) {
+ sprintf(max5, "%4dk", (int)bytes/1024);
+ return max5;
+ }
+ sprintf(max5, "%4dM", (int)bytes/(1024*1024));
+ return max5;
+}
+
+/*
+
+ New proposed interface, 9th of February 2000:
+
+ pgrsStartNow() - sets start time
+ pgrsMode(type) - kind of display
+ pgrsSetDownloadSize(x) - known expected download size
+ pgrsSetUploadSize(x) - known expected upload size
+ pgrsSetDownloadCounter() - amount of data currently downloaded
+ pgrsSetUploadCounter() - amount of data currently uploaded
+ pgrsUpdate() - show progress
+ pgrsDone() - transfer complete
+
+*/
+#if 1
+void pgrsDone(struct UrlData *data)
+{
+ if(!(data->progress.flags & PGRS_HIDE))
+ fprintf(stderr, "\n");
+}
+void pgrsMode(struct UrlData *data, int mode)
+{
+ /* mode should include a hidden mode as well */
+ if(data->conf&(CONF_NOPROGRESS|CONF_MUTE))
+ data->progress.flags |= PGRS_HIDE; /* don't show anything */
+ else {
+ data->progress.mode = mode; /* store type */
+ }
+
+}
+
+void pgrsStartNow(struct UrlData *data)
+{
+ data->progress.start = tvnow();
+}
+
+void pgrsSetDownloadCounter(struct UrlData *data, double size)
+{
+ data->progress.downloaded = size;
+}
+
+void pgrsSetUploadCounter(struct UrlData *data, double size)
+{
+ data->progress.uploaded = size;
+}
+
+void pgrsSetDownloadSize(struct UrlData *data, double size)
+{
+ data->progress.size_dl = size;
+ data->progress.flags |= PGRS_DL_SIZE_KNOWN;
+}
+
+void pgrsSetUploadSize(struct UrlData *data, double size)
+{
+ data->progress.size_ul = size;
+ data->progress.flags |= PGRS_UL_SIZE_KNOWN;
+}
+
+/* EXAMPLE OUTPUT to follow:
+
+ % Total % Received % Xferd Average Speed Time Curr.
+ Download Upload Total Current Left Speed
+100 12345 100 12345 100 12345 12345 12345 2:47:33 2:00:02 2:00:02 12345
+
+ */
+
+void pgrsUpdate(struct UrlData *data)
+{
+ struct timeval now;
+
+ if(data->progress.flags & PGRS_HIDE)
+ ; /* We do enter this function even if we don't wanna see anything, since
+ this is were lots of the calculations are being made that will be used
+ even when not displayed! */
+ else if(!(data->progress.flags & PGRS_HEADERS_OUT)) {
+ if ( data->progress.mode == CURL_PROGRESS_STATS ) {
+ fprintf(data->err,
+ " %% Total %% Received %% Xferd Average Speed Time Curr.\n"
+ " Download Upload Total Current Left Speed\n");
+ }
+ data->progress.flags |= PGRS_HEADERS_OUT; /* headers are shown */
+ }
+
+ now = tvnow(); /* what time is it */
+
+ switch(data->progress.mode) {
+ case CURL_PROGRESS_STATS:
+ {
+ static long lastshow;
+ char max5[6][6];
+ double dlpercen=0;
+ double ulpercen=0;
+ double total_percen=0;
+
+ double total_transfer;
+ double total_expected_transfer;
+
+ double timespent;
+ double dlspeed;
+ double ulspeed;
+
+#define CURR_TIME 5
+
+ static double speeder[ CURR_TIME ];
+ static int speeder_c=0;
+
+ int nowindex = speeder_c% CURR_TIME;
+ int checkindex;
+ int count;
+
+ char time_left[10];
+ char time_total[10];
+ char time_current[10];
+
+ double ulestimate=0;
+ double dlestimate=0;
+
+ double total_estimate;
+
+ if(lastshow == tvlong(now))
+ return; /* never update this more than once a second if the end isn't
+ reached */
+ lastshow = now.tv_sec;
+
+ /* The exact time spent so far */
+ timespent = tvdiff (now, data->progress.start);
+
+ /* The average download speed this far */
+ dlspeed = data->progress.downloaded/(timespent!=0.0?timespent:1.0);
+
+ /* The average upload speed this far */
+ ulspeed = data->progress.uploaded/(timespent!=0.0?timespent:1.0);
+
+ /* Let's do the "current speed" thing, which should use the fastest
+ of the dl/ul speeds */
+
+ speeder[ nowindex ] = data->progress.downloaded>data->progress.uploaded?
+ data->progress.downloaded:data->progress.uploaded;
+ speeder_c++; /* increase */
+ count = ((speeder_c>=CURR_TIME)?CURR_TIME:speeder_c) - 1;
+ checkindex = (speeder_c>=CURR_TIME)?speeder_c%CURR_TIME:0;
+
+ /* find out the average speed the last CURR_TIME seconds */
+ data->progress.current_speed =
+ (speeder[nowindex]-speeder[checkindex])/(count?count:1);
+
+ if(data->progress.flags & PGRS_HIDE)
+ return;
+
+ /* Figure out the estimated time of arrival for the upload */
+ if(data->progress.flags & PGRS_UL_SIZE_KNOWN) {
+ if(!ulspeed)
+ ulspeed=1;
+ ulestimate = data->progress.size_ul / ulspeed;
+ ulpercen = (data->progress.uploaded / data->progress.size_ul)*100;
+ }
+
+ /* ... and the download */
+ if(data->progress.flags & PGRS_DL_SIZE_KNOWN) {
+ if(!dlspeed)
+ dlspeed=1;
+ dlestimate = data->progress.size_dl / dlspeed;
+ dlpercen = (data->progress.downloaded / 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, total_estimate-(int) timespent);
+ time2str(time_total, 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, timespent);
+
+ /* Get the total amount of data expected to get transfered */
+ 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;
+
+
+ fprintf(stderr,
+ "\r%3d %s %3d %s %3d %s %s %s %s %s %s %s",
+ (int)total_percen, /* total % */
+ max5data(total_expected_transfer, max5[2]), /* total size */
+ (int)dlpercen, /* rcvd % */
+ max5data(data->progress.downloaded, max5[0]), /* rcvd size */
+ (int)ulpercen, /* xfer % */
+ max5data(data->progress.uploaded, max5[1]), /* xfer size */
+
+ max5data(dlspeed, max5[3]), /* avrg dl speed */
+ max5data(ulspeed, max5[4]), /* avrg ul speed */
+ time_total, /* total time */
+ time_current, /* current time */
+ time_left, /* time left */
+ max5data(data->progress.current_speed, max5[5]) /* current speed */
+ );
+ }
+
+
+ }
+}
+
+
+#endif
+
+#if 0
+/* --- start of (the former) progress routines --- */
int progressmax=-1;
static int prev = 0;
static int width = 0;
-void ProgressInit(struct UrlData *data, int max)
+void ProgressInit(struct UrlData *data, int max/*, int options, int moremax*/)
{
if(data->conf&(CONF_NOPROGRESS|CONF_MUTE))
return;
@@ -87,14 +335,6 @@ void ProgressInit(struct UrlData *data, int max)
}
-void time2str(char *r, int t)
-{
- int h = (t/3600);
- int m = (t-(h*3600))/60;
- int s = (t-(h*3600)-(m*60));
- sprintf(r,"%3d:%02d:%02d",h,m,s);
-}
-
void ProgressShow(struct UrlData *data,
int point, struct timeval start, struct timeval now, bool force)
{
@@ -223,3 +463,4 @@ void ProgressEnd(struct UrlData *data)
}
/* --- end of progress routines --- */
+#endif
diff --git a/lib/progress.h b/lib/progress.h
index 6babd89ca..be94f9529 100644
--- a/lib/progress.h
+++ b/lib/progress.h
@@ -42,13 +42,39 @@
#include "timeval.h"
+#if 0
void ProgressInit(struct UrlData *data, int max);
void ProgressShow(struct UrlData *data,
int point, struct timeval start, struct timeval now, bool force);
void ProgressEnd(struct UrlData *data);
void ProgressMode(int mode);
+#endif
+
+void pgrsMode(struct UrlData *data, int mode);
+void pgrsStartNow(struct UrlData *data);
+void pgrsSetDownloadSize(struct UrlData *data, double size);
+void pgrsSetUploadSize(struct UrlData *data, double size);
+void pgrsSetDownloadCounter(struct UrlData *data, double size);
+ void pgrsSetUploadCounter(struct UrlData *data, double size);
+void pgrsUpdate(struct UrlData *data);
+
/* Don't show progress for sizes smaller than: */
#define LEAST_SIZE_PROGRESS BUFSIZE
+#define PROGRESS_DOWNLOAD (1<<0)
+#define PROGRESS_UPLOAD (1<<1)
+#define PROGRESS_DOWN_AND_UP (PROGRESS_UPLOAD | PROGRESS_DOWNLOAD)
+
+#define PGRS_SHOW_DL (1<<0)
+#define PGRS_SHOW_UL (1<<1)
+#define PGRS_DONE_DL (1<<2)
+#define PGRS_DONE_UL (1<<3)
+#define PGRS_HIDE (1<<4)
+#define PGRS_UL_SIZE_KNOWN (1<<5)
+#define PGRS_DL_SIZE_KNOWN (1<<6)
+
+#define PGRS_HEADERS_OUT (1<<7) /* set when the headers have been written */
+
+
#endif /* __PROGRESS_H */