"list graphs" action: Support searching for plugin- and type-instances.
[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 "graph.h"
11 #include "graph_ident.h"
12 #include "graph_def.h"
13 #include "graph_config.h"
14 #include "common.h"
15 #include "filesystem.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 time_t gl_last_update = 0;
36
37 /*
38  * Private functions
39  */
40 int gl_add_graph_internal (graph_config_t *cfg, /* {{{ */
41     graph_config_t ***gl_array, size_t *gl_array_num)
42 {
43   graph_config_t **tmp;
44
45 #define ARRAY_PTR  (*gl_array)
46 #define ARRAY_SIZE (*gl_array_num)
47
48   if (cfg == NULL)
49     return (EINVAL);
50
51   tmp = realloc (ARRAY_PTR, sizeof (*ARRAY_PTR) * (ARRAY_SIZE + 1));
52   if (tmp == NULL)
53     return (ENOMEM);
54   ARRAY_PTR = tmp;
55
56   ARRAY_PTR[ARRAY_SIZE] = cfg;
57   ARRAY_SIZE++;
58
59 #undef ARRAY_SIZE
60 #undef ARRAY_PTR
61
62   return (0);
63 } /* }}} int gl_add_graph_internal */
64
65 static int gl_register_file (const graph_ident_t *file, /* {{{ */
66     __attribute__((unused)) void *user_data)
67 {
68   graph_config_t *cfg;
69   int num_graphs = 0;
70   size_t i;
71
72   for (i = 0; i < gl_active_num; i++)
73   {
74     graph_config_t *cfg = gl_active[i];
75     int status;
76
77     if (!graph_matches_ident (cfg, file))
78       continue;
79
80     status = graph_add_file (cfg, file);
81     if (status != 0)
82     {
83       /* report error */;
84     }
85     else
86     {
87       num_graphs++;
88     }
89   }
90
91   if (num_graphs == 0)
92   {
93     cfg = graph_create (file);
94     gl_add_graph_internal (cfg, &gl_active, &gl_active_num);
95     graph_add_file (cfg, file);
96   }
97
98   return (0);
99 } /* }}} int gl_register_file */
100
101 static const char *get_part_from_param (const char *prim_key, /* {{{ */
102     const char *sec_key)
103 {
104   const char *val;
105
106   val = param (prim_key);
107   if (val != NULL)
108     return (val);
109   
110   return (param (sec_key));
111 } /* }}} const char *get_part_from_param */
112
113 static int gl_clear_instances (void) /* {{{ */
114 {
115   size_t i;
116
117   for (i = 0; i < gl_active_num; i++)
118     graph_clear_instances (gl_active[i]);
119
120   return (0);
121 } /* }}} int gl_clear_instances */
122
123
124 /*
125  * Global functions
126  */
127 int gl_add_graph (graph_config_t *cfg) /* {{{ */
128 {
129   return (gl_add_graph_internal (cfg, &gl_staging, &gl_staging_num));
130 } /* }}} int gl_add_graph */
131
132 int gl_config_submit (void) /* {{{ */
133 {
134   graph_config_t **old;
135   size_t old_num;
136   size_t i;
137
138   old = gl_active;
139   old_num = gl_active_num;
140
141   gl_active = gl_staging;
142   gl_active_num = gl_staging_num;
143
144   gl_staging = NULL;
145   gl_staging_num = 0;
146
147   for (i = 0; i < old_num; i++)
148   {
149     graph_destroy (old[i]);
150     old[i] = NULL;
151   }
152   free (old);
153
154   return (0);
155 } /* }}} int graph_config_submit */
156
157 int gl_graph_get_all (graph_callback_t callback, /* {{{ */
158     void *user_data)
159 {
160   size_t i;
161
162   if (callback == NULL)
163     return (EINVAL);
164
165   gl_update ();
166
167   for (i = 0; i < gl_active_num; i++)
168   {
169     int status;
170
171     status = (*callback) (gl_active[i], user_data);
172     if (status != 0)
173       return (status);
174   }
175
176   return (0);
177 } /* }}} int gl_graph_get_all */
178
179 graph_config_t *gl_graph_get_selected (void) /* {{{ */
180 {
181   const char *host = get_part_from_param ("graph_host", "host");
182   const char *plugin = get_part_from_param ("graph_plugin", "plugin");
183   const char *plugin_instance = get_part_from_param ("graph_plugin_instance", "plugin_instance");
184   const char *type = get_part_from_param ("graph_type", "type");
185   const char *type_instance = get_part_from_param ("graph_type_instance", "type_instance");
186   graph_ident_t *ident;
187   size_t i;
188
189   if ((host == NULL)
190       || (plugin == NULL) || (plugin_instance == NULL)
191       || (type == NULL) || (type_instance == NULL))
192     return (NULL);
193
194   ident = ident_create (host, plugin, plugin_instance, type, type_instance);
195
196   gl_update ();
197
198   for (i = 0; i < gl_active_num; i++)
199   {
200     if (graph_compare (gl_active[i], ident) != 0)
201       continue;
202
203     ident_destroy (ident);
204     return (gl_active[i]);
205   }
206
207   ident_destroy (ident);
208   return (NULL);
209 } /* }}} graph_config_t *gl_graph_get_selected */
210
211 /* gl_instance_get_all, gl_graph_instance_get_all {{{ */
212 struct gl_inst_callback_data /* {{{ */
213 {
214   graph_config_t *cfg;
215   graph_inst_callback_t callback;
216   void *user_data;
217 }; /* }}} struct gl_inst_callback_data */
218
219 static int gl_inst_callback_handler (graph_instance_t *inst, /* {{{ */
220     void *user_data)
221 {
222   struct gl_inst_callback_data *data = user_data;
223
224   return ((*data->callback) (data->cfg, inst, data->user_data));
225 } /* }}} int gl_inst_callback_handler */
226
227 int gl_graph_instance_get_all (graph_config_t *cfg, /* {{{ */
228     graph_inst_callback_t callback, void *user_data)
229 {
230   struct gl_inst_callback_data data =
231   {
232     cfg,
233     callback,
234     user_data
235   };
236
237   if ((cfg == NULL) || (callback == NULL))
238     return (EINVAL);
239
240   return (graph_inst_foreach (cfg, gl_inst_callback_handler, &data));
241 } /* }}} int gl_graph_instance_get_all */
242
243 int gl_instance_get_all (graph_inst_callback_t callback, /* {{{ */
244     void *user_data)
245 {
246   size_t i;
247
248   gl_update ();
249
250   for (i = 0; i < gl_active_num; i++)
251   {
252     int status;
253
254     status = gl_graph_instance_get_all (gl_active[i], callback, user_data);
255     if (status != 0)
256       return (status);
257   }
258
259   return (0);
260 } /* }}} int gl_instance_get_all */
261 /* }}} gl_instance_get_all, gl_graph_instance_get_all */
262
263 int gl_search (const char *term, graph_inst_callback_t callback, /* {{{ */
264     void *user_data)
265 {
266   size_t i;
267
268   for (i = 0; i < gl_active_num; i++)
269   {
270     int status;
271
272     status = graph_inst_search (gl_active[i], term,
273         /* callback  = */ callback,
274         /* user data = */ user_data);
275     if (status != 0)
276       return (status);
277   }
278
279   return (0);
280 } /* }}} int gl_search */
281
282 int gl_search_field (graph_ident_field_t field, /* {{{ */
283     const char *field_value,
284     graph_inst_callback_t callback, void *user_data)
285 {
286   size_t i;
287
288   if ((field_value == NULL) || (callback == NULL))
289     return (EINVAL);
290
291   for (i = 0; i < gl_active_num; i++)
292   {
293     int status;
294
295     status = graph_inst_search_field (gl_active[i],
296         field, field_value,
297         /* callback  = */ callback,
298         /* user data = */ user_data);
299     if (status != 0)
300       return (status);
301   }
302
303   return (0);
304 } /* }}} int gl_search_field */
305
306 int gl_update (void) /* {{{ */
307 {
308   time_t now;
309   int status;
310
311   /*
312   printf ("Content-Type: text/plain\n\n");
313   */
314
315   now = time (NULL);
316
317   if ((gl_last_update + UPDATE_INTERVAL) >= now)
318     return (0);
319
320   graph_read_config ();
321
322   gl_clear_instances ();
323   status = fs_scan (/* callback = */ gl_register_file, /* user data = */ NULL);
324
325   gl_last_update = now;
326
327   return (status);
328 } /* }}} int gl_update */
329
330 /* vim: set sw=2 sts=2 et fdm=marker : */