X-Git-Url: https://git.octo.it/?p=collection4.git;a=blobdiff_plain;f=src%2Fgraph_list.c;h=ecd873bae4824e90258821865e7ff12e3dc0c9e6;hp=fd0dca788e2ecef2bd53c52671a2480ffb07abb6;hb=3791b9f1f09c4c39ed96922b7f1640314805a175;hpb=06dbb6105d7df41e8a4d9a7f5898bcfa98b79fa8 diff --git a/src/graph_list.c b/src/graph_list.c index fd0dca7..ecd873b 100644 --- a/src/graph_list.c +++ b/src/graph_list.c @@ -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,20 +266,40 @@ 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; - 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)); @@ -286,7 +317,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); } @@ -299,6 +330,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++) @@ -312,13 +346,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 @@ -646,15 +678,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); } @@ -670,6 +712,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; @@ -681,10 +726,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) { @@ -699,10 +745,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 */ @@ -733,8 +783,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; @@ -752,6 +817,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; @@ -1014,7 +1082,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 (); @@ -1024,24 +1097,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 */