src/graph_list.[ch]: Implement "gl_foreach_host".
[collection4.git] / src / graph_list.c
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
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"
17
18 #include <fcgiapp.h>
19 #include <fcgi_stdio.h>
20
21 /*
22  * Defines
23  */
24 #define UPDATE_INTERVAL 10
25
26 /*
27  * Global variables
28  */
29 static graph_config_t **gl_active = NULL;
30 static size_t gl_active_num = 0;
31
32 static graph_config_t **gl_staging = NULL;
33 static size_t gl_staging_num = 0;
34
35 static char **host_list = NULL;
36 static size_t host_list_len = 0;
37
38 static time_t gl_last_update = 0;
39
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;
47
48 #define ARRAY_PTR  (*gl_array)
49 #define ARRAY_SIZE (*gl_array_num)
50
51   if (cfg == NULL)
52     return (EINVAL);
53
54   tmp = realloc (ARRAY_PTR, sizeof (*ARRAY_PTR) * (ARRAY_SIZE + 1));
55   if (tmp == NULL)
56     return (ENOMEM);
57   ARRAY_PTR = tmp;
58
59   ARRAY_PTR[ARRAY_SIZE] = cfg;
60   ARRAY_SIZE++;
61
62 #undef ARRAY_SIZE
63 #undef ARRAY_PTR
64
65   return (0);
66 } /* }}} int gl_add_graph_internal */
67
68 static int gl_register_host (const char *host) /* {{{ */
69 {
70   char **tmp;
71   size_t i;
72
73   if (host == NULL)
74     return (EINVAL);
75
76   for (i = 0; i < host_list_len; i++)
77     if (strcmp (host_list[i], host) == 0)
78       return (0);
79
80   tmp = realloc (host_list, sizeof (*host_list) * (host_list_len + 1));
81   if (tmp == NULL)
82     return (ENOMEM);
83   host_list = tmp;
84
85   host_list[host_list_len] = strdup (host);
86   if (host_list[host_list_len] == NULL)
87     return (ENOMEM);
88
89   host_list_len++;
90   return (0);
91 } /* }}} int gl_register_host */
92
93 static int gl_clear_hosts (void) /* {{{ */
94 {
95   size_t i;
96
97   for (i = 0; i < host_list_len; i++)
98     free (host_list[i]);
99   free (host_list);
100
101   host_list = NULL;
102   host_list_len = 0;
103
104   return (0);
105 } /* }}} int gl_clear_hosts */
106
107 static int gl_compare_hosts (const void *v0, const void *v1) /* {{{ */
108 {
109   return (strcmp (v0, v1));
110 } /* }}} int gl_compare_hosts */
111
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;
118
119   for (i = 0; i < gl_active_num; i++)
120   {
121     graph_config_t *cfg = gl_active[i];
122     int status;
123
124     if (!graph_matches_ident (cfg, file))
125       continue;
126
127     status = graph_add_file (cfg, file);
128     if (status != 0)
129     {
130       /* report error */;
131     }
132     else
133     {
134       num_graphs++;
135     }
136   }
137
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   }
144
145   gl_register_host (ident_get_host (file));
146
147   return (0);
148 } /* }}} int gl_register_file */
149
150 static const char *get_part_from_param (const char *prim_key, /* {{{ */
151     const char *sec_key)
152 {
153   const char *val;
154
155   val = param (prim_key);
156   if (val != NULL)
157     return (val);
158   
159   return (param (sec_key));
160 } /* }}} const char *get_part_from_param */
161
162 static int gl_clear_instances (void) /* {{{ */
163 {
164   size_t i;
165
166   for (i = 0; i < gl_active_num; i++)
167     graph_clear_instances (gl_active[i]);
168
169   return (0);
170 } /* }}} int gl_clear_instances */
171
172
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 */
180
181 int gl_config_submit (void) /* {{{ */
182 {
183   graph_config_t **old;
184   size_t old_num;
185   size_t i;
186
187   old = gl_active;
188   old_num = gl_active_num;
189
190   gl_active = gl_staging;
191   gl_active_num = gl_staging_num;
192
193   gl_staging = NULL;
194   gl_staging_num = 0;
195
196   for (i = 0; i < old_num; i++)
197   {
198     graph_destroy (old[i]);
199     old[i] = NULL;
200   }
201   free (old);
202
203   return (0);
204 } /* }}} int graph_config_submit */
205
206 int gl_graph_get_all (graph_callback_t callback, /* {{{ */
207     void *user_data)
208 {
209   size_t i;
210
211   if (callback == NULL)
212     return (EINVAL);
213
214   gl_update ();
215
216   for (i = 0; i < gl_active_num; i++)
217   {
218     int status;
219
220     status = (*callback) (gl_active[i], user_data);
221     if (status != 0)
222       return (status);
223   }
224
225   return (0);
226 } /* }}} int gl_graph_get_all */
227
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;
237
238   if ((host == NULL)
239       || (plugin == NULL) || (plugin_instance == NULL)
240       || (type == NULL) || (type_instance == NULL))
241     return (NULL);
242
243   ident = ident_create (host, plugin, plugin_instance, type, type_instance);
244
245   gl_update ();
246
247   for (i = 0; i < gl_active_num; i++)
248   {
249     if (graph_compare (gl_active[i], ident) != 0)
250       continue;
251
252     ident_destroy (ident);
253     return (gl_active[i]);
254   }
255
256   ident_destroy (ident);
257   return (NULL);
258 } /* }}} graph_config_t *gl_graph_get_selected */
259
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 */
267
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;
272
273   return ((*data->callback) (data->cfg, inst, data->user_data));
274 } /* }}} int gl_inst_callback_handler */
275
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   };
285
286   if ((cfg == NULL) || (callback == NULL))
287     return (EINVAL);
288
289   return (graph_inst_foreach (cfg, gl_inst_callback_handler, &data));
290 } /* }}} int gl_graph_instance_get_all */
291
292 int gl_instance_get_all (graph_inst_callback_t callback, /* {{{ */
293     void *user_data)
294 {
295   size_t i;
296
297   gl_update ();
298
299   for (i = 0; i < gl_active_num; i++)
300   {
301     int status;
302
303     status = gl_graph_instance_get_all (gl_active[i], callback, user_data);
304     if (status != 0)
305       return (status);
306   }
307
308   return (0);
309 } /* }}} int gl_instance_get_all */
310 /* }}} gl_instance_get_all, gl_graph_instance_get_all */
311
312 int gl_search (const char *term, graph_inst_callback_t callback, /* {{{ */
313     void *user_data)
314 {
315   size_t i;
316
317   for (i = 0; i < gl_active_num; i++)
318   {
319     int status;
320
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   }
327
328   return (0);
329 } /* }}} int gl_search */
330
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;
336
337   if ((field_value == NULL) || (callback == NULL))
338     return (EINVAL);
339
340   for (i = 0; i < gl_active_num; i++)
341   {
342     int status;
343
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   }
351
352   return (0);
353 } /* }}} int gl_search_field */
354
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;
360
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   }
367
368   return (0);
369 } /* }}} int gl_foreach_host */
370
371 int gl_update (void) /* {{{ */
372 {
373   time_t now;
374   int status;
375
376   /*
377   printf ("Content-Type: text/plain\n\n");
378   */
379
380   now = time (NULL);
381
382   if ((gl_last_update + UPDATE_INTERVAL) >= now)
383     return (0);
384
385   graph_read_config ();
386
387   gl_clear_instances ();
388   gl_clear_hosts ();
389   status = fs_scan (/* callback = */ gl_register_file, /* user data = */ NULL);
390
391   if (host_list_len > 0)
392     qsort (host_list, host_list_len, sizeof (*host_list),
393         gl_compare_hosts);
394
395   gl_last_update = now;
396
397   return (status);
398 } /* }}} int gl_update */
399
400 /* vim: set sw=2 sts=2 et fdm=marker : */