b5b3163df7433d073a040e30feb61298e77e5891
[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 #include <math.h>
10
11 #include <rrd.h>
12
13 #include "common.h"
14 #include "action_graph.h"
15 #include "graph_list.h"
16 #include "utils_params.h"
17 #include "utils_array.h"
18
19 #include <fcgiapp.h>
20 #include <fcgi_stdio.h>
21
22 struct data_source_s
23 {
24   char *file;
25   char *name;
26   char *legend;
27   double scale;
28   _Bool nan_to_zero;
29   _Bool draw_area;
30   uint32_t color;
31 };
32 typedef struct data_source_s data_source_t;
33
34 struct graph_def_s
35 {
36   data_source_t *data_sources;
37   size_t data_sources_num;
38
39   _Bool stack;
40
41   int def_num;
42 };
43 typedef struct graph_def_s graph_def_t;
44
45 static void emulate_graph (int argc, char **argv) /* {{{ */
46 {
47   int i;
48
49   printf ("rrdtool \\\n");
50   for (i = 0; i < argc; i++)
51   {
52     if (i < (argc - 1))
53       printf ("  \"%s\" \\\n", argv[i]);
54     else
55       printf ("  \"%s\"\n", argv[i]);
56   }
57 } /* }}} void emulate_graph */
58
59 static int ag_info_print (rrd_info_t *info) /* {{{ */
60 {
61   if (info->type == RD_I_VAL)
62     printf ("[info] %s = %g;\n", info->key, info->value.u_val);
63   else if (info->type == RD_I_CNT)
64     printf ("[info] %s = %lu;\n", info->key, info->value.u_cnt);
65   else if (info->type == RD_I_STR)
66     printf ("[info] %s = %s;\n", info->key, info->value.u_str);
67   else if (info->type == RD_I_INT)
68     printf ("[info] %s = %i;\n", info->key, info->value.u_int);
69   else if (info->type == RD_I_BLO)
70     printf ("[info] %s = [blob, %lu bytes];\n", info->key, info->value.u_blo.size);
71   else
72     printf ("[info] %s = [unknown type %#x];\n", info->key, info->type);
73
74   return (0);
75 } /* }}} int ag_info_print */
76
77 static int output_graph (rrd_info_t *info) /* {{{ */
78 {
79   rrd_info_t *img;
80
81   for (img = info; img != NULL; img = img->next)
82     if ((strcmp ("image", img->key) == 0)
83         && (img->type == RD_I_BLO))
84       break;
85
86   if (img == NULL)
87     return (ENOENT);
88
89   printf ("Content-Type: image/png\n"
90       "Content-Length: %lu\n"
91       "\n",
92       img->value.u_blo.size);
93   fwrite (img->value.u_blo.ptr, img->value.u_blo.size,
94       /* nmemb = */ 1, stdout);
95
96   return (0);
97 } /* }}} int output_graph */
98
99 #define OUTPUT_ERROR(...) do {             \
100   printf ("Content-Type: text/plain\n\n"); \
101   printf (__VA_ARGS__);                    \
102   return (0);                              \
103 } while (0)
104
105 int action_graph (void) /* {{{ */
106 {
107   str_array_t *args;
108   graph_config_t *cfg;
109   graph_instance_t *inst;
110   rrd_info_t *info;
111   int status;
112
113   cfg = graph_get_selected ();
114   if (cfg == NULL)
115     OUTPUT_ERROR ("graph_get_selected () failed.\n");
116
117   inst = inst_get_selected (cfg);
118   if (inst == NULL)
119     OUTPUT_ERROR ("inst_get_selected (%p) failed.\n", (void *) cfg);
120
121   args = array_create ();
122   if (args == NULL)
123     return (ENOMEM);
124
125   array_append (args, "graph");
126   array_append (args, "-");
127   array_append (args, "--imgformat");
128   array_append (args, "PNG");
129
130   status = gl_instance_get_rrdargs (cfg, inst, args);
131   if (status != 0)
132   {
133     array_destroy (args);
134     OUTPUT_ERROR ("gl_instance_get_rrdargs failed with status %i.\n", status);
135   }
136
137   rrd_clear_error ();
138   info = rrd_graph_v (array_argc (args), array_argv (args));
139   if ((info == NULL) || rrd_test_error ())
140   {
141     printf ("Content-Type: text/plain\n\n");
142     printf ("rrd_graph_v failed: %s\n", rrd_get_error ());
143     emulate_graph (array_argc (args), array_argv (args));
144   }
145   else
146   {
147     int status;
148
149     status = output_graph (info);
150     if (status != 0)
151     {
152       rrd_info_t *ptr;
153
154       printf ("Content-Type: text/plain\n\n");
155       printf ("output_graph failed. Maybe the \"image\" info was not found?\n\n");
156
157       for (ptr = info; ptr != NULL; ptr = ptr->next)
158       {
159         ag_info_print (ptr);
160       }
161     }
162   }
163
164   if (info != NULL)
165     rrd_info_free (info);
166
167   array_destroy (args);
168   args = NULL;
169
170   return (0);
171 } /* }}} int action_graph */
172
173 /* vim: set sw=2 sts=2 et fdm=marker : */