]> sjero.net Git - wget/commitdiff
[svn] New timer functions. Published in <sxs8zkp28vk.fsf@florida.arsdigita.de>.
authorhniksic <devnull@localhost>
Tue, 24 Apr 2001 23:09:45 +0000 (16:09 -0700)
committerhniksic <devnull@localhost>
Tue, 24 Apr 2001 23:09:45 +0000 (16:09 -0700)
src/ChangeLog
src/ftp.c
src/http.c
src/retr.c
src/retr.h
src/utils.c
src/utils.h

index 78c48bb7e519bf9d72a255a56a385e8ee394cb92..313b504dc30337e061ad9afde2f53ccc0f6e24b2 100644 (file)
@@ -1,3 +1,26 @@
+2001-04-25  Hrvoje Niksic  <hniksic@arsdigita.com>
+
+       * utils.c: Document timer functions.
+
+       * retr.c (rate): Use it.
+       (rate): Print in GB/s if transfer rate exceeds 1 GB/s.
+
+       * utils.c (wtimer_granularity): New function.
+
+2001-04-24  Hrvoje Niksic  <hniksic@arsdigita.com>
+
+       * retr.c (show_progress): Ditto.
+
+       * ftp.c (getftp): Ditto.
+
+       * http.c (gethttp): Use new timer functions.
+
+       * utils.c (wtimer_allocate): New function.
+       (wtimer_new): Ditto.
+       (wtimer_delete): Ditto.
+       (wtimer_reset): Ditto.
+       (wtimer_elapsed): Ditto.
+
 2001-04-24  Hrvoje Niksic  <hniksic@arsdigita.com>
 
        * utils.c (long_to_string): New, faster version.  Favors smaller
index 9a0f9a3fa3b2d00d5ad99f8e89e512b1a7c094e8..1e8ad517d20d737c5f7e060a31bf25725ec5d016 100644 (file)
--- a/src/ftp.c
+++ b/src/ftp.c
@@ -114,6 +114,7 @@ getftp (struct urlinfo *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;
@@ -870,10 +871,11 @@ Error in server response, closing control connection.\n"));
                   legible (expected_bytes - restval));
       logputs (LOG_VERBOSE, _(" (unauthoritative)\n"));
     }
-  reset_timer ();
+  timer = wtimer_new ();
   /* Get the contents of the document.  */
   res = get_contents (dtsock, fp, len, restval, expected_bytes, &con->rbuf, 0);
-  con->dltime = elapsed_time ();
+  con->dltime = wtimer_elapsed (timer);
+  wtimer_delete (timer);
   tms = time_str (NULL);
   tmrate = rate (*len - restval, con->dltime, 0);
   /* Close data connection socket.  */
index 7b9578d19d35288a844810a7be8a0cc9ba773f7d..22fabdc6360793f05d7f4d160480a9af6adb9a39 100644 (file)
@@ -526,6 +526,7 @@ gethttp (struct urlinfo *u, struct http_stat *hs, int *dt)
   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
@@ -1333,12 +1334,13 @@ Accept: %s\r\n\
      should be some overhead information.  */
   if (opt.save_headers)
     fwrite (all_headers, 1, all_length, fp);
