From 84396de6731454b46c70b1278a9270c24d6a6684 Mon Sep 17 00:00:00 2001
From: hniksic <devnull@localhost>
Date: Mon, 26 Nov 2001 04:49:10 -0800
Subject: [PATCH] [svn] Allocate a timer directly in get_contents. Published in
 <sxsherhbsvl.fsf@florida.arsdigita.de>.

---
 src/ChangeLog  |  7 ++++++
 src/ftp.c      |  8 +++----
 src/http.c     |  8 +++----
 src/progress.c | 63 ++++++++++++++++++++++----------------------------
 src/progress.h |  4 ++--
 src/retr.c     | 44 ++++++++++++++++++++++++-----------
 src/retr.h     |  3 ++-
 7 files changed, 75 insertions(+), 62 deletions(-)

diff --git a/src/ChangeLog b/src/ChangeLog
index 0ac18691..26b8aeae 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,10 @@
+2001-11-26  Hrvoje Niksic  <hniksic@arsdigita.com>
+
+	* progress.c: Don't allocate new timers; use the timing data
+	propagated from the caller.
+
+	* retr.c (get_contents): Allocate and use a timer.
+
 2001-11-26  Hrvoje Niksic  <hniksic@arsdigita.com>
 
 	* http.c (last_host_ip): Made into an address_list.
diff --git a/src/ftp.c b/src/ftp.c
index 1c438542..012eacd7 100644
--- a/src/ftp.c
+++ b/src/ftp.c
@@ -127,7 +127,6 @@ getftp (struct url *u, long *len, long restval, ccon *con)
   FILE *fp;
   char *user, *passwd, *respline;
   char *tms, *tmrate;
-  struct wget_timer *timer;
   unsigned char pasv_addr[6];
   int cmd = con->cmd;
   int passive_mode_open = 0;
@@ -875,11 +874,10 @@ Error in server response, closing control connection.\n"));
 		   legible (expected_bytes - restval));
       logputs (LOG_VERBOSE, _(" (unauthoritative)\n"));
     }
-  timer = wtimer_new ();
+
   /* Get the contents of the document.  */
-  res = get_contents (dtsock, fp, len, restval, expected_bytes, &con->rbuf, 0);
-  con->dltime = wtimer_elapsed (timer);
-  wtimer_delete (timer);
+  res = get_contents (dtsock, fp, len, restval, expected_bytes, &con->rbuf,
+		      0, &con->dltime);
   tms = time_str (NULL);
   tmrate = retr_rate (*len - restval, con->dltime, 0);
   /* Close data connection socket.  */
diff --git a/src/http.c b/src/http.c
index a886f488..4313176f 100644
--- a/src/http.c
+++ b/src/http.c
@@ -546,7 +546,6 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
   static SSL_CTX *ssl_ctx = NULL;
   SSL *ssl = NULL;
 #endif /* HAVE_SSL */
-  struct wget_timer *timer;
   char *cookies = NULL;
 
   /* Whether this connection will be kept alive after the HTTP request
@@ -1344,13 +1343,12 @@ Refusing to truncate existing file `%s'.\n\n"), *hs->local_file);
      should be some overhead information.  */
   if (opt.save_headers)
     fwrite (all_headers, 1, all_length, fp);
-  timer = wtimer_new ();
+
   /* Get the contents of the document.  */
   hs->res = get_contents (sock, fp, &hs->len, hs->restval,
 			  (contlen != -1 ? contlen : 0),
-			  &rbuf, keep_alive);
-  hs->dltime = wtimer_elapsed (timer);
-  wtimer_delete (timer);
+			  &rbuf, keep_alive, &hs->dltime);
+
   {
     /* Close or flush the file.  We have to be careful to check for
        error here.  Checking the result of fwrite() is not enough --
diff --git a/src/progress.c b/src/progress.c
index 817e2edc..e010d2d3 100644
--- a/src/progress.c
+++ b/src/progress.c
@@ -39,21 +39,21 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 struct progress_implementation {
   char *name;
   void *(*create) (long, long);
-  void (*update) (void *, long);
-  void (*finish) (void *);
+  void (*update) (void *, long, long);
+  void (*finish) (void *, long);
   void (*set_params) (const char *);
 };
 
 /* Necessary forward declarations. */
 
 static void *dot_create PARAMS ((long, long));
-static void dot_update PARAMS ((void *, long));
-static void dot_finish PARAMS ((void *));
+static void dot_update PARAMS ((void *, long, long));
+static void dot_finish PARAMS ((void *, long));
 static void dot_set_params PARAMS ((const char *));
 
 static void *bar_create PARAMS ((long, long));
-static void bar_update PARAMS ((void *, long));
-static void bar_finish PARAMS ((void *));
+static void bar_update PARAMS ((void *, long, long));
+static void bar_finish PARAMS ((void *, long));
 static void bar_set_params PARAMS ((const char *));
 
 static struct progress_implementation implementations[] = {
@@ -132,21 +132,22 @@ progress_create (long initial, long total)
   return current_impl->create (initial, total);
 }
 
-/* Inform the progress gauge of newly received bytes. */
+/* Inform the progress gauge of newly received bytes.  DLTIME is the
+   time in milliseconds since the beginning of the download.  */
 
 void
-progress_update (void *progress, long howmuch)
+progress_update (void *progress, long howmuch, long dltime)
 {
-  current_impl->update (progress, howmuch);
+  current_impl->update (progress, howmuch, dltime);
 }
 
 /* Tell the progress gauge to clean up.  Calling this will free the
    PROGRESS object, the further use of which is not allowed.  */
 
 void
-progress_finish (void *progress)
+progress_finish (void *progress, long dltime)
 {
-  current_impl->finish (progress);
+  current_impl->finish (progress, dltime);
 }
 
 /* Dot-printing. */
@@ -161,9 +162,6 @@ struct dot_progress {
 
   int rows;			/* number of rows printed so far */
   int dots;			/* number of dots printed in this row */
-
-  struct wget_timer *timer;	/* timer used to measure per-row
-				   download rates. */
   long last_timer_value;
 };
 
@@ -178,7 +176,6 @@ dot_create (long initial, long total)
 
   dp->initial_length = initial;
   dp->total_length   = total;
-  dp->timer = wtimer_new ();
 
   if (dp->initial_length)
     {
@@ -227,18 +224,17 @@ print_percentage (long bytes, long expected)
 }
 
 static void
-print_download_speed (struct dot_progress *dp, long bytes)
+print_download_speed (struct dot_progress *dp, long bytes, long dltime)
 {
-  long timer_value = wtimer_elapsed (dp->timer);
   logprintf (LOG_VERBOSE, " %s",
-	     retr_rate (bytes, timer_value - dp->last_timer_value, 1));
-  dp->last_timer_value = timer_value;
+	     retr_rate (bytes, dltime - dp->last_timer_value, 1));
+  dp->last_timer_value = dltime;
 }
 
 /* Dot-progress backend for progress_update. */
 
 static void
-dot_update (void *progress, long howmuch)
+dot_update (void *progress, long howmuch, long dltime)
 {
   struct dot_progress *dp = progress;
   int dot_bytes = opt.dot_bytes;
@@ -266,7 +262,8 @@ dot_update (void *progress, long howmuch)
 	    print_percentage (dp->rows * row_bytes, dp->total_length);
 
 	  print_download_speed (dp,
-				row_bytes - (dp->initial_length % row_bytes));
+				row_bytes - (dp->initial_length % row_bytes),
+				dltime);
 	}
     }
 
@@ -276,7 +273,7 @@ dot_update (void *progress, long howmuch)
 /* Dot-progress backend for progress_finish. */
 
 static void
-dot_finish (void *progress)
+dot_finish (void *progress, long dltime)
 {
   struct dot_progress *dp = progress;
   int dot_bytes = opt.dot_bytes;
@@ -301,12 +298,12 @@ dot_finish (void *progress)
 
   print_download_speed (dp, dp->dots * dot_bytes
 			+ dp->accumulated
-			- dp->initial_length % row_bytes);
+			- dp->initial_length % row_bytes,
+			dltime);
   logputs (LOG_VERBOSE, "\n\n");
 
   log_set_flush (0);
 
-  wtimer_delete (dp->timer);
   xfree (dp);
 }
 
@@ -379,8 +376,6 @@ struct bar_progress {
 				   download finishes */
   long count;			/* bytes downloaded so far */
 
-  struct wget_timer *timer;	/* timer used to measure the download
-				   rates. */
   long last_update;		/* time of the last screen update. */
 
   int width;			/* screen width at the time the
@@ -403,11 +398,10 @@ bar_create (long initial, long total)
 
   bp->initial_length = initial;
   bp->total_length   = total;
-  bp->timer = wtimer_new ();
   bp->width = screen_width;
   bp->buffer = xmalloc (bp->width + 1);
 
-  logputs (LOG_VERBOSE, "\n");
+  logputs (LOG_VERBOSE, "\n\n");
 
   create_image (bp, 0);
   display_image (bp->buffer);
@@ -416,11 +410,10 @@ bar_create (long initial, long total)
 }
 
 static void
-bar_update (void *progress, long howmuch)
+bar_update (void *progress, long howmuch, long dltime)
 {
   struct bar_progress *bp = progress;
   int force_update = 0;
-  long dltime = wtimer_elapsed (bp->timer);
 
   bp->count += howmuch;
   if (bp->total_length > 0
@@ -449,24 +442,22 @@ bar_update (void *progress, long howmuch)
 }
 
 static void
-bar_finish (void *progress)
+bar_finish (void *progress, long dltime)
 {
   struct bar_progress *bp = progress;
-  long elapsed = wtimer_elapsed (bp->timer);
 
-  if (elapsed == 0)
+  if (dltime == 0)
     /* If the download was faster than the granularity of the timer,
        fake some output so that we don't get the ugly "----.--" rate
        at the download finish.  */
-    elapsed = 1;
+    dltime = 1;
 
-  create_image (bp, elapsed);
+  create_image (bp, dltime);
   display_image (bp->buffer);
 
   logputs (LOG_VERBOSE, "\n\n");
 
   xfree (bp->buffer);
-  wtimer_delete (bp->timer);
   xfree (bp);
 }
 
diff --git a/src/progress.h b/src/progress.h
index 50cd2116..bb0abad8 100644
--- a/src/progress.h
+++ b/src/progress.h
@@ -21,7 +21,7 @@ int valid_progress_implementation_p PARAMS ((const char *));
 void set_progress_implementation PARAMS ((const char *));
 
 void *progress_create PARAMS ((long, long));
-void progress_update PARAMS ((void *, long));
-void progress_finish PARAMS ((void *));
+void progress_update PARAMS ((void *, long, long));
+void progress_finish PARAMS ((void *, long));
 
 RETSIGTYPE progress_handle_sigwinch PARAMS ((int));
diff --git a/src/retr.c b/src/retr.c
index dc1587e4..f4b80fdd 100644
--- a/src/retr.c
+++ b/src/retr.c
@@ -77,32 +77,38 @@ int global_download_count;
    from fd immediately, flush or discard the buffer.  */
 int
 get_contents (int fd, FILE *fp, long *len, long restval, long expected,
-	      struct rbuf *rbuf, int use_expected)
+	      struct rbuf *rbuf, int use_expected, long *elapsed)
 {
   int res = 0;
   static char c[8192];
   void *progress = NULL;
+  struct wget_timer *timer = NULL;
 
   *len = restval;
+
   if (opt.verbose)
     progress = progress_create (restval, expected);
+  if (opt.verbose || elapsed != NULL)
+    timer = wtimer_new ();
 
   if (rbuf && RBUF_FD (rbuf) == fd)
     {
-      int need_flush = 0;
+      int sz = 0;
       while ((res = rbuf_flush (rbuf, c, sizeof (c))) != 0)
 	{
-	  if (fwrite (c, sizeof (char), res, fp) < res)
-	    return -2;
-	  if (opt.verbose)
-	    progress_update (progress, res);
+	  fwrite (c, sizeof (char), res, fp);
 	  *len += res;
-	  need_flush = 1;
+	  sz += res;
 	}
-      if (need_flush)
+      if (sz)
 	fflush (fp);
       if (ferror (fp))
-	return -2;
+	{
+	  res = -2;
+	  goto out;
+	}
+      if (opt.verbose)
+	progress_update (progress, sz, wtimer_elapsed (timer));
     }
   /* Read from fd while there is available data.
 
@@ -131,9 +137,12 @@ get_contents (int fd, FILE *fp, long *len, long restval, long expected,
 	     packets typically won't be too tiny anyway.  */
 	  fflush (fp);
 	  if (ferror (fp))
-	    return -2;
+	    {
+	      res = -2;
+	      goto out;
+	    }
 	  if (opt.verbose)
-	    progress_update (progress, res);
+	    progress_update (progress, res, wtimer_elapsed (timer));
 	  *len += res;
 	}
       else
@@ -141,8 +150,17 @@ get_contents (int fd, FILE *fp, long *len, long restval, long expected,
     }
   if (res < -1)
     res = -1;
-  if (opt.verbose)
-    progress_finish (progress);
+
+ out:
+  if (timer)
+    {
+      long dltime = wtimer_elapsed (timer);
+      if (opt.verbose)
+	progress_finish (progress, dltime);
+      if (elapsed)
+	*elapsed = dltime;
+      wtimer_delete (timer);
+    }
   return res;
 }
 
diff --git a/src/retr.h b/src/retr.h
index 18cea141..22f3949f 100644
--- a/src/retr.h
+++ b/src/retr.h
@@ -22,7 +22,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #include "rbuf.h"
 
-int get_contents PARAMS ((int, FILE *, long *, long, long, struct rbuf *, int));
+int get_contents PARAMS ((int, FILE *, long *, long, long, struct rbuf *,
+			  int, long *));
 
 uerr_t retrieve_url PARAMS ((const char *, char **, char **,
 			     const char *, int *));