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 }; /* }}} struct graph_config_s */
38 /*
39 * Private functions
40 */
41 static graph_instance_t *graph_find_instance (graph_config_t *cfg, /* {{{ */
42 const graph_ident_t *ident)
43 {
44 if ((cfg == NULL) || (ident == NULL))
45 return (NULL);
47 return (inst_find_matching (cfg->instances, ident));
48 } /* }}} graph_instance_t *graph_find_instance */
50 /*
51 * Config functions
52 */
53 static graph_ident_t *graph_config_get_selector (const oconfig_item_t *ci) /* {{{ */
54 {
55 char *host = NULL;
56 char *plugin = NULL;
57 char *plugin_instance = NULL;
58 char *type = NULL;
59 char *type_instance = NULL;
60 graph_ident_t *ret;
61 int i;
63 for (i = 0; i < ci->children_num; i++)
64 {
65 oconfig_item_t *child;
67 child = ci->children + i;
69 if (strcasecmp ("Host", child->key) == 0)
70 graph_config_get_string (child, &host);
71 else if (strcasecmp ("Plugin", child->key) == 0)
72 graph_config_get_string (child, &plugin);
73 else if (strcasecmp ("PluginInstance", child->key) == 0)
74 graph_config_get_string (child, &plugin_instance);
75 else if (strcasecmp ("Type", child->key) == 0)
76 graph_config_get_string (child, &type);
77 else if (strcasecmp ("TypeInstance", child->key) == 0)
78 graph_config_get_string (child, &type_instance);
79 /* else: ignore all other directives here. */
80 } /* for */
82 ret = ident_create (host, plugin, plugin_instance, type, type_instance);
84 free (host);
85 free (plugin);
86 free (plugin_instance);
87 free (type);
88 free (type_instance);
90 return (ret);
91 } /* }}} int graph_config_get_selector */
93 /*
94 * Global functions
95 */
96 graph_config_t *graph_create (const graph_ident_t *selector) /* {{{ */
97 {
98 graph_config_t *cfg;
100 cfg = malloc (sizeof (*cfg));
101 if (cfg == NULL)
102 return (NULL);
103 memset (cfg, 0, sizeof (*cfg));
105 if (selector != NULL)
106 cfg->select = ident_clone (selector);
107 else
108 cfg->select = NULL;
110 cfg->title = NULL;
111 cfg->vertical_label = NULL;
112 cfg->defs = NULL;
113 cfg->instances = NULL;
115 return (cfg);
116 } /* }}} int graph_create */
118 void graph_destroy (graph_config_t *cfg) /* {{{ */
119 {
120 if (cfg == NULL)
121 return;
123 ident_destroy (cfg->select);
125 free (cfg->title);
126 free (cfg->vertical_label);
128 def_destroy (cfg->defs);
129 inst_destroy (cfg->instances);
130 } /* }}} void graph_destroy */
132 int graph_config_add (const oconfig_item_t *ci) /* {{{ */
133 {
134 graph_ident_t *select;
135 graph_config_t *cfg = NULL;
136 int i;
138 select = graph_config_get_selector (ci);
139 if (select == NULL)
140 return (EINVAL);
142 cfg = graph_create (/* selector = */ NULL);
143 if (cfg == NULL)
144 return (ENOMEM);
146 cfg->select = select;
148 for (i = 0; i < ci->children_num; i++)
149 {
150 oconfig_item_t *child;
152 child = ci->children + i;
154 if (strcasecmp ("Title", child->key) == 0)
155 graph_config_get_string (child, &cfg->title);
156 else if (strcasecmp ("VerticalLabel", child->key) == 0)
157 graph_config_get_string (child, &cfg->vertical_label);
158 else if (strcasecmp ("ShowZero", child->key) == 0)
159 graph_config_get_bool (child, &cfg->show_zero);
160 else if (strcasecmp ("DEF", child->key) == 0)
161 def_config (cfg, child);
162 } /* for */
164 gl_add_graph (cfg);
166 return (0);
167 } /* }}} graph_config_add */
169 int graph_add_file (graph_config_t *cfg, const graph_ident_t *file) /* {{{ */
170 {
171 graph_instance_t *inst;
173 inst = graph_find_instance (cfg, file);
174 if (inst == NULL)
175 {
176 inst = inst_create (cfg, file);
177 if (inst == NULL)
178 return (ENOMEM);
180 if (cfg->instances == NULL)
181 cfg->instances = inst;
182 else
183 inst_append (cfg->instances, inst);
184 }
186 return (inst_add_file (inst, file));
187 } /* }}} int graph_add_file */
189 int graph_get_title (graph_config_t *cfg, /* {{{ */
190 char *buffer, size_t buffer_size)
191 {
192 if ((cfg == NULL) || (buffer == NULL) || (buffer_size < 1))
193 return (EINVAL);
195 if (cfg->title == NULL)
196 cfg->title = ident_to_string (cfg->select);
198 if (cfg->title == NULL)
199 return (ENOMEM);
201 strncpy (buffer, cfg->title, buffer_size);
202 buffer[buffer_size - 1] = 0;
204 return (0);
205 } /* }}} int graph_get_title */
207 int graph_get_params (graph_config_t *cfg, /* {{{ */
208 char *buffer, size_t buffer_size)
209 {
210 buffer[0] = 0;
212 #define COPY_FIELD(field) do { \
213 const char *str = ident_get_##field (cfg->select); \
214 char uri_str[1024]; \
215 uri_escape (uri_str, str, sizeof (uri_str)); \
216 strlcat (buffer, #field, buffer_size); \
217 strlcat (buffer, "=", buffer_size); \
218 strlcat (buffer, uri_str, buffer_size); \
219 } while (0)
221 COPY_FIELD(host);
222 strlcat (buffer, ";", buffer_size);
223 COPY_FIELD(plugin);
224 strlcat (buffer, ";", buffer_size);
225 COPY_FIELD(plugin_instance);
226 strlcat (buffer, ";", buffer_size);
227 COPY_FIELD(type);
228 strlcat (buffer, ";", buffer_size);
229 COPY_FIELD(type_instance);
231 #undef COPY_FIELD
233 return (0);
234 } /* }}} int graph_get_params */
236 graph_ident_t *graph_get_selector (graph_config_t *cfg) /* {{{ */
237 {
238 if (cfg == NULL)
239 return (NULL);
241 return (ident_clone (cfg->select));
242 } /* }}} graph_ident_t *graph_get_selector */
244 graph_instance_t *graph_get_instances (graph_config_t *cfg) /* {{{ */
245 {
246 if (cfg == NULL)
247 return (NULL);
249 return (cfg->instances);
250 } /* }}} graph_instance_t *graph_get_instances */
252 graph_def_t *graph_get_defs (graph_config_t *cfg) /* {{{ */
253 {
254 if (cfg == NULL)
255 return (NULL);
257 return (cfg->defs);
258 } /* }}} graph_def_t *graph_get_defs */
260 int graph_add_def (graph_config_t *cfg, graph_def_t *def) /* {{{ */
261 {
262 if ((cfg == NULL) || (def == NULL))
263 return (EINVAL);
265 if (cfg->defs == NULL)
266 {
267 cfg->defs = def;
268 return (0);
269 }
271 return (def_append (cfg->defs, def));
272 } /* }}} int graph_add_def */
274 _Bool graph_matches (graph_config_t *cfg, const graph_ident_t *ident) /* {{{ */
275 {
276 if ((cfg == NULL) || (ident == NULL))
277 return (0);
279 return (ident_matches (cfg->select, ident));
280 } /* }}} _Bool graph_matches */
282 struct graph_search_data_s
283 {
284 graph_config_t *cfg;
285 graph_inst_callback_t callback;
286 void *user_data;
287 };
288 typedef struct graph_search_data_s graph_search_data_t;
290 static int graph_search_submit (graph_instance_t *inst, /* {{{ */
291 void *user_data)
292 {
293 graph_search_data_t *data = user_data;
295 if ((inst == NULL) || (data == NULL))
296 return (EINVAL);
298 return ((*data->callback) (data->cfg, inst, data->user_data));
299 } /* }}} int graph_search_submit */
301 int graph_inst_foreach (graph_config_t *cfg, /* {{{ */
302 inst_callback_t cb, void *user_data)
303 {
304 return (inst_foreach (cfg->instances, cb, user_data));
305 } /* }}} int graph_inst_foreach */
307 int graph_search (graph_config_t *cfg, const char *term, /* {{{ */
308 graph_inst_callback_t callback,
309 void *user_data)
310 {
311 graph_search_data_t data = { cfg, callback, user_data };
312 char buffer[1024];
313 int status;
315 status = graph_get_title (cfg, buffer, sizeof (buffer));
316 if (status != 0)
317 {
318 fprintf (stderr, "graph_search: graph_get_title failed\n");
319 return (status);
320 }
322 strtolower (buffer);
324 if (strstr (buffer, term) != NULL)
325 {
326 status = inst_foreach (cfg->instances, graph_search_submit, &data);
327 if (status != 0)
328 return (status);
329 }
330 else
331 {
332 status = inst_search (cfg, cfg->instances, term,
333 graph_search_submit, &data);
334 if (status != 0)
335 return (status);
336 }
338 return (0);
339 } /* }}} int graph_search */
341 int graph_compare (graph_config_t *cfg, const graph_ident_t *ident) /* {{{ */
342 {
343 if ((cfg == NULL) || (ident == NULL))
344 return (0);
346 return (ident_compare (cfg->select, ident));
347 } /* }}} int graph_compare */
349 int graph_clear_instances (graph_config_t *cfg) /* {{{ */
350 {
351 if (cfg == NULL)
352 return (EINVAL);
354 inst_destroy (cfg->instances);
355 cfg->instances = NULL;
357 return (0);
358 } /* }}} int graph_clear_instances */
360 int graph_get_rrdargs (graph_config_t *cfg, graph_instance_t *inst, /* {{{ */
361 str_array_t *args)
362 {
363 if ((cfg == NULL) || (inst == NULL) || (args == NULL))
364 return (EINVAL);
366 if (cfg->title != NULL)
367 {
368 array_append (args, "-t");
369 array_append (args, cfg->title);
370 }
372 if (cfg->vertical_label != NULL)
373 {
374 array_append (args, "-v");
375 array_append (args, cfg->vertical_label);
376 }
378 if (cfg->show_zero)
379 {
380 array_append (args, "-l");
381 array_append (args, "0");
382 }
384 return (0);
385 } /* }}} int graph_get_rrdargs */
387 /* vim: set sw=2 sts=2 et fdm=marker : */