10 #include "graph_list.h"
11 #include "graph_ident.h"
12 #include "graph_def.h"
13 #include "graph_config.h"
15 #include "filesystem.h"
16 #include "utils_params.h"
19 #include <fcgi_stdio.h>
24 #define UPDATE_INTERVAL 10
26 #define ANY_TOKEN "/any/"
27 #define ALL_TOKEN "/all/"
32 struct gl_ident_stage_s /* {{{ */
36 char *plugin_instance;
40 typedef struct gl_ident_stage_s gl_ident_stage_t;
42 struct graph_config_s /* {{{ */
44 graph_ident_t *select;
51 graph_instance_t *instances;
54 }; /* }}} struct graph_config_s */
59 static graph_config_t *graph_config_head = NULL;
60 static graph_config_t *graph_config_staging = NULL;
62 static time_t gl_last_update = 0;
68 /* "Safe" version of strcmp(3): Either or both pointers may be NULL. */
69 static int strcmp_s (const char *s1, const char *s2) /* {{{ */
71 if ((s1 == NULL) && (s2 == NULL))
77 assert ((s1 != NULL) && (s2 != NULL));
79 return (strcmp (s1, s2));
80 } /* }}} int strcmp_s */
84 * Copy part of an identifier. If the "template" value is ANY_TOKEN, "value" is
85 * copied and returned. This function is used when creating graph_instance_t
86 * from graph_config_t.
89 static graph_instance_t *graph_find_instance (graph_config_t *cfg, /* {{{ */
90 const graph_ident_t *ident)
92 if ((cfg == NULL) || (ident == NULL))
95 return (inst_find_matching (cfg->instances, ident));
96 } /* }}} graph_instance_t *graph_find_instance */
98 static int graph_add_file (graph_config_t *cfg, const graph_ident_t *file) /* {{{ */
100 graph_instance_t *inst;
102 inst = graph_find_instance (cfg, file);
105 inst = inst_create (cfg, file);
109 if (cfg->instances == NULL)
110 cfg->instances = inst;
112 inst_append (cfg->instances, inst);
115 return (inst_add_file (inst, file));
116 } /* }}} int graph_add_file */
118 static int graph_append (graph_config_t **head, /* {{{ */
121 graph_config_t *last;
127 head = &graph_config_head;
136 while (last->next != NULL)
142 } /* }}} int graph_append */
144 static graph_config_t *graph_create (const graph_ident_t *selector) /* {{{ */
148 cfg = malloc (sizeof (*cfg));
151 memset (cfg, 0, sizeof (*cfg));
153 if (selector != NULL)
154 cfg->select = ident_clone (selector);
159 cfg->vertical_label = NULL;
161 cfg->instances = NULL;
165 } /* }}} int graph_create */
167 static void graph_destroy (graph_config_t *cfg) /* {{{ */
169 graph_config_t *next;
176 ident_destroy (cfg->select);
179 free (cfg->vertical_label);
181 def_destroy (cfg->defs);
182 inst_destroy (cfg->instances);
184 graph_destroy (next);
185 } /* }}} void graph_destroy */
187 static int gl_register_file (const graph_ident_t *file, /* {{{ */
188 __attribute__((unused)) void *user_data)
193 for (cfg = graph_config_head; cfg != NULL; cfg = cfg->next)
197 if (!ident_matches (cfg->select, file))
200 status = graph_add_file (cfg, file);
213 cfg = graph_create (file);
214 graph_append (/* head = */ NULL, cfg);
215 graph_add_file (cfg, file);
219 } /* }}} int gl_register_file */
221 static const char *get_part_from_param (const char *prim_key, /* {{{ */
226 val = param (prim_key);
230 return (param (sec_key));
231 } /* }}} const char *get_part_from_param */
233 static int gl_clear_instances (void) /* {{{ */
237 for (cfg = graph_config_head; cfg != NULL; cfg = cfg->next)
239 inst_destroy (cfg->instances);
240 cfg->instances = NULL;
244 } /* }}} int gl_clear_instances */
250 static graph_ident_t *graph_config_get_selector (const oconfig_item_t *ci) /* {{{ */
254 char *plugin_instance = NULL;
256 char *type_instance = NULL;
260 for (i = 0; i < ci->children_num; i++)
262 oconfig_item_t *child;
264 child = ci->children + i;
266 if (strcasecmp ("Host", child->key) == 0)
267 graph_config_get_string (child, &host);
268 else if (strcasecmp ("Plugin", child->key) == 0)
269 graph_config_get_string (child, &plugin);
270 else if (strcasecmp ("PluginInstance", child->key) == 0)
271 graph_config_get_string (child, &plugin_instance);
272 else if (strcasecmp ("Type", child->key) == 0)
273 graph_config_get_string (child, &type);
274 else if (strcasecmp ("TypeInstance", child->key) == 0)
275 graph_config_get_string (child, &type_instance);
276 /* else: ignore all other directives here. */
279 ret = ident_create (host, plugin, plugin_instance, type, type_instance);
283 free (plugin_instance);
285 free (type_instance);
288 } /* }}} int graph_config_get_selector */
293 int graph_config_add (const oconfig_item_t *ci) /* {{{ */
295 graph_ident_t *select;
296 graph_config_t *cfg = NULL;
299 select = graph_config_get_selector (ci);
303 cfg = graph_create (/* selector = */ NULL);
307 cfg->select = select;
309 for (i = 0; i < ci->children_num; i++)
311 oconfig_item_t *child;
313 child = ci->children + i;
315 if (strcasecmp ("Title", child->key) == 0)
316 graph_config_get_string (child, &cfg->title);
317 else if (strcasecmp ("VerticalLabel", child->key) == 0)
318 graph_config_get_string (child, &cfg->vertical_label);
319 else if (strcasecmp ("DEF", child->key) == 0)
320 def_config (cfg, child);
323 graph_append (&graph_config_staging, cfg);
326 } /* }}} graph_config_add */
328 int graph_config_submit (void) /* {{{ */
332 tmp = graph_config_head;
333 graph_config_head = graph_config_staging;
334 graph_config_staging = NULL;
339 } /* }}} int graph_config_submit */
341 int gl_graph_get_all (gl_cfg_callback callback, /* {{{ */
346 if (callback == NULL)
351 for (cfg = graph_config_head; cfg != NULL; cfg = cfg->next)
355 status = (*callback) (cfg, user_data);
361 } /* }}} int gl_graph_get_all */
363 graph_config_t *graph_get_selected (void) /* {{{ */
365 const char *host = get_part_from_param ("graph_host", "host");
366 const char *plugin = get_part_from_param ("graph_plugin", "plugin");
367 const char *plugin_instance = get_part_from_param ("graph_plugin_instance", "plugin_instance");
368 const char *type = get_part_from_param ("graph_type", "type");
369 const char *type_instance = get_part_from_param ("graph_type_instance", "type_instance");
370 graph_ident_t *ident;
374 || (plugin == NULL) || (plugin_instance == NULL)
375 || (type == NULL) || (type_instance == NULL))
378 ident = ident_create (host, plugin, plugin_instance, type, type_instance);
382 for (cfg = graph_config_head; cfg != NULL; cfg = cfg->next)
384 if (ident_compare (ident, cfg->select) != 0)
387 ident_destroy (ident);
391 ident_destroy (ident);
393 } /* }}} graph_config_t *graph_get_selected */
395 /* gl_instance_get_all, gl_graph_instance_get_all {{{ */
396 struct gl_inst_callback_data /* {{{ */
399 gl_inst_callback callback;
401 }; /* }}} struct gl_inst_callback_data */
403 static int gl_inst_callback_handler (graph_instance_t *inst, /* {{{ */
406 struct gl_inst_callback_data *data = user_data;
408 return ((*data->callback) (data->cfg, inst, data->user_data));
409 } /* }}} int gl_inst_callback_handler */
411 int gl_graph_instance_get_all (graph_config_t *cfg, /* {{{ */
412 gl_inst_callback callback, void *user_data)
414 struct gl_inst_callback_data data =
421 if ((cfg == NULL) || (callback == NULL))
424 return (inst_foreach (cfg->instances, gl_inst_callback_handler, &data));
425 } /* }}} int gl_graph_instance_get_all */
427 int gl_instance_get_all (gl_inst_callback callback, /* {{{ */
434 for (cfg = graph_config_head; cfg != NULL; cfg = cfg->next)
438 status = gl_graph_instance_get_all (cfg, callback, user_data);
444 } /* }}} int gl_instance_get_all */
445 /* }}} gl_instance_get_all, gl_graph_instance_get_all */
447 int gl_graph_get_title (graph_config_t *cfg, /* {{{ */
448 char *buffer, size_t buffer_size)
450 if ((cfg == NULL) || (buffer == NULL) || (buffer_size < 1))
453 if (cfg->title == NULL)
454 cfg->title = ident_to_string (cfg->select);
456 if (cfg->title == NULL)
459 strncpy (buffer, cfg->title, buffer_size);
460 buffer[buffer_size - 1] = 0;
463 } /* }}} int gl_graph_get_title */
465 graph_ident_t *gl_graph_get_selector (graph_config_t *cfg) /* {{{ */
470 return (ident_clone (cfg->select));
471 } /* }}} graph_ident_t *gl_graph_get_selector */
473 graph_instance_t *gl_graph_get_instances (graph_config_t *cfg) /* {{{ */
478 return (cfg->instances);
479 } /* }}} graph_instance_t *gl_graph_get_instances */
481 graph_def_t *gl_graph_get_defs (graph_config_t *cfg) /* {{{ */
487 } /* }}} graph_def_t *gl_graph_get_defs */
489 int gl_graph_add_def (graph_config_t *cfg, graph_def_t *def) /* {{{ */
491 if ((cfg == NULL) || (def == NULL))
494 if (cfg->defs == NULL)
500 return (def_append (cfg->defs, def));
501 } /* }}} int gl_graph_add_def */
503 int gl_update (void) /* {{{ */
510 printf ("Content-Type: text/plain\n\n");
515 if ((gl_last_update + UPDATE_INTERVAL) >= now)
518 graph_read_config ();
520 memset (&gl, 0, sizeof (gl));
523 gl.plugin_instance = NULL;
525 gl.type_instance = NULL;
527 gl_clear_instances ();
528 status = fs_scan (/* callback = */ gl_register_file, /* user data = */ NULL);
530 gl_last_update = now;
533 } /* }}} int gl_update */
535 /* vim: set sw=2 sts=2 et fdm=marker : */