"CHANGES.2000" did not exist on "94af496ac44b092e095790bc95e2edaac9f364e6"
Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Curl.
*
* The Initial Developer of the Original Code is Daniel Stenberg.
*
* Portions created by the Initial Developer are Copyright (C) 1998.
* All Rights Reserved.
*
* ------------------------------------------------------------
* Main author:
* - Daniel Stenberg <Daniel.Stenberg@haxx.nu>
*
* http://curl.haxx.nu
*
* $Source$
* $Revision$
* $Date$
* $Author$
* $State$
* $Locker$
*
* ------------------------------------------------------------
****************************************************************************/
#include <string.h>
#include "setup.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
#include <curl/curl.h>
#include "urldata.h"
#include "progress.h"
void time2str(char *r, int t)
{
int h = (t/3600);
int m = (t-(h*3600))/60;
int s = (t-(h*3600)-(m*60));
Daniel Stenberg
committed
sprintf(r,"%2d:%02d:%02d",h,m,s);
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
}
/* 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)
{
Daniel Stenberg
committed
if(!(data->progress.flags & PGRS_HIDE)) {
data->progress.lastshow=0;
pgrsUpdate(data); /* the final (forced) update */
Daniel Stenberg
committed
}
}
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 pgrsTime(struct UrlData *data, timerid timer)
{
switch(timer) {
default:
case TIMER_NONE:
/* mistake filter */
break;
case TIMER_NAMELOOKUP:
data->progress.t_nslookup = tvnow();
break;
case TIMER_CONNECT:
data->progress.t_connect = tvnow();
break;
case TIMER_PRETRANSFER:
data->progress.t_pretransfer = tvnow();
break;
case TIMER_POSTRANSFER:
/* this is the normal end-of-transfer thing */
break;
}
}
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)
{
Daniel Stenberg
committed
if(size > 0) {
data->progress.size_dl = size;
data->progress.flags |= PGRS_DL_SIZE_KNOWN;
}
}
void pgrsSetUploadSize(struct UrlData *data, double size)
{
Daniel Stenberg
committed
if(size > 0) {
data->progress.size_ul = size;
data->progress.flags |= PGRS_UL_SIZE_KNOWN;
}
}
/* EXAMPLE OUTPUT to follow:
Daniel Stenberg
committed
% 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
*/
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,
Daniel Stenberg
committed
" %% Total %% Received %% Xferd Average Speed Time Curr.\n"
" Dload 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:
default:
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
{
char max5[6][6];
double dlpercen=0;
double ulpercen=0;
double total_percen=0;
double total_transfer;
double total_expected_transfer;
#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;
Daniel Stenberg
committed
if(data->progress.lastshow == tvlong(now))
return; /* never update this more than once a second if the end isn't
reached */
Daniel Stenberg
committed
data->progress.lastshow = now.tv_sec;
/* The exact time spent so far */
data->progress.timespent = tvdiff (now, data->progress.start);
/* The average download speed this far */
data->progress.dlspeed = data->progress.downloaded/(data->progress.timespent!=0.0?data->progress.timespent:1.0);
/* The average upload speed this far */
data->progress.ulspeed = data->progress.uploaded/(data->progress.timespent!=0.0?data->progress.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(!data->progress.ulspeed)
data->progress.ulspeed=1;
ulestimate = data->progress.size_ul / data->progress.ulspeed;
ulpercen = (data->progress.uploaded / data->progress.size_ul)*100;
}
/* ... and the download */
if(data->progress.flags & PGRS_DL_SIZE_KNOWN) {
if(!data->progress.dlspeed)
data->progress.dlspeed=1;
dlestimate = data->progress.size_dl / data->progress.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) data->progress.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, data->progress.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,
Daniel Stenberg
committed
"\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(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.current_speed, max5[5]) /* current speed */
);
}
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
break;
#if 0
case CURL_PROGRESS_BAR:
/* original progress bar code by Lars Aas */
if (progressmax == -1) {
int prevblock = prev / 1024;
int thisblock = point / 1024;
while ( thisblock > prevblock ) {
fprintf( data->err, "#" );
prevblock++;
}
prev = point;
}
else {
char line[256];
char outline[256];
char format[40];
float frac = (float) point / (float) progressmax;
float percent = frac * 100.0f;
int barwidth = width - 7;
int num = (int) (((float)barwidth) * frac);
int i = 0;
for ( i = 0; i < num; i++ ) {
line[i] = '#';
}
line[i] = '\0';
sprintf( format, "%%-%ds %%5.1f%%%%", barwidth );
sprintf( outline, format, line, percent );
fprintf( data->err, "\r%s", outline );
}
prev = point;
break;
#endif
}
}
#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/*, int options, int moremax*/)
#ifdef __EMX__
/* 20000318 mgs */
int scr_size [2];
#endif
if(data->conf&(CONF_NOPROGRESS|CONF_MUTE))
return;
prev = 0;
/* TODO: get terminal width through ansi escapes or something similar.
try to update width when xterm is resized... - 19990617 larsa */
#ifndef __EMX__
/* 20000318 mgs
* OS/2 users most likely won't have this env var set, and besides that
* we're using our own way to determine screen width */
if (curl_GetEnv("COLUMNS") != NULL)
width = atoi(curl_GetEnv("COLUMNS"));
else
width = 79;
#else
/* 20000318 mgs
* We use this emx library call to get the screen width, and subtract
* one from what we got in order to avoid a problem with the cursor
* advancing to the next line if we print a string that is as long as
* the screen is wide. */
_scrsize(scr_size);
width = scr_size[0] - 1;
#endif
progressmax = max;
if(-1 == max)
return;
if(progressmax <= LEAST_SIZE_PROGRESS) {
progressmax = -1; /* disable */
return;
}
if ( data->progressmode == CURL_PROGRESS_STATS )
fprintf(data->err,
Daniel Stenberg
committed
" %% Received Total Speed Estimated Time Left Curr.Speed\n");
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
}
void ProgressShow(struct UrlData *data,
int point, struct timeval start, struct timeval now, bool force)
{
switch ( data->progressmode ) {
case CURL_PROGRESS_STATS:
{
static long lastshow;
double percen;
double spent;
double speed;
#define CURR_TIME 5
static int speeder[ CURR_TIME ];
static int speeder_c=0;
int nowindex = speeder_c% CURR_TIME;
int checkindex;
int count;
if(!force && (point != progressmax) && (lastshow == tvlong(now)))
return; /* never update this more than once a second if the end isn't
reached */
spent = tvdiff (now, start);
speed = point/(spent!=0.0?spent:1.0);
if(!speed)
speed=1;
/* point is where we are right now */
speeder[ nowindex ] = point;
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->current_speed = (speeder[nowindex]-speeder[checkindex])/(count?count:1);
#if 0
printf("NOW %d(%d) THEN %d(%d) DIFF %lf COUNT %d\n",
speeder[nowindex], nowindex,
speeder[checkindex], checkindex,
data->current_speed, count);
#endif
if(data->conf&(CONF_NOPROGRESS|CONF_MUTE))
return;
if(-1 != progressmax) {
Daniel Stenberg
committed
char left[20];
char estim[20];
char timespent[20];
int estimate = progressmax/(int) speed;
time2str(left,estimate-(int) spent);
time2str(estim,estimate);
Daniel Stenberg
committed
time2str(timespent,spent);
percen=(double)point/progressmax;
percen=percen*100;
Daniel Stenberg
committed
fprintf(stderr, "\r%3d %10d %10d %6.0lf %s %s %s %6.0lf ",
Daniel Stenberg
committed
speed, estim, timespent, left, data->current_speed);
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
}
else
fprintf(data->err,
"\r%d bytes received in %.3lf seconds (%.0lf bytes/sec)",
point, spent, speed);
lastshow = now.tv_sec;
break;
}
case CURL_PROGRESS_BAR: /* 19990617 larsa */
{
if (point == prev) break;
if (progressmax == -1) {
int prevblock = prev / 1024;
int thisblock = point / 1024;
while ( thisblock > prevblock ) {
fprintf( data->err, "#" );
prevblock++;
}
prev = point;
} else {
char line[256];
char outline[256];
char format[40];
float frac = (float) point / (float) progressmax;
float percent = frac * 100.0f;
int barwidth = width - 7;
int num = (int) (((float)barwidth) * frac);
int i = 0;
for ( i = 0; i < num; i++ ) {
line[i] = '#';
}
line[i] = '\0';
sprintf( format, "%%-%ds %%5.1f%%%%", barwidth );
sprintf( outline, format, line, percent );
fprintf( data->err, "\r%s", outline );
}
prev = point;
break;
}
default: /* 19990617 larsa */
{
int prevblock = prev / 1024;
int thisblock = point / 1024;
if (prev == point) break;
while ( thisblock > prevblock ) {
fprintf( data->err, "#" );
prevblock++;
}
prev = point;
break;
}
}
}
void ProgressEnd(struct UrlData *data)
{
if(data->conf&(CONF_NOPROGRESS|CONF_MUTE))
return;
fputs("\n", data->err);
}
/* --- end of progress routines --- */