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 int width = 0, height = 0, text_lead = 0;
42 count = config_setting_length(list);
44 pr_info("%s: Parsing %d images\n", db->name, count);
45 db->images = calloc(sizeof(*db->images), count + 1);
47 for (i = 0; i < count; i++) {
48 image = config_setting_get_elem(list, i);
49 db->images[i] = calloc(sizeof(*db->images[i]), 1);
51 config_setting_lookup_string(image, "database", &database);
52 config_setting_lookup_int(image, "text_lead", &text_lead);
55 * The config_setting_lookup_* functions will leave
56 * the destination unchanged in case requested value
57 * is not found. If that is the case, the value from
58 * previous image group is used. That makes it
59 * possible for the user to only define once all
60 * fields and then leave identical fields unset on the
61 * following groups, making it easier to define many
62 * almost identical images.
65 config_setting_lookup_string(image, "filename", &filename);
67 pr_err("Database %s does not have \"filename\" entry "
73 config_setting_lookup_int(image, "width", &width);
75 pr_err("Database %s does not have \"width\" entry "
81 config_setting_lookup_int(image, "height", &height);
83 pr_err("Database %s does not have \"height\" entry "
89 config_setting_lookup_string(image, "timestart", ×tart);
91 pr_err("Database %s does not have \"timestart\" entry "
97 config_setting_lookup_string(image, "timeend", &timeend);
99 pr_err("Database %s does not have \"timeend\" entry "
105 config_setting_lookup_string(image, "imageformat",
108 pr_err("Database %s does not have \"imageformat\" "\
109 "entry in image data\n",
114 str_list = config_setting_get_member(image, "options");
116 read_strings_from_list(str_list, &options);
118 str_list = config_setting_get_member(image, "text");
120 read_strings_from_list(str_list, &text);
122 db->images[i]->rrd_database =
123 database ? strdup(database) : NULL;
124 db->images[i]->image_filename = strdup(filename);
125 db->images[i]->width = width;
126 db->images[i]->height = height;
127 strncpy(db->images[i]->timestart, timestart,
128 sizeof(db->images[i]->timestart));
129 strncpy(db->images[i]->timeend, timeend,
130 sizeof(db->images[i]->timeend));
131 strncpy(db->images[i]->imageformat, imageformat,
132 sizeof(db->images[i]->imageformat));
133 db->images[i]->options = options;
134 db->images[i]->text_lead = text_lead;
135 db->images[i]->text = text;
141 static int (*str_to_parser(const char *str))(char *rrd_data, const char **parser_data)
146 if (!strcmp(str, "cpu"))
149 if (!strcmp(str, "mem"))
152 if (!strcmp(str, "cpu_mem"))
153 return cpu_mem_parser;
155 if (!strcmp(str, "digitemp"))
156 return digitemp_parser;
158 if (!strcmp(str, "digitemp_mod"))
159 return digitemp_parser_mod;
161 if (!strcmp(str, "script"))
162 return script_parser;
164 if (!strcmp(str, "netstats"))
165 return netstats_parser;
167 if (!strcmp(str, "onewire"))
168 return onewire_parser;
173 static int parse_data_sources(config_setting_t *rrd, struct rrd_database *db)
175 config_setting_t *list, *group;
177 const char *type = NULL, *name = NULL;
182 list = config_setting_get_member(rrd, "sources");
184 pr_info("No data sources\n");
188 if (!config_setting_is_list(list)) {
189 pr_err("Data sources have no list\n");
193 count = config_setting_length(list);
194 db->sources = calloc(sizeof(*db->sources), count + 1);
196 for (i = 0; i < count; i++) {
197 group = config_setting_get_elem(list, i);
199 config_setting_lookup_string(group, "type", &type);
200 config_setting_lookup_string(group, "name", &name);
201 config_setting_lookup_float(group, "min", &min);
202 config_setting_lookup_float(group, "max", &max);
203 config_setting_lookup_int(group, "heartbeat", &heartbeat);
205 db->sources[i].type = strdup(type);
206 db->sources[i].name = strdup(name);
207 db->sources[i].heartbeat = heartbeat;
208 db->sources[i].min = min;
209 db->sources[i].max = max;
215 static int parse_archives(config_setting_t *rrd, struct rrd_database *db)
217 config_setting_t *list, *group;
219 const char *type = NULL;
224 list = config_setting_get_member(rrd, "archives");
226 pr_info("No archive found\n");
230 if (!config_setting_is_list(list)) {
231 pr_err("Archive does not contain a list\n");
235 count = config_setting_length(list);
236 db->archives = calloc(sizeof(*db->archives), count + 1);
238 for (i = 0; i < count; i++) {
239 group = config_setting_get_elem(list, i);
241 config_setting_lookup_string(group, "type", &type);
242 config_setting_lookup_float(group, "xff", &xff);
243 config_setting_lookup_int(group, "steps", &steps);
244 config_setting_lookup_int(group, "rows", &rows);
246 db->archives[i].type = strdup(type);
247 db->archives[i].xff = xff;
248 db->archives[i].steps = steps;
249 db->archives[i].rows = rows;
255 static int parse_database(config_setting_t *rrd, struct rrd_database *db)
257 config_setting_t *list, *str_list;
258 const char *name, *parser = NULL, *filename, **parser_data;
260 if (!config_setting_lookup_string(rrd, "name", &name)) {
261 pr_err("Database entry does not contain name\n");
265 pr_info("parsing database %s\n", name);
266 db->name = strdup(name);
268 if (!config_setting_lookup_string(rrd, "filename", &filename)) {
269 pr_err("Database %s does not contain filename\n", db->name);
272 db->filename = strdup(filename);
274 if (!config_setting_lookup_int(rrd, "interval", &db->interval)) {
275 pr_err("Database %s does not have interval set\n", name);
279 /* Parser is not a mandatory parameter */
280 config_setting_lookup_string(rrd, "parser", &parser);
281 db->parse = str_to_parser(parser);
283 list = config_setting_get_member(rrd, "image");
284 parse_images(list, db);
285 parse_data_sources(rrd, db);
286 parse_archives(rrd, db);
288 str_list = config_setting_get_member(rrd, "parser_data");
290 read_strings_from_list(str_list, &parser_data);
291 db->parser_data = parser_data;
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);
336 #define CONFIG_ADD_STRING(_config, _setting, _name, _val) \
338 _setting = config_setting_add(_config, _name, \
339 CONFIG_TYPE_STRING); \
340 config_setting_set_string(_setting, _val); \
343 #define CONFIG_ADD_INT(_config, _setting, _name, _val) \
345 _setting = config_setting_add(_config, _name, \
347 config_setting_set_int(_setting, _val); \
350 #define CONFIG_ADD_FLOAT(_config, _setting, _name, _val) \
352 _setting = config_setting_add(_config, _name, \
353 CONFIG_TYPE_FLOAT); \
354 config_setting_set_float(_setting, _val); \
357 static void put_strings_to_list(config_setting_t *config,
358 const char *entry_name, const char **strings)
360 config_setting_t *list, *setting;
363 list = config_setting_add(config, entry_name, CONFIG_TYPE_LIST);
364 for (i = 0; strings[i]; i++)
365 CONFIG_ADD_STRING(list, setting, NULL, strings[i]);
368 static void put_image_to_list(config_setting_t *config,
369 struct rrd_image *image)
371 config_setting_t *setting, *group;
373 group = config_setting_add(config, "image", CONFIG_TYPE_GROUP);
375 CONFIG_ADD_STRING(group, setting, "rrd_database", image->rrd_database);
376 CONFIG_ADD_STRING(group, setting, "filename", image->image_filename);
377 CONFIG_ADD_INT(group, setting, "width", image->width);
378 CONFIG_ADD_INT(group, setting, "height", image->height);
379 CONFIG_ADD_STRING(group, setting, "timestart", image->timestart);
380 CONFIG_ADD_STRING(group, setting, "timeend", image->timeend);
381 CONFIG_ADD_STRING(group, setting, "imageformat", image->imageformat);
383 put_strings_to_list(group, "options", image->options);
385 CONFIG_ADD_INT(group, setting, "text_lead", image->text_lead);
387 put_strings_to_list(group, "text", image->text);
390 static void put_data_source_to_list(config_setting_t *list,
391 struct rrd_data_source *source)
393 config_setting_t *setting, *group;
395 group = config_setting_add(list, "data_source", CONFIG_TYPE_GROUP);
397 CONFIG_ADD_STRING(group, setting, "type", source->type);
398 CONFIG_ADD_STRING(group, setting, "name", source->name);
399 CONFIG_ADD_INT(group, setting, "heartbeat", source->heartbeat);
400 CONFIG_ADD_FLOAT(group, setting, "min", source->min);
401 CONFIG_ADD_FLOAT(group, setting, "max", source->max);
404 static void put_archive_to_list(config_setting_t *list,
405 struct rrd_archive *archive)
407 config_setting_t *setting, *group;
409 group = config_setting_add(list, "archive", CONFIG_TYPE_GROUP);
411 CONFIG_ADD_STRING(group, setting, "type", archive->type);
412 CONFIG_ADD_FLOAT(group, setting, "xff", archive->xff);
413 CONFIG_ADD_INT(group, setting, "steps", archive->steps);
414 CONFIG_ADD_INT(group, setting, "rows", archive->rows);
417 static char *parser_to_str(int (*parser)(char *rrd_data, const char **parser_data))
419 if (parser == cpu_parser)
422 if (parser == mem_parser)
425 if (parser == cpu_mem_parser)
428 if (parser == digitemp_parser)
431 if (parser == digitemp_parser_mod)
432 return "digitemp_mod";
434 if (parser == script_parser)
437 if (parser == netstats_parser)
440 if (parser == onewire_parser)
446 static void put_database_to_list(config_setting_t *config,
447 struct rrd_database *db)
449 config_setting_t *setting;
450 config_setting_t *list, *group;
451 char *str = parser_to_str(db->parse);
454 group = config_setting_add(config, RRD_DATABASE_LIST,
457 CONFIG_ADD_STRING(group, setting, "name", db->name);
458 CONFIG_ADD_STRING(group, setting, "filename", db->filename);
459 CONFIG_ADD_INT(group, setting, "interval", db->interval);
460 CONFIG_ADD_STRING(group, setting, "parser", str);
463 put_strings_to_list(group, "parser_data", db->parser_data);
465 list = config_setting_add(group, "image", CONFIG_TYPE_LIST);
466 for (i = 0; db->images[i]; i++) {
467 put_image_to_list(list, db->images[i]);
471 list = config_setting_add(group, "sources", CONFIG_TYPE_LIST);
472 for (i = 0; db->sources[i].type; i++) {
473 put_data_source_to_list(list, &db->sources[i]);
478 list = config_setting_add(group, "archives", CONFIG_TYPE_LIST);
479 for (i = 0; db->archives[i].type; i++) {
480 put_archive_to_list(list, &db->archives[i]);
485 int write_database(const char *conffile, struct rrd_database **rrd_db)
488 config_setting_t *root, *rrd_database_list;
492 config_init(&config);
494 config_set_tab_width(&config, 4);
496 root = config_root_setting(&config);
498 rrd_database_list = config_setting_add(root, RRD_DATABASE_LIST,
500 for (i = 0; rrd_db[i]; i++) {
501 put_database_to_list(rrd_database_list, rrd_db[i]);
504 ret = !config_write_file(&config, conffile);
506 pr_err("Error while writing file.\n");
508 config_destroy(&config);