Implement "DEF" configuration.
[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
24   graph_def_t *next;
25 };
26
27 /*
28  * Private functions
29  */
30 #define DEF_CONFIG_FIELD(field) \
31 static int def_config_##field (const oconfig_item_t *ci, graph_ident_t *ident) \
32 {                                                                              \
33   char *tmp = NULL;                                                            \
34   int status = graph_config_get_string (ci, &tmp);                             \
35   if (status != 0)                                                             \
36     return (status);                                                           \
37   ident_set_##field (ident, tmp);                                              \
38   free (tmp);                                                                  \
39   return (0);                                                                  \
40 } /* }}} int def_config_field */
41
42 DEF_CONFIG_FIELD (host);
43 DEF_CONFIG_FIELD (plugin);
44 DEF_CONFIG_FIELD (plugin_instance);
45 DEF_CONFIG_FIELD (type);
46 DEF_CONFIG_FIELD (type_instance);
47
48 #undef DEF_CONFIG_FIELD
49
50 /*
51  * Public functions
52  */
53 graph_def_t *def_create (graph_config_t *cfg, graph_ident_t *ident, /* {{{ */
54     const char *ds_name)
55 {
56   graph_ident_t *selector;
57   graph_def_t *ret;
58
59   if ((cfg == NULL) || (ident == NULL) || (ds_name == NULL))
60     return (NULL);
61
62   selector = gl_graph_get_selector (cfg);
63   if (selector == NULL)
64     return (NULL);
65
66   ret = malloc (sizeof (*ret));
67   if (ret == NULL)
68   {
69     ident_destroy (selector);
70     return (NULL);
71   }
72   memset (ret, 0, sizeof (*ret));
73   ret->legend = NULL;
74
75   ret->ds_name = strdup (ds_name);
76   if (ret->ds_name == NULL)
77   {
78     ident_destroy (selector);
79     free (ret);
80     return (NULL);
81   }
82
83   ret->color = get_random_color ();
84   ret->next = NULL;
85
86   ret->select = ident_copy_with_selector (selector, ident,
87       IDENT_FLAG_REPLACE_ALL);
88   if (ret->select == NULL)
89   {
90     ident_destroy (selector);
91     free (ret->ds_name);
92     free (ret);
93     return (NULL);
94   }
95
96   ident_destroy (selector);
97   return (ret);
98 } /* }}} graph_def_t *def_create */
99
100 void def_destroy (graph_def_t *def) /* {{{ */
101 {
102   graph_def_t *next;
103
104   if (def == NULL)
105     return;
106
107   next = def->next;
108
109   ident_destroy (def->select);
110
111   free (def->ds_name);
112
113   free (def);
114
115   def_destroy (next);
116 } /* }}} void def_destroy */
117
118 int def_config (graph_config_t *cfg, const oconfig_item_t *ci) /* {{{ */
119 {
120   graph_ident_t *ident;
121   char *ds_name = NULL;
122   char *legend = NULL;
123   graph_def_t *def;
124   int i;
125
126   ident = gl_graph_get_selector (cfg);
127   if (ident == NULL)
128     return (ENOMEM);
129
130   for (i = 0; i < ci->children_num; i++)
131   {
132     oconfig_item_t *child;
133
134 #define HANDLE_FIELD(name,field) \
135     else if (strcasecmp (name, child->key) == 0) \
136       def_config_##field (child, ident)
137
138     child = ci->children + i;
139     if (strcasecmp ("DSName", child->key) == 0)
140       graph_config_get_string (child, &ds_name);
141     else if (strcasecmp ("Legend", child->key) == 0)
142       graph_config_get_string (child, &legend);
143     HANDLE_FIELD ("Host", host);
144     HANDLE_FIELD ("Plugin", plugin);
145     HANDLE_FIELD ("PluginInstance", plugin_instance);
146     HANDLE_FIELD ("Type", type);
147     HANDLE_FIELD ("TypeInstance", type_instance);
148
149 #undef HANDLE_FIELD
150   }
151
152   def = def_create (cfg, ident, ds_name);
153   if (def == NULL)
154   {
155     fprintf (stderr, "def_config: def_create failed (ds_name = %s)\n",
156         (ds_name != NULL) ? ds_name : "(null)");
157     ident_destroy (ident);
158     return (EINVAL);
159   }
160
161   def->legend = legend;
162
163   ident_destroy (ident);
164   free (ds_name);
165
166   return (gl_graph_add_def (cfg, def));
167 } /* }}} int def_config */
168
169 int def_append (graph_def_t *head, graph_def_t *def) /* {{{ */
170 {
171   graph_def_t *ptr;
172
173   if ((head == NULL) || (def == NULL))
174     return (EINVAL);
175
176   ptr = head;
177   while (ptr->next != NULL)
178     ptr = ptr->next;
179
180   ptr->next = def;
181
182   return (0);
183 } /* }}} int def_append */
184
185 graph_def_t *def_search (graph_def_t *head, graph_ident_t *ident, /* {{{ */
186     const char *ds_name)
187 {
188   graph_def_t *ptr;
189
190   if ((head == NULL) || (ident == NULL) || (ds_name == NULL))
191     return (NULL);
192
193   for (ptr = head; ptr != NULL; ptr = ptr->next)
194   {
195     if (!ident_matches (ptr->select, ident))
196       continue;
197
198     if (strcmp (ptr->ds_name, ds_name) == 0)
199       return (ptr);
200   }
201
202   return (NULL);
203 } /* }}} graph_def_t *def_search */
204
205 _Bool def_matches (graph_def_t *def, graph_ident_t *ident) /* {{{ */
206 {
207   return (ident_matches (def->select, ident));
208 } /* }}} _Bool def_matches */
209
210 int def_foreach (graph_def_t *def, def_callback_t callback, /* {{{ */
211     void *user_data)
212 {
213   graph_def_t *ptr;
214
215   if ((def == NULL) || (callback == NULL))
216     return (EINVAL);
217
218   for (ptr = def; ptr != NULL; ptr = ptr->next)
219   {
220     int status;
221
222     status = (*callback) (ptr, user_data);
223     if (status != 0)
224       return (status);
225   }
226
227   return (0);
228 } /* }}} int def_foreach */
229
230 int def_get_rrdargs (graph_def_t *def, graph_ident_t *ident, /* {{{ */
231     str_array_t *args)
232 {
233   char *file;
234   int index;
235
236   if ((def == NULL) || (ident == NULL) || (args == NULL))
237     return (EINVAL);
238
239   file = ident_to_file (ident);
240   if (file == NULL)
241   {
242     DEBUG ("gl_ident_get_rrdargs: ident_to_file returned NULL.\n");
243     return (-1);
244   }
245
246   DEBUG ("gl_ident_get_rrdargs: file = %s;\n", file);
247
248   index = array_argc (args);
249
250   /* CDEFs */
251   array_append_format (args, "DEF:def_%04i_min=%s:%s:MIN",
252       index, file, def->ds_name);
253   array_append_format (args, "DEF:def_%04i_avg=%s:%s:AVERAGE",
254       index, file, def->ds_name);
255   array_append_format (args, "DEF:def_%04i_max=%s:%s:MAX",
256       index, file, def->ds_name);
257   /* VDEFs */
258   array_append_format (args, "VDEF:vdef_%04i_min=def_%04i_min,MINIMUM",
259       index, index);
260   array_append_format (args, "VDEF:vdef_%04i_avg=def_%04i_avg,AVERAGE",
261       index, index);
262   array_append_format (args, "VDEF:vdef_%04i_max=def_%04i_max,MAXIMUM",
263       index, index);
264   array_append_format (args, "VDEF:vdef_%04i_lst=def_%04i_avg,LAST",
265       index, index);
266
267   /* Graph part */
268   array_append_format (args, "LINE1:def_%04i_avg#%06"PRIx32":%s",
269       index, def->color,
270       (def->legend != NULL) ? def->legend : def->ds_name);
271   array_append_format (args, "GPRINT:vdef_%04i_min:%%lg min,", index);
272   array_append_format (args, "GPRINT:vdef_%04i_avg:%%lg avg,", index);
273   array_append_format (args, "GPRINT:vdef_%04i_max:%%lg max,", index);
274   array_append_format (args, "GPRINT:vdef_%04i_lst:%%lg last\\l", index);
275
276   free (file);
277
278   return (0);
279 } /* }}} int def_get_rrdargs */
280
281 /* vim: set sw=2 sts=2 et fdm=marker : */