graph_instance.[ch]: Move the graph_instance_t code into an own module.
[collection4.git] / graph_instance.c
1 #include <stdlib.h>
2 #include <string.h>
3 #include <errno.h>
4
5 #include "graph_instance.h"
6 #include "graph_ident.h"
7 #include "common.h"
8 #include "utils_params.h"
9
10 #include <fcgiapp.h>
11 #include <fcgi_stdio.h>
12
13 struct graph_instance_s /* {{{ */
14 {
15   graph_ident_t *select;
16
17   graph_ident_t **files;
18   size_t files_num;
19
20   graph_instance_t *next;
21 }; /* }}} struct graph_instance_s */
22
23 struct def_callback_data_s
24 {
25   graph_instance_t *inst;
26   str_array_t *args;
27 };
28 typedef struct def_callback_data_s def_callback_data_t;
29
30 /*
31  * Private functions
32  */
33 /* Create one DEF for each data source in the file. Called by
34  * "inst_get_default_defs" for each file. */
35 static graph_def_t *ident_get_default_defs (graph_config_t *cfg, /* {{{ */
36     graph_ident_t *ident, graph_def_t *def_head)
37 {
38   graph_def_t *defs = NULL;
39   char *file;
40   char **dses = NULL;
41   size_t dses_num = 0;
42   int status;
43   size_t i;
44
45   if ((cfg == NULL) || (ident == NULL))
46     return (def_head);
47
48   file = ident_to_file (ident);
49   if (file == NULL)
50   {
51     fprintf (stderr, "ident_get_default_defs: ident_to_file failed\n");
52     return (def_head);
53   }
54
55   status = ds_list_from_rrd_file (file, &dses_num, &dses);
56   if (status != 0)
57   {
58     free (file);
59     return (def_head);
60   }
61
62   for (i = 0; i < dses_num; i++)
63   {
64     graph_def_t *def;
65
66     def = def_search (def_head, ident, dses[i]);
67     if (def != NULL)
68       continue;
69
70     def = def_create (cfg, ident, dses[i]);
71     if (def == NULL)
72       continue;
73
74     if (defs == NULL)
75       defs = def;
76     else
77       def_append (defs, def);
78
79     free (dses[i]);
80   }
81
82   free (dses);
83   free (file);
84
85   return (defs);
86 } /* }}} int ident_get_default_defs */
87
88 /* Create one or more DEFs for each file in the graph instance. The number
89  * depends on the number of data sources in each of the files. Called from
90  * "inst_get_rrdargs" if no DEFs are available from the configuration.
91  * */
92 static graph_def_t *inst_get_default_defs (graph_config_t *cfg, /* {{{ */
93     graph_instance_t *inst)
94 {
95   graph_def_t *defs = NULL;
96   size_t i;
97
98   if ((cfg == NULL) || (inst == NULL))
99     return (NULL);
100
101   for (i = 0; i < inst->files_num; i++)
102   {
103     graph_def_t *def;
104
105     def = ident_get_default_defs (cfg, inst->files[i], defs);
106     if (def == NULL)
107       continue;
108
109     if (defs == NULL)
110       defs = def;
111     else
112       def_append (defs, def);
113   }
114
115   return (defs);
116 } /* }}} graph_def_t *inst_get_default_defs */
117
118 /* Called with each DEF in turn. Calls "def_get_rrdargs" with every appropriate
119  * file / DEF pair. */
120 static int gl_instance_get_rrdargs_cb (graph_def_t *def, void *user_data) /* {{{ */
121 {
122   def_callback_data_t *data = user_data;
123   graph_instance_t *inst = data->inst;
124   str_array_t *args = data->args;
125
126   size_t i;
127
128   for (i = 0; i < inst->files_num; i++)
129   {
130     if (!def_matches (def, inst->files[i]))
131       continue;
132
133     def_get_rrdargs (def, inst->files[i], args);
134   }
135
136   return (0);
137 } /* }}} int gl_instance_get_rrdargs_cb */
138
139 static const char *get_part_from_param (const char *prim_key, /* {{{ */
140     const char *sec_key)
141 {
142   const char *val;
143
144   val = param (prim_key);
145   if (val != NULL)
146     return (val);
147   
148   return (param (sec_key));
149 } /* }}} const char *get_part_from_param */
150
151 /*
152  * Public functions
153  */
154 graph_instance_t *inst_create (graph_config_t *cfg, /* {{{ */
155     const graph_ident_t *ident)
156 {
157   graph_instance_t *i;
158   graph_ident_t *selector;
159
160   if ((cfg == NULL) || (ident == NULL))
161     return (NULL);
162
163   i = malloc (sizeof (*i));
164   if (i == NULL)
165     return (NULL);
166   memset (i, 0, sizeof (*i));
167
168   selector = gl_graph_get_selector (cfg);
169   if (selector == NULL)
170   {
171     fprintf (stderr, "inst_create: gl_graph_get_selector failed\n");
172     free (i);
173     return (NULL);
174   }
175
176   i->select = ident_copy_with_selector (selector, ident,
177       IDENT_FLAG_REPLACE_ANY);
178   if (i->select == NULL)
179   {
180     fprintf (stderr, "inst_create: ident_copy_with_selector failed\n");
181     ident_destroy (selector);
182     free (i);
183     return (NULL);
184   }
185
186   ident_destroy (selector);
187
188   i->files = NULL;
189   i->files_num = 0;
190
191   i->next = NULL;
192
193   return (i);
194 } /* }}} graph_instance_t *inst_create */
195
196 void inst_destroy (graph_instance_t *inst) /* {{{ */
197 {
198   graph_instance_t *next;
199   size_t i;
200
201   if (inst == NULL)
202     return;
203
204   next = inst->next;
205
206   ident_destroy (inst->select);
207
208   for (i = 0; i < inst->files_num; i++)
209     ident_destroy (inst->files[i]);
210   free (inst->files);
211
212   free (inst);
213
214   inst_destroy (next);
215 } /* }}} void inst_destroy */
216
217 int inst_add_file (graph_instance_t *inst, /* {{{ */
218     const graph_ident_t *file)
219 {
220   graph_ident_t **tmp;
221
222   tmp = realloc (inst->files, sizeof (*inst->files) * (inst->files_num + 1));
223   if (tmp == NULL)
224     return (ENOMEM);
225   inst->files = tmp;
226
227   inst->files[inst->files_num] = ident_clone (file);
228   if (inst->files[inst->files_num] == NULL)
229     return (ENOMEM);
230
231   inst->files_num++;
232
233   return (0);
234 } /* }}} int inst_add_file */
235
236 graph_instance_t *inst_get_selected (graph_config_t *cfg) /* {{{ */
237 {
238   const char *host = get_part_from_param ("inst_host", "host");
239   const char *plugin = get_part_from_param ("inst_plugin", "plugin");
240   const char *plugin_instance = get_part_from_param ("inst_plugin_instance", "plugin_instance");
241   const char *type = get_part_from_param ("inst_type", "type");
242   const char *type_instance = get_part_from_param ("inst_type_instance", "type_instance");
243   graph_ident_t *ident;
244   graph_instance_t *inst;
245
246   if (cfg == NULL)
247     cfg = graph_get_selected ();
248
249   if (cfg == NULL)
250   {
251     DEBUG ("inst_get_selected: cfg == NULL;\n");
252     return (NULL);
253   }
254
255   if ((host == NULL)
256       || (plugin == NULL) || (plugin_instance == NULL)
257       || (type == NULL) || (type_instance == NULL))
258   {
259     DEBUG ("inst_get_selected: A parameter is NULL.\n");
260     return (NULL);
261   }
262
263   ident = ident_create (host, plugin, plugin_instance, type, type_instance);
264
265   for (inst = gl_graph_get_instances (cfg); inst != NULL; inst = inst->next)
266   {
267     if (ident_compare (ident, inst->select) != 0)
268       continue;
269
270     ident_destroy (ident);
271     return (inst);
272   }
273
274   DEBUG ("inst_get_selected: No match found.\n");
275   ident_destroy (ident);
276   return (NULL);
277 } /* }}} graph_instance_t *inst_get_selected */
278
279 int inst_get_rrdargs (graph_config_t *cfg, /* {{{ */
280     graph_instance_t *inst,
281     str_array_t *args)
282 {
283   def_callback_data_t data = { inst, args };
284   graph_def_t *defs;
285   int status;
286
287   if ((cfg == NULL) || (inst == NULL) || (args == NULL))
288     return (EINVAL);
289
290 /* FIXME: Re-enable title and vertical label stuff. */
291 #if 0
292   if (cfg->title != NULL)
293   {
294     array_append (args, "-t");
295     array_append (args, cfg->title);
296   }
297
298   if (cfg->vertical_label != NULL)
299   {
300     array_append (args, "-v");
301     array_append (args, cfg->vertical_label);
302   }
303 #endif
304
305   defs = gl_graph_get_defs (cfg);
306   if (defs == NULL)
307   {
308     defs = inst_get_default_defs (cfg, inst);
309
310     if (defs == NULL)
311       return (-1);
312
313     status = def_foreach (defs, gl_instance_get_rrdargs_cb, &data);
314
315     def_destroy (defs);
316   }
317   else
318   {
319     status = def_foreach (defs, gl_instance_get_rrdargs_cb, &data);
320   }
321
322   return (status);
323 } /* }}} int inst_get_rrdargs */
324
325 graph_ident_t *inst_get_selector (graph_instance_t *inst) /* {{{ */
326 {
327   if (inst == NULL)
328     return (NULL);
329
330   return (ident_clone (inst->select));
331 } /* }}} graph_ident_t *inst_get_selector */
332
333 int inst_get_params (graph_config_t *cfg, graph_instance_t *inst, /* {{{ */
334     char *buffer, size_t buffer_size)
335 {
336   graph_ident_t *cfg_select;
337
338   if ((cfg == NULL) || (inst == NULL)
339       || (buffer == NULL) || (buffer_size < 1))
340     return (EINVAL);
341
342   cfg_select = gl_graph_get_selector (cfg);
343   if (cfg_select == NULL)
344   {
345     fprintf (stderr, "inst_get_params: gl_graph_get_selector failed");
346     return (-1);
347   }
348
349   buffer[0] = 0;
350
351 #define COPY_FIELD(field) do {                                  \
352   const char *cfg_f  = ident_get_##field (cfg_select);          \
353   const char *inst_f = ident_get_##field (inst->select);        \
354   if (strcmp (cfg_f, inst_f) == 0)                              \
355   {                                                             \
356     strlcat (buffer, #field, buffer_size);                      \
357     strlcat (buffer, "=", buffer_size);                         \
358     strlcat (buffer, cfg_f, buffer_size);                       \
359   }                                                             \
360   else                                                          \
361   {                                                             \
362     strlcat (buffer, "graph_", buffer_size);                    \
363     strlcat (buffer, #field, buffer_size);                      \
364     strlcat (buffer, "=", buffer_size);                         \
365     strlcat (buffer, cfg_f, buffer_size);                       \
366     strlcat (buffer, ";", buffer_size);                         \
367     strlcat (buffer, "inst_", buffer_size);                     \
368     strlcat (buffer, #field, buffer_size);                      \
369     strlcat (buffer, "=", buffer_size);                         \
370     strlcat (buffer, inst_f, buffer_size);                      \
371   }                                                             \
372 } while (0)
373
374   COPY_FIELD(host);
375   strlcat (buffer, ";", buffer_size);
376   COPY_FIELD(plugin);
377   strlcat (buffer, ";", buffer_size);
378   COPY_FIELD(plugin_instance);
379   strlcat (buffer, ";", buffer_size);
380   COPY_FIELD(type);
381   strlcat (buffer, ";", buffer_size);
382   COPY_FIELD(type_instance);
383
384 #undef COPY_FIELD
385
386   ident_destroy (cfg_select);
387
388   return (0);
389 } /* }}} int inst_get_params */
390
391 int inst_append (graph_instance_t *head, graph_instance_t *inst) /* {{{ */
392 {
393   graph_instance_t *ptr;
394
395   if ((head == NULL) || (inst == NULL))
396     return (EINVAL);
397
398   ptr = head;
399   while (ptr->next != NULL)
400     ptr = ptr->next;
401
402   ptr->next = inst;
403
404   return (0);
405 } /* }}} int inst_append */
406
407 int inst_foreach (graph_instance_t *inst, /* {{{ */
408                 inst_callback cb, void *user_data)
409 {
410   graph_instance_t *ptr;
411
412   if ((inst == NULL) || (cb == NULL))
413     return (EINVAL);
414
415   for (ptr = inst; ptr != NULL; ptr = ptr->next)
416   {
417     int status;
418
419     status = (*cb) (ptr, user_data);
420     if (status != 0)
421       return (status);
422   }
423
424   return (0);
425 } /* }}} int inst_foreach */
426
427 graph_instance_t *inst_find_matching (graph_instance_t *inst, /* {{{ */
428     const graph_ident_t *ident)
429 {
430   graph_instance_t *ptr;
431
432   if ((inst == NULL) || (ident == NULL))
433     return (NULL);
434
435   for (ptr = inst; ptr != NULL; ptr = ptr->next)
436     if (ident_matches (ptr->select, ident))
437       return (ptr);
438
439   return (NULL);
440 } /* }}} graph_instance_t *inst_find_matching */
441
442 /* vim: set sw=2 sts=2 et fdm=marker : */