sleeptime = get_next_update(db_list, &db_name);
- t = time(0) + sleeptime;
- strftime(timestr, sizeof(timestr), "%T", localtime(&t));
- pr_info("Next scheduled event \"%s\" at %s, in %d seconds\n",
- db_name, timestr, sleeptime);
+ if (sleeptime >= 0) {
+ t = time(0) + sleeptime;
+ strftime(timestr, sizeof(timestr), "%T", localtime(&t));
+ pr_info("Next scheduled event \"%s\" at %s, in %d seconds\n",
+ db_name, timestr, sleeptime);
+ } else
+ pr_info("All jobs active, sleeping until event arrives\n");
poll_job_requests(sleeptime);
}
#include "parser.h"
#include "debug.h"
#include "string.h"
+#include "utils.h"
#define MAX_ARGS 512
#define ARGSTR_LEN 32768
return 0;
}
+static int rrdtool_update_data_multi(struct rrd_database *rrd)
+{
+ char **data = NULL;
+ int ret, i, d;
+ char cmd[] = RRDTOOL_CMD;
+ char *cmdline[512] = {
+ RRDTOOL_CMD,
+ "update",
+ (char *const)rrd->filename,
+ };
+ int old_last_update = rrd->last_update;
+
+ ret = rrd->parser->parse_multi(&data, rrd->parser_data,
+ &rrd->parser_state, rrd->last_update);
+ if (ret < 0) {
+ pr_err("Parser failure: %d\n", ret);
+ goto out;
+ }
+
+ for (i = 3, d = 0; i < ARRAY_SIZE(cmdline) - 1; i++, d++) {
+ time_t then;
+
+ if (!data[d])
+ break;
+
+ sanitize_rrd_update_data(data[d]);
+
+ then = atoi(data[d]);
+ write_to_logfile(rrd, data[d], then);
+ cmdline[i] = data[d];
+ pr_info("Data: %s\n", data[d]);
+
+ rrd->last_update = then;
+ }
+
+ cmdline[i] = 0;
+
+ if (ret)
+ run(cmd, cmdline);
+
+out:
+ if (data)
+ for (d = 0; data[d]; d++)
+ free(data[d]);
+ free(data);
+
+ if (old_last_update == rrd->last_update) {
+ rrd->update_backoff = time(NULL) + 10;
+ pr_info("Setting backoff\n");
+ } else
+ rrd->update_backoff = 0;
+
+ /*
+ * Re-schedule job processing in case we are too far behind
+ * with updates on this database and can start parsing more
+ * data immediately.
+ */
+ notify_job_request();
+
+ return 0;
+}
+
static int do_rrdtool_update_data(struct rrd_database *rrd)
{
char data[RRD_DATA_MAX_LEN + 12]; /* 12 == "%s:" + NULL termination */
bzero(data, sizeof(data));
l = sprintf(data, "%zd:", now);
- if (rrd->parser && rrd->parser->parse) {
+ if (rrd->parser && rrd->parser->parse_multi) {
+ rrdtool_update_data_multi(rrd);
+ } else if (rrd->parser && rrd->parser->parse) {
rrd->parser->parse(data + l, rrd->parser_data,
&rrd->parser_state);
- data[RRD_DATA_MAX_LEN + 2] = '\0';
+ data[RRD_DATA_MAX_LEN + l] = '\0';
pr_info("Data: %s\n", data);
write_to_logfile(rrd, data, now);
run(cmd, cmdline);
- }
+ rrd->last_update = now;
+ } else
+ rrd->last_update = now;
if (rrd->pre_draw_cmd && !strcmp(rrd->pre_draw_cmd[0], "shell")) {
run(rrd->pre_draw_cmd[1], &rrd->pre_draw_cmd[1]);
queue_work(WORK_PRIORITY_LOW, "rrdtool_post_draw_cmd",
(work_fn_t *)run_post_draw_cmd, rrd);
+ rrd->update_active = 0;
+
return 0;
}
int rrdtool_update_data(struct rrd_database *rrd)
{
- time_t now = time(0);
-
- /*
- * This will put our last update slightly into past, but
- * ensures our update interval will not drift over time.
- */
- rrd->last_update = now - now % rrd->interval;
+ rrd->update_active = 1;
return queue_work(WORK_PRIORITY_HIGH, "rrdtool_update_data",
(work_fn_t *)do_rrdtool_update_data, rrd);
struct rrd_database *get_outdated_db(struct rrd_database **dblist)
{
int i;
- time_t now = time(0);
+ time_t now = time(0), last;
for (i = 0; dblist[i]; i++) {
- if ((dblist[i]->last_update + dblist[i]->interval) - now <= 0)
+ last = max(ROUND_UP(dblist[i]->last_update, dblist[i]->interval),
+ dblist[i]->update_backoff);
+ if (!dblist[i]->update_active && last - now <= 0)
return dblist[i];
}
}
/*
- * See how long we may sleep until it is required to run an update
- * again
+ * See how long we may sleep until next update interval window begins
*/
int get_next_update(struct rrd_database **dblist, const char **name)
{
time_t now = time(0);
for (i = 0; dblist[i]; i++) {
- diff = dblist[i]->last_update + dblist[i]->interval - now;
+ diff = ROUND_UP(dblist[i]->last_update, dblist[i]->interval) - now;
+ diff = max(diff, dblist[i]->update_backoff - now);
+
+ if (dblist[i]->update_active)
+ diff = (now + dblist[i]->interval) % dblist[i]->interval;
+
if (!sleeptime) {
sleeptime = diff;
*name = dblist[i]->name;
sleeptime = diff;
*name = dblist[i]->name;
}
- if (sleeptime <= 0)
- return 0;
}
+ if (sleeptime == 0)
+ sleeptime = -1;
+
return sleeptime;
}
}
db->last_update = atoi(buf);
+ pr_info("Last update for %s is: %ld, %ld sec ago\n", db->name, db->last_update,
+ time(NULL) - db->last_update);
clear_zombie(child);