9 #define RRD_DATABASE_LIST "rrd_database"
10 #define RRD_DATABASE_NAME "name"
12 static int read_strings_from_list(config_setting_t *list, const char ***strings)
14 config_setting_t *string;
16 int str_count = config_setting_length(list);
19 strs = calloc(sizeof(*strs), str_count + 1);
21 for (j = 0; j < str_count; j++) {
24 string = config_setting_get_elem(list, j);
25 str = config_setting_get_string(string);
26 strs[j] = strdup(str);
33 static int parse_images(config_setting_t *list, struct rrd_database *db)
36 config_setting_t *image, *str_list;
37 const char *database = NULL, *filename = NULL, *timestart = NULL;
38 const char *timeend = NULL, *imageformat = NULL;
39 const char **options = NULL, **text = NULL;
40 const char *updatestr = NULL;
41 int width = 0, height = 0, text_lead = 0;
43 count = config_setting_length(list);
45 pr_info("%s: Parsing %d images\n", db->name, count);
46 db->images = calloc(sizeof(*db->images), count + 1);
48 for (i = 0; i < count; i++) {
49 image = config_setting_get_elem(list, i);
50 db->images[i] = calloc(sizeof(*db->images[i]), 1);
52 config_setting_lookup_string(image, "database", &database);
53 config_setting_lookup_int(image, "text_lead", &text_lead);
56 * The config_setting_lookup_* functions will leave
57 * the destination unchanged in case requested value
58 * is not found. If that is the case, the value from
59 * previous image group is used. That makes it
60 * possible for the user to only define once all
61 * fields and then leave identical fields unset on the
62 * following groups, making it easier to define many
63 * almost identical images.
66 config_setting_lookup_string(image, "filename", &filename);
68 pr_err("Database %s does not have \"filename\" entry "
74 config_setting_lookup_int(image, "width", &width);
76 pr_err("Database %s does not have \"width\" entry "
82 config_setting_lookup_int(image, "height", &height);
84 pr_err("Database %s does not have \"height\" entry "
90 config_setting_lookup_string(image, "timestart", ×tart);
92 pr_err("Database %s does not have \"timestart\" entry "
98 config_setting_lookup_string(image, "timeend", &timeend);
100 pr_err("Database %s does not have \"timeend\" entry "
106 config_setting_lookup_string(image, "imageformat",
109 pr_err("Database %s does not have \"imageformat\" "\
110 "entry in image data\n",
115 config_setting_lookup_string(image, "update_string",
118 str_list = config_setting_get_member(image, "options");
120 read_strings_from_list(str_list, &options);
122 str_list = config_setting_get_member(image, "text");
124 read_strings_from_list(str_list, &text);
126 db->images[i]->rrd_database =
127 database ? strdup(database) : NULL;
128 db->images[i]->image_filename = strdup(filename);
129 db->images[i]->width = width;
130 db->images[i]->height = height;
131 strncpy(db->images[i]->timestart, timestart,
132 sizeof(db->images[i]->timestart) - 1);
133 strncpy(db->images[i]->timeend, timeend,
134 sizeof(db->images[i]->timeend) - 1);
135 strncpy(db->images[i]->imageformat, imageformat,
136 sizeof(db->images[i]->imageformat) - 1);
137 db->images[i]->options = options;
138 db->images[i]->text_lead = text_lead;
139 db->images[i]->text = text;
142 db->images[i]->updatestr = strdup(updatestr);
148 static int parse_data_sources(config_setting_t *rrd, struct rrd_database *db)
150 config_setting_t *list, *group;
152 const char *type = NULL, *name = NULL;
157 list = config_setting_get_member(rrd, "sources");
159 pr_info("No data sources\n");
163 if (!config_setting_is_list(list)) {
164 pr_err("Data sources have no list\n");
168 count = config_setting_length(list);
169 db->sources = calloc(sizeof(*db->sources), count + 1);
171 for (i = 0; i < count; i++) {
172 group = config_setting_get_elem(list, i);
174 config_setting_lookup_string(group, "type", &type);
175 config_setting_lookup_string(group, "name", &name);
176 config_setting_lookup_float(group, "min", &min);
177 config_setting_lookup_float(group, "max", &max);
178 config_setting_lookup_int(group, "heartbeat", &heartbeat);
180 db->sources[i].type = strdup(type);
181 db->sources[i].name = strdup(name);
182 db->sources[i].heartbeat = heartbeat;
183 db->sources[i].min = min;
184 db->sources[i].max = max;
190 static int parse_archives(config_setting_t *rrd, struct rrd_database *db)
192 config_setting_t *list, *group;
194 const char *type = NULL;
199 list = config_setting_get_member(rrd, "archives");
201 pr_info("No archive found\n");
205 if (!config_setting_is_list(list)) {
206 pr_err("Archive does not contain a list\n");
210 count = config_setting_length(list);
211 db->archives = calloc(sizeof(*db->archives), count + 1);
213 for (i = 0; i < count; i++) {
214 group = config_setting_get_elem(list, i);
216 config_setting_lookup_string(group, "type", &type);
217 config_setting_lookup_float(group, "xff", &xff);
218 config_setting_lookup_int(group, "steps", &steps);
219 config_setting_lookup_int(group, "rows", &rows);
221 db->archives[i].type = strdup(type);
222 db->archives[i].xff = xff;
223 db->archives[i].steps = steps;
224 db->archives[i].rows = rows;
230 static int parse_database(config_setting_t *rrd, struct rrd_database *db)
232 config_setting_t *list, *str_list;
233 const char *name, *parser = NULL, *filename, **parser_data;
234 const char **pre_draw_cmd;
235 const char **post_draw_cmd;
236 const char *logfile = NULL, *logfile_timestamp_fmt = NULL;
238 if (!config_setting_lookup_string(rrd, "name", &name)) {
239 pr_err("Database entry does not contain name\n");
243 pr_info("parsing database %s\n", name);
244 db->name = strdup(name);
246 if (!config_setting_lookup_string(rrd, "filename", &filename)) {
247 pr_err("Database %s does not contain filename\n", db->name);
250 db->filename = strdup(filename);
252 if (!config_setting_lookup_int(rrd, "interval", &db->interval)) {
253 pr_err("Database %s does not have interval set\n", name);
257 /* Parser is not a mandatory parameter */
258 config_setting_lookup_string(rrd, "parser", &parser);
259 db->parser = str_to_parser(parser);
261 list = config_setting_get_member(rrd, "image");
262 parse_images(list, db);
263 parse_data_sources(rrd, db);
264 parse_archives(rrd, db);
266 str_list = config_setting_get_member(rrd, "parser_data");
268 read_strings_from_list(str_list, &parser_data);
269 db->parser_data = parser_data;
272 str_list = config_setting_get_member(rrd, "pre_draw_cmd");
274 read_strings_from_list(str_list, &pre_draw_cmd);
275 db->pre_draw_cmd = (char *const *)pre_draw_cmd;
278 str_list = config_setting_get_member(rrd, "post_draw_cmd");
280 read_strings_from_list(str_list, &post_draw_cmd);
281 db->post_draw_cmd = (char *const *)post_draw_cmd;
284 config_setting_lookup_string(rrd, "logfile", &logfile);
286 db->logfile = strdup(logfile);
288 config_setting_lookup_string(rrd, "logfile_timestamp_fmt",
289 &logfile_timestamp_fmt);
290 if (logfile_timestamp_fmt)
291 db->logfile_timestamp_fmt = strdup(logfile_timestamp_fmt);
297 struct rrd_database **populate_database(const char *conffile)
299 struct rrd_database **rrd_db = NULL;
301 config_setting_t *rrd_database;
304 config_init(&config);
306 if (!config_read_file(&config, conffile)) {
307 pr_err("%s:%d - %s\n", config_error_file(&config),
308 config_error_line(&config),
309 config_error_text(&config));
313 rrd_database = config_lookup(&config, "rrd_database");
314 count = config_setting_length(rrd_database);
317 * Allocate one element extra. The last one is zeroed out to
318 * indicate the end of the db list
320 rrd_db = calloc(count + 1, sizeof(*rrd_db));
322 pr_info("There are %d database entries\n", count);
324 for (i = 0; i < count; i++) {
325 config_setting_t *rrd;
326 rrd_db[i] = calloc(1, sizeof(*rrd_db[i]));
327 rrd = config_setting_get_elem(rrd_database, i);
328 parse_database(rrd, rrd_db[i]);
332 config_destroy(&config);