1 /**
2 * collection4 - graph_list.c
3 * Copyright (C) 2010 Florian octo Forster
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301 USA
19 *
20 * Authors:
21 * Florian octo Forster <ff at octo.it>
22 **/
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <stdint.h>
27 #include <inttypes.h>
28 #include <string.h>
29 #include <time.h>
30 #include <errno.h>
32 #include "graph_list.h"
33 #include "common.h"
34 #include "filesystem.h"
35 #include "graph.h"
36 #include "graph_config.h"
37 #include "graph_def.h"
38 #include "graph_ident.h"
39 #include "utils_cgi.h"
41 #include <fcgiapp.h>
42 #include <fcgi_stdio.h>
44 /*
45 * Defines
46 */
47 #define UPDATE_INTERVAL 10
49 /*
50 * Global variables
51 */
52 static graph_config_t **gl_active = NULL;
53 static size_t gl_active_num = 0;
55 static graph_config_t **gl_staging = NULL;
56 static size_t gl_staging_num = 0;
58 static char **host_list = NULL;
59 static size_t host_list_len = 0;
61 static time_t gl_last_update = 0;
63 /*
64 * Private functions
65 */
66 static int gl_add_graph_internal (graph_config_t *cfg, /* {{{ */
67 graph_config_t ***gl_array, size_t *gl_array_num)
68 {
69 graph_config_t **tmp;
71 #define ARRAY_PTR (*gl_array)
72 #define ARRAY_SIZE (*gl_array_num)
74 if (cfg == NULL)
75 return (EINVAL);
77 tmp = realloc (ARRAY_PTR, sizeof (*ARRAY_PTR) * (ARRAY_SIZE + 1));
78 if (tmp == NULL)
79 return (ENOMEM);
80 ARRAY_PTR = tmp;
82 ARRAY_PTR[ARRAY_SIZE] = cfg;
83 ARRAY_SIZE++;
85 #undef ARRAY_SIZE
86 #undef ARRAY_PTR
88 return (0);
89 } /* }}} int gl_add_graph_internal */
91 static int gl_register_host (const char *host) /* {{{ */
92 {
93 char **tmp;
94 size_t i;
96 if (host == NULL)
97 return (EINVAL);
99 for (i = 0; i < host_list_len; i++)
100 if (strcmp (host_list[i], host) == 0)
101 return (0);
103 tmp = realloc (host_list, sizeof (*host_list) * (host_list_len + 1));
104 if (tmp == NULL)
105 return (ENOMEM);
106 host_list = tmp;
108 host_list[host_list_len] = strdup (host);
109 if (host_list[host_list_len] == NULL)
110 return (ENOMEM);
112 host_list_len++;
113 return (0);
114 } /* }}} int gl_register_host */
116 static int gl_clear_hosts (void) /* {{{ */
117 {
118 size_t i;
120 for (i = 0; i < host_list_len; i++)
121 free (host_list[i]);
122 free (host_list);
124 host_list = NULL;
125 host_list_len = 0;
127 return (0);
128 } /* }}} int gl_clear_hosts */
130 static int gl_compare_hosts (const void *v0, const void *v1) /* {{{ */
131 {
132 return (strcmp (v0, v1));
133 } /* }}} int gl_compare_hosts */
135 static int gl_register_file (const graph_ident_t *file, /* {{{ */
136 __attribute__((unused)) void *user_data)
137 {
138 graph_config_t *cfg;
139 int num_graphs = 0;
140 size_t i;
142 for (i = 0; i < gl_active_num; i++)
143 {
144 graph_config_t *cfg = gl_active[i];
145 int status;
147 if (!graph_matches_ident (cfg, file))
148 continue;
150 status = graph_add_file (cfg, file);
151 if (status != 0)
152 {
153 /* report error */;
154 }
155 else
156 {
157 num_graphs++;
158 }
159 }
161 if (num_graphs == 0)
162 {
163 cfg = graph_create (file);
164 gl_add_graph_internal (cfg, &gl_active, &gl_active_num);
165 graph_add_file (cfg, file);
166 }
168 gl_register_host (ident_get_host (file));
170 return (0);
171 } /* }}} int gl_register_file */
173 static const char *get_part_from_param (const char *prim_key, /* {{{ */
174 const char *sec_key)
175 {
176 const char *val;
178 val = param (prim_key);
179 if (val != NULL)
180 return (val);
182 return (param (sec_key));
183 } /* }}} const char *get_part_from_param */
185 static int gl_clear_instances (void) /* {{{ */
186 {
187 size_t i;
189 for (i = 0; i < gl_active_num; i++)
190 graph_clear_instances (gl_active[i]);
192 return (0);
193 } /* }}} int gl_clear_instances */
196 /*
197 * Global functions
198 */
199 int gl_add_graph (graph_config_t *cfg) /* {{{ */
200 {
201 return (gl_add_graph_internal (cfg, &gl_staging, &gl_staging_num));
202 } /* }}} int gl_add_graph */
204 int gl_config_submit (void) /* {{{ */
205 {
206 graph_config_t **old;
207 size_t old_num;
208 size_t i;
210 old = gl_active;
211 old_num = gl_active_num;
213 gl_active = gl_staging;
214 gl_active_num = gl_staging_num;
216 gl_staging = NULL;
217 gl_staging_num = 0;
219 for (i = 0; i < old_num; i++)
220 {
221 graph_destroy (old[i]);
222 old[i] = NULL;
223 }
224 free (old);
226 return (0);
227 } /* }}} int graph_config_submit */
229 int gl_graph_get_all (graph_callback_t callback, /* {{{ */
230 void *user_data)
231 {
232 size_t i;
234 if (callback == NULL)
235 return (EINVAL);
237 gl_update ();
239 for (i = 0; i < gl_active_num; i++)
240 {
241 int status;
243 status = (*callback) (gl_active[i], user_data);
244 if (status != 0)
245 return (status);
246 }
248 return (0);
249 } /* }}} int gl_graph_get_all */
251 graph_config_t *gl_graph_get_selected (void) /* {{{ */
252 {
253 const char *host = get_part_from_param ("graph_host", "host");
254 const char *plugin = get_part_from_param ("graph_plugin", "plugin");
255 const char *plugin_instance = get_part_from_param ("graph_plugin_instance", "plugin_instance");
256 const char *type = get_part_from_param ("graph_type", "type");
257 const char *type_instance = get_part_from_param ("graph_type_instance", "type_instance");
258 graph_ident_t *ident;
259 size_t i;
261 if ((host == NULL)
262 || (plugin == NULL) || (plugin_instance == NULL)
263 || (type == NULL) || (type_instance == NULL))
264 return (NULL);
266 ident = ident_create (host, plugin, plugin_instance, type, type_instance);
268 gl_update ();
270 for (i = 0; i < gl_active_num; i++)
271 {
272 if (graph_compare (gl_active[i], ident) != 0)
273 continue;
275 ident_destroy (ident);
276 return (gl_active[i]);
277 }
279 ident_destroy (ident);
280 return (NULL);
281 } /* }}} graph_config_t *gl_graph_get_selected */
283 /* gl_instance_get_all, gl_graph_instance_get_all {{{ */
284 struct gl_inst_callback_data /* {{{ */
285 {
286 graph_config_t *cfg;
287 graph_inst_callback_t callback;
288 void *user_data;
289 }; /* }}} struct gl_inst_callback_data */
291 static int gl_inst_callback_handler (graph_instance_t *inst, /* {{{ */
292 void *user_data)
293 {
294 struct gl_inst_callback_data *data = user_data;
296 return ((*data->callback) (data->cfg, inst, data->user_data));
297 } /* }}} int gl_inst_callback_handler */
299 int gl_graph_instance_get_all (graph_config_t *cfg, /* {{{ */
300 graph_inst_callback_t callback, void *user_data)
301 {
302 struct gl_inst_callback_data data =
303 {
304 cfg,
305 callback,
306 user_data
307 };
309 if ((cfg == NULL) || (callback == NULL))
310 return (EINVAL);
312 return (graph_inst_foreach (cfg, gl_inst_callback_handler, &data));
313 } /* }}} int gl_graph_instance_get_all */
315 int gl_instance_get_all (graph_inst_callback_t callback, /* {{{ */
316 void *user_data)
317 {
318 size_t i;
320 gl_update ();
322 for (i = 0; i < gl_active_num; i++)
323 {
324 int status;
326 status = gl_graph_instance_get_all (gl_active[i], callback, user_data);
327 if (status != 0)
328 return (status);
329 }
331 return (0);
332 } /* }}} int gl_instance_get_all */
333 /* }}} gl_instance_get_all, gl_graph_instance_get_all */
335 int gl_search (const char *term, graph_inst_callback_t callback, /* {{{ */
336 void *user_data)
337 {
338 size_t i;
340 for (i = 0; i < gl_active_num; i++)
341 {
342 int status;
344 status = graph_inst_search (gl_active[i], term,
345 /* callback = */ callback,
346 /* user data = */ user_data);
347 if (status != 0)
348 return (status);
349 }
351 return (0);
352 } /* }}} int gl_search */
354 int gl_search_field (graph_ident_field_t field, /* {{{ */
355 const char *field_value,
356 graph_inst_callback_t callback, void *user_data)
357 {
358 size_t i;
360 if ((field_value == NULL) || (callback == NULL))
361 return (EINVAL);
363 for (i = 0; i < gl_active_num; i++)
364 {
365 int status;
367 status = graph_inst_search_field (gl_active[i],
368 field, field_value,
369 /* callback = */ callback,
370 /* user data = */ user_data);
371 if (status != 0)
372 return (status);
373 }
375 return (0);
376 } /* }}} int gl_search_field */
378 int gl_foreach_host (int (*callback) (const char *host, void *user_data), /* {{{ */
379 void *user_data)
380 {
381 int status;
382 size_t i;
384 for (i = 0; i < host_list_len; i++)
385 {
386 status = (*callback) (host_list[i], user_data);
387 if (status != 0)
388 return (status);
389 }
391 return (0);
392 } /* }}} int gl_foreach_host */
394 int gl_update (void) /* {{{ */
395 {
396 time_t now;
397 int status;
399 /*
400 printf ("Content-Type: text/plain\n\n");
401 */
403 now = time (NULL);
405 if ((gl_last_update + UPDATE_INTERVAL) >= now)
406 return (0);
408 graph_read_config ();
410 gl_clear_instances ();
411 gl_clear_hosts ();
412 status = fs_scan (/* callback = */ gl_register_file, /* user data = */ NULL);
414 if (host_list_len > 0)
415 qsort (host_list, host_list_len, sizeof (*host_list),
416 gl_compare_hosts);
418 gl_last_update = now;
420 return (status);
421 } /* }}} int gl_update */
423 /* vim: set sw=2 sts=2 et fdm=marker : */