src/graph_list.[ch]: Use the data provider to read a list of files.
[collection4.git] / src / graph_list.c
index 7327683..a0f0f29 100644 (file)
@@ -75,6 +75,9 @@ static size_t host_list_len = 0;
 
 static time_t gl_last_update = 0;
 
+/* TODO: Turn this into an array for multiple data providers. */
+static data_provider_t *data_provider = NULL;
+
 /*
  * Private functions
  */
@@ -209,6 +212,14 @@ static int gl_register_file (const graph_ident_t *file, /* {{{ */
   return (0);
 } /* }}} int gl_register_file */
 
+static int gl_register_ident (const 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 +266,43 @@ 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 = */ "  " };
   struct flock lock;
+  struct stat statbuf;
   int status;
   size_t i;
 
+  memset (&statbuf, 0, sizeof (statbuf));
+  status = stat (CACHE_FILE, &statbuf);
+  if (status == 0)
+  {
+    if (statbuf.st_mtime >= gl_last_update)
+    {
+      fprintf (stderr, "gl_update_cache: Not writing to cache because it's "
+          "at least as new as our internal data\n");
+      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 +320,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 +333,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 +349,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
@@ -647,15 +681,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 +715,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 +729,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 +748,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 +786,23 @@ 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_register_data_provider (const char *name, data_provider_t *p) /* {{{ */
+{
+  fprintf (stderr, "gl_register_data_provider (name = %s, ptr = %p)\n",
+      name, (void *) p);
+
+  if (data_provider == NULL)
+    data_provider = malloc (sizeof (*data_provider));
+  if (data_provider == NULL)
+    return (ENOMEM);
+
+  *data_provider = *p;
+
+  return (0);
+} /* }}} int gl_register_data_provider */
+
+int gl_graph_get_all (_Bool include_dynamic, /* {{{ */
+    graph_callback_t callback, void *user_data)
 {
   size_t i;
 
@@ -753,6 +820,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 +1085,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 +1100,41 @@ 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);
+    if (data_provider == NULL)
+    {
+      fprintf (stderr, "No data provider has been registered\n");
+      return (ENOENT);
+    }
+
+    /* Clear state */
+    gl_clear_instances ();
+    gl_clear_hosts ();
+    gl_destroy (&gl_dynamic, &gl_dynamic_num);
+
+    /* TODO: Iterate over all data providers */
+    data_provider->get_idents (data_provider->private_data,
+        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 */