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