Ejemplo n.º 1
0
sdb_timeseries_t *
sdb_timeseries_create(size_t data_names_len, const char * const *data_names,
		size_t data_len)
{
	sdb_timeseries_t *ts;
	size_t i;

	ts = calloc(1, sizeof(*ts));
	if (! ts)
		return NULL;

	if (stringv_copy(&ts->data_names, &ts->data_names_len,
				data_names, data_names_len)) {
		sdb_timeseries_destroy(ts);
		return NULL;
	}

	ts->data = calloc(data_names_len, sizeof(*ts->data));
	if (! ts->data) {
		sdb_timeseries_destroy(ts);
		return NULL;
	}
	for (i = 0; i < data_names_len; ++i) {
		ts->data[i] = calloc(data_len, sizeof(**ts->data));
		if (! ts->data[i]) {
			sdb_timeseries_destroy(ts);
			return NULL;
		}
	}
	ts->data_len = data_len;
	return ts;
} /* sdb_timeseries_create */
Ejemplo n.º 2
0
static sdb_timeseries_t *
sdb_rrd_fetch(const char *id, sdb_timeseries_opts_t *opts,
		sdb_object_t *user_data)
{
	sdb_timeseries_t *ts;

	time_t start = (time_t)SDB_TIME_TO_SECS(opts->start);
	time_t end = (time_t)SDB_TIME_TO_SECS(opts->end);

	unsigned long step = 0;
	unsigned long ds_cnt = 0;
	unsigned long val_cnt = 0;
	char **ds_namv = NULL;
	rrd_value_t *data = NULL;

	if (user_data) {
		/* -> use RRDCacheD */
		char *addr = SDB_OBJ_WRAPPER(user_data)->data;

		if (! rrdcached_connect(addr))
			return NULL;

#ifdef HAVE_RRD_CLIENT_H
		if (rrdc_flush(id)) {
			sdb_log(SDB_LOG_ERR, "Failed to flush '%s' through RRDCacheD: %s",
					id, rrd_get_error());
			return NULL;
		}
#endif
	}

#define FREE_RRD_DATA() \
	do { \
		size_t i; \
		for (i = 0; i < ds_cnt; ++i) \
			rrd_freemem(ds_namv[i]); \
		rrd_freemem(ds_namv); \
		rrd_freemem(data); \
	} while (0)

	/* limit to about 1000 data-points for now
	 * TODO: make this configurable */
	step = (end - start) / 1000;

	if (rrd_fetch_r(id, "AVERAGE", &start, &end, &step,
				&ds_cnt, &ds_namv, &data)) {
		char errbuf[1024];
		sdb_strerror(errno, errbuf, sizeof(errbuf));
		sdb_log(SDB_LOG_ERR, "Failed to fetch data from %s: %s", id, errbuf);
		return NULL;
	}

	val_cnt = (unsigned long)(end - start) / step;

	/* RRDtool does not support fetching specific data-sources, so we'll have
	 * to filter the requested ones after fetching them all */
	if (opts->data_names && opts->data_names_len)
		ts = sdb_timeseries_create(opts->data_names_len,
				(const char * const *)opts->data_names, val_cnt);
	else
		ts = sdb_timeseries_create(ds_cnt, (const char * const *)ds_namv, val_cnt);
	if (! ts) {
		char errbuf[1024];
		sdb_strerror(errno, errbuf, sizeof(errbuf));
		sdb_log(SDB_LOG_ERR, "Failed to allocate time-series object: %s", errbuf);
		FREE_RRD_DATA();
		return NULL;
	}

	ts->start = SECS_TO_SDB_TIME(start + (time_t)step);
	ts->end = SECS_TO_SDB_TIME(end);

	if (copy_data(ts, data, (time_t)step, (size_t)ds_cnt, ds_namv) < 0) {
		FREE_RRD_DATA();
		sdb_timeseries_destroy(ts);
		return NULL;
	}

	FREE_RRD_DATA();
	return ts;
} /* sdb_rrd_fetch */