-  reset_timer ();
+  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 = elapsed_time ();
+  hs->dltime = wtimer_elapsed (timer);
+  wtimer_delete (timer);
   {
     /* Close or flush the file.  We have to be careful to check for
        error here.  Checking the result of fwrite() is not enough --
index 1667f52e0c7d589b5d262974dc9c1e567f101b47..dd6380d3d4c399c94e07c0aff6a75fc8047e948f 100644 (file)
@@ -47,13 +47,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 extern int errno;
 #endif
 
-#ifdef WINDOWS
-LARGE_INTEGER internal_time;
-#else
-/* Internal variables used by the timer.  */
-static long internal_secs, internal_msecs;
-#endif
-
 /* See the comment in gethttp() why this is needed. */
 int global_download_count;
 
@@ -175,10 +168,11 @@ print_percentage (long bytes, long expected)
 static int
 show_progress (long res, long expected, enum spflags flags)
 {
+  static struct wget_timer *timer;
   static long line_bytes;
   static long offs, initial_skip;
   static int ndot, nrow;
-  static long last_timer, time_offset;
+  static long last_timer_value, time_offset;
   int any_output = 0;
 
   if (flags == SP_FINISH)
@@ -186,7 +180,7 @@ show_progress (long res, long expected, enum spflags flags)
       int dot = ndot;
       char *tmpstr = (char *)alloca (2 * opt.dots_in_line + 1);
       char *tmpp = tmpstr;
-      time_offset = elapsed_time () - last_timer;
+      time_offset = wtimer_elapsed (timer) - last_timer_value;
       for (; dot < opt.dots_in_line; dot++)
        {
          if (!(dot % opt.dot_spacing))
@@ -217,7 +211,10 @@ show_progress (long res, long expected, enum spflags flags)
       offs = 0L;
       ndot = nrow = 0;
       line_bytes = (long)opt.dots_in_line * opt.dot_bytes;
-      last_timer = elapsed_time ();
+      if (!timer)
+       timer = wtimer_allocate ();
+      wtimer_reset (timer);
+      last_timer_value = 0;
       time_offset = 0;
       initial_skip = res;
       if (res)
@@ -247,8 +244,8 @@ show_progress (long res, long expected, enum spflags flags)
       ++ndot;
       if (ndot == opt.dots_in_line)
        {
-         time_offset = elapsed_time () - last_timer;
-         last_timer += time_offset;
+         time_offset = wtimer_elapsed (timer) - last_timer_value;
+         last_timer_value += time_offset;
 
          ndot = 0;
          ++nrow;
@@ -264,66 +261,11 @@ show_progress (long res, long expected, enum spflags flags)
   /* Reenable flushing.  */
   opt.no_flush = 0;
   if (any_output)
-    /* Force flush.  #### Oh, what a kludge!  */
+    /* Force flush.  */
     logflush ();
   return any_output;
 }
 \f
-/* Reset the internal timer.  */
-void
-reset_timer (void)
-{
-#ifndef WINDOWS
-  /* Under Unix, the preferred way to measure the passage of time is
-     through gettimeofday() because of its granularity.  However, on
-     some old or weird systems, gettimeofday() might not be available.
-     There we use the simple time().  */
-# ifdef HAVE_GETTIMEOFDAY
-  struct timeval t;
-  gettimeofday (&t, NULL);
-  internal_secs = t.tv_sec;
-  internal_msecs = t.tv_usec / 1000;
-# else  /* not HAVE_GETTIMEOFDAY */
-  internal_secs = time (NULL);
-  internal_msecs = 0;
-# endif /* not HAVE_GETTIMEOFDAY */
-#else  /* WINDOWS */
-  /* Under Windows, use Windows-specific APIs. */
-  FILETIME ft;
-  SYSTEMTIME st;
-  GetSystemTime(&st);
-  SystemTimeToFileTime(&st,&ft);
-  internal_time.HighPart = ft.dwHighDateTime;
-  internal_time.LowPart = ft.dwLowDateTime;
-#endif /* WINDOWS */
-}
-
-/* Return the time elapsed from the last call to reset_timer(), in
-   milliseconds.  */
-long
-elapsed_time (void)
-{
-#ifndef WINDOWS
-# ifdef HAVE_GETTIMEOFDAY
-  struct timeval t;
-  gettimeofday (&t, NULL);
-  return ((t.tv_sec - internal_secs) * 1000
-         + (t.tv_usec / 1000 - internal_msecs));
-# else  /* not HAVE_GETTIMEOFDAY */
-  return 1000 * ((long)time (NULL) - internal_secs);
-# endif /* not HAVE_GETTIMEOFDAY */
-#else  /* WINDOWS */
-  FILETIME ft;
-  SYSTEMTIME st;
-  LARGE_INTEGER li;
-  GetSystemTime(&st);
-  SystemTimeToFileTime(&st,&ft);
-  li.HighPart = ft.dwHighDateTime;
-  li.LowPart = ft.dwLowDateTime;
-  return (long) ((li.QuadPart - internal_time.QuadPart) / 1e4);
-#endif /* WINDOWS */
-}
-
 /* Print out the appropriate download rate.  Appropriate means that if
    rate is > 1024 bytes per second, kilobytes are used, and if rate >
    1024 * 1024 bps, megabytes are used.
@@ -336,15 +278,25 @@ rate (long bytes, long msecs, int pad)
   static char res[15];
   double dlrate;
 
-  if (!msecs)
-    ++msecs;
+  if (msecs == 0)
+    /* If elapsed time is 0, it means we're under the granularity of
+       the timer.  This often happens on systems that use time() for
+       the timer.  */
+    msecs = wtimer_granularity ();
+
   dlrate = (double)1000 * bytes / msecs;
   if (dlrate < 1024.0)
     sprintf (res, pad ? "%7.2f B/s" : "%.2f B/s", dlrate);
   else if (dlrate < 1024.0 * 1024.0)
     sprintf (res, pad ? "%7.2f KB/s" : "%.2f KB/s", dlrate / 1024.0);
-  else
+  else if (dlrate < 1024.0 * 1024.0 * 1024.0)
     sprintf (res, pad ? "%7.2f MB/s" : "%.2f MB/s", dlrate / (1024.0 * 1024.0));
+  else
+    /* Maybe someone will need this one day.  More realistically, it
+       will get tickled by buggy timers. */
+    sprintf (res, pad ? "%7.2f GB/s" : "%.2f GB/s",
+            dlrate / (1024.0 * 1024.0 * 1024.0));
+
   return res;
 }
 \f
index c69c493eea1e4873ddd5ba52c231d37e936f442e..4455e7bd9e6f81f5283c75495d4d50c019d03330 100644 (file)
@@ -28,10 +28,7 @@ uerr_t retrieve_url PARAMS ((const char *, char **, char **,
                             const char *, int *));
 uerr_t retrieve_from_file PARAMS ((const char *, int, int *));
 
-void reset_timer PARAMS ((void));
-long elapsed_time PARAMS ((void));
 char *rate PARAMS ((long, long, int));
-
 void printwhat PARAMS ((int, int));
 
 void downloaded_increase PARAMS ((unsigned long));
index 7163ea7166cecd4c3a16203ddf4a15ff7e6a8f26..a8e30b9fa5d61dde680623715baf4b1c32a2a82e 100644 (file)
@@ -1532,6 +1532,160 @@ long_to_string (char *buffer, long number)
 #undef DIGITS_18
 #undef DIGITS_19
 \f
+/* Support for timers. */
+
+#undef TIMER_WINDOWS
+#undef TIMER_GETTIMEOFDAY
+#undef TIMER_TIME
+
+/* Depending on the OS and availability of gettimeofday(), one and
+   only one of the above constants will be defined.  Virtually all
+   modern Unix systems will define TIMER_GETTIMEOFDAY; Windows will
+   use TIMER_WINDOWS.  TIMER_TIME is a catch-all method for
+   non-Windows systems without gettimeofday.
+
+   #### Perhaps we should also support ftime(), which exists on old
+   BSD 4.2-influenced systems?  (It also existed under MS DOS Borland
+   C, if memory serves me.)  */
+
+#ifdef WINDOWS
+# define TIMER_WINDOWS
+#else  /* not WINDOWS */
+# ifdef HAVE_GETTIMEOFDAY
+#  define TIMER_GETTIMEOFDAY
+# else
+#  define TIMER_TIME
+# endif
+#endif /* not WINDOWS */
+
+struct wget_timer {
+#ifdef TIMER_GETTIMEOFDAY
+  long secs;
+  long usecs;
+#endif
+
+#ifdef TIMER_TIME
+  time_t secs;
+#endif
+
+#ifdef TIMER_WINDOWS
+  ULARGE_INTEGER wintime;
+#endif
+};
+
+/* Allocate a timer.  It is not legal to do anything with a freshly
+   allocated timer, except call wtimer_reset().  */
+
+struct wget_timer *
+wtimer_allocate (void)
+{
+  struct wget_timer *wt =
+    (struct wget_timer *)xmalloc (sizeof (struct wget_timer));
+  return wt;
+}
+
+/* Allocate a new timer and reset it.  Return the new timer. */
+
+struct wget_timer *
+wtimer_new (void)
+{
+  struct wget_timer *wt = wtimer_allocate ();
+  wtimer_reset (wt);
+  return wt;
+}
+
+/* Free the resources associated with the timer.  Its further use is
+   prohibited.  */
+
+void
+wtimer_delete (struct wget_timer *wt)
+{
+  xfree (wt);
+}
+
+/* Reset timer WT.  This establishes the starting point from which
+   wtimer_elapsed() will return the number of elapsed
+   milliseconds.  It is allowed to reset a previously used timer.  */
+
+void
+wtimer_reset (struct wget_timer *wt)
+{
+#ifdef TIMER_GETTIMEOFDAY
+  struct timeval t;
+  gettimeofday (&t, NULL);
+  wt->secs  = t.tv_sec;
+  wt->usecs = t.tv_usec;
+#endif
+
+#ifdef TIMER_TIME
+  wt->secs = time (NULL);
+#endif
+
+#ifdef TIMER_WINDOWS
+  FILETIME ft;
+  SYSTEMTIME st;
+  GetSystemTime (&st);
+  SystemTimeToFileTime (&st, &ft);
+  wt->wintime.HighPart = ft.dwHighDateTime;
+  wt->wintime.LowPart  = ft.dwLowDateTime;
+#endif
+}
+
+/* Return the number of milliseconds elapsed since the timer was last
+   reset.  It is allowed to call this function more than once to get
+   increasingly higher elapsed values.  */
+
+long
+wtimer_elapsed (struct wget_timer *wt)
+{
+#ifdef TIMER_GETTIMEOFDAY
+  struct timeval t;
+  gettimeofday (&t, NULL);
+  return (t.tv_sec - wt->secs) * 1000 + (t.tv_usec - wt->usecs) / 1000;
+#endif
+
+#ifdef TIMER_TIME
+  time_t now = time (NULL);
+  return 1000 * (now - wt->secs);
+#endif
+
+#ifdef WINDOWS
+  FILETIME ft;
+  SYSTEMTIME st;
+  ULARGE_INTEGER uli;
+  GetSystemTime (&st);
+  SystemTimeToFileTime (&st, &ft);
+  uli.HighPart = ft.dwHighDateTime;
+  uli.LowPart = ft.dwLowDateTime;
+  return (long)((uli.QuadPart - wt->wintime.QuadPart) / 10000);
+#endif
+}
+
+/* Return the assessed granularity of the timer implementation.  This
+   is important for certain code that tries to deal with "zero" time
+   intervals.  */
+
+long
+wtimer_granularity (void)
+{
+#ifdef TIMER_GETTIMEOFDAY
+  /* Granularity of gettimeofday is hugely architecture-dependent.
+     However, it appears that on modern machines it is better than
+     1ms.  */
+  return 1;
+#endif
+
+#ifdef TIMER_TIME
+  /* This is clear. */
+  return 1000;
+#endif
+
+#ifdef TIMER_WINDOWS
+  /* ? */
+  return 1;
+#endif
+}
+\f
 /* This should probably be at a better place, but it doesn't really
    fit into html-parse.c.  */
 
index 2624322f22b1da993e212f4faf5877397bb4c5c5..edc779f75c14caf8fd1ced30228187094ed03a0c 100644 (file)
@@ -39,6 +39,8 @@ struct file_memory {
   int mmap_p;
 };
 
+struct wget_timer;
+
 char *time_str PARAMS ((time_t *));
 char *datetime_str PARAMS ((time_t *));
 
@@ -88,6 +90,13 @@ char *legible_very_long PARAMS ((VERY_LONG_TYPE));
 int numdigit PARAMS ((long));
 void long_to_string PARAMS ((char *, long));
 
+struct wget_timer *wtimer_allocate PARAMS ((void));
+struct wget_timer *wtimer_new PARAMS ((void));
+void wtimer_delete PARAMS ((struct wget_timer *));
+void wtimer_reset PARAMS ((struct wget_timer *));
+long wtimer_elapsed PARAMS ((struct wget_timer *));
+long wtimer_granularity PARAMS ((void));
+
 char *html_quote_string PARAMS ((const char *));
 
 #endif /* UTILS_H */