]> git.itanic.dy.fi Git - rrdd/blob - rrdtool.c
rrdtool: Reduce excess parallelism
[rrdd] / rrdtool.c
1 #include <time.h>
2
3 #include <sys/types.h>
4 #include <sys/stat.h>
5 #include <unistd.h>
6 #include <string.h>
7
8 #include "rrdtool.h"
9 #include "process.h"
10 #include "parser.h"
11 #include "debug.h"
12 #include "string.h"
13
14 #define MAX_ARGS        512
15 #define ARGSTR_LEN      32768
16
17 #define RRDTOOL_CMD "/usr/bin/rrdtool"
18
19 /*
20  * Add new argument to a argument list
21  *
22  * args         pointer list to arguments
23  * argcnt       argument counter
24  * argstr       array where the actual arguments are stored
25  * idx          index in the argstr where the new argument will be appended
26  */
27 #define add_arg(args, argcnt, argstr, idx, fmt, arg...) \
28         args[argcnt] = argstr + idx;                    \
29         idx += sprintf(argstr + idx, fmt, ##arg);       \
30         argcnt++;                                       \
31         argstr[++idx] = 0
32
33 int rrdtool_draw_image(struct rrd_image *image)
34 {
35         int pid;
36         char cmd[] = RRDTOOL_CMD;
37 //      char cmd[] = "echo";
38         char *args[512], argstr[ARGSTR_LEN];
39         int idx = 0, argcnt = 0, i,j;
40         char timestamp[256];
41         char tmp[256];
42         char tmpfile[256];
43         time_t t = time(0);
44
45         pr_info("Drawing image %s\n", image->image_filename);
46
47         tmpfile[0] = 0;
48         strncat(tmpfile, image->image_filename, sizeof(tmp) - strlen(tmp) - 1);
49         strncat(tmpfile, ".tmp", sizeof(tmp) - strlen(tmp) - 1);
50
51         strftime(tmp, 256, "%d.%m.%Y %T (%Z) ", localtime(&t));
52         for (i = 0, j = 0; j < 256;) {
53                 if (tmp[i] == ':') {
54                         timestamp[j++] = '\\';
55                 }
56                 timestamp[j++] = tmp[i++];
57                 if (!tmp[i])
58                         break;
59         }
60         timestamp[j] = 0;
61
62
63         add_arg(args, argcnt, argstr, idx, " ");
64         add_arg(args, argcnt, argstr, idx, "graph");
65         add_arg(args, argcnt, argstr, idx, "%s", tmpfile);
66
67         add_arg(args, argcnt, argstr, idx, "--start");
68         add_arg(args, argcnt, argstr, idx, "%s", image->timestart);
69         add_arg(args, argcnt, argstr, idx, "--end");
70         add_arg(args, argcnt, argstr, idx, "%s", image->timeend);
71         add_arg(args, argcnt, argstr, idx, "--width");
72         add_arg(args, argcnt, argstr, idx, "%d", image->width);
73         add_arg(args, argcnt, argstr, idx, "--height");
74         add_arg(args, argcnt, argstr, idx, "%d", image->height);
75         add_arg(args, argcnt, argstr, idx, "--imgformat");
76         add_arg(args, argcnt, argstr, idx, "%s", image->imageformat);
77
78         for (i = 0; image->options[i]; i++) {
79                 add_arg(args, argcnt, argstr, idx, "%s", image->options[i]);
80         }
81
82         for (i = 0; image->text[i]; i++) {
83                 args[argcnt++] = image->text[i];
84         }
85
86         add_arg(args, argcnt, argstr, idx, "COMMENT:Last update %s\\c", timestamp);
87
88         args[argcnt] = 0;
89
90         pid = run(cmd, args);
91         harvest_zombies(pid);
92
93         rename(tmpfile, image->image_filename);
94
95         return 0;
96 }
97
98 int rrdtool_draw_images(struct rrd_image **image)
99 {
100         int i;
101         for (i = 0; image[i]; i++)
102                 rrdtool_draw_image(image[i]);
103
104         return 0;
105 }
106
107 static int sanitize_rrd_update_data(char *data)
108 {
109         char clean_data[RRD_DATA_MAX_LEN];
110         int entries = 0;
111         int minus;
112         char *src, *end, *cln;
113
114         data[RRD_DATA_MAX_LEN - 1] = 0;
115         src = data;
116         cln = clean_data;
117
118         while (src < data + RRD_DATA_MAX_LEN && *src) {
119                 minus = 0;
120                 if (*src == '-') {
121                         src++;
122                         minus = 1;
123                 }
124
125                 end = skip_numbers(src);
126
127                 if (*end == '.') {
128                         end++;
129                         end = skip_numbers(end);
130                 }
131
132                 if (*end == ':' || !*end) {
133                         if (minus) {
134                                 *cln = '-';
135                                 cln++;
136                         }
137                         for (; src <= end; src++, cln++)
138                                 *cln = *src;
139
140                         goto next;
141                 }
142
143                 while (*end != ':' && *end)
144                         end++;
145                 *cln = 'U';
146                 cln++;
147                 *cln = ':';
148                 cln++;
149         next:
150                 end++;
151                 src = end;
152                 entries++;
153         }
154
155         strncpy(data, clean_data, RRD_DATA_MAX_LEN);
156         return entries;
157 }
158
159 int rrdtool_update_data(struct rrd_database *rrd)
160 {
161         int pid;
162         char data[RRD_DATA_MAX_LEN + 2];
163         char cmd[] = RRDTOOL_CMD;
164 //      char cmd[] = "echo";
165         char *cmdline[] = {
166                 "",
167                 "update",
168                 rrd->filename,
169                 data,
170                 0
171         };
172         int l;
173
174         rrd->last_update = time(0);
175         if (do_fork())
176                 return 0;
177
178         l = sprintf(data, "N:");
179
180         if (rrd->parse) {
181                 rrd->parse(data + l, rrd->parser_data);
182                 sanitize_rrd_update_data(data + l);
183                 pid = run(cmd, cmdline);
184                 harvest_zombies(pid);
185         }
186
187         if (rrd->images)
188                 rrdtool_draw_images(rrd->images);
189
190         while (harvest_zombies(0));
191         exit(0);
192 }
193
194 static int database_exists(struct rrd_database *db)
195 {
196         struct stat s;
197
198         /* If the filename exists, stat will return zero */
199         if (db->filename)
200                 return !stat(db->filename, &s);
201
202         return 1;
203 }
204
205 static int create_database(struct rrd_database *db)
206 {
207         char cmd[] = RRDTOOL_CMD;
208 //      char cmd[] = "echo";
209         char *args[512], argstr[ARGSTR_LEN];
210         int idx = 0, argcnt = 0;
211         int child, i;
212
213         if (!db->sources || !db->archives) {
214                 printf("Cannot create db \"%s\", insufficient source data\n",
215                         db->filename);
216                 return -1;
217         }
218
219         add_arg(args, argcnt, argstr, idx, " ");
220         add_arg(args, argcnt, argstr, idx, "create");
221         add_arg(args, argcnt, argstr, idx, "%s", db->filename);
222         add_arg(args, argcnt, argstr, idx, "--step");
223         add_arg(args, argcnt, argstr, idx, "%d", db->interval);
224
225         for (i = 0; db->sources[i].type; i++) {
226                 add_arg(args, argcnt, argstr, idx, "DS:%s:%s:%d:%f:%f",
227                         db->sources[i].name,
228                         db->sources[i].type,
229                         db->sources[i].heartbeat,
230                         db->sources[i].min,
231                         db->sources[i].max);
232         }
233
234         for (i = 0; db->archives[i].type; i++) {
235                 add_arg(args, argcnt, argstr, idx, "RRA:%s:%f:%d:%d",
236                         db->archives[i].type,
237                         db->archives[i].xff,
238                         db->archives[i].steps,
239                         db->archives[i].rows);
240         }
241
242         child = run(cmd, args);
243
244         harvest_zombies(child);
245
246         return 0;
247 }
248
249 int rrdtool_check_databases(struct rrd_database *dbs[])
250 {
251         struct rrd_database *db;
252         int i;
253
254         for (i = 0, db = dbs[i]; db; i++, db = dbs[i]) {
255                 if (database_exists(db)) {
256                         printf("database %s found\n", db->filename);
257                         continue;
258                 }
259                 printf("Database %s missing, creating\n", db->filename);
260                 create_database(db);
261         }
262         printf("All done\n");
263
264         return 0;
265 }