X-Git-Url: https://git.tokkee.org/?p=sysdb.git;a=blobdiff_plain;f=src%2Fplugins%2Ftimeseries%2Frrdtool.c;h=8ab7f69e20b5f728a1d439922c1a22d849e7eaa5;hp=7d6c30b68ff236d6b59dc417fce56706fe63dde0;hb=dcf7802ad0958d4752b2c13f70e2fdf345d3509f;hpb=49b5a4d2e8e4fb1e4f67c2a368d8d2e3e76b765f diff --git a/src/plugins/timeseries/rrdtool.c b/src/plugins/timeseries/rrdtool.c index 7d6c30b..8ab7f69 100644 --- a/src/plugins/timeseries/rrdtool.c +++ b/src/plugins/timeseries/rrdtool.c @@ -1,6 +1,6 @@ /* * SysDB - src/plugins/timeseries/rrdtool.c - * Copyright (C) 2014 Sebastian 'tokkee' Harl + * Copyright (C) 2014-2016 Sebastian 'tokkee' Harl * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -37,6 +37,8 @@ #include #include +#include +#include #include #ifdef HAVE_RRD_CLIENT_H # include @@ -49,10 +51,114 @@ SDB_PLUGIN_MAGIC; * instances. */ static bool rrdcached_in_use = 0; +static bool +rrdcached_connect(char *addr) +{ +#ifdef HAVE_RRD_CLIENT_H + rrd_clear_error(); + if (! rrdc_is_connected(addr)) { + if (rrdc_connect(addr)) { + sdb_log(SDB_LOG_ERR, "Failed to connectd to RRDCacheD at %s: %s", + addr, rrd_get_error()); + return 0; + } + } +#else + sdb_log(SDB_LOG_ERR, "Callback called with RRDCacheD address " + "but your build of SysDB does not support that"); + return 0; +#endif + return 1; +} /* rrdcached_connect */ + /* * plugin API */ +static sdb_timeseries_info_t * +sdb_rrd_describe(const char *id, sdb_object_t *user_data) +{ + rrd_info_t *info, *iter; + char filename[strlen(id) + 1]; + sdb_timeseries_info_t *ts_info; + + strncpy(filename, id, sizeof(filename)); + + if (user_data) { + /* -> use RRDCacheD */ + char *addr = SDB_OBJ_WRAPPER(user_data)->data; + + if (! rrdcached_connect(addr)) + return NULL; + +#ifdef HAVE_RRD_CLIENT_H + /* TODO: detect and use rrdc_info if possible */ + sdb_log(SDB_LOG_ERR, "DESCRIBE not yet supported via RRDCacheD"); + return NULL; +#endif + } + else { + rrd_clear_error(); + info = rrd_info_r(filename); + } + if (! info) { + sdb_log(SDB_LOG_ERR, "Failed to extract header information from '%s': %s", + filename, rrd_get_error()); + return NULL; + } + + ts_info = calloc(1, sizeof(*ts_info)); + if (! ts_info) { + sdb_log(SDB_LOG_ERR, "Failed to allocate memory"); + rrd_info_free(info); + return NULL; + } + + for (iter = info; iter != NULL; iter = iter->next) { + size_t len, n, m; + char *ds_name; + char **tmp; + + /* Parse the DS name. The raw value is not exposed via the rrd_info + * interface. */ + n = strlen("ds["); + if (strncmp(iter->key, "ds[", n)) + continue; + + len = strlen(iter->key); + m = strlen("].index"); + if ((len < m) || strcmp(iter->key + len - m, "].index")) + continue; + + ds_name = iter->key + n; + len -= n; + ds_name[len - m] = '\0'; + + /* Append the new datum. */ + tmp = realloc(ts_info->data_names, + (ts_info->data_names_len + 1) * sizeof(*ts_info->data_names)); + if (! tmp) { + sdb_log(SDB_LOG_ERR, "Failed to allocate memory"); + sdb_timeseries_info_destroy(ts_info); + rrd_info_free(info); + return NULL; + } + + ts_info->data_names = tmp; + ts_info->data_names[ts_info->data_names_len] = strdup(ds_name); + if (! ts_info->data_names[ts_info->data_names_len]) { + sdb_log(SDB_LOG_ERR, "Failed to allocate memory"); + sdb_timeseries_info_destroy(ts_info); + rrd_info_free(info); + return NULL; + } + ts_info->data_names_len++; + } + rrd_info_free(info); + + return ts_info; +} /* sdb_rrd_describe */ + static sdb_timeseries_t * sdb_rrd_fetch(const char *id, sdb_timeseries_opts_t *opts, sdb_object_t *user_data) @@ -70,30 +176,18 @@ sdb_rrd_fetch(const char *id, sdb_timeseries_opts_t *opts, rrd_value_t *data = NULL, *data_ptr; if (user_data) { -#ifdef HAVE_RRD_CLIENT_H /* -> use RRDCacheD */ char *addr = SDB_OBJ_WRAPPER(user_data)->data; - rrd_clear_error(); - if (! rrdc_is_connected(addr)) { - if (rrdc_connect(addr)) { - sdb_log(SDB_LOG_ERR, "timeseries::rrdtool: Failed to " - "connectd to RRDCacheD at %s: %s", - addr, rrd_get_error()); - return NULL; - } - } + if (! rrdcached_connect(addr)) + return NULL; +#ifdef HAVE_RRD_CLIENT_H if (rrdc_flush(id)) { - sdb_log(SDB_LOG_ERR, "timeseries::rrdtool: Failed to flush " - "'%s' through RRDCacheD: %s", id, rrd_get_error()); + sdb_log(SDB_LOG_ERR, "Failed to flush '%s' through RRDCacheD: %s", + id, rrd_get_error()); return NULL; } -#else - sdb_log(SDB_LOG_ERR, "timeseries::rrdtool: Callback called with " - "RRDCacheD address but your build of SysDB does not support " - "that"); - return NULL; #endif } @@ -114,8 +208,7 @@ sdb_rrd_fetch(const char *id, sdb_timeseries_opts_t *opts, &ds_cnt, &ds_namv, &data)) { char errbuf[1024]; sdb_strerror(errno, errbuf, sizeof(errbuf)); - sdb_log(SDB_LOG_ERR, "rrdtool plugin: Failed to fetch data " - "from %s: %s", id, errbuf); + sdb_log(SDB_LOG_ERR, "Failed to fetch data from %s: %s", id, errbuf); return NULL; } @@ -125,8 +218,7 @@ sdb_rrd_fetch(const char *id, sdb_timeseries_opts_t *opts, if (! ts) { char errbuf[1024]; sdb_strerror(errno, errbuf, sizeof(errbuf)); - sdb_log(SDB_LOG_ERR, "rrdtool plugin: Failed to allocate " - "time-series object: %s", errbuf); + sdb_log(SDB_LOG_ERR, "Failed to allocate time-series object: %s", errbuf); FREE_RRD_DATA(); return NULL; } @@ -151,6 +243,10 @@ sdb_rrd_fetch(const char *id, sdb_timeseries_opts_t *opts, return ts; } /* sdb_rrd_fetch */ +static sdb_timeseries_fetcher_t fetcher_impl = { + sdb_rrd_describe, sdb_rrd_fetch, +}; + static int sdb_rrdcached_shutdown(sdb_object_t __attribute__((unused)) *user_data) { @@ -167,50 +263,45 @@ sdb_rrd_config_rrdcached(oconfig_item_t *ci) char *addr = NULL; if (rrdcached_in_use) { - sdb_log(SDB_LOG_ERR, "timeseries::rrdtool: RRDCacheD does " - "not support multiple connections"); + sdb_log(SDB_LOG_ERR, "RRDCacheD does not support multiple connections"); return -1; } #ifndef HAVE_RRD_CLIENT_H - sdb_log(SDB_LOG_ERR, "timeseries::rrdtool: RRDCacheD client " - "support not available in your SysDB build"); + sdb_log(SDB_LOG_ERR, "RRDCacheD client support not available in your SysDB build"); return -1; #else if (oconfig_get_string(ci, &addr)) { - sdb_log(SDB_LOG_ERR, "timeseries::unixsock: RRDCacheD requires " - "a single string argument\n\tUsage "); + sdb_log(SDB_LOG_ERR, "RRDCacheD requires a single string argument\n" + "\tUsage "); return -1; } if ((*addr != '/') && strncmp(addr, "unix:", strlen("unix:"))) { /* XXX: add (optional) support for rrdc_fetch if available */ - sdb_log(SDB_LOG_ERR, "timeseries::unixsock: RRDCacheD only " - "supports local (UNIX socket) addresses"); + sdb_log(SDB_LOG_ERR, "RRDCacheD only supports local (UNIX socket) addresses"); return -1; } addr = strdup(addr); if (! addr) { char errbuf[1024]; - sdb_log(SDB_LOG_ERR, "timeseries::unixsock: Failed to duplicate " - "string: %s", sdb_strerror(errno, errbuf, sizeof(errbuf))); + sdb_log(SDB_LOG_ERR, "Failed to duplicate string: %s", + sdb_strerror(errno, errbuf, sizeof(errbuf))); return -1; } if (ci->children_num) - sdb_log(SDB_LOG_WARNING, "timeseries::unixsock: RRDCacheD does " - "not support any child config options"); + sdb_log(SDB_LOG_WARNING, "RRDCacheD does not support any child config options"); ud = sdb_object_create_wrapper("rrdcached-addr", addr, free); if (! ud) { char errbuf[1024]; - sdb_log(SDB_LOG_ERR, "timeseries::unixsock: Failed to create " - "user-data object: %s", + sdb_log(SDB_LOG_ERR, "Failed to create user-data object: %s", sdb_strerror(errno, errbuf, sizeof(errbuf))); free(addr); return -1; } - sdb_plugin_register_ts_fetcher("rrdcached", sdb_rrd_fetch, ud); + sdb_plugin_register_timeseries_fetcher("rrdcached", &fetcher_impl, ud); sdb_plugin_register_shutdown("rrdcached", sdb_rrdcached_shutdown, NULL); sdb_object_deref(ud); rrdcached_in_use = 1; @@ -234,8 +325,7 @@ sdb_rrd_config(oconfig_item_t *ci) if (! strcasecmp(child->key, "RRDCacheD")) sdb_rrd_config_rrdcached(child); else - sdb_log(SDB_LOG_WARNING, "timeseries::rrdtool: Ignoring " - "unknown config option '%s'.", child->key); + sdb_log(SDB_LOG_WARNING, "Ignoring unknown config option '%s'.", child->key); } return 0; } /* sdb_rrd_config */ @@ -251,7 +341,7 @@ sdb_module_init(sdb_plugin_info_t *info) sdb_plugin_set_info(info, SDB_PLUGIN_INFO_VERSION, SDB_VERSION); sdb_plugin_set_info(info, SDB_PLUGIN_INFO_PLUGIN_VERSION, SDB_VERSION); - sdb_plugin_register_ts_fetcher("rrdtool", sdb_rrd_fetch, NULL); + sdb_plugin_register_timeseries_fetcher("rrdtool", &fetcher_impl, NULL); sdb_plugin_register_config(sdb_rrd_config); return 0; } /* sdb_module_init */