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>
10 #include "graph.h"
11 #include "graph_list.h"
12 #include "graph_ident.h"
13 #include "graph_def.h"
14 #include "graph_config.h"
15 #include "common.h"
16 #include "filesystem.h"
17 #include "utils_cgi.h"
19 #include <fcgiapp.h>
20 #include <fcgi_stdio.h>
22 /*
23 * Data types
24 */
25 struct graph_config_s /* {{{ */
26 {
27 graph_ident_t *select;
29 char *title;
30 char *vertical_label;
31 _Bool show_zero;
33 graph_def_t *defs;
35 graph_instance_t **instances;
36 size_t instances_num;
37 }; /* }}} struct graph_config_s */
39 /*
40 * Private functions
41 */
43 /*
44 * Config functions
45 */
46 static graph_ident_t *graph_config_get_selector (const oconfig_item_t *ci) /* {{{ */
47 {
48 char *host = NULL;
49 char *plugin = NULL;
50 char *plugin_instance = NULL;
51 char *type = NULL;
52 char *type_instance = NULL;
53 graph_ident_t *ret;
54 int i;
56 for (i = 0; i < ci->children_num; i++)
57 {
58 oconfig_item_t *child;
60 child = ci->children + i;
62 if (strcasecmp ("Host", child->key) == 0)
63 graph_config_get_string (child, &host);
64 else if (strcasecmp ("Plugin", child->key) == 0)
65 graph_config_get_string (child, &plugin);
66 else if (strcasecmp ("PluginInstance", child->key) == 0)
67 graph_config_get_string (child, &plugin_instance);
68 else if (strcasecmp ("Type", child->key) == 0)
69 graph_config_get_string (child, &type);
70 else if (strcasecmp ("TypeInstance", child->key) == 0)
71 graph_config_get_string (child, &type_instance);
72 /* else: ignore all other directives here. */
73 } /* for */
75 ret = ident_create (host, plugin, plugin_instance, type, type_instance);
77 free (host);
78 free (plugin);
79 free (plugin_instance);
80 free (type);
81 free (type_instance);
83 return (ret);
84 } /* }}} int graph_config_get_selector */
86 /*
87 * Global functions
88 */
89 graph_config_t *graph_create (const graph_ident_t *selector) /* {{{ */
90 {
91 graph_config_t *cfg;
93 cfg = malloc (sizeof (*cfg));
94 if (cfg == NULL)
95 return (NULL);
96 memset (cfg, 0, sizeof (*cfg));
98 if (selector != NULL)
99 cfg->select = ident_clone (selector);
100 else
101 cfg->select = NULL;
103 cfg->title = NULL;
104 cfg->vertical_label = NULL;
105 cfg->defs = NULL;
106 cfg->instances = NULL;
108 return (cfg);
109 } /* }}} int graph_create */
111 void graph_destroy (graph_config_t *cfg) /* {{{ */
112 {
113 size_t i;
115 if (cfg == NULL)
116 return;
118 ident_destroy (cfg->select);
120 free (cfg->title);
121 free (cfg->vertical_label);
123 def_destroy (cfg->defs);
125 for (i = 0; i < cfg->instances_num; i++)
126 inst_destroy (cfg->instances[i]);
127 free (cfg->instances);
128 } /* }}} void graph_destroy */
130 int graph_config_add (const oconfig_item_t *ci) /* {{{ */
131 {
132 graph_ident_t *select;
133 graph_config_t *cfg = NULL;
134 int i;
136 select = graph_config_get_selector (ci);
137 if (select == NULL)
138 return (EINVAL);
140 cfg = graph_create (/* selector = */ NULL);
141 if (cfg == NULL)
142 return (ENOMEM);
144 cfg->select = select;
146 for (i = 0; i < ci->children_num; i++)
147 {
148 oconfig_item_t *child;
150 child = ci->children + i;
152 if (strcasecmp ("Title", child->key) == 0)
153 graph_config_get_string (child, &cfg->title);
154 else if (strcasecmp ("VerticalLabel", child->key) == 0)
155 graph_config_get_string (child, &cfg->vertical_label);
156 else if (strcasecmp ("ShowZero", child->key) == 0)
157 graph_config_get_bool (child, &cfg->show_zero);
158 else if (strcasecmp ("DEF", child->key) == 0)
159 def_config (cfg, child);
160 } /* for */
162 gl_add_graph (cfg);
164 return (0);
165 } /* }}} graph_config_add */
167 int graph_add_file (graph_config_t *cfg, const graph_ident_t *file) /* {{{ */
168 {
169 graph_instance_t *inst;
171 inst = graph_inst_find_matching (cfg, file);
172 if (inst == NULL)
173 {
174 graph_instance_t **tmp;
176 tmp = realloc (cfg->instances,
177 sizeof (*cfg->instances) * (cfg->instances_num + 1));
178 if (tmp == NULL)
179 return (ENOMEM);
180 cfg->instances = tmp;
182 inst = inst_create (cfg, file);
183 if (inst == NULL)
184 return (ENOMEM);
186 cfg->instances[cfg->instances_num] = inst;
187 cfg->instances_num++;
188 }
190 return (inst_add_file (inst, file));
191 } /* }}} int graph_add_file */
193 int graph_get_title (graph_config_t *cfg, /* {{{ */
194 char *buffer, size_t buffer_size)
195 {
196 if ((cfg == NULL) || (buffer == NULL) || (buffer_size < 1))
197 return (EINVAL);
199 if (cfg->title == NULL)
200 cfg->title = ident_to_string (cfg->select);
202 if (cfg->title == NULL)
203 return (ENOMEM);
205 strncpy (buffer, cfg->title, buffer_size);
206 buffer[buffer_size - 1] = 0;
208 return (0);
209 } /* }}} int graph_get_title */
211 int graph_get_params (graph_config_t *cfg, /* {{{ */
212 char *buffer, size_t buffer_size)
213 {
214 buffer[0] = 0;
216 #define COPY_FIELD(field) do { \
217 const char *str = ident_get_##field (cfg->select); \
218 char uri_str[1024]; \
219 uri_escape (uri_str, str, sizeof (uri_str)); \
220 strlcat (buffer, #field, buffer_size); \
221 strlcat (buffer, "=", buffer_size); \
222 strlcat (buffer, uri_str, buffer_size); \
223 } while (0)
225 COPY_FIELD(host);
226 strlcat (buffer, ";", buffer_size);
227 COPY_FIELD(plugin);
228 strlcat (buffer, ";", buffer_size);
229 COPY_FIELD(plugin_instance);
230 strlcat (buffer, ";", buffer_size);
231 COPY_FIELD(type);
232 strlcat (buffer, ";", buffer_size);
233 COPY_FIELD(type_instance);
235 #undef COPY_FIELD
237 return (0);
238 } /* }}} int graph_get_params */
240 graph_ident_t *graph_get_selector (graph_config_t *cfg) /* {{{ */
241 {
242 if (cfg == NULL)
243 return (NULL);
245 return (ident_clone (cfg->select));
246 } /* }}} graph_ident_t *graph_get_selector */
248 graph_def_t *graph_get_defs (graph_config_t *cfg) /* {{{ */
249 {
250 if (cfg == NULL)
251 return (NULL);
253 return (cfg->defs);
254 } /* }}} graph_def_t *graph_get_defs */
256 int graph_add_def (graph_config_t *cfg, graph_def_t *def) /* {{{ */
257 {
258 if ((cfg == NULL) || (def == NULL))
259 return (EINVAL);
261 if (cfg->defs == NULL)
262 {
263 cfg->defs = def;
264 return (0);
265 }
267 return (def_append (cfg->defs, def));
268 } /* }}} int graph_add_def */
270 _Bool graph_matches_ident (graph_config_t *cfg, const graph_ident_t *ident) /* {{{ */
271 {
272 if ((cfg == NULL) || (ident == NULL))
273 return (0);
275 return (ident_matches (cfg->select, ident));
276 } /* }}} _Bool graph_matches_ident */
278 _Bool graph_matches_field (graph_config_t *cfg, /* {{{ */
279 graph_ident_field_t field, const char *field_value)
280 {
281 const char *selector_value;
283 if ((cfg == NULL) || (field_value == NULL))
284 return (0);
286 selector_value = ident_get_field (cfg->select, field);
287 if (selector_value == NULL)
288 return (0);
290 if (IS_ALL (selector_value) || IS_ANY (selector_value))
291 return (1);
292 else if (strcasecmp (selector_value, field_value) == 0)
293 return (1);
295 return (0);
296 } /* }}} _Bool graph_matches_field */
298 int graph_inst_foreach (graph_config_t *cfg, /* {{{ */
299 inst_callback_t cb, void *user_data)
300 {
301 size_t i;
302 int status;
304 for (i = 0; i < cfg->instances_num; i++)
305 {
306 status = (*cb) (cfg->instances[i], user_data);
307 if (status != 0)
308 return (status);
309 }
311 return (0);
312 } /* }}} int graph_inst_foreach */
314 graph_instance_t *graph_inst_find_exact (graph_config_t *cfg, /* {{{ */
315 graph_ident_t *ident)
316 {
317 size_t i;
319 if ((cfg == NULL) || (ident == NULL))
320 return (NULL);
322 for (i = 0; i < cfg->instances_num; i++)
323 if (inst_compare_ident (cfg->instances[i], ident) == 0)
324 return (cfg->instances[i]);
326 return (NULL);
327 } /* }}} graph_instance_t *graph_inst_find_exact */
329 graph_instance_t *graph_inst_find_matching (graph_config_t *cfg, /* {{{ */
330 const graph_ident_t *ident)
331 {
332 size_t i;
334 if ((cfg == NULL) || (ident == NULL))
335 return (NULL);
337 for (i = 0; i < cfg->instances_num; i++)
338 if (inst_matches_ident (cfg->instances[i], ident))
339 return (cfg->instances[i]);
341 return (NULL);
342 } /* }}} graph_instance_t *graph_inst_find_matching */
344 int graph_inst_search (graph_config_t *cfg, const char *term, /* {{{ */
345 graph_inst_callback_t cb,
346 void *user_data)
347 {
348 char buffer[1024];
349 int status;
350 size_t i;
352 status = graph_get_title (cfg, buffer, sizeof (buffer));
353 if (status != 0)
354 {
355 fprintf (stderr, "graph_inst_search: graph_get_title failed\n");
356 return (status);
357 }
359 strtolower (buffer);
361 if (strstr (buffer, term) != NULL)
362 {
363 for (i = 0; i < cfg->instances_num; i++)
364 {
365 status = (*cb) (cfg, cfg->instances[i], user_data);
366 if (status != 0)
367 return (status);
368 }
369 }
370 else
371 {
372 for (i = 0; i < cfg->instances_num; i++)
373 {
374 if (inst_matches_string (cfg, cfg->instances[i], term))
375 {
376 status = (*cb) (cfg, cfg->instances[i], user_data);
377 if (status != 0)
378 return (status);
379 }
380 }
381 }
383 return (0);
384 } /* }}} int graph_inst_search */
386 int graph_inst_search_field (graph_config_t *cfg, /* {{{ */
387 graph_ident_field_t field, const char *field_value,
388 graph_inst_callback_t callback, void *user_data)
389 {
390 size_t i;
392 if ((cfg == NULL) || (field_value == NULL) || (callback == NULL))
393 return (EINVAL);
395 if (!graph_matches_field (cfg, field, field_value))
396 return (0);
398 for (i = 0; i < cfg->instances_num; i++)
399 {
400 if (inst_matches_field (cfg->instances[i], field, field_value))
401 {
402 int status;
404 status = (*callback) (cfg, cfg->instances[i], user_data);
405 if (status != 0)
406 return (status);
407 }
408 }
410 return (0);
411 } /* }}} int graph_inst_search_field */
413 int graph_compare (graph_config_t *cfg, const graph_ident_t *ident) /* {{{ */
414 {
415 if ((cfg == NULL) || (ident == NULL))
416 return (0);
418 return (ident_compare (cfg->select, ident));
419 } /* }}} int graph_compare */
421 int graph_clear_instances (graph_config_t *cfg) /* {{{ */
422 {
423 size_t i;
425 if (cfg == NULL)
426 return (EINVAL);
428 for (i = 0; i < cfg->instances_num; i++)
429 inst_destroy (cfg->instances[i]);
430 free (cfg->instances);
431 cfg->instances = NULL;
432 cfg->instances_num = 0;
434 return (0);
435 } /* }}} int graph_clear_instances */
437 int graph_get_rrdargs (graph_config_t *cfg, graph_instance_t *inst, /* {{{ */
438 str_array_t *args)
439 {
440 if ((cfg == NULL) || (inst == NULL) || (args == NULL))
441 return (EINVAL);
443 if (cfg->title != NULL)
444 {
445 array_append (args, "-t");
446 array_append (args, cfg->title);
447 }
449 if (cfg->vertical_label != NULL)
450 {
451 array_append (args, "-v");
452 array_append (args, cfg->vertical_label);
453 }
455 if (cfg->show_zero)
456 {
457 array_append (args, "-l");
458 array_append (args, "0");
459 }
461 return (0);
462 } /* }}} int graph_get_rrdargs */
464 /* vim: set sw=2 sts=2 et fdm=marker : */