src/graph_list.c: cachefile → cache_file
[collection4.git] / src / graph_list.c
index 7327683..b979672 100644 (file)
@@ -38,6 +38,7 @@
 
 #include "graph_list.h"
 #include "common.h"
+#include "data_provider.h"
 #include "filesystem.h"
 #include "graph.h"
 #include "graph_config.h"
@@ -54,7 +55,6 @@
  * Defines
  */
 #define UPDATE_INTERVAL 900
-#define CACHE_FILE "/tmp/collection4.json"
 
 /*
  * Global variables
@@ -209,6 +209,14 @@ static int gl_register_file (const graph_ident_t *file, /* {{{ */
   return (0);
 } /* }}} int gl_register_file */
 
+static int gl_register_ident (graph_ident_t *ident, /* {{{ */
+    __attribute__((unused)) void *user_data)
+{
+  /* TODO: Check for duplicates if multiple data providers are used. */
+
+  return (gl_register_file (ident, user_data));
+} /* }}} int gl_register_ident */
+
 static const char *get_part_from_param (const char *prim_key, /* {{{ */
     const char *sec_key)
 {
@@ -255,21 +263,41 @@ static void gl_dump_cb (void *ctx, /* {{{ */
   }
 } /* }}} void gl_dump_cb */
 
-static int gl_dump (void) /* {{{ */
+static int gl_update_cache (void) /* {{{ */
 {
   int fd;
   yajl_gen handler;
   yajl_gen_config handler_config = { /* pretty = */ 1, /* indent = */ "  " };
+  const char *cache_file = graph_config_get_cache_file ();
   struct flock lock;
+  struct stat statbuf;
   int status;
   size_t i;
 
-  fd = open (CACHE_FILE, O_WRONLY | O_TRUNC | O_CREAT,
+  memset (&statbuf, 0, sizeof (statbuf));
+  status = stat (cache_file, &statbuf);
+  if (status == 0)
+  {
+    if (statbuf.st_mtime >= gl_last_update)
+      /* Not writing to cache because it's at least as new as our internal data */
+      return (0);
+  }
+  else
+  {
+    status = errno;
+    fprintf (stderr, "gl_update_cache: stat(2) failed with status %i\n",
+        status);
+    /* Continue writing the file if possible. */
+  }
+
+  fd = open (cache_file, O_WRONLY | O_TRUNC | O_CREAT,
       S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
   if (fd < 0)
   {
-    fprintf (stderr, "gl_dump: open(2) failed with status %i\n", errno);
-    return (errno);
+    status = errno;
+    fprintf (stderr, "gl_update_cache: open(2) failed with status %i\n",
+        status);
+    return (status);
   }
 
   memset (&lock, 0, sizeof (lock));
@@ -287,7 +315,7 @@ static int gl_dump (void) /* {{{ */
     if (errno == EINTR)
       continue;
 
-    fprintf (stderr, "gl_dump: fcntl(2) failed with status %i\n", errno);
+    fprintf (stderr, "gl_update_cache: fcntl(2) failed with status %i\n", errno);
     close (fd);
     return (errno);
   }
@@ -300,6 +328,9 @@ static int gl_dump (void) /* {{{ */
     return (-1);
   }
 
+  fprintf (stderr, "gl_update_cache: Start writing data\n");
+  fflush (stderr);
+
   yajl_gen_array_open (handler);
 
   for (i = 0; i < gl_active_num; i++)
@@ -313,13 +344,11 @@ static int gl_dump (void) /* {{{ */
   yajl_gen_free (handler);
   close (fd);
 
-  return (0);
-} /* }}} int gl_dump */
+  fprintf (stderr, "gl_update_cache: Finished writing data\n");
+  fflush (stderr);
 
-static int gl_scan_directory (void)
-{
-  return (-1);
-} /* }}} int gl_scan_directory */
+  return (0);
+} /* }}} int gl_update_cache */
 
 /*
  * JSON parsing functions
@@ -591,7 +620,7 @@ static int gl_read_cache (_Bool block) /* {{{ */
   int status;
   time_t now;
 
