b8e0ce4e5402e9f76cf67ca879b15ef568418230
1 #include <stdlib.h>
2 #include <string.h>
3 #include <errno.h>
5 #include "graph_def.h"
6 #include "graph.h"
7 #include "graph_config.h"
8 #include "common.h"
9 #include "oconfig.h"
11 #include <fcgiapp.h>
12 #include <fcgi_stdio.h>
14 /*
15 * Data structures
16 */
17 struct graph_def_s
18 {
19 graph_ident_t *select;
21 char *ds_name;
22 char *legend;
23 uint32_t color;
24 _Bool stack;
25 _Bool area;
26 char *format;
28 graph_def_t *next;
29 };
31 /*
32 * Private functions
33 */
34 #define DEF_CONFIG_FIELD(field) \
35 static int def_config_##field (const oconfig_item_t *ci, graph_ident_t *ident) \
36 { \
37 char *tmp = NULL; \
38 int status = graph_config_get_string (ci, &tmp); \
39 if (status != 0) \
40 return (status); \
41 ident_set_##field (ident, tmp); \
42 free (tmp); \
43 return (0); \
44 } /* }}} int def_config_field */
46 DEF_CONFIG_FIELD (host);
47 DEF_CONFIG_FIELD (plugin);
48 DEF_CONFIG_FIELD (plugin_instance);
49 DEF_CONFIG_FIELD (type);
50 DEF_CONFIG_FIELD (type_instance);
52 #undef DEF_CONFIG_FIELD
54 static int def_config_color (const oconfig_item_t *ci, uint32_t *ret_color) /* {{{ */
55 {
56 char *tmp;
57 char *endptr;
58 uint32_t color;
60 if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
61 return (EINVAL);
63 tmp = ci->values[0].value.string;
65 endptr = NULL;
66 errno = 0;
67 color = (uint32_t) strtoul (tmp, &endptr, /* base = */ 16);
68 if ((errno != 0) || (endptr == tmp) || (color > 0x00ffffff))
69 return (EINVAL);
71 *ret_color = color;
73 return (0);
74 } /* }}} int def_config_color */
76 static graph_def_t *def_config_get_obj (graph_config_t *cfg, /* {{{ */
77 const oconfig_item_t *ci)
78 {
79 graph_ident_t *ident;
80 char *ds_name = NULL;
81 graph_def_t *def;
82 int i;
84 ident = graph_get_selector (cfg);
85 if (ident == NULL)
86 {
87 fprintf (stderr, "def_config_get_obj: graph_get_selector failed");
88 return (NULL);
89 }
91 for (i = 0; i < ci->children_num; i++)
92 {
93 oconfig_item_t *child;
95 #define HANDLE_FIELD(name,field) \
96 else if (strcasecmp (name, child->key) == 0) \
97 def_config_##field (child, ident)
99 child = ci->children + i;
100 if (strcasecmp ("DSName", child->key) == 0)
101 graph_config_get_string (child, &ds_name);
103 HANDLE_FIELD ("Host", host);
104 HANDLE_FIELD ("Plugin", plugin);
105 HANDLE_FIELD ("PluginInstance", plugin_instance);
106 HANDLE_FIELD ("Type", type);
107 HANDLE_FIELD ("TypeInstance", type_instance);
109 #undef HANDLE_FIELD
110 }
112 def = def_create (cfg, ident, ds_name);
113 if (def == NULL)
114 {
115 fprintf (stderr, "def_config_get_obj: def_create failed\n");
116 ident_destroy (ident);
117 free (ds_name);
118 return (NULL);
119 }
121 ident_destroy (ident);
122 free (ds_name);
124 return (def);
125 } /* }}} graph_def_t *def_config_get_obj */
127 /*
128 * Public functions
129 */
130 graph_def_t *def_create (graph_config_t *cfg, graph_ident_t *ident, /* {{{ */
131 const char *ds_name)
132 {
133 graph_ident_t *selector;
134 graph_def_t *ret;
136 if ((cfg == NULL) || (ident == NULL) || (ds_name == NULL))
137 return (NULL);
139 selector = graph_get_selector (cfg);
140 if (selector == NULL)
141 return (NULL);
143 ret = malloc (sizeof (*ret));
144 if (ret == NULL)
145 {
146 ident_destroy (selector);
147 return (NULL);
148 }
149 memset (ret, 0, sizeof (*ret));
150 ret->legend = NULL;
151 ret->format = NULL;
153 ret->ds_name = strdup (ds_name);
154 if (ret->ds_name == NULL)
155 {
156 ident_destroy (selector);
157 free (ret);
158 return (NULL);
159 }
161 ret->color = get_random_color ();
162 ret->next = NULL;
164 ret->select = ident_copy_with_selector (selector, ident,
165 IDENT_FLAG_REPLACE_ALL);
166 if (ret->select == NULL)
167 {
168 ident_destroy (selector);
169 free (ret->ds_name);
170 free (ret);
171 return (NULL);
172 }
174 ident_destroy (selector);
175 return (ret);
176 } /* }}} graph_def_t *def_create */
178 void def_destroy (graph_def_t *def) /* {{{ */
179 {
180 graph_def_t *next;
182 if (def == NULL)
183 return;
185 next = def->next;
187 ident_destroy (def->select);
189 free (def->ds_name);
190 free (def->legend);
191 free (def->format);
193 free (def);
195 def_destroy (next);
196 } /* }}} void def_destroy */
198 int def_config (graph_config_t *cfg, const oconfig_item_t *ci) /* {{{ */
199 {
200 graph_def_t *def;
201 int i;
203 def = def_config_get_obj (cfg, ci);
204 if (def == NULL)
205 return (EINVAL);
207 for (i = 0; i < ci->children_num; i++)
208 {
209 oconfig_item_t *child;
211 child = ci->children + i;
212 if (strcasecmp ("Legend", child->key) == 0)
213 graph_config_get_string (child, &def->legend);
214 else if (strcasecmp ("Color", child->key) == 0)
215 def_config_color (child, &def->color);
216 else if (strcasecmp ("Stack", child->key) == 0)
217 graph_config_get_bool (child, &def->stack);
218 else if (strcasecmp ("Area", child->key) == 0)
219 graph_config_get_bool (child, &def->area);
220 else if (strcasecmp ("Format", child->key) == 0)
221 graph_config_get_string (child, &def->format);
222 else
223 fprintf (stderr, "def_config: Ignoring unknown config option \"%s\"",
224 child->key);
225 }
227 return (graph_add_def (cfg, def));
228 } /* }}} int def_config */
230 int def_append (graph_def_t *head, graph_def_t *def) /* {{{ */
231 {
232 graph_def_t *ptr;
234 if ((head == NULL) || (def == NULL))
235 return (EINVAL);
237 ptr = head;
238 while (ptr->next != NULL)
239 ptr = ptr->next;
241 ptr->next = def;
243 return (0);
244 } /* }}} int def_append */
246 graph_def_t *def_search (graph_def_t *head, graph_ident_t *ident, /* {{{ */
247 const char *ds_name)
248 {
249 graph_def_t *ptr;
251 if ((head == NULL) || (ident == NULL) || (ds_name == NULL))
252 return (NULL);
254 for (ptr = head; ptr != NULL; ptr = ptr->next)
255 {
256 if (!ident_matches (ptr->select, ident))
257 continue;
259 if (strcmp (ptr->ds_name, ds_name) == 0)
260 return (ptr);
261 }
263 return (NULL);
264 } /* }}} graph_def_t *def_search */
266 _Bool def_matches (graph_def_t *def, graph_ident_t *ident) /* {{{ */
267 {
268 return (ident_matches (def->select, ident));
269 } /* }}} _Bool def_matches */
271 int def_foreach (graph_def_t *def, def_callback_t callback, /* {{{ */
272 void *user_data)
273 {
274 graph_def_t *ptr;
276 if ((def == NULL) || (callback == NULL))
277 return (EINVAL);
279 for (ptr = def; ptr != NULL; ptr = ptr->next)
280 {
281 int status;
283 status = (*callback) (ptr, user_data);
284 if (status != 0)
285 return (status);
286 }
288 return (0);
289 } /* }}} int def_foreach */
291 int def_get_rrdargs (graph_def_t *def, graph_ident_t *ident, /* {{{ */
292 str_array_t *args)
293 {
294 char *file;
295 int index;
297 if ((def == NULL) || (ident == NULL) || (args == NULL))
298 return (EINVAL);
300 file = ident_to_file (ident);
301 if (file == NULL)
302 {
303 DEBUG ("gl_ident_get_rrdargs: ident_to_file returned NULL.\n");
304 return (-1);
305 }
307 DEBUG ("gl_ident_get_rrdargs: file = %s;\n", file);
309 index = array_argc (args);
311 /* CDEFs */
312 array_append_format (args, "DEF:def_%04i_min=%s:%s:MIN",
313 index, file, def->ds_name);
314 array_append_format (args, "DEF:def_%04i_avg=%s:%s:AVERAGE",
315 index, file, def->ds_name);
316 array_append_format (args, "DEF:def_%04i_max=%s:%s:MAX",
317 index, file, def->ds_name);
318 /* VDEFs */
319 array_append_format (args, "VDEF:vdef_%04i_min=def_%04i_min,MINIMUM",
320 index, index);
321 array_append_format (args, "VDEF:vdef_%04i_avg=def_%04i_avg,AVERAGE",
322 index, index);
323 array_append_format (args, "VDEF:vdef_%04i_max=def_%04i_max,MAXIMUM",
324 index, index);
325 array_append_format (args, "VDEF:vdef_%04i_lst=def_%04i_avg,LAST",
326 index, index);
328 /* Graph part */
329 array_append_format (args, "%s:def_%04i_avg#%06"PRIx32":%s%s",
330 def->area ? "AREA" : "LINE1",
331 index, def->color,
332 (def->legend != NULL) ? def->legend : def->ds_name,
333 def->stack ? ":STACK" : "");
334 array_append_format (args, "GPRINT:vdef_%04i_min:%s min,",
335 index, (def->format != NULL) ? def->format : "%lg");
336 array_append_format (args, "GPRINT:vdef_%04i_avg:%s avg,",
337 index, (def->format != NULL) ? def->format : "%lg");
338 array_append_format (args, "GPRINT:vdef_%04i_max:%s max,",
339 index, (def->format != NULL) ? def->format : "%lg");
340 array_append_format (args, "GPRINT:vdef_%04i_lst:%s last\\l",
341 index, (def->format != NULL) ? def->format : "%lg");
343 free (file);
345 return (0);
346 } /* }}} int def_get_rrdargs */
348 /* vim: set sw=2 sts=2 et fdm=marker : */