Commit 7413ee66 authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

all new progress stuff on the way in

parent 41fb29e8
Loading
Loading
Loading
Loading
+251 −10
Original line number Diff line number Diff line
@@ -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
+26 −0
Original line number Diff line number Diff line
@@ -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 */