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