Hostinfo day 4: Implement command processing code.
[virt-hostinfo.git] / hostinfod / main.c
index 17da054..fa835bb 100644 (file)
@@ -27,6 +27,7 @@
 #include <dirent.h>
 #include <time.h>
 #include <sys/types.h>
+#include <sys/time.h>
 #include <sys/stat.h>
 #include <sys/socket.h>
 #include <sys/un.h>
@@ -514,6 +515,22 @@ guest_force_close (struct guest_description *hval)
   guest_removed (hval);
 }
 
+/* Difference between two timespec structures (r = a - b) */
+static struct timespec *
+diff_timespec (struct timespec *r,
+              const struct timespec *a, const struct timespec *b)
+{
+  if (a->tv_nsec - b->tv_nsec < 0) {
+    r->tv_sec = a->tv_sec - b->tv_sec - 1;
+    r->tv_nsec = 1000000000 + a->tv_nsec - b->tv_nsec;
+  } else {
+    r->tv_sec = a->tv_sec - b->tv_sec;
+    r->tv_nsec = a->tv_nsec - b->tv_nsec;
+  }
+
+  return r;
+}
+
 /* This is called when there is some event from the guest, eg.
  * connection finished, read, write or closed.
  */
@@ -524,9 +541,16 @@ guest_event (const apr_pollfd_t *pollfd, void *hvalv)
   int err, max, r, extra;
   socklen_t len;
   char *p;
-  time_t now;
-
-  time (&now);
+  struct timespec now;
+
+#ifdef HAVE_CLOCK_GETTIME
+  clock_gettime (CLOCK_MONOTONIC, &now);
+#else
+  struct timeval tv;
+  gettimeofday (&tv, NULL);
+  now.tv_sec = tv.tv_sec;
+  now.tv_nsec = tv.tv_usec * 1000;
+#endif
 
   /* If the guest keeps doing bad stuff, eventually lose patience with it. */
   if (hval->penalty >= 100) {
@@ -537,9 +561,15 @@ guest_event (const apr_pollfd_t *pollfd, void *hvalv)
   }
 
   /* Decrement the penalty once a minute, so the guest can recover. */
-  if (hval->penalty > 0 && now - hval->last_penalty_decr >= 60) {
-    hval->penalty--;
-    hval->last_penalty_decr = now;
+  if (hval->penalty > 0) {
+    struct timespec diff;
+
+    diff_timespec (&diff, &now, &hval->last_penalty_decr);
+
+    if (diff.tv_sec >= 60) {
+      hval->penalty--;
+      hval->last_penalty_decr = now;
+    }
   }
 
   switch (hval->state) {
@@ -621,7 +651,7 @@ guest_event (const apr_pollfd_t *pollfd, void *hvalv)
 
     *(p+1) = '\0';
 
-    execute_command (now, hval, hval->request);
+    execute_command (&now, hval, hval->request);
 
     hval->request_posn = 0;
     break;