Free the graph_def structure.
[collection4.git] / action_graph.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <errno.h>
5 #include <stdint.h>
6 #include <inttypes.h>
7 #include <dirent.h> /* for PATH_MAX */
8 #include <assert.h>
9
10 #include <fcgiapp.h>
11 #include <fcgi_stdio.h>
12
13 #include <rrd.h>
14
15 #include "common.h"
16 #include "action_graph.h"
17 #include "graph_list.h"
18 #include "utils_params.h"
19
20 struct data_source_s
21 {
22   char *file;
23   char *name;
24   char *legend;
25   double scale;
26   _Bool nan_to_zero;
27   _Bool draw_area;
28   uint32_t color;
29 };
30 typedef struct data_source_s data_source_t;
31
32 struct graph_def_s
33 {
34   data_source_t *data_sources;
35   size_t data_sources_num;
36
37   _Bool stack;
38 };
39 typedef struct graph_def_s graph_def_t;
40
41 static void graph_def_free (graph_def_t *gd)
42 {
43   size_t i;
44
45   if (gd == NULL)
46     return;
47
48   for (i = 0; i < gd->data_sources_num; i++)
49   {
50     free (gd->data_sources[i].file);
51     free (gd->data_sources[i].name);
52     free (gd->data_sources[i].legend);
53   }
54   free (gd->data_sources);
55   free (gd);
56 } /* }}} void graph_def_free */
57
58 static int graph_def_add_ds (graph_def_t *gd, /* {{{ */
59     const char *file,
60     const char *in_ds_name, size_t ds_name_len)
61 {
62   char ds_name[ds_name_len + 1];
63   data_source_t *ds;
64
65   strncpy (ds_name, in_ds_name, sizeof (ds_name));
66   ds_name[sizeof (ds_name) - 1] = 0;
67
68   ds = realloc (gd->data_sources, sizeof (*ds) * (gd->data_sources_num + 1));
69   if (ds == NULL)
70     return (ENOMEM);
71   gd->data_sources = ds;
72
73   ds = gd->data_sources + gd->data_sources_num;
74   memset (ds, 0, sizeof (*ds));
75
76   ds->file = strdup (file);
77   if (ds->file == NULL)
78     return (ENOMEM);
79
80   ds->name = strdup (ds_name);
81   if (ds->name == NULL)
82   {
83     free (ds->file);
84     return (ENOMEM);
85   }
86
87   ds->legend = NULL;
88   ds->color = 0xff0000;
89
90   gd->data_sources_num++;
91
92   return (0);
93 } /* }}} int graph_def_add_ds */
94
95 static graph_def_t *graph_def_from_rrd_file (char *file) /* {{{ */
96 {
97   char *rrd_argv[] = { "info", file, NULL };
98   int rrd_argc = (sizeof (rrd_argv) / sizeof (rrd_argv[0])) - 1;
99   rrd_info_t *info;
100   rrd_info_t *ptr;
101   graph_def_t *gd;
102
103   gd = malloc (sizeof (*gd));
104   if (gd == NULL)
105     return (NULL);
106   memset (gd, 0, sizeof (*gd));
107
108   gd->data_sources = NULL;
109
110   info = rrd_info (rrd_argc, rrd_argv);
111   if (info == NULL)
112   {
113     printf ("%s: rrd_info (%s) failed.\n", __func__, file);
114     free (gd);
115     return (NULL);
116   }
117
118   for (ptr = info; ptr != NULL; ptr = ptr->next)
119   {
120     size_t keylen;
121     size_t dslen;
122
123     if (strncmp ("ds[", ptr->key, strlen ("ds[")) != 0)
124       continue;
125
126     keylen = strlen (ptr->key);
127     if (keylen < strlen ("ds[?].index"))
128       continue;
129
130     dslen = keylen - strlen ("ds[].index");
131     assert (dslen >= 1);
132
133     if (strcmp ("].index", ptr->key + (strlen ("ds[") + dslen)) != 0)
134       continue;
135
136     graph_def_add_ds (gd, file, ptr->key + strlen ("ds["), dslen);
137   }
138
139   rrd_info_free (info);
140
141   return (gd);
142 } /* }}} graph_def_t *graph_def_from_rrd_file */
143
144 static graph_def_t *graph_def_from_gl (const graph_list_t *gl) /* {{{ */
145 {
146   char rrd_file[PATH_MAX];
147
148   if ((gl->plugin_instance == NULL) && (gl->type_instance == NULL))
149     snprintf (rrd_file, sizeof (rrd_file), "%s/%s/%s/%s.rrd",
150         DATA_DIR, gl->host, gl->plugin, gl->type);
151   else if (gl->type_instance == NULL)
152     snprintf (rrd_file, sizeof (rrd_file), "%s/%s/%s-%s/%s.rrd",
153         DATA_DIR, gl->host, gl->plugin, gl->plugin_instance, gl->type);
154   else if (gl->plugin_instance == NULL)
155     snprintf (rrd_file, sizeof (rrd_file), "%s/%s/%s/%s-%s.rrd",
156         DATA_DIR, gl->host, gl->plugin, gl->type, gl->type_instance);
157   else
158     snprintf (rrd_file, sizeof (rrd_file), "%s/%s/%s-%s/%s-%s.rrd",
159         DATA_DIR, gl->host, gl->plugin, gl->plugin_instance,
160         gl->type, gl->type_instance);
161   rrd_file[sizeof (rrd_file) - 1] = 0;
162
163   printf ("rrd_file = %s;\n", rrd_file);
164
165   return (graph_def_from_rrd_file (rrd_file));
166 } /* }}} graph_def_t *graph_def_from_gl */
167
168 static int init_gl (graph_list_t *gl) /* {{{ */
169 {
170   gl->host = param ("host");
171   gl->plugin = param ("plugin");
172   gl->plugin_instance = param ("plugin_instance");
173   gl->type = param ("type");
174   gl->type_instance = param ("type_instance");
175
176   if ((gl->host == NULL)
177       || (gl->plugin == NULL)
178       || (gl->type == NULL))
179     return (EINVAL);
180
181   if ((gl->host[0] == 0) || (gl->host[0] == '.')
182       || (gl->plugin[0] == 0) || (gl->plugin[0] == '.')
183       || (gl->type[0] == 0) || (gl->type[0] == '.'))
184     return (EINVAL);
185
186   if ((strchr (gl->plugin, '-') != NULL)
187       || (strchr (gl->type, '-') != NULL))
188     return (EINVAL);
189
190   if ((gl->plugin_instance != NULL)
191       && (gl->plugin_instance[0] == 0))
192     gl->plugin_instance = NULL;
193
194   if ((gl->type_instance != NULL)
195       && (gl->type_instance[0] == 0))
196     gl->type_instance = NULL;
197
198   return (0);
199 } /* }}} int init_gl */
200
201 int action_graph (void) /* {{{ */
202 {
203   graph_list_t gl;
204   graph_def_t *gd;
205   int status;
206   size_t i;
207
208   memset (&gl, 0, sizeof (gl));
209   status = init_gl (&gl);
210   if (status != 0)
211   {
212     printf ("Content-Type: text/plain\n\n"
213         "init_gl failed with status %i.\n", status);
214     return (status);
215   }
216
217   printf ("Content-Type: text/plain\n\n"
218       "Hello, this is %s\n", __func__);
219   gd = graph_def_from_gl (&gl);
220   if (gd == NULL)
221   {
222     printf ("graph_def_from_gl failed.\n");
223     return (0);
224   }
225
226   for (i = 0; i < gd->data_sources_num; i++)
227   {
228     printf ("data source %lu: %s @ %s\n",
229         (unsigned long) i, gd->data_sources[i].name, gd->data_sources[i].file);
230   }
231
232   graph_def_free (gd);
233
234   return (0);
235 } /* }}} int action_graph */
236
237 /* vim: set sw=2 sts=2 et fdm=marker : */