9 #include <fcgi_stdio.h>
11 #include "graph_list.h"
13 #include "utils_params.h"
18 #define UPDATE_INTERVAL 10
20 #define ANY_TOKEN "/any/"
21 #define ALL_TOKEN "/all/"
26 struct graph_ident_s /* {{{ */
30 char *plugin_instance;
33 }; /* }}} struct graph_ident_s */
35 struct graph_instance_s /* {{{ */
42 graph_instance_t *next;
43 }; /* }}} struct graph_instance_s */
45 struct graph_config_s /* {{{ */
52 graph_instance_t *instances;
55 }; /* }}} struct graph_config_s */
60 static graph_config_t *graph_config_head = NULL;
62 static graph_ident_t *graph_list = NULL;
63 static size_t graph_list_length = 0;
64 static time_t gl_last_update = 0;
69 /* FIXME: These "print_*" functions are used for debugging. They should be
70 * removed at some point. */
71 static int print_files (const graph_instance_t *inst) /* {{{ */
75 for (i = 0; i < inst->files_num; i++)
77 graph_ident_t *file = inst->files + i;
79 printf (" File \"%s/%s-%s/%s-%s\"\n",
81 file->plugin, file->plugin_instance,
82 file->type, file->type_instance);
86 } /* }}} int print_instances */
88 static int print_instances (const graph_config_t *cfg) /* {{{ */
90 graph_instance_t *inst;
92 for (inst = cfg->instances; inst != NULL; inst = inst->next)
94 printf (" Instance \"%s/%s-%s/%s-%s\"\n",
96 inst->select.plugin, inst->select.plugin_instance,
97 inst->select.type, inst->select.type_instance);
103 } /* }}} int print_instances */
105 static int print_graphs (void) /* {{{ */
109 for (cfg = graph_config_head; cfg != NULL; cfg = cfg->next)
111 printf ("Graph \"%s/%s-%s/%s-%s\"\n",
113 cfg->select.plugin, cfg->select.plugin_instance,
114 cfg->select.type, cfg->select.type_instance);
116 print_instances (cfg);
120 } /* }}} int print_graphs */
122 /* "Safe" version of strcmp(3): Either or both pointers may be NULL. */
123 static int strcmp_s (const char *s1, const char *s2) /* {{{ */
125 if ((s1 == NULL) && (s2 == NULL))
131 assert ((s1 != NULL) && (s2 != NULL));
133 return (strcmp (s1, s2));
134 } /* }}} int strcmp_s */
136 static _Bool part_matches (const char *sel, const char *val) /* {{{ */
138 if ((sel == NULL) && (val == NULL))
141 if (sel == NULL) /* && (val != NULL) */
144 if ((strcasecmp (ALL_TOKEN, sel) == 0)
145 || (strcasecmp (ANY_TOKEN, sel) == 0))
148 if (val == NULL) /* && (sel != NULL) */
151 if (strcmp (sel, val) == 0)
155 } /* }}} _Bool part_matches */
157 static _Bool file_matches (const graph_ident_t *sel, /* {{{ */
158 const graph_ident_t *val)
160 if ((sel == NULL) && (val == NULL))
162 else if (sel == NULL)
164 else if (val == NULL)
167 if (!part_matches (sel->host, val->host))
170 if (!part_matches (sel->plugin, val->plugin))
173 if (!part_matches (sel->plugin_instance, val->plugin_instance))
176 if (!part_matches (sel->type, val->type))
179 if (!part_matches (sel->type_instance, val->type_instance))
183 } /* }}} _Bool ident_compare */
186 * Copy part of an identifier. If the "template" value is ANY_TOKEN, "value" is
187 * copied and returned. This function is used when creating graph_instance_t
188 * from graph_config_t.
190 static char *identifier_copy_part (const char *template, const char *value) /* {{{ */
192 if (template == NULL)
196 else if (strcasecmp (ANY_TOKEN, template) == 0)
198 /* ANY in the graph selection => concrete value in the instance. */
202 return (strdup (value));
204 else if (strcasecmp (ALL_TOKEN, template) == 0)
206 /* ALL in the graph selection => ALL in the instance. */
207 return (strdup (ALL_TOKEN));
211 assert (value != NULL);
212 assert (strcmp (template, value) == 0);
213 return (strdup (template));
215 } /* }}} int identifier_copy_part */
217 static graph_instance_t *instance_create (graph_config_t *cfg, /* {{{ */
218 const graph_ident_t *file)
222 if ((cfg == NULL) || (file == NULL))
225 i = malloc (sizeof (*i));
228 memset (i, 0, sizeof (*i));
230 i->select.host = identifier_copy_part (cfg->select.host, file->host);
231 i->select.plugin = identifier_copy_part (cfg->select.plugin, file->plugin);
232 i->select.plugin_instance = identifier_copy_part (cfg->select.plugin_instance,
233 file->plugin_instance);
234 i->select.type = identifier_copy_part (cfg->select.type, file->type);
235 i->select.type_instance = identifier_copy_part (cfg->select.type_instance,
236 file->type_instance);
243 if (cfg->instances == NULL)
247 graph_instance_t *last;
249 last = cfg->instances;
250 while (last->next != NULL)
257 } /* }}} graph_instance_t *instance_create */
259 static int instance_add_file (graph_instance_t *inst, /* {{{ */
260 const graph_ident_t *file)
264 tmp = realloc (inst->files, sizeof (*inst->files) * (inst->files_num + 1));
268 tmp = inst->files + inst->files_num;
270 memset (tmp, 0, sizeof (*tmp));
271 tmp->host = strdup (file->host);
272 tmp->plugin = strdup (file->plugin);
273 if (file->plugin_instance != NULL)
274 tmp->plugin_instance = strdup (file->plugin_instance);
276 tmp->plugin_instance = NULL;
277 tmp->type = strdup (file->type);
278 if (file->type_instance != NULL)
279 tmp->type_instance = strdup (file->type_instance);
281 tmp->type_instance = NULL;
286 } /* }}} int instance_add_file */
288 static graph_instance_t *graph_find_instance (graph_config_t *cfg, /* {{{ */
289 const graph_ident_t *file)
293 if ((cfg == NULL) || (file == NULL))
296 for (i = cfg->instances; i != NULL; i = i->next)
297 if (file_matches (&i->select, file))
301 } /* }}} graph_instance_t *graph_find_instance */
303 static int graph_add_file (graph_config_t *cfg, const graph_ident_t *file) /* {{{ */
305 graph_instance_t *inst;
307 inst = graph_find_instance (cfg, file);
310 inst = instance_create (cfg, file);
315 return (instance_add_file (inst, file));
316 } /* }}} int graph_add_file */
318 static int graph_append (graph_config_t *cfg) /* {{{ */
320 graph_config_t *last;
325 if (graph_config_head == NULL)
327 graph_config_head = cfg;
331 last = graph_config_head;
332 while (last->next != NULL)
338 } /* }}} int graph_append */
340 static int graph_create_from_file (const graph_ident_t *file) /* {{{ */
344 cfg = malloc (sizeof (*cfg));
347 memset (cfg, 0, sizeof (*cfg));
349 cfg->select.host = strdup (file->host);
350 cfg->select.plugin = strdup (file->plugin);
351 cfg->select.plugin_instance = strdup (file->plugin_instance);
352 cfg->select.type = strdup (file->type);
353 cfg->select.type_instance = strdup (file->type_instance);
356 cfg->vertical_label = NULL;
357 cfg->instances = NULL;
362 return (graph_add_file (cfg, file));
363 } /* }}} int graph_create_from_file */
365 static int register_file (const graph_ident_t *file) /* {{{ */
370 for (cfg = graph_config_head; cfg != NULL; cfg = cfg->next)
374 if (!file_matches (&cfg->select, file))
377 status = graph_add_file (cfg, file);
389 graph_create_from_file (file);
392 } /* }}} int register_file */
394 static int FIXME_graph_create_from_file (const graph_ident_t *file) /* {{{ */
398 cfg = malloc (sizeof (*cfg));
401 memset (cfg, 0, sizeof (*cfg));
403 cfg->select.host = strdup (file->host);
404 cfg->select.plugin = strdup (file->plugin);
405 cfg->select.plugin_instance = strdup (file->plugin_instance);
406 cfg->select.type = strdup (file->type);
407 cfg->select.type_instance = strdup (file->type_instance);
410 cfg->vertical_label = NULL;
411 cfg->instances = NULL;
417 } /* }}} int FIXME_graph_create_from_file */
419 /* FIXME: Actually read the config file here. */
420 static int read_graph_config (void) /* {{{ */
422 if (graph_config_head != NULL)
428 ident.host = ANY_TOKEN;
429 ident.plugin = "cpu";
430 ident.plugin_instance = ANY_TOKEN;
432 ident.type_instance = ALL_TOKEN;
433 FIXME_graph_create_from_file (&ident);
435 ident.plugin = "memory";
436 ident.plugin_instance = "";
437 ident.type = "memory";
438 FIXME_graph_create_from_file (&ident);
440 ident.plugin = "swap";
441 ident.plugin_instance = "";
443 FIXME_graph_create_from_file (&ident);
445 ident.plugin = ANY_TOKEN;
446 ident.plugin_instance = ANY_TOKEN;
447 ident.type = "ps_state";
448 FIXME_graph_create_from_file (&ident);
450 ident.host = ALL_TOKEN;
451 ident.plugin = "cpu";
452 ident.plugin_instance = ALL_TOKEN;
454 ident.type_instance = "idle";
455 FIXME_graph_create_from_file (&ident);
458 } /* }}} int read_graph_config */
462 static int gl_compare (const void *p0, const void *p1) /* {{{ */
464 const graph_ident_t *gl0 = p0;
465 const graph_ident_t *gl1 = p1;
468 status = strcmp (gl0->host, gl1->host);
472 status = strcmp (gl0->plugin, gl1->plugin);
476 status = strcmp_s (gl0->plugin_instance, gl1->plugin_instance);
480 status = strcmp (gl0->type, gl1->type);
484 return (strcmp_s (gl0->type_instance, gl1->type_instance));
485 } /* }}} int gl_compare */
487 static void gl_clear_entry (graph_ident_t *gl) /* {{{ */
494 free (gl->plugin_instance);
496 free (gl->type_instance);
500 gl->plugin_instance = NULL;
502 gl->type_instance = NULL;
503 } /* }}} void gl_clear_entry */
505 static void gl_clear (void) /* {{{ */
509 for (i = 0; i < graph_list_length; i++)
510 gl_clear_entry (graph_list + i);
514 graph_list_length = 0;
516 } /* }}} void gl_clear */
518 static int gl_add_copy (graph_ident_t *gl) /* {{{ */
526 ptr = realloc (graph_list, sizeof (*graph_list) * (graph_list_length + 1));
531 ptr = graph_list + graph_list_length;
532 memset (ptr, 0, sizeof (*ptr));
535 ptr->plugin_instance = NULL;
537 ptr->type_instance = NULL;
539 #define DUP_OR_BREAK(member) do { \
540 ptr->member = NULL; \
541 if (gl->member != NULL) \
543 ptr->member = strdup (gl->member); \
544 if (ptr->member == NULL) \
553 DUP_OR_BREAK(plugin);
554 DUP_OR_BREAK(plugin_instance);
556 DUP_OR_BREAK(type_instance);
567 free (ptr->plugin_instance);
569 free (ptr->type_instance);
575 } /* }}} int gl_add_copy */
577 static int callback_type (const char *type, void *user_data) /* {{{ */
582 if ((type == NULL) || (user_data == NULL))
586 if ((gl->type != NULL) || (gl->type_instance != NULL))
589 gl->type = strdup (type);
590 if (gl->type == NULL)
593 gl->type_instance = strchr (gl->type, '-');
594 if (gl->type_instance != NULL)
596 *gl->type_instance = 0;
601 gl->type_instance = gl->type + strlen (gl->type);
606 status = gl_add_copy (gl);
610 gl->type_instance = NULL;
613 } /* }}} int callback_type */
615 static int callback_plugin (const char *plugin, void *user_data) /* {{{ */
620 if ((plugin == NULL) || (user_data == NULL))
624 if ((gl->plugin != NULL) || (gl->plugin_instance != NULL))
627 gl->plugin = strdup (plugin);
628 if (gl->plugin == NULL)
631 gl->plugin_instance = strchr (gl->plugin, '-');
632 if (gl->plugin_instance != NULL)
634 *gl->plugin_instance = 0;
635 gl->plugin_instance++;
639 gl->plugin_instance = gl->plugin + strlen (gl->plugin);
642 status = foreach_type (gl->host, plugin, callback_type, gl);
646 gl->plugin_instance = NULL;
649 } /* }}} int callback_plugin */
651 static int callback_host (const char *host, void *user_data) /* {{{ */
656 if ((host == NULL) || (user_data == NULL))
660 if (gl->host != NULL)
663 gl->host = strdup (host);
664 if (gl->host == NULL)
667 status = foreach_plugin (host, callback_plugin, gl);
673 } /* }}} int callback_host */
675 static const char *get_part_from_param (const char *prim_key, /* {{{ */
680 val = param (prim_key);
684 return (param (sec_key));
685 } /* }}} const char *get_part_from_param */
690 int gl_instance_get_params (graph_config_t *cfg, graph_instance_t *inst, /* {{{ */
691 char *buffer, size_t buffer_size)
693 if ((inst == NULL) || (buffer == NULL) || (buffer_size < 1))
698 #define COPY_FIELD(field) do { \
699 if (strcmp (cfg->select.field, inst->select.field) == 0) \
701 strlcat (buffer, #field, buffer_size); \
702 strlcat (buffer, "=", buffer_size); \
703 strlcat (buffer, cfg->select.field, buffer_size); \
707 strlcat (buffer, "graph_", buffer_size); \
708 strlcat (buffer, #field, buffer_size); \
709 strlcat (buffer, "=", buffer_size); \
710 strlcat (buffer, cfg->select.field, buffer_size); \
711 strlcat (buffer, ";", buffer_size); \
712 strlcat (buffer, "inst_", buffer_size); \
713 strlcat (buffer, #field, buffer_size); \
714 strlcat (buffer, "=", buffer_size); \
715 strlcat (buffer, inst->select.field, buffer_size); \
720 strlcat (buffer, ";", buffer_size);
722 strlcat (buffer, ";", buffer_size);
723 COPY_FIELD(plugin_instance);
724 strlcat (buffer, ";", buffer_size);
726 strlcat (buffer, ";", buffer_size);
727 COPY_FIELD(type_instance);
732 } /* }}} int gl_instance_get_params */
734 graph_instance_t *inst_get_selected (graph_config_t *cfg) /* {{{ */
736 const char *host = get_part_from_param ("inst_host", "host");
737 const char *plugin = get_part_from_param ("inst_plugin", "plugin");
738 const char *plugin_instance = get_part_from_param ("inst_plugin_instance", "plugin_instance");
739 const char *type = get_part_from_param ("inst_type", "type");
740 const char *type_instance = get_part_from_param ("inst_type_instance", "type_instance");
741 graph_instance_t *inst;
744 cfg = graph_get_selected ();
750 || (plugin == NULL) || (plugin_instance == NULL)
751 || (type == NULL) || (type_instance == NULL))
754 for (inst = cfg->instances; inst != NULL; inst = inst->next)
756 if ((strcmp (inst->select.host, host) != 0)
757 || (strcmp (inst->select.plugin, plugin) != 0)
758 || (strcmp (inst->select.plugin_instance, plugin_instance) != 0)
759 || (strcmp (inst->select.type, type) != 0)
760 || (strcmp (inst->select.type_instance, type_instance) != 0))
767 } /* }}} graph_instance_t *inst_get_selected */
769 int gl_graph_get_all (gl_cfg_callback callback, /* {{{ */
774 if (callback == NULL)
777 for (cfg = graph_config_head; cfg != NULL; cfg = cfg->next)
781 status = (*callback) (cfg, user_data);
787 } /* }}} int gl_graph_get_all */
789 graph_config_t *graph_get_selected (void) /* {{{ */
791 const char *host = get_part_from_param ("graph_host", "host");
792 const char *plugin = get_part_from_param ("graph_plugin", "plugin");
793 const char *plugin_instance = get_part_from_param ("graph_plugin_instance", "plugin_instance");
794 const char *type = get_part_from_param ("graph_type", "type");
795 const char *type_instance = get_part_from_param ("graph_type_instance", "type_instance");
799 || (plugin == NULL) || (plugin_instance == NULL)
800 || (type == NULL) || (type_instance == NULL))
803 for (cfg = graph_config_head; cfg != NULL; cfg = cfg->next)
805 if ((strcmp (cfg->select.host, host) != 0)
806 || (strcmp (cfg->select.plugin, plugin) != 0)
807 || (strcmp (cfg->select.plugin_instance, plugin_instance) != 0)
808 || (strcmp (cfg->select.type, type) != 0)
809 || (strcmp (cfg->select.type_instance, type_instance) != 0))
816 } /* }}} graph_config_t *graph_get_selected */
818 int gl_graph_instance_get_all (graph_config_t *cfg, /* {{{ */
819 gl_inst_callback callback, void *user_data)
821 graph_instance_t *inst;
823 if ((cfg == NULL) || (callback == NULL))
826 for (inst = cfg->instances; inst != NULL; inst = inst->next)
830 status = (*callback) (cfg, inst, user_data);
836 } /* }}} int gl_graph_instance_get_all */
838 int gl_graph_get_title (graph_config_t *cfg, /* {{{ */
839 char *buffer, size_t buffer_size)
841 if ((cfg == NULL) || (buffer == NULL) || (buffer_size < 1))
845 strlcat (buffer, cfg->select.host, buffer_size);
846 strlcat (buffer, "/", buffer_size);
847 strlcat (buffer, cfg->select.plugin, buffer_size);
848 if (cfg->select.plugin_instance[0] != 0)
850 strlcat (buffer, "-", buffer_size);
851 strlcat (buffer, cfg->select.plugin_instance, buffer_size);
853 strlcat (buffer, "/", buffer_size);
854 strlcat (buffer, cfg->select.type, buffer_size);
855 if (cfg->select.type_instance[0] != 0)
857 strlcat (buffer, "-", buffer_size);
858 strlcat (buffer, cfg->select.type_instance, buffer_size);
862 } /* }}} int gl_graph_get_title */
864 int gl_instance_get_all (gl_inst_callback callback, /* {{{ */
869 for (cfg = graph_config_head; cfg != NULL; cfg = cfg->next)
871 graph_instance_t *inst;
873 for (inst = cfg->instances; inst != NULL; inst = inst->next)
877 status = (*callback) (cfg, inst, user_data);
884 } /* }}} int gl_instance_get_all */
886 int gl_update (void) /* {{{ */
893 printf ("Content-Type: text/plain\n\n");
896 read_graph_config ();
900 if ((gl_last_update + UPDATE_INTERVAL) >= now)
905 memset (&gl, 0, sizeof (gl));
908 gl.plugin_instance = NULL;
910 gl.type_instance = NULL;
912 status = foreach_host (callback_host, &gl);
914 /* print_graphs (); */
916 if (graph_list_length > 1)
917 qsort (graph_list, graph_list_length, sizeof (*graph_list), gl_compare);
920 } /* }}} int gl_update */
922 int gl_foreach (gl_callback callback, void *user_data) /* {{{ */
926 for (i = 0; i < graph_list_length; i++)
930 status = (*callback) ((void *) (graph_list + i), user_data);
936 } /* }}} int gl_foreach */
938 /* vim: set sw=2 sts=2 et fdm=marker : */