-  fd = open (CACHE_FILE, O_RDONLY);
+  fd = open (graph_config_get_cache_file (), O_RDONLY);
   if (fd < 0)
   {
     fprintf (stderr, "gl_read_cache: open(2) failed with status %i\n", errno);
@@ -647,15 +676,25 @@ static int gl_read_cache (_Bool block) /* {{{ */
 
   now = time (NULL);
 
-  if (statbuf.st_mtime <= gl_last_update)
+  if (block)
+  {
+    /* Read the file. No excuses. */
+  }
+  else if (statbuf.st_mtime <= gl_last_update)
   {
     /* Our current data is at least as new as the cache. Return. */
+    fprintf (stderr, "gl_read_cache: Not using cache because "
+        "the internal data is newer\n");
+    fflush (stderr);
     close (fd);
     return (0);
   }
   else if ((statbuf.st_mtime + UPDATE_INTERVAL) < now)
   {
-    /* We'll scan the directory anyway, so there is no need to parse the cache here. */
+    /* We'll scan the directory anyway, so there is no need to parse the cache
+     * here. */
+    fprintf (stderr, "gl_read_cache: Not using cache because it's too old\n");
+    fflush (stderr);
     close (fd);
     return (0);
   }
@@ -671,6 +710,9 @@ static int gl_read_cache (_Bool block) /* {{{ */
       /* alloc funcs = */ NULL,
       &context);
 
+  fprintf (stderr, "gl_read_cache: Start parsing data\n");
+  fflush (stderr);
+
   while (42)
   {
     ssize_t rd_status;
@@ -682,10 +724,11 @@ static int gl_read_cache (_Bool block) /* {{{ */
       if ((errno == EINTR) || (errno == EAGAIN))
         continue;
 
+      status = errno;
       fprintf (stderr, "gl_read_cache: read(2) failed with status %i\n",
-          errno);
+          status);
       close (fd);
-      return (errno);
+      return (status);
     }
     else if (rd_status == 0)
     {
@@ -700,10 +743,14 @@ static int gl_read_cache (_Bool block) /* {{{ */
     }
   }
 
-  fprintf (stderr, "gl_read_cache: Closing cache file and returning\n");
+  yajl_free (handle);
+
   gl_last_update = statbuf.st_mtime;
   close (fd);
 
+  fprintf (stderr, "gl_read_cache: Finished parsing data\n");
+  fflush (stderr);
+
   return (0);
 } /* }}} int gl_read_cache */
 
@@ -734,8 +781,8 @@ int gl_config_submit (void) /* {{{ */
   return (0);
 } /* }}} int graph_config_submit */
 
-int gl_graph_get_all (graph_callback_t callback, /* {{{ */
-    void *user_data)
+int gl_graph_get_all (_Bool include_dynamic, /* {{{ */
+    graph_callback_t callback, void *user_data)
 {
   size_t i;
 
@@ -753,6 +800,9 @@ int gl_graph_get_all (graph_callback_t callback, /* {{{ */
       return (status);
   }
 
+  if (!include_dynamic)
+    return (0);
+
   for (i = 0; i < gl_dynamic_num; i++)
   {
     int status;
@@ -1015,7 +1065,12 @@ int gl_update (_Bool request_served) /* {{{ */
   now = time (NULL);
 
   if ((gl_last_update + UPDATE_INTERVAL) >= now)
+  {
+    /* Write data to cache if appropriate */
+    if (request_served)
+      gl_update_cache ();
     return (0);
+  }
 
   /* Clear state */
   gl_clear_instances ();
@@ -1025,24 +1080,33 @@ int gl_update (_Bool request_served) /* {{{ */
   graph_read_config ();
 
   status = gl_read_cache (/* block = */ 1);
+  /* We have *something* to work with. Even if it's outdated, just get on with
+   * handling the request and take care of re-reading data later on. */
+  if ((status == 0) && !request_served)
+    return (0);
 
   if ((status != 0)
-      || ((gl_last_update + UPDATE_INTERVAL) >= now))
+      || ((gl_last_update + UPDATE_INTERVAL) < now))
   {
-    status = fs_scan (/* callback = */ gl_register_file,
-        /* user data = */ NULL);
+    /* Clear state */
+    gl_clear_instances ();
+    gl_clear_hosts ();
+    gl_destroy (&gl_dynamic, &gl_dynamic_num);
+
+    data_provider_get_idents (gl_register_ident, /* user data = */ NULL);
+
+    gl_last_update = now;
   }
 
   if (host_list_len > 0)
     qsort (host_list, host_list_len, sizeof (*host_list),
         gl_compare_hosts);
 
-  gl_last_update = now;
-
   for (i = 0; i < gl_active_num; i++)
     graph_sort_instances (gl_active[i]);
 
-  gl_dump ();
+  if (request_served)
+    gl_update_cache ();
 
   return (status);
 } /* }}} int gl_update */