Converted timeval_sub_timespec() to timeval_cmp().
authorSebastian Harl <sh@tokkee.org>
Tue, 3 Feb 2009 12:05:21 +0000 (13:05 +0100)
committerSebastian Harl <sh@tokkee.org>
Thu, 5 Feb 2009 20:10:26 +0000 (21:10 +0100)
The third (return) argument is now of type 'struct timeval' (instead of
'struct timespec') as well. Also, it may now be NULL, in which case the
difference is not returned. This is a more general and thus more flexible
approach that permitted to remove the custom timeval_sub*() implementations in
the multimeter and ntpd plugins.

The return value has been changed to reflect the return value used by
functions like strcmp(), i.e. it is less than, equal to, or greater than zero
if the first argument is less than, equal to, or greater than the second
argument respectively.

In the cases where a 'struct timespec' is required, the return value is now
converted by multiplying the tv_usec member with 1000.

src/collectd.c
src/common.c
src/common.h
src/multimeter.c
src/ntpd.c
src/rrdtool.c

index 548a8fd..17905c7 100644 (file)
@@ -301,6 +301,7 @@ static int do_loop (void)
 {
        struct timeval tv_now;
        struct timeval tv_next;
+       struct timeval tv_wait;
        struct timespec ts_wait;
 
        while (loop == 0)
@@ -331,14 +332,17 @@ static int do_loop (void)
                        return (-1);
                }
 
-               if (timeval_sub_timespec (&tv_next, &tv_now, &ts_wait) != 0)
+               if (timeval_cmp (tv_next, tv_now, &tv_wait) <= 0)
                {
-                       WARNING ("Not sleeping because "
-                                       "`timeval_sub_timespec' returned "
-                                       "non-zero!");
+                       WARNING ("Not sleeping because the next interval is "
+                                       "%i.%06i seconds in the past!",
+                                       (int) tv_wait.tv_sec, (int) tv_wait.tv_usec);
                        continue;
                }
 
+               ts_wait.tv_sec  = tv_wait.tv_sec;
+               ts_wait.tv_nsec = (long) (1000 * tv_wait.tv_usec);
+
                while ((loop == 0) && (nanosleep (&ts_wait, &ts_wait) == -1))
                {
                        if (errno != EINTR)
index aeea28d..7cc1d9d 100644 (file)
@@ -347,28 +347,56 @@ int escape_slashes (char *buf, int buf_len)
        return (0);
 } /* int escape_slashes */
 
-int timeval_sub_timespec (struct timeval *tv0, struct timeval *tv1, struct timespec *ret)
+int timeval_cmp (struct timeval tv0, struct timeval tv1, struct timeval *delta)
 {
-       if ((tv0 == NULL) || (tv1 == NULL) || (ret == NULL))
-               return (-2);
+       struct timeval *larger;
+       struct timeval *smaller;
 
-       if ((tv0->tv_sec < tv1->tv_sec)
-                       || ((tv0->tv_sec == tv1->tv_sec) && (tv0->tv_usec < tv1->tv_usec)))
-               return (-1);
+       int status;
 
-       ret->tv_sec  = tv0->tv_sec - tv1->tv_sec;
-       ret->tv_nsec = 1000 * ((long) (tv0->tv_usec - tv1->tv_usec));
+       NORMALIZE_TIMEVAL (tv0);
+       NORMALIZE_TIMEVAL (tv1);
 
-       if (ret->tv_nsec < 0)
+       if ((tv0.tv_sec == tv1.tv_sec) && (tv0.tv_usec == tv1.tv_usec))
        {
-               assert (ret->tv_sec > 0);
+               if (delta != NULL) {
+                       delta->tv_sec  = 0;
+                       delta->tv_usec = 0;
+               }
+               return (0);
+       }
 
-               ret->tv_nsec += 1000000000;
-               ret->tv_sec  -= 1;
+       if ((tv0.tv_sec < tv1.tv_sec)
+                       || ((tv0.tv_sec == tv1.tv_sec) && (tv0.tv_usec < tv1.tv_usec)))
+       {
+               larger  = &tv1;
+               smaller = &tv0;
+               status  = -1;
+       }
+       else
+       {
+               larger  = &tv0;
+               smaller = &tv1;
+               status  = 1;
        }
 
-       return (0);
-}
+       if (delta != NULL) {
+               delta->tv_sec = larger->tv_sec - smaller->tv_sec;
+
+               if (smaller->tv_usec <= larger->tv_usec)
+                       delta->tv_usec = larger->tv_usec - smaller->tv_usec;
+               else
+               {
+                       --delta->tv_sec;
+                       delta->tv_usec = 1000000 + larger->tv_usec - smaller->tv_usec;
+               }
+       }
+
+       assert ((delta == NULL)
+                       || ((0 <= delta->tv_usec) && (delta->tv_usec < 1000000)));
+
+       return (status);
+} /* int timeval_cmp */
 
 int check_create_dir (const char *file_orig)
 {
index d372872..85db3ad 100644 (file)
@@ -160,8 +160,27 @@ int escape_slashes (char *buf, int buf_len);
 
 int strsubstitute (char *str, char c_from, char c_to);
 
-/* FIXME: `timeval_sub_timespec' needs a description */
-int timeval_sub_timespec (struct timeval *tv0, struct timeval *tv1, struct timespec *ret);
+/*
+ * NAME
+ *   timeval_cmp
+ *
+ * DESCRIPTION
+ *   Compare the two time values `tv0' and `tv1' and store the absolut value
+ *   of the difference in the time value pointed to by `delta' if it does not
+ *   equal NULL.
+ *
+ * RETURN VALUE
+ *   Returns an integer less than, equal to, or greater than zero if `tv0' is
+ *   less than, equal to, or greater than `tv1' respectively.
+ */
+int timeval_cmp (struct timeval tv0, struct timeval tv1, struct timeval *delta);
+
+/* make sure tv_usec stores less than a second */
+#define NORMALIZE_TIMEVAL(tv) \
+       do { \
+               (tv).tv_sec += (tv).tv_usec / 1000000; \
+               (tv).tv_usec = (tv).tv_usec % 1000000; \
+       } while (0)
 
 int check_create_dir (const char *file_orig);
 
index 9c9c2c1..e3da00a 100644 (file)
 
 static int fd = -1;
 
-static int multimeter_timeval_sub (struct timeval *tv1, struct timeval *tv2,
-                struct timeval *res)
-{
-        if ((tv1->tv_sec < tv2->tv_sec) ||
-           ((tv1->tv_sec == tv2->tv_sec) && (tv1->tv_usec < tv2->tv_usec)))
-               return (-1);
-
-        res->tv_sec  = tv1->tv_sec  - tv2->tv_sec;
-        res->tv_usec = tv1->tv_usec - tv2->tv_usec;
-
-        assert ((res->tv_sec > 0) || ((res->tv_sec == 0) && (res->tv_usec > 0)));
-
-        while (res->tv_usec < 0)
-        {
-               res->tv_usec += 1000000;
-                res->tv_sec--;
-        }
-       return (0);
-}
-
 #define LINE_LENGTH 14
 static int multimeter_read_value(double *value)
 {
@@ -105,7 +85,7 @@ static int multimeter_read_value(double *value)
                                                        sizeof (errbuf)));
                                return (-1);
                        }
