10 #include "graph_list.h"
11 #include "graph_ident.h"
12 #include "graph_def.h"
14 #include "utils_params.h"
17 #include <fcgi_stdio.h>
22 #define UPDATE_INTERVAL 10
24 #define ANY_TOKEN "/any/"
25 #define ALL_TOKEN "/all/"
30 struct gl_ident_stage_s /* {{{ */
34 char *plugin_instance;
38 typedef struct gl_ident_stage_s gl_ident_stage_t;
40 struct graph_instance_s /* {{{ */
42 graph_ident_t *select;
44 graph_ident_t **files;
47 graph_instance_t *next;
48 }; /* }}} struct graph_instance_s */
50 struct graph_config_s /* {{{ */
52 graph_ident_t *select;
59 graph_instance_t *instances;
62 }; /* }}} struct graph_config_s */
67 static graph_config_t *graph_config_head = NULL;
69 static time_t gl_last_update = 0;
74 /* FIXME: These "print_*" functions are used for debugging. They should be
75 * removed at some point. */
76 static int print_files (const graph_instance_t *inst) /* {{{ */
80 for (i = 0; i < inst->files_num; i++)
82 graph_ident_t *ident = inst->files[i];
85 file = ident_to_file (ident);
86 printf (" File \"%s\"\n", file);
91 } /* }}} int print_instances */
93 static int print_instances (const graph_config_t *cfg) /* {{{ */
95 graph_instance_t *inst;
97 for (inst = cfg->instances; inst != NULL; inst = inst->next)
101 str = ident_to_string (inst->select);
102 printf (" Instance \"%s\"\n", str);
109 } /* }}} int print_instances */
111 static int print_graphs (void) /* {{{ */
115 for (cfg = graph_config_head; cfg != NULL; cfg = cfg->next)
119 str = ident_to_string (cfg->select);
120 printf ("Graph \"%s\"\n", str);
123 print_instances (cfg);
127 } /* }}} int print_graphs */
130 /* "Safe" version of strcmp(3): Either or both pointers may be NULL. */
131 static int strcmp_s (const char *s1, const char *s2) /* {{{ */
133 if ((s1 == NULL) && (s2 == NULL))
139 assert ((s1 != NULL) && (s2 != NULL));
141 return (strcmp (s1, s2));
142 } /* }}} int strcmp_s */
145 static void instance_destroy (graph_instance_t *inst) /* {{{ */
147 graph_instance_t *next;
155 ident_destroy (inst->select);
157 for (i = 0; i < inst->files_num; i++)
158 ident_destroy (inst->files[i]);
163 instance_destroy (next);
164 } /* }}} void instance_destroy */
167 * Copy part of an identifier. If the "template" value is ANY_TOKEN, "value" is
168 * copied and returned. This function is used when creating graph_instance_t
169 * from graph_config_t.
171 static graph_instance_t *instance_create (graph_config_t *cfg, /* {{{ */
172 const graph_ident_t *file)
176 if ((cfg == NULL) || (file == NULL))
179 i = malloc (sizeof (*i));
182 memset (i, 0, sizeof (*i));
184 i->select = ident_copy_with_selector (cfg->select, file,
185 IDENT_FLAG_REPLACE_ANY);
186 if (i->select == NULL)
188 DEBUG ("instance_create: ident_copy_with_selector returned NULL.\n");
198 if (cfg->instances == NULL)
202 graph_instance_t *last;
204 last = cfg->instances;
205 while (last->next != NULL)
212 } /* }}} graph_instance_t *instance_create */
214 static int instance_add_file (graph_instance_t *inst, /* {{{ */
215 const graph_ident_t *file)
219 tmp = realloc (inst->files, sizeof (*inst->files) * (inst->files_num + 1));
224 inst->files[inst->files_num] = ident_clone (file);
225 if (inst->files[inst->files_num] == NULL)
231 } /* }}} int instance_add_file */
233 static graph_instance_t *graph_find_instance (graph_config_t *cfg, /* {{{ */
234 const graph_ident_t *file)
238 if ((cfg == NULL) || (file == NULL))
241 for (i = cfg->instances; i != NULL; i = i->next)
242 if (ident_matches (i->select, file))
246 } /* }}} graph_instance_t *graph_find_instance */
248 static int graph_add_file (graph_config_t *cfg, const graph_ident_t *file) /* {{{ */
250 graph_instance_t *inst;
252 inst = graph_find_instance (cfg, file);
255 inst = instance_create (cfg, file);
260 return (instance_add_file (inst, file));
261 } /* }}} int graph_add_file */
263 static int graph_append (graph_config_t *cfg) /* {{{ */
265 graph_config_t *last;
270 if (graph_config_head == NULL)
272 graph_config_head = cfg;
276 last = graph_config_head;
277 while (last->next != NULL)
283 } /* }}} int graph_append */
285 static graph_config_t *graph_create (const graph_ident_t *selector) /* {{{ */
289 cfg = malloc (sizeof (*cfg));
292 memset (cfg, 0, sizeof (*cfg));
294 cfg->select = ident_clone (selector);
297 cfg->vertical_label = NULL;
299 cfg->instances = NULL;
303 } /* }}} int graph_create */
305 static void graph_destroy (graph_config_t *cfg) /* {{{ */
307 graph_config_t *next;
314 ident_destroy (cfg->select);
317 free (cfg->vertical_label);
319 def_destroy (cfg->defs);
320 instance_destroy (cfg->instances);
322 graph_destroy (next);
323 } /* }}} void graph_destroy */
325 static int register_file (const graph_ident_t *file) /* {{{ */
330 for (cfg = graph_config_head; cfg != NULL; cfg = cfg->next)
334 if (!ident_matches (cfg->select, file))
337 status = graph_add_file (cfg, file);
350 cfg = graph_create (file);
352 graph_add_file (cfg, file);
356 } /* }}} int register_file */
358 static int FIXME_graph_create_from_file (const char *host, /* {{{ */
359 const char *plugin, const char *plugin_instance,
360 const char *type, const char *type_instance,
365 cfg = malloc (sizeof (*cfg));
368 memset (cfg, 0, sizeof (*cfg));
370 cfg->select = ident_create (host, plugin, plugin_instance, type, type_instance);
374 cfg->title = strdup (title);
375 cfg->vertical_label = NULL;
376 cfg->instances = NULL;
382 } /* }}} int FIXME_graph_create_from_file */
384 /* FIXME: Actually read the config file here. */
385 static int read_graph_config (void) /* {{{ */
387 if (graph_config_head != NULL)
390 FIXME_graph_create_from_file (ANY_TOKEN, "cpu", ANY_TOKEN, "cpu", ALL_TOKEN,
391 "CPU {instance} usage");
392 FIXME_graph_create_from_file (ANY_TOKEN, "memory", "", "memory", ALL_TOKEN,
394 FIXME_graph_create_from_file (ANY_TOKEN, "swap", "", "swap", ALL_TOKEN,
396 FIXME_graph_create_from_file (ANY_TOKEN, ANY_TOKEN, ANY_TOKEN, "ps_state", ALL_TOKEN,
398 FIXME_graph_create_from_file (ANY_TOKEN, "cpu", ALL_TOKEN, "cpu", "idle",
399 "CPU idle overview");
402 } /* }}} int read_graph_config */
404 static void gl_clear (void) /* {{{ */
408 cfg = graph_config_head;
409 graph_config_head = NULL;
413 } /* }}} void gl_clear */
415 static int callback_type (const char *type, void *user_data) /* {{{ */
417 gl_ident_stage_t *gl;
418 graph_ident_t *ident;
421 if ((type == NULL) || (user_data == NULL))
425 if ((gl->type != NULL) || (gl->type_instance != NULL))
428 gl->type = strdup (type);
429 if (gl->type == NULL)
432 gl->type_instance = strchr (gl->type, '-');
433 if (gl->type_instance != NULL)
435 *gl->type_instance = 0;
440 gl->type_instance = gl->type + strlen (gl->type);
443 ident = ident_create (gl->host,
444 gl->plugin, gl->plugin_instance,
445 gl->type, gl->type_instance);
452 status = register_file (ident);
453 ident_destroy (ident);
458 gl->type_instance = NULL;
461 } /* }}} int callback_type */
463 static int callback_plugin (const char *plugin, void *user_data) /* {{{ */
465 gl_ident_stage_t *gl;
468 if ((plugin == NULL) || (user_data == NULL))
472 if ((gl->plugin != NULL) || (gl->plugin_instance != NULL))
475 gl->plugin = strdup (plugin);
476 if (gl->plugin == NULL)
479 gl->plugin_instance = strchr (gl->plugin, '-');
480 if (gl->plugin_instance != NULL)
482 *gl->plugin_instance = 0;
483 gl->plugin_instance++;
487 gl->plugin_instance = gl->plugin + strlen (gl->plugin);
490 status = foreach_type (gl->host, plugin, callback_type, gl);
494 gl->plugin_instance = NULL;
497 } /* }}} int callback_plugin */
499 static int callback_host (const char *host, void *user_data) /* {{{ */
501 gl_ident_stage_t *gl;
504 if ((host == NULL) || (user_data == NULL))
508 if (gl->host != NULL)
511 gl->host = strdup (host);
512 if (gl->host == NULL)
515 status = foreach_plugin (host, callback_plugin, gl);
521 } /* }}} int callback_host */
523 static const char *get_part_from_param (const char *prim_key, /* {{{ */
528 val = param (prim_key);
532 return (param (sec_key));
533 } /* }}} const char *get_part_from_param */
535 int gl_ident_get_rrdargs (graph_config_t *cfg, /* {{{ */
536 graph_instance_t *inst,
537 graph_ident_t *ident,
546 if ((cfg == NULL) || (inst == NULL) || (ident == NULL) || (args == NULL))
549 file = ident_to_file (ident);
552 DEBUG ("gl_ident_get_rrdargs: ident_to_file returned NULL.\n");
556 DEBUG ("gl_ident_get_rrdargs: file = %s;\n", file);
558 status = ds_list_from_rrd_file (file, &dses_num, &dses);
565 for (i = 0; i < dses_num; i++)
569 DEBUG ("gl_ident_get_rrdargs: ds[%lu] = %s;\n", (unsigned long) i, dses[i]);
571 index = array_argc (args);
574 array_append_format (args, "DEF:def_%04i_min=%s:%s:MIN",
575 index, file, dses[i]);
576 array_append_format (args, "DEF:def_%04i_avg=%s:%s:AVERAGE",
577 index, file, dses[i]);
578 array_append_format (args, "DEF:def_%04i_max=%s:%s:MAX",
579 index, file, dses[i]);
581 array_append_format (args, "VDEF:vdef_%04i_min=def_%04i_min,MINIMUM",
583 array_append_format (args, "VDEF:vdef_%04i_avg=def_%04i_avg,AVERAGE",
585 array_append_format (args, "VDEF:vdef_%04i_max=def_%04i_max,MAXIMUM",
587 array_append_format (args, "VDEF:vdef_%04i_lst=def_%04i_avg,LAST",
591 array_append_format (args, "LINE1:def_%04i_avg#%06"PRIx32":%s",
592 index, get_random_color (), dses[i]);
593 array_append_format (args, "GPRINT:vdef_%04i_min:%%lg min,", index);
594 array_append_format (args, "GPRINT:vdef_%04i_avg:%%lg avg,", index);
595 array_append_format (args, "GPRINT:vdef_%04i_max:%%lg max,", index);
596 array_append_format (args, "GPRINT:vdef_%04i_lst:%%lg last\\l", index);
605 } /* }}} int gl_ident_get_rrdargs */
610 int gl_instance_get_params (graph_config_t *cfg, graph_instance_t *inst, /* {{{ */
611 char *buffer, size_t buffer_size)
613 if ((inst == NULL) || (buffer == NULL) || (buffer_size < 1))
618 #define COPY_FIELD(field) do { \
619 const char *cfg_f = ident_get_##field (cfg->select); \
620 const char *inst_f = ident_get_##field (inst->select); \
621 if (strcmp (cfg_f, inst_f) == 0) \
623 strlcat (buffer, #field, buffer_size); \
624 strlcat (buffer, "=", buffer_size); \
625 strlcat (buffer, cfg_f, buffer_size); \
629 strlcat (buffer, "graph_", buffer_size); \
630 strlcat (buffer, #field, buffer_size); \
631 strlcat (buffer, "=", buffer_size); \
632 strlcat (buffer, cfg_f, buffer_size); \
633 strlcat (buffer, ";", buffer_size); \
634 strlcat (buffer, "inst_", buffer_size); \
635 strlcat (buffer, #field, buffer_size); \
636 strlcat (buffer, "=", buffer_size); \
637 strlcat (buffer, inst_f, buffer_size); \
642 strlcat (buffer, ";", buffer_size);
644 strlcat (buffer, ";", buffer_size);
645 COPY_FIELD(plugin_instance);
646 strlcat (buffer, ";", buffer_size);
648 strlcat (buffer, ";", buffer_size);
649 COPY_FIELD(type_instance);
654 } /* }}} int gl_instance_get_params */
656 graph_instance_t *inst_get_selected (graph_config_t *cfg) /* {{{ */
658 const char *host = get_part_from_param ("inst_host", "host");
659 const char *plugin = get_part_from_param ("inst_plugin", "plugin");
660 const char *plugin_instance = get_part_from_param ("inst_plugin_instance", "plugin_instance");
661 const char *type = get_part_from_param ("inst_type", "type");
662 const char *type_instance = get_part_from_param ("inst_type_instance", "type_instance");
663 graph_ident_t *ident;
664 graph_instance_t *inst;
667 cfg = graph_get_selected ();
671 DEBUG ("inst_get_selected: cfg == NULL;\n");
676 || (plugin == NULL) || (plugin_instance == NULL)
677 || (type == NULL) || (type_instance == NULL))
679 DEBUG ("inst_get_selected: A parameter is NULL.\n");
683 ident = ident_create (host, plugin, plugin_instance, type, type_instance);
685 for (inst = cfg->instances; inst != NULL; inst = inst->next)
687 if (ident_compare (ident, inst->select) != 0)
690 ident_destroy (ident);
694 DEBUG ("inst_get_selected: No match found.\n");
695 ident_destroy (ident);
697 } /* }}} graph_instance_t *inst_get_selected */
699 int gl_graph_get_all (gl_cfg_callback callback, /* {{{ */
704 if (callback == NULL)
709 for (cfg = graph_config_head; cfg != NULL; cfg = cfg->next)
713 status = (*callback) (cfg, user_data);
719 } /* }}} int gl_graph_get_all */
721 graph_config_t *graph_get_selected (void) /* {{{ */
723 const char *host = get_part_from_param ("graph_host", "host");
724 const char *plugin = get_part_from_param ("graph_plugin", "plugin");
725 const char *plugin_instance = get_part_from_param ("graph_plugin_instance", "plugin_instance");
726 const char *type = get_part_from_param ("graph_type", "type");
727 const char *type_instance = get_part_from_param ("graph_type_instance", "type_instance");
728 graph_ident_t *ident;
732 || (plugin == NULL) || (plugin_instance == NULL)
733 || (type == NULL) || (type_instance == NULL))
736 ident = ident_create (host, plugin, plugin_instance, type, type_instance);
740 for (cfg = graph_config_head; cfg != NULL; cfg = cfg->next)
742 if (ident_compare (ident, cfg->select) != 0)
745 ident_destroy (ident);
749 ident_destroy (ident);
751 } /* }}} graph_config_t *graph_get_selected */
753 int gl_graph_instance_get_all (graph_config_t *cfg, /* {{{ */
754 gl_inst_callback callback, void *user_data)
756 graph_instance_t *inst;
758 if ((cfg == NULL) || (callback == NULL))
761 for (inst = cfg->instances; inst != NULL; inst = inst->next)
765 status = (*callback) (cfg, inst, user_data);
771 } /* }}} int gl_graph_instance_get_all */
773 int gl_graph_get_title (graph_config_t *cfg, /* {{{ */
774 char *buffer, size_t buffer_size)
778 if ((cfg == NULL) || (buffer == NULL) || (buffer_size < 1))
781 if (cfg->title != NULL)
784 str = ident_to_string (cfg->select);
789 strncpy (buffer, str, buffer_size);
790 buffer[buffer_size - 1] = 0;
795 } /* }}} int gl_graph_get_title */
797 graph_ident_t *gl_graph_get_selector (graph_config_t *cfg) /* {{{ */
802 return (ident_clone (cfg->select));
803 } /* }}} graph_ident_t *gl_graph_get_selector */
805 int gl_instance_get_all (gl_inst_callback callback, /* {{{ */
812 for (cfg = graph_config_head; cfg != NULL; cfg = cfg->next)
814 graph_instance_t *inst;
816 for (inst = cfg->instances; inst != NULL; inst = inst->next)
820 status = (*callback) (cfg, inst, user_data);
827 } /* }}} int gl_instance_get_all */
829 int gl_instance_get_rrdargs (graph_config_t *cfg, /* {{{ */
830 graph_instance_t *inst,
835 if ((cfg == NULL) || (inst == NULL) || (args == NULL))
838 if (cfg->title != NULL)
840 array_append (args, "-t");
841 array_append (args, cfg->title);
844 for (i = 0; i < inst->files_num; i++)
849 def = def_search (cfg->defs, inst->files[i]);
852 def = def_create (cfg, inst->files[i]);
856 if (cfg->defs == NULL)
859 def_append (cfg->defs, def);
862 status = def_get_rrdargs (def, inst->files[i], args);
868 } /* }}} int gl_instance_get_rrdargs */
870 graph_ident_t *gl_instance_get_selector (graph_instance_t *inst) /* {{{ */
875 return (ident_clone (inst->select));
876 } /* }}} graph_ident_t *gl_instance_get_selector */
880 int gl_update (void) /* {{{ */
887 printf ("Content-Type: text/plain\n\n");
892 if ((gl_last_update + UPDATE_INTERVAL) >= now)
897 read_graph_config ();
899 memset (&gl, 0, sizeof (gl));
902 gl.plugin_instance = NULL;
904 gl.type_instance = NULL;
906 status = foreach_host (callback_host, &gl);
908 /* print_graphs (); */
911 } /* }}} int gl_update */
913 /* vim: set sw=2 sts=2 et fdm=marker : */