src/graph.[ch]: Implement "graph_get_params".
[collection4.git] / src / graph.c
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>
9
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"
18
19 #include <fcgiapp.h>
20 #include <fcgi_stdio.h>
21
22 /*
23  * Data types
24  */
25 struct graph_config_s /* {{{ */
26 {
27   graph_ident_t *select;
28
29   char *title;
30   char *vertical_label;
31   _Bool show_zero;
32
33   graph_def_t *defs;
34
35   graph_instance_t *instances;
36 }; /* }}} struct graph_config_s */
37
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);
46
47   return (inst_find_matching (cfg->instances, ident));
48 } /* }}} graph_instance_t *graph_find_instance */
49
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;
62
63   for (i = 0; i < ci->children_num; i++)
64   {
65     oconfig_item_t *child;
66
67     child = ci->children + i;
68
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 */
81
82   ret = ident_create (host, plugin, plugin_instance, type, type_instance);
83
84   free (host);
85   free (plugin);
86   free (plugin_instance);
87   free (type);
88   free (type_instance);
89
90   return (ret);
91 } /* }}} int graph_config_get_selector */
92
93 /*
94  * Global functions
95  */
96 graph_config_t *graph_create (const graph_ident_t *selector) /* {{{ */
97 {
98   graph_config_t *cfg;
99
100   cfg = malloc (sizeof (*cfg));
101   if (cfg == NULL)
102     return (NULL);
103   memset (cfg, 0, sizeof (*cfg));
104
105   if (selector != NULL)
106     cfg->select = ident_clone (selector);
107   else
108     cfg->select = NULL;
109
110   cfg->title = NULL;
111   cfg->vertical_label = NULL;
112   cfg->defs = NULL;
113   cfg->instances = NULL;
114
115   return (cfg);
116 } /* }}} int graph_create */
117
118 void graph_destroy (graph_config_t *cfg) /* {{{ */
119 {
120   if (cfg == NULL)
121     return;
122
123   ident_destroy (cfg->select);
124
125   free (cfg->title);
126   free (cfg->vertical_label);
127
128   def_destroy (cfg->defs);
129   inst_destroy (cfg->instances);
130 } /* }}} void graph_destroy */
131
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;
137
138   select = graph_config_get_selector (ci);
139   if (select == NULL)
140     return (EINVAL);
141
142   cfg = graph_create (/* selector = */ NULL);
143   if (cfg == NULL)
144     return (ENOMEM);
145
146   cfg->select = select;
147
148   for (i = 0; i < ci->children_num; i++)
149   {
150     oconfig_item_t *child;
151
152     child = ci->children + i;
153
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 */
163
164   gl_add_graph (cfg);
165
166   return (0);
167 } /* }}} graph_config_add */
168
169 int graph_add_file (graph_config_t *cfg, const graph_ident_t *file) /* {{{ */
170 {
171   graph_instance_t *inst;
172
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);
179
180     if (cfg->instances == NULL)
181       cfg->instances = inst;
182     else
183       inst_append (cfg->instances, inst);
184   }
185
186   return (inst_add_file (inst, file));
187 } /* }}} int graph_add_file */
188
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);
194
195   if (cfg->title == NULL)
196     cfg->title = ident_to_string (cfg->select);
197
198   if (cfg->title == NULL)
199     return (ENOMEM);
200
201   strncpy (buffer, cfg->title, buffer_size);
202   buffer[buffer_size - 1] = 0;
203
204   return (0);
205 } /* }}} int graph_get_title */
206
207 int graph_get_params (graph_config_t *cfg, /* {{{ */
208     char *buffer, size_t buffer_size)
209 {
210   buffer[0] = 0;
211
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)
220
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);
230
231 #undef COPY_FIELD
232
233   return (0);
234 } /* }}} int graph_get_params */
235
236 graph_ident_t *graph_get_selector (graph_config_t *cfg) /* {{{ */
237 {
238   if (cfg == NULL)
239     return (NULL);
240
241   return (ident_clone (cfg->select));
242 } /* }}} graph_ident_t *graph_get_selector */
243
244 graph_instance_t *graph_get_instances (graph_config_t *cfg) /* {{{ */
245 {
246   if (cfg == NULL)
247     return (NULL);
248
249   return (cfg->instances);
250 } /* }}} graph_instance_t *graph_get_instances */
251
252 graph_def_t *graph_get_defs (graph_config_t *cfg) /* {{{ */
253 {
254   if (cfg == NULL)
255     return (NULL);
256
257   return (cfg->defs);
258 } /* }}} graph_def_t *graph_get_defs */
259
260 int graph_add_def (graph_config_t *cfg, graph_def_t *def) /* {{{ */
261 {
262   if ((cfg == NULL) || (def == NULL))
263     return (EINVAL);
264
265   if (cfg->defs == NULL)
266   {
267     cfg->defs = def;
268     return (0);
269   }
270
271   return (def_append (cfg->defs, def));
272 } /* }}} int graph_add_def */
273
274 _Bool graph_matches (graph_config_t *cfg, const graph_ident_t *ident) /* {{{ */
275 {
276   if ((cfg == NULL) || (ident == NULL))
277     return (0);
278
279   return (ident_matches (cfg->select, ident));
280 } /* }}} _Bool graph_matches */
281
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;
289
290 static int graph_search_submit (graph_instance_t *inst, /* {{{ */
291     void *user_data)
292 {
293   graph_search_data_t *data = user_data;
294
295   if ((inst == NULL) || (data == NULL))
296     return (EINVAL);
297
298   return ((*data->callback) (data->cfg, inst, data->user_data));
299 } /* }}} int graph_search_submit */
300
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 */
306
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;
314
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   }
321
322   strtolower (buffer);
323
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   }
337
338   return (0);
339 } /* }}} int graph_search */
340
341 int graph_compare (graph_config_t *cfg, const graph_ident_t *ident) /* {{{ */
342 {
343   if ((cfg == NULL) || (ident == NULL))
344     return (0);
345
346   return (ident_compare (cfg->select, ident));
347 } /* }}} int graph_compare */
348
349 int graph_clear_instances (graph_config_t *cfg) /* {{{ */
350 {
351   if (cfg == NULL)
352     return (EINVAL);
353
354   inst_destroy (cfg->instances);
355   cfg->instances = NULL;
356
357   return (0);
358 } /* }}} int graph_clear_instances */
359
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);
365
366   if (cfg->title != NULL)
367   {
368     array_append (args, "-t");
369     array_append (args, cfg->title);
370   }
371
372   if (cfg->vertical_label != NULL)
373   {
374     array_append (args, "-v");
375     array_append (args, cfg->vertical_label);
376   }
377
378   if (cfg->show_zero)
379   {
380     array_append (args, "-l");
381     array_append (args, "0");
382   }
383
384   return (0);
385 } /* }}} int graph_get_rrdargs */
386
387 /* vim: set sw=2 sts=2 et fdm=marker : */