-                       if (multimeter_timeval_sub (&time_end, &time_now, &timeout) == -1)
+                       if (timeval_cmp (time_end, time_now, &timeout) < 0)
                                break;
 
                        status = select(fd+1, &rfds, NULL, NULL, &timeout);
index 44964bb..14f06eb 100644 (file)
@@ -310,31 +310,6 @@ static void ntpd_submit (char *type, char *type_inst, double value)
        plugin_dispatch_values (&vl);
 }
 
-/* returns `tv0 - tv1' in milliseconds or 0 if `tv1 > tv0' */
-static int timeval_sub (const struct timeval *tv0, const struct timeval *tv1)
-{
-       int sec;
-       int usec;
-
-       if ((tv0->tv_sec < tv1->tv_sec)
-                       || ((tv0->tv_sec == tv1->tv_sec) && (tv0->tv_usec < tv1->tv_usec)))
-               return (0);
-
-       sec  = tv0->tv_sec  - tv1->tv_sec;
-       usec = tv0->tv_usec - tv1->tv_usec;
-
-       while (usec < 0)
-       {
-               usec += 1000000;
-               sec  -= 1;
-       }
-
-       if (sec < 0)
-               return (0);
-
-       return ((sec * 1000) + ((usec + 500) / 1000));
-}
-
 static int ntpd_connect (void)
 {
        char *host;
@@ -459,6 +434,8 @@ static int ntpd_receive_response (int *res_items, int *res_size,
        done = 0;
        while (done == 0)
        {
+               struct timeval time_left;
+
                if (gettimeofday (&time_now, NULL) < 0)
                {
                        char errbuf[1024];
@@ -467,8 +444,14 @@ static int ntpd_receive_response (int *res_items, int *res_size,
                        return (-1);
                }
 
+               if (timeval_cmp (time_end, time_now, &time_left) <= 0)
+                       timeout = 0;
+               else
+                       timeout = 1000 * time_left.tv_sec
+                               + ((time_left.tv_usec + 500) / 1000);
+
                /* timeout reached */
-               if ((timeout = timeval_sub (&time_end, &time_now)) == 0)
+               if (timeout <= 0)
                        break;
 
                poll_s.fd      = sd;
index 3265561..95bde69 100644 (file)
@@ -308,10 +308,9 @@ static void *rrd_queue_thread (void *data)
                     break;
 
                   gettimeofday (&tv_now, /* timezone = */ NULL);
-                  status = timeval_sub_timespec (&tv_next_update, &tv_now,
-                      &ts_wait);
+                  status = timeval_cmp (tv_next_update, tv_now, NULL);
                   /* We're good to go */
-                  if (status != 0)
+                  if (status <= 0)
                     break;
 
                   /* We're supposed to wait a bit with this update, so we'll