1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <stdint.h>
4 #include <inttypes.h>
5 #include <string.h>
6 #include <time.h>
7 #include <errno.h>
8 #include <assert.h>
10 #include "graph_list.h"
11 #include "graph_ident.h"
12 #include "graph_def.h"
13 #include "common.h"
14 #include "utils_params.h"
16 #include <fcgiapp.h>
17 #include <fcgi_stdio.h>
19 /*
20 * Defines
21 */
22 #define UPDATE_INTERVAL 10
24 #define ANY_TOKEN "/any/"
25 #define ALL_TOKEN "/all/"
27 /*
28 * Data types
29 */
30 struct gl_ident_stage_s /* {{{ */
31 {
32 char *host;
33 char *plugin;
34 char *plugin_instance;
35 char *type;
36 char *type_instance;
37 }; /* }}} */
38 typedef struct gl_ident_stage_s gl_ident_stage_t;
40 struct graph_instance_s /* {{{ */
41 {
42 graph_ident_t *select;
44 graph_ident_t **files;
45 size_t files_num;
47 graph_instance_t *next;
48 }; /* }}} struct graph_instance_s */
50 struct graph_config_s /* {{{ */
51 {
52 graph_ident_t *select;
54 char *title;
55 char *vertical_label;
57 graph_def_t *defs;
59 graph_instance_t *instances;
61 graph_config_t *next;
62 }; /* }}} struct graph_config_s */
64 /*
65 * Global variables
66 */
67 static graph_config_t *graph_config_head = NULL;
69 static time_t gl_last_update = 0;
71 /*
72 * Private functions
73 */
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) /* {{{ */
77 {
78 size_t i;
80 for (i = 0; i < inst->files_num; i++)
81 {
82 graph_ident_t *ident = inst->files[i];
83 char *file;
85 file = ident_to_file (ident);
86 printf (" File \"%s\"\n", file);
87 free (file);
88 }
90 return (0);
91 } /* }}} int print_instances */
93 static int print_instances (const graph_config_t *cfg) /* {{{ */
94 {
95 graph_instance_t *inst;
97 for (inst = cfg->instances; inst != NULL; inst = inst->next)
98 {
99 char *str;
101 str = ident_to_string (inst->select);
102 printf (" Instance \"%s\"\n", str);
103 free (str);
105 print_files (inst);
106 }
108 return (0);
109 } /* }}} int print_instances */
111 static int print_graphs (void) /* {{{ */
112 {
113 graph_config_t *cfg;
115 for (cfg = graph_config_head; cfg != NULL; cfg = cfg->next)
116 {
117 char *str;
119 str = ident_to_string (cfg->select);
120 printf ("Graph \"%s\"\n", str);
121 free (str);
123 print_instances (cfg);
124 }
126 return (0);
127 } /* }}} int print_graphs */
129 #if 0
130 /* "Safe" version of strcmp(3): Either or both pointers may be NULL. */
131 static int strcmp_s (const char *s1, const char *s2) /* {{{ */
132 {
133 if ((s1 == NULL) && (s2 == NULL))
134 return (0);
135 else if (s1 == NULL)
136 return (1);
137 else if (s2 == NULL)
138 return (-1);
139 assert ((s1 != NULL) && (s2 != NULL));
141 return (strcmp (s1, s2));
142 } /* }}} int strcmp_s */
143 #endif
145 static void instance_destroy (graph_instance_t *inst) /* {{{ */
146 {
147 graph_instance_t *next;
148 size_t i;
150 if (inst == NULL)
151 return;
153 next = inst->next;
155 ident_destroy (inst->select);
157 for (i = 0; i < inst->files_num; i++)
158 ident_destroy (inst->files[i]);
159 free (inst->files);
161 free (inst);
163 instance_destroy (next);
164 } /* }}} void instance_destroy */
166 /*
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.
170 */
171 static graph_instance_t *instance_create (graph_config_t *cfg, /* {{{ */
172 const graph_ident_t *file)
173 {
174 graph_instance_t *i;
176 if ((cfg == NULL) || (file == NULL))
177 return (NULL);
179 i = malloc (sizeof (*i));
180 if (i == NULL)
181 return (NULL);
182 memset (i, 0, sizeof (*i));
184 i->select = ident_copy_with_selector (cfg->select, file,
185 IDENT_FLAG_REPLACE_ANY);
187 i->files = NULL;
188 i->files_num = 0;
190 i->next = NULL;
192 if (cfg->instances == NULL)
193 cfg->instances = i;
194 else
195 {
196 graph_instance_t *last;
198 last = cfg->instances;
199 while (last->next != NULL)
200 last = last->next;
202 last->next = i;
203 }
205 return (i);
206 } /* }}} graph_instance_t *instance_create */
208 static int instance_add_file (graph_instance_t *inst, /* {{{ */
209 const graph_ident_t *file)
210 {
211 graph_ident_t **tmp;
213 tmp = realloc (inst->files, sizeof (*inst->files) * (inst->files_num + 1));
214 if (tmp == NULL)
215 return (ENOMEM);
216 inst->files = tmp;
218 inst->files[inst->files_num] = ident_clone (file);
219 if (inst->files[inst->files_num] == NULL)
220 return (ENOMEM);
222 inst->files_num++;
224 return (0);
225 } /* }}} int instance_add_file */
227 static graph_instance_t *graph_find_instance (graph_config_t *cfg, /* {{{ */
228 const graph_ident_t *file)
229 {
230 graph_instance_t *i;
232 if ((cfg == NULL) || (file == NULL))
233 return (NULL);
235 for (i = cfg->instances; i != NULL; i = i->next)
236 if (ident_matches (i->select, file))
237 return (i);
239 return (NULL);
240 } /* }}} graph_instance_t *graph_find_instance */
242 static int graph_add_file (graph_config_t *cfg, const graph_ident_t *file) /* {{{ */
243 {
244 graph_instance_t *inst;
246 inst = graph_find_instance (cfg, file);
247 if (inst == NULL)
248 {
249 inst = instance_create (cfg, file);
250 if (inst == NULL)
251 return (ENOMEM);
252 }
254 return (instance_add_file (inst, file));
255 } /* }}} int graph_add_file */
257 static int graph_append (graph_config_t *cfg) /* {{{ */
258 {
259 graph_config_t *last;
261 if (cfg == NULL)
262 return (EINVAL);
264 if (graph_config_head == NULL)
265 {
266 graph_config_head = cfg;
267 return (0);
268 }
270 last = graph_config_head;
271 while (last->next != NULL)
272 last = last->next;
274 last->next = cfg;
276 return (0);
277 } /* }}} int graph_append */
279 static graph_config_t *graph_create (const graph_ident_t *selector) /* {{{ */
280 {
281 graph_config_t *cfg;
283 cfg = malloc (sizeof (*cfg));
284 if (cfg == NULL)
285 return (NULL);
286 memset (cfg, 0, sizeof (*cfg));
288 cfg->select = ident_clone (selector);
290 cfg->title = NULL;
291 cfg->vertical_label = NULL;
292 cfg->defs = NULL;
293 cfg->instances = NULL;
294 cfg->next = NULL;
296 return (cfg);
297 } /* }}} int graph_create */
299 static void graph_destroy (graph_config_t *cfg) /* {{{ */
300 {
301 graph_config_t *next;
303 if (cfg == NULL)
304 return;
306 next = cfg->next;
308 ident_destroy (cfg->select);
310 free (cfg->title);
311 free (cfg->vertical_label);
313 def_destroy (cfg->defs);
314 instance_destroy (cfg->instances);
316 graph_destroy (next);
317 } /* }}} void graph_destroy */
319 static int register_file (const graph_ident_t *file) /* {{{ */
320 {
321 graph_config_t *cfg;
322 int num_graphs = 0;
324 for (cfg = graph_config_head; cfg != NULL; cfg = cfg->next)
325 {
326 int status;
328 if (!ident_matches (cfg->select, file))
329 continue;
331 status = graph_add_file (cfg, file);
332 if (status != 0)
333 {
334 /* report error */;
335 }
336 else
337 {
338 num_graphs++;
339 }
340 }
342 if (num_graphs == 0)
343 {
344 cfg = graph_create (file);
345 graph_append (cfg);
346 graph_add_file (cfg, file);
347 }
349 return (0);
350 } /* }}} int register_file */
352 static int FIXME_graph_create_from_file (const char *host, /* {{{ */
353 const char *plugin, const char *plugin_instance,
354 const char *type, const char *type_instance,
355 const char *title)
356 {
357 graph_config_t *cfg;
359 cfg = malloc (sizeof (*cfg));
360 if (cfg == NULL)
361 return (ENOMEM);
362 memset (cfg, 0, sizeof (*cfg));
364 cfg->select = ident_create (host, plugin, plugin_instance, type, type_instance);
366 cfg->title = NULL;
367 if (title != NULL)
368 cfg->title = strdup (title);
369 cfg->vertical_label = NULL;
370 cfg->instances = NULL;
371 cfg->next = NULL;
373 graph_append (cfg);
375 return (0);
376 } /* }}} int FIXME_graph_create_from_file */
378 /* FIXME: Actually read the config file here. */
379 static int read_graph_config (void) /* {{{ */
380 {
381 if (graph_config_head != NULL)
382 return (0);
384 FIXME_graph_create_from_file (ANY_TOKEN, "cpu", ANY_TOKEN, "cpu", ALL_TOKEN,
385 "CPU {instance} usage");
386 FIXME_graph_create_from_file (ANY_TOKEN, "memory", "", "memory", ALL_TOKEN,
387 "Memory usage");
388 FIXME_graph_create_from_file (ANY_TOKEN, "swap", "", "swap", ALL_TOKEN,
389 "Swap");
390 FIXME_graph_create_from_file (ANY_TOKEN, ANY_TOKEN, ANY_TOKEN, "ps_state", ALL_TOKEN,
391 "Processes");
392 FIXME_graph_create_from_file (ANY_TOKEN, "cpu", ALL_TOKEN, "cpu", "idle",
393 "CPU idle overview");
395 return (0);
396 } /* }}} int read_graph_config */
398 static void gl_clear (void) /* {{{ */
399 {
400 graph_config_t *cfg;
402 cfg = graph_config_head;
403 graph_config_head = NULL;
404 graph_destroy (cfg);
406 gl_last_update = 0;
407 } /* }}} void gl_clear */
409 static int callback_type (const char *type, void *user_data) /* {{{ */
410 {
411 gl_ident_stage_t *gl;
412 graph_ident_t *ident;
413 int status;
415 if ((type == NULL) || (user_data == NULL))
416 return (EINVAL);
418 gl = user_data;
419 if ((gl->type != NULL) || (gl->type_instance != NULL))
420 return (EINVAL);
422 gl->type = strdup (type);
423 if (gl->type == NULL)
424 return (ENOMEM);
426 gl->type_instance = strchr (gl->type, '-');
427 if (gl->type_instance != NULL)
428 {
429 *gl->type_instance = 0;
430 gl->type_instance++;
431 }
432 else
433 {
434 gl->type_instance = gl->type + strlen (gl->type);
435 }
437 ident = ident_create (gl->host,
438 gl->plugin, gl->plugin_instance,
439 gl->type, gl->type_instance);
440 if (ident == 0)
441 {
442 status = -1;
443 }
444 else
445 {
446 status = register_file (ident);
447 ident_destroy (ident);
448 }
450 free (gl->type);
451 gl->type = NULL;
452 gl->type_instance = NULL;
454 return (status);
455 } /* }}} int callback_type */
457 static int callback_plugin (const char *plugin, void *user_data) /* {{{ */
458 {
459 gl_ident_stage_t *gl;
460 int status;
462 if ((plugin == NULL) || (user_data == NULL))
463 return (EINVAL);
465 gl = user_data;
466 if ((gl->plugin != NULL) || (gl->plugin_instance != NULL))
467 return (EINVAL);
469 gl->plugin = strdup (plugin);
470 if (gl->plugin == NULL)
471 return (ENOMEM);
473 gl->plugin_instance = strchr (gl->plugin, '-');
474 if (gl->plugin_instance != NULL)
475 {
476 *gl->plugin_instance = 0;
477 gl->plugin_instance++;
478 }
479 else
480 {
481 gl->plugin_instance = gl->plugin + strlen (gl->plugin);
482 }
484 status = foreach_type (gl->host, plugin, callback_type, gl);
486 free (gl->plugin);
487 gl->plugin = NULL;
488 gl->plugin_instance = NULL;
490 return (status);
491 } /* }}} int callback_plugin */
493 static int callback_host (const char *host, void *user_data) /* {{{ */
494 {
495 gl_ident_stage_t *gl;
496 int status;
498 if ((host == NULL) || (user_data == NULL))
499 return (EINVAL);
501 gl = user_data;
502 if (gl->host != NULL)
503 return (EINVAL);
505 gl->host = strdup (host);
506 if (gl->host == NULL)
507 return (ENOMEM);
509 status = foreach_plugin (host, callback_plugin, gl);
511 free (gl->host);
512 gl->host = NULL;
514 return (status);
515 } /* }}} int callback_host */
517 static const char *get_part_from_param (const char *prim_key, /* {{{ */
518 const char *sec_key)
519 {
520 const char *val;
522 val = param (prim_key);
523 if (val != NULL)
524 return (val);
526 return (param (sec_key));
527 } /* }}} const char *get_part_from_param */
529 int gl_ident_get_rrdargs (graph_config_t *cfg, /* {{{ */
530 graph_instance_t *inst,
531 graph_ident_t *ident,
532 str_array_t *args)
533 {
534 char *file;
535 char **dses = NULL;
536 size_t dses_num = 0;
537 int status;
538 size_t i;
540 if ((cfg == NULL) || (inst == NULL) || (ident == NULL) || (args == NULL))
541 return (EINVAL);
543 file = ident_to_file (ident);
544 if (file == NULL)
545 {
546 DEBUG ("gl_ident_get_rrdargs: ident_to_file returned NULL.\n");
547 return (-1);
548 }
550 DEBUG ("gl_ident_get_rrdargs: file = %s;\n", file);
552 status = ds_list_from_rrd_file (file, &dses_num, &dses);
553 if (status != 0)
554 {
555 free (file);
556 return (status);
557 }
559 for (i = 0; i < dses_num; i++)
560 {
561 int index;
563 DEBUG ("gl_ident_get_rrdargs: ds[%lu] = %s;\n", (unsigned long) i, dses[i]);
565 index = array_argc (args);
567 /* CDEFs */
568 array_append_format (args, "DEF:def_%04i_min=%s:%s:MIN",
569 index, file, dses[i]);
570 array_append_format (args, "DEF:def_%04i_avg=%s:%s:AVERAGE",
571 index, file, dses[i]);
572 array_append_format (args, "DEF:def_%04i_max=%s:%s:MAX",
573 index, file, dses[i]);
574 /* VDEFs */
575 array_append_format (args, "VDEF:vdef_%04i_min=def_%04i_min,MINIMUM",
576 index, index);
577 array_append_format (args, "VDEF:vdef_%04i_avg=def_%04i_avg,AVERAGE",
578 index, index);
579 array_append_format (args, "VDEF:vdef_%04i_max=def_%04i_max,MAXIMUM",
580 index, index);
581 array_append_format (args, "VDEF:vdef_%04i_lst=def_%04i_avg,LAST",
582 index, index);
584 /* Graph part */
585 array_append_format (args, "LINE1:def_%04i_avg#%06"PRIx32":%s",
586 index, get_random_color (), dses[i]);
587 array_append_format (args, "GPRINT:vdef_%04i_min:%%lg min,", index);
588 array_append_format (args, "GPRINT:vdef_%04i_avg:%%lg avg,", index);
589 array_append_format (args, "GPRINT:vdef_%04i_max:%%lg max,", index);
590 array_append_format (args, "GPRINT:vdef_%04i_lst:%%lg last\\l", index);
592 free (dses[i]);
593 }
594 free (dses);
596 free (file);
598 return (0);
599 } /* }}} int gl_ident_get_rrdargs */
601 /*
602 * Global functions
603 */
604 int gl_instance_get_params (graph_config_t *cfg, graph_instance_t *inst, /* {{{ */
605 char *buffer, size_t buffer_size)
606 {
607 if ((inst == NULL) || (buffer == NULL) || (buffer_size < 1))
608 return (EINVAL);
610 buffer[0] = 0;
612 #define COPY_FIELD(field) do { \
613 const char *cfg_f = ident_get_##field (cfg->select); \
614 const char *inst_f = ident_get_##field (inst->select); \
615 if (strcmp (cfg_f, inst_f) == 0) \
616 { \
617 strlcat (buffer, #field, buffer_size); \
618 strlcat (buffer, "=", buffer_size); \
619 strlcat (buffer, cfg_f, buffer_size); \
620 } \
621 else \
622 { \
623 strlcat (buffer, "graph_", buffer_size); \
624 strlcat (buffer, #field, buffer_size); \
625 strlcat (buffer, "=", buffer_size); \
626 strlcat (buffer, cfg_f, buffer_size); \
627 strlcat (buffer, ";", buffer_size); \
628 strlcat (buffer, "inst_", buffer_size); \
629 strlcat (buffer, #field, buffer_size); \
630 strlcat (buffer, "=", buffer_size); \
631 strlcat (buffer, inst_f, buffer_size); \
632 } \
633 } while (0)
635 COPY_FIELD(host);
636 strlcat (buffer, ";", buffer_size);
637 COPY_FIELD(plugin);
638 strlcat (buffer, ";", buffer_size);
639 COPY_FIELD(plugin_instance);
640 strlcat (buffer, ";", buffer_size);
641 COPY_FIELD(type);
642 strlcat (buffer, ";", buffer_size);
643 COPY_FIELD(type_instance);
645 #undef COPY_FIELD
647 return (0);
648 } /* }}} int gl_instance_get_params */
650 graph_instance_t *inst_get_selected (graph_config_t *cfg) /* {{{ */
651 {
652 const char *host = get_part_from_param ("inst_host", "host");
653 const char *plugin = get_part_from_param ("inst_plugin", "plugin");
654 const char *plugin_instance = get_part_from_param ("inst_plugin_instance", "plugin_instance");
655 const char *type = get_part_from_param ("inst_type", "type");
656 const char *type_instance = get_part_from_param ("inst_type_instance", "type_instance");
657 graph_ident_t *ident;
658 graph_instance_t *inst;
660 if (cfg == NULL)
661 cfg = graph_get_selected ();
663 if (cfg == NULL)
664 {
665 DEBUG ("inst_get_selected: cfg == NULL;\n");
666 return (NULL);
667 }
669 if ((host == NULL)
670 || (plugin == NULL) || (plugin_instance == NULL)
671 || (type == NULL) || (type_instance == NULL))
672 {
673 DEBUG ("inst_get_selected: A parameter is NULL.\n");
674 return (NULL);
675 }
677 ident = ident_create (host, plugin, plugin_instance, type, type_instance);
679 for (inst = cfg->instances; inst != NULL; inst = inst->next)
680 {
681 if (ident_compare (ident, inst->select) != 0)
682 continue;
684 ident_destroy (ident);
685 return (inst);
686 }
688 DEBUG ("inst_get_selected: No match found.\n");
689 ident_destroy (ident);
690 return (NULL);
691 } /* }}} graph_instance_t *inst_get_selected */
693 int gl_graph_get_all (gl_cfg_callback callback, /* {{{ */
694 void *user_data)
695 {
696 graph_config_t *cfg;
698 if (callback == NULL)
699 return (EINVAL);
701 gl_update ();
703 for (cfg = graph_config_head; cfg != NULL; cfg = cfg->next)
704 {
705 int status;
707 status = (*callback) (cfg, user_data);
708 if (status != 0)
709 return (status);
710 }
712 return (0);
713 } /* }}} int gl_graph_get_all */
715 graph_config_t *graph_get_selected (void) /* {{{ */
716 {
717 const char *host = get_part_from_param ("graph_host", "host");
718 const char *plugin = get_part_from_param ("graph_plugin", "plugin");
719 const char *plugin_instance = get_part_from_param ("graph_plugin_instance", "plugin_instance");
720 const char *type = get_part_from_param ("graph_type", "type");
721 const char *type_instance = get_part_from_param ("graph_type_instance", "type_instance");
722 graph_ident_t *ident;
723 graph_config_t *cfg;
725 if ((host == NULL)
726 || (plugin == NULL) || (plugin_instance == NULL)
727 || (type == NULL) || (type_instance == NULL))
728 return (NULL);
730 ident = ident_create (host, plugin, plugin_instance, type, type_instance);
732 gl_update ();
734 for (cfg = graph_config_head; cfg != NULL; cfg = cfg->next)
735 {
736 if (ident_compare (ident, cfg->select) != 0)
737 continue;
739 ident_destroy (ident);
740 return (cfg);
741 }
743 ident_destroy (ident);
744 return (NULL);
745 } /* }}} graph_config_t *graph_get_selected */
747 int gl_graph_instance_get_all (graph_config_t *cfg, /* {{{ */
748 gl_inst_callback callback, void *user_data)
749 {
750 graph_instance_t *inst;
752 if ((cfg == NULL) || (callback == NULL))
753 return (EINVAL);
755 for (inst = cfg->instances; inst != NULL; inst = inst->next)
756 {
757 int status;
759 status = (*callback) (cfg, inst, user_data);
760 if (status != 0)
761 return (status);
762 }
764 return (0);
765 } /* }}} int gl_graph_instance_get_all */
767 int gl_graph_get_title (graph_config_t *cfg, /* {{{ */
768 char *buffer, size_t buffer_size)
769 {
770 char *str;
772 if ((cfg == NULL) || (buffer == NULL) || (buffer_size < 1))
773 return (EINVAL);
775 if (cfg->title != NULL)
776 str = cfg->title;
777 else
778 str = ident_to_string (cfg->select);
780 if (str == NULL)
781 return (ENOMEM);
783 strncpy (buffer, str, buffer_size);
784 buffer[buffer_size - 1] = 0;
786 free (str);
788 return (0);
789 } /* }}} int gl_graph_get_title */
791 graph_ident_t *gl_graph_get_selector (graph_config_t *cfg) /* {{{ */
792 {
793 if (cfg == NULL)
794 return (NULL);
796 return (ident_clone (cfg->select));
797 } /* }}} graph_ident_t *gl_graph_get_selector */
799 int gl_instance_get_all (gl_inst_callback callback, /* {{{ */
800 void *user_data)
801 {
802 graph_config_t *cfg;
804 gl_update ();
806 for (cfg = graph_config_head; cfg != NULL; cfg = cfg->next)
807 {
808 graph_instance_t *inst;
810 for (inst = cfg->instances; inst != NULL; inst = inst->next)
811 {
812 int status;
814 status = (*callback) (cfg, inst, user_data);
815 if (status != 0)
816 return (status);
817 }
818 }
820 return (0);
821 } /* }}} int gl_instance_get_all */
823 int gl_instance_get_rrdargs (graph_config_t *cfg, /* {{{ */
824 graph_instance_t *inst,
825 str_array_t *args)
826 {
827 size_t i;
829 if ((cfg == NULL) || (inst == NULL) || (args == NULL))
830 return (EINVAL);
832 if (cfg->title != NULL)
833 {
834 array_append (args, "-t");
835 array_append (args, cfg->title);
836 }
838 for (i = 0; i < inst->files_num; i++)
839 {
840 graph_def_t *def;
841 int status;
843 def = def_search (cfg->defs, inst->files[i]);
844 if (def == NULL)
845 {
846 def = def_create (cfg, inst->files[i]);
847 if (def == NULL)
848 return (-1);
850 if (cfg->defs == NULL)
851 cfg->defs = def;
852 else
853 def_append (cfg->defs, def);
854 }
856 status = def_get_rrdargs (def, inst->files[i], args);
857 if (status != 0)
858 return (status);
859 }
861 return (0);
862 } /* }}} int gl_instance_get_rrdargs */
864 graph_ident_t *gl_instance_get_selector (graph_instance_t *inst) /* {{{ */
865 {
866 if (inst == NULL)
867 return (NULL);
869 return (ident_clone (inst->select));
870 } /* }}} graph_ident_t *gl_instance_get_selector */
872 /* DELETEME */
874 int gl_update (void) /* {{{ */
875 {
876 time_t now;
877 gl_ident_stage_t gl;
878 int status;
880 /*
881 printf ("Content-Type: text/plain\n\n");
882 */
884 now = time (NULL);
886 if ((gl_last_update + UPDATE_INTERVAL) >= now)
887 return (0);
889 gl_clear ();
891 read_graph_config ();
893 memset (&gl, 0, sizeof (gl));
894 gl.host = NULL;
895 gl.plugin = NULL;
896 gl.plugin_instance = NULL;
897 gl.type = NULL;
898 gl.type_instance = NULL;
900 status = foreach_host (callback_host, &gl);
902 /* print_graphs (); */
904 return (status);
905 } /* }}} int gl_update */
907 /* vim: set sw=2 sts=2 et fdm=marker : */