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>
9 #include "graph_list.h"
10 #include "common.h"
11 #include "filesystem.h"
12 #include "graph.h"
13 #include "graph_config.h"
14 #include "graph_def.h"
15 #include "graph_ident.h"
16 #include "utils_cgi.h"
18 #include <fcgiapp.h>
19 #include <fcgi_stdio.h>
21 /*
22 * Defines
23 */
24 #define UPDATE_INTERVAL 10
26 /*
27 * Global variables
28 */
29 static graph_config_t **gl_active = NULL;
30 static size_t gl_active_num = 0;
32 static graph_config_t **gl_staging = NULL;
33 static size_t gl_staging_num = 0;
35 static char **host_list = NULL;
36 static size_t host_list_len = 0;
38 static time_t gl_last_update = 0;
40 /*
41 * Private functions
42 */
43 int gl_add_graph_internal (graph_config_t *cfg, /* {{{ */
44 graph_config_t ***gl_array, size_t *gl_array_num)
45 {
46 graph_config_t **tmp;
48 #define ARRAY_PTR (*gl_array)
49 #define ARRAY_SIZE (*gl_array_num)
51 if (cfg == NULL)
52 return (EINVAL);
54 tmp = realloc (ARRAY_PTR, sizeof (*ARRAY_PTR) * (ARRAY_SIZE + 1));
55 if (tmp == NULL)
56 return (ENOMEM);
57 ARRAY_PTR = tmp;
59 ARRAY_PTR[ARRAY_SIZE] = cfg;
60 ARRAY_SIZE++;
62 #undef ARRAY_SIZE
63 #undef ARRAY_PTR
65 return (0);
66 } /* }}} int gl_add_graph_internal */
68 static int gl_register_host (const char *host) /* {{{ */
69 {
70 char **tmp;
71 size_t i;
73 if (host == NULL)
74 return (EINVAL);
76 for (i = 0; i < host_list_len; i++)
77 if (strcmp (host_list[i], host) == 0)
78 return (0);
80 tmp = realloc (host_list, sizeof (*host_list) * (host_list_len + 1));
81 if (tmp == NULL)
82 return (ENOMEM);
83 host_list = tmp;
85 host_list[host_list_len] = strdup (host);
86 if (host_list[host_list_len] == NULL)
87 return (ENOMEM);
89 host_list_len++;
90 return (0);
91 } /* }}} int gl_register_host */
93 static int gl_clear_hosts (void) /* {{{ */
94 {
95 size_t i;
97 for (i = 0; i < host_list_len; i++)
98 free (host_list[i]);
99 free (host_list);
101 host_list = NULL;
102 host_list_len = 0;
104 return (0);
105 } /* }}} int gl_clear_hosts */
107 static int gl_compare_hosts (const void *v0, const void *v1) /* {{{ */
108 {
109 return (strcmp (v0, v1));
110 } /* }}} int gl_compare_hosts */
112 static int gl_register_file (const graph_ident_t *file, /* {{{ */
113 __attribute__((unused)) void *user_data)
114 {
115 graph_config_t *cfg;
116 int num_graphs = 0;
117 size_t i;
119 for (i = 0; i < gl_active_num; i++)
120 {
121 graph_config_t *cfg = gl_active[i];
122 int status;
124 if (!graph_matches_ident (cfg, file))
125 continue;
127 status = graph_add_file (cfg, file);
128 if (status != 0)
129 {
130 /* report error */;
131 }
132 else
133 {
134 num_graphs++;
135 }
136 }
138 if (num_graphs == 0)
139 {
140 cfg = graph_create (file);
141 gl_add_graph_internal (cfg, &gl_active, &gl_active_num);
142 graph_add_file (cfg, file);
143 }
145 gl_register_host (ident_get_host (file));
147 return (0);
148 } /* }}} int gl_register_file */
150 static const char *get_part_from_param (const char *prim_key, /* {{{ */
151 const char *sec_key)
152 {
153 const char *val;
155 val = param (prim_key);
156 if (val != NULL)
157 return (val);
159 return (param (sec_key));
160 } /* }}} const char *get_part_from_param */
162 static int gl_clear_instances (void) /* {{{ */
163 {
164 size_t i;
166 for (i = 0; i < gl_active_num; i++)
167 graph_clear_instances (gl_active[i]);
169 return (0);
170 } /* }}} int gl_clear_instances */
173 /*
174 * Global functions
175 */
176 int gl_add_graph (graph_config_t *cfg) /* {{{ */
177 {
178 return (gl_add_graph_internal (cfg, &gl_staging, &gl_staging_num));
179 } /* }}} int gl_add_graph */
181 int gl_config_submit (void) /* {{{ */
182 {
183 graph_config_t **old;
184 size_t old_num;
185 size_t i;
187 old = gl_active;
188 old_num = gl_active_num;
190 gl_active = gl_staging;
191 gl_active_num = gl_staging_num;
193 gl_staging = NULL;
194 gl_staging_num = 0;
196 for (i = 0; i < old_num; i++)
197 {
198 graph_destroy (old[i]);
199 old[i] = NULL;
200 }
201 free (old);
203 return (0);
204 } /* }}} int graph_config_submit */
206 int gl_graph_get_all (graph_callback_t callback, /* {{{ */
207 void *user_data)
208 {
209 size_t i;
211 if (callback == NULL)
212 return (EINVAL);
214 gl_update ();
216 for (i = 0; i < gl_active_num; i++)
217 {
218 int status;
220 status = (*callback) (gl_active[i], user_data);
221 if (status != 0)
222 return (status);
223 }
225 return (0);
226 } /* }}} int gl_graph_get_all */
228 graph_config_t *gl_graph_get_selected (void) /* {{{ */
229 {
230 const char *host = get_part_from_param ("graph_host", "host");
231 const char *plugin = get_part_from_param ("graph_plugin", "plugin");
232 const char *plugin_instance = get_part_from_param ("graph_plugin_instance", "plugin_instance");
233 const char *type = get_part_from_param ("graph_type", "type");
234 const char *type_instance = get_part_from_param ("graph_type_instance", "type_instance");
235 graph_ident_t *ident;
236 size_t i;
238 if ((host == NULL)
239 || (plugin == NULL) || (plugin_instance == NULL)
240 || (type == NULL) || (type_instance == NULL))
241 return (NULL);
243 ident = ident_create (host, plugin, plugin_instance, type, type_instance);
245 gl_update ();
247 for (i = 0; i < gl_active_num; i++)
248 {
249 if (graph_compare (gl_active[i], ident) != 0)
250 continue;
252 ident_destroy (ident);
253 return (gl_active[i]);
254 }
256 ident_destroy (ident);
257 return (NULL);
258 } /* }}} graph_config_t *gl_graph_get_selected */
260 /* gl_instance_get_all, gl_graph_instance_get_all {{{ */
261 struct gl_inst_callback_data /* {{{ */
262 {
263 graph_config_t *cfg;
264 graph_inst_callback_t callback;
265 void *user_data;
266 }; /* }}} struct gl_inst_callback_data */
268 static int gl_inst_callback_handler (graph_instance_t *inst, /* {{{ */
269 void *user_data)
270 {
271 struct gl_inst_callback_data *data = user_data;
273 return ((*data->callback) (data->cfg, inst, data->user_data));
274 } /* }}} int gl_inst_callback_handler */
276 int gl_graph_instance_get_all (graph_config_t *cfg, /* {{{ */
277 graph_inst_callback_t callback, void *user_data)
278 {
279 struct gl_inst_callback_data data =
280 {
281 cfg,
282 callback,
283 user_data
284 };
286 if ((cfg == NULL) || (callback == NULL))
287 return (EINVAL);
289 return (graph_inst_foreach (cfg, gl_inst_callback_handler, &data));
290 } /* }}} int gl_graph_instance_get_all */
292 int gl_instance_get_all (graph_inst_callback_t callback, /* {{{ */
293 void *user_data)
294 {
295 size_t i;
297 gl_update ();
299 for (i = 0; i < gl_active_num; i++)
300 {
301 int status;
303 status = gl_graph_instance_get_all (gl_active[i], callback, user_data);
304 if (status != 0)
305 return (status);
306 }
308 return (0);
309 } /* }}} int gl_instance_get_all */
310 /* }}} gl_instance_get_all, gl_graph_instance_get_all */
312 int gl_search (const char *term, graph_inst_callback_t callback, /* {{{ */
313 void *user_data)
314 {
315 size_t i;
317 for (i = 0; i < gl_active_num; i++)
318 {
319 int status;
321 status = graph_inst_search (gl_active[i], term,
322 /* callback = */ callback,
323 /* user data = */ user_data);
324 if (status != 0)
325 return (status);
326 }
328 return (0);
329 } /* }}} int gl_search */
331 int gl_search_field (graph_ident_field_t field, /* {{{ */
332 const char *field_value,
333 graph_inst_callback_t callback, void *user_data)
334 {
335 size_t i;
337 if ((field_value == NULL) || (callback == NULL))
338 return (EINVAL);
340 for (i = 0; i < gl_active_num; i++)
341 {
342 int status;
344 status = graph_inst_search_field (gl_active[i],
345 field, field_value,
346 /* callback = */ callback,
347 /* user data = */ user_data);
348 if (status != 0)
349 return (status);
350 }
352 return (0);
353 } /* }}} int gl_search_field */
355 int gl_foreach_host (int (*callback) (const char *host, void *user_data), /* {{{ */
356 void *user_data)
357 {
358 int status;
359 size_t i;
361 for (i = 0; i < host_list_len; i++)
362 {
363 status = (*callback) (host_list[i], user_data);
364 if (status != 0)
365 return (status);
366 }
368 return (0);
369 } /* }}} int gl_foreach_host */
371 int gl_update (void) /* {{{ */
372 {
373 time_t now;
374 int status;
376 /*
377 printf ("Content-Type: text/plain\n\n");
378 */
380 now = time (NULL);
382 if ((gl_last_update + UPDATE_INTERVAL) >= now)
383 return (0);
385 graph_read_config ();
387 gl_clear_instances ();
388 gl_clear_hosts ();
389 status = fs_scan (/* callback = */ gl_register_file, /* user data = */ NULL);
391 if (host_list_len > 0)
392 qsort (host_list, host_list_len, sizeof (*host_list),
393 gl_compare_hosts);
395 gl_last_update = now;
397 return (status);
398 } /* }}} int gl_update */
400 /* vim: set sw=2 sts=2 et fdm=marker : */