]> sjero.net Git - wget/blobdiff - src/progress.c
[svn] Fixes by Christian Biere:
[wget] / src / progress.c
index 8ae09c32689df0492222116eee374749080aebab..3fae615dcae86f0d8ba2d2af28941c97cf3bbc5b 100644 (file)
@@ -50,7 +50,8 @@ so, delete this exception statement from your version.  */
 #include "retr.h"
 
 struct progress_implementation {
-  char *name;
+  const char *name;
+  int interactive;
   void *(*create) PARAMS ((long, long));
   void (*update) PARAMS ((void *, long, double));
   void (*finish) PARAMS ((void *, double));
@@ -70,8 +71,8 @@ static void bar_finish PARAMS ((void *, double));
 static void bar_set_params PARAMS ((const char *));
 
 static struct progress_implementation implementations[] = {
-  { "dot", dot_create, dot_update, dot_finish, dot_set_params },
-  { "bar", bar_create, bar_update, bar_finish, bar_set_params }
+  { "dot", 0, dot_create, dot_update, dot_finish, dot_set_params },
+  { "bar", 1, bar_create, bar_update, bar_finish, bar_set_params }
 };
 static struct progress_implementation *current_impl;
 static int current_impl_locked;
@@ -168,6 +169,17 @@ progress_create (long initial, long total)
   return current_impl->create (initial, total);
 }
 
+/* Return non-zero if the progress gauge is "interactive", i.e. if it
+   can profit from being called regularly even in absence of data.
+   The progress bar is interactive because it regularly updates the
+   ETA and current update.  */
+
+int
+progress_interactive_p (void *progress)
+{
+  return current_impl->interactive;
+}
+
 /* Inform the progress gauge of newly received bytes.  DLTIME is the
    time in milliseconds since the beginning of the download.  */
 
@@ -425,6 +437,11 @@ static volatile sig_atomic_t received_sigwinch;
    past.  */
 #define DLSPEED_SAMPLE_MIN 150
 
+/* The time after which the download starts to be considered
+   "stalled", i.e. the current bandwidth is not printed and the recent
+   download speeds are scratched.  */
+#define STALL_START_TIME 5000
+
 struct bar_progress {
   long initial_length;         /* how many bytes have been downloaded
                                   previously. */
@@ -466,8 +483,12 @@ struct bar_progress {
                                   position. */
   long recent_bytes;           /* bytes downloaded so far. */
 
+  int stalled;                 /* set when no data arrives for longer
+                                  than STALL_START_TIME, then reset
+                                  when new data arrives. */
+
   /* create_image() uses these to make sure that ETA information
-     doesn't flash. */
+     doesn't flicker. */
   double last_eta_time;                /* time of the last update to download
                                   speed and ETA, measured since the
                                   beginning of download. */
@@ -615,6 +636,38 @@ update_speed_ring (struct bar_progress *bp, long howmuch, double dltime)
   if (recent_age < DLSPEED_SAMPLE_MIN)
     return;
 
+  if (howmuch == 0)
+    {
+      /* If we're not downloading anything, we might be stalling,
+        i.e. not downloading anything for an extended period of time.
+        Since 0-reads do not enter the history ring, recent_age
+        effectively measures the time since last read.  */
+      if (recent_age >= STALL_START_TIME)
+       {
+         /* If we're stalling, reset the ring contents because it's
+            stale and because it will make bar_update stop printing
+            the (bogus) current bandwidth.  */
+         bp->stalled = 1;
+         xzero (*hist);
+         bp->recent_bytes = 0;
+       }
+      return;
+    }
+
+  /* We now have a non-zero amount of to store to the speed ring.  */
+
+  /* If the stall status was acquired, reset it. */
+  if (bp->stalled)
+    {
+      bp->stalled = 0;
+      /* "recent_age" includes the the entired stalled period, which
+        could be very long.  Don't update the speed ring with that
+        value because the current bandwidth would start too small.
+        Start with an arbitrary (but more reasonable) time value and
+        let it level out.  */
+      recent_age = 1000;
+    }
+
   /* Store "recent" bytes and download time to history ring at the
      position POS.  */
 
@@ -781,7 +834,7 @@ create_image (struct bar_progress *bp, double dl_total_time)
   /* " 1012.45K/s" */
   if (hist->total_time && hist->total_bytes)
     {
-      static char *short_units[] = { "B/s", "K/s", "M/s", "G/s" };
+      static const char *short_units[] = { "B/s", "K/s", "M/s", "G/s" };
       int units = 0;
       /* Calculate the download speed using the history ring and
         recent data that hasn't made it to the ring yet.  */
@@ -797,7 +850,7 @@ create_image (struct bar_progress *bp, double dl_total_time)
   /* " ETA xx:xx:xx"; wait for three seconds before displaying the ETA.
      That's because the ETA value needs a while to become
      reliable.  */
-  if (bp->total_length > 0 && dl_total_time > 3000)
+  if (bp->total_length > 0 && bp->count > 0 && dl_total_time > 3000)
     {
       long eta;
       int eta_hrs, eta_min, eta_sec;
@@ -886,8 +939,6 @@ bar_set_params (const char *params)
          TTY -- when logging to file, it is better to review the
          dots.  */
        || !isatty (fileno (stderr))
-#else
-       1
 #endif
        /* Normally we don't depend on terminal type because the
          progress bar only uses ^M to move the cursor to the