From: Costa Tsaousis Date: Sun, 13 Nov 2016 23:45:06 +0000 (+0200) Subject: Merge pull request #1243 from ktsaou/master X-Git-Tag: v1.5.0~186 X-Git-Url: https://arthur.barton.de/gitweb/?a=commitdiff_plain;h=bfc740c587f758fc4737407d979435a604f71edf;hp=facff406cb0438c189e09831ed61292a4defc818;p=netdata.git Merge pull request #1243 from ktsaou/master synchronized plugins, database, API and presentation timings --- diff --git a/src/apps_plugin.c b/src/apps_plugin.c index d367fc35..10987917 100644 --- a/src/apps_plugin.c +++ b/src/apps_plugin.c @@ -2828,22 +2828,16 @@ int main(int argc, char **argv) , RATES_DETAIL ); -#ifndef PROFILING_MODE - unsigned long long sunext = (time(NULL) - (time(NULL) % update_every) + update_every) * 1000000ULL; -#endif /* PROFILING_MODE */ - + unsigned long long step = update_every * 1000000ULL; global_iterations_counter = 1; for(;1; global_iterations_counter++) { -#ifndef PROFILING_MODE - unsigned long long sunow; - // delay until it is our time to run - while((sunow = time_usec()) < sunext) - sleep_usec(sunext - sunow); + unsigned long long now = time_usec(); + unsigned long long next = now - (now % step) + step; - // find the next time we need to run - while(time_usec() > sunext) - sunext += update_every * 1000000ULL; -#endif /* PROFILING_MODE */ + while(now < next) { + sleep_usec(next - now); + now = time_usec(); + } if(!collect_data_for_all_processes_from_proc()) { error("Cannot collect /proc data for running processes. Disabling apps.plugin..."); @@ -2879,11 +2873,7 @@ int main(int argc, char **argv) time_t current_t = time(NULL); -#ifndef PROFILING_MODE // restart check (14400 seconds) if(current_t - started_t > 14400) exit(0); -#else - if(current_t - started_t > 10) exit(0); -#endif /* PROFILING_MODE */ } } diff --git a/src/plugin_proc.c b/src/plugin_proc.c index 3e19d85a..1aa2fb58 100644 --- a/src/plugin_proc.c +++ b/src/plugin_proc.c @@ -61,20 +61,15 @@ void *proc_main(void *ptr) unsigned long long sutime_ipc = 0ULL; unsigned long long sutime_sys_kernel_mm_ksm = 0ULL; - // the next time we will run - aligned properly - unsigned long long sunext = (time(NULL) - (time(NULL) % rrd_update_every) + rrd_update_every) * 1000000ULL; - + unsigned long long step = rrd_update_every * 1000000ULL; for(;;) { - unsigned long long sunow; - if(unlikely(netdata_exit)) break; + unsigned long long now = time_usec(); + unsigned long long next = now - (now % step) + step; - // delay until it is our time to run - while((sunow = time_usec()) < sunext) - sleep_usec(sunext - sunow); - - // find the next time we need to run - while(time_usec() > sunext) - sunext += rrd_update_every * 1000000ULL; + while(now < next) { + sleep_usec(next - now); + now = time_usec(); + } if(unlikely(netdata_exit)) break; @@ -83,161 +78,161 @@ void *proc_main(void *ptr) if(!vdo_sys_kernel_mm_ksm) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_sys_kernel_mm_ksm()."); - sunow = time_usec(); - vdo_sys_kernel_mm_ksm = do_sys_kernel_mm_ksm(rrd_update_every, (sutime_sys_kernel_mm_ksm > 0)?sunow - sutime_sys_kernel_mm_ksm:0ULL); - sutime_sys_kernel_mm_ksm = sunow; + now = time_usec(); + vdo_sys_kernel_mm_ksm = do_sys_kernel_mm_ksm(rrd_update_every, (sutime_sys_kernel_mm_ksm > 0)?now - sutime_sys_kernel_mm_ksm:0ULL); + sutime_sys_kernel_mm_ksm = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_loadavg) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_loadavg()."); - sunow = time_usec(); - vdo_proc_loadavg = do_proc_loadavg(rrd_update_every, (sutime_proc_loadavg > 0)?sunow - sutime_proc_loadavg:0ULL); - sutime_proc_loadavg = sunow; + now = time_usec(); + vdo_proc_loadavg = do_proc_loadavg(rrd_update_every, (sutime_proc_loadavg > 0)?now - sutime_proc_loadavg:0ULL); + sutime_proc_loadavg = now; } if(unlikely(netdata_exit)) break; if(!vdo_ipc) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_ipc()."); - sunow = time_usec(); - vdo_ipc = do_ipc(rrd_update_every, (sutime_ipc > 0)?sunow - sutime_ipc:0ULL); - sutime_ipc = sunow; + now = time_usec(); + vdo_ipc = do_ipc(rrd_update_every, (sutime_ipc > 0)?now - sutime_ipc:0ULL); + sutime_ipc = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_interrupts) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_interrupts()."); - sunow = time_usec(); - vdo_proc_interrupts = do_proc_interrupts(rrd_update_every, (sutime_proc_interrupts > 0)?sunow - sutime_proc_interrupts:0ULL); - sutime_proc_interrupts = sunow; + now = time_usec(); + vdo_proc_interrupts = do_proc_interrupts(rrd_update_every, (sutime_proc_interrupts > 0)?now - sutime_proc_interrupts:0ULL); + sutime_proc_interrupts = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_softirqs) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_softirqs()."); - sunow = time_usec(); - vdo_proc_softirqs = do_proc_softirqs(rrd_update_every, (sutime_proc_softirqs > 0)?sunow - sutime_proc_softirqs:0ULL); - sutime_proc_softirqs = sunow; + now = time_usec(); + vdo_proc_softirqs = do_proc_softirqs(rrd_update_every, (sutime_proc_softirqs > 0)?now - sutime_proc_softirqs:0ULL); + sutime_proc_softirqs = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_net_softnet_stat) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_softnet_stat()."); - sunow = time_usec(); - vdo_proc_net_softnet_stat = do_proc_net_softnet_stat(rrd_update_every, (sutime_proc_net_softnet_stat > 0)?sunow - sutime_proc_net_softnet_stat:0ULL); - sutime_proc_net_softnet_stat = sunow; + now = time_usec(); + vdo_proc_net_softnet_stat = do_proc_net_softnet_stat(rrd_update_every, (sutime_proc_net_softnet_stat > 0)?now - sutime_proc_net_softnet_stat:0ULL); + sutime_proc_net_softnet_stat = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_sys_kernel_random_entropy_avail) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_sys_kernel_random_entropy_avail()."); - sunow = time_usec(); - vdo_proc_sys_kernel_random_entropy_avail = do_proc_sys_kernel_random_entropy_avail(rrd_update_every, (sutime_proc_sys_kernel_random_entropy_avail > 0)?sunow - sutime_proc_sys_kernel_random_entropy_avail:0ULL); - sutime_proc_sys_kernel_random_entropy_avail = sunow; + now = time_usec(); + vdo_proc_sys_kernel_random_entropy_avail = do_proc_sys_kernel_random_entropy_avail(rrd_update_every, (sutime_proc_sys_kernel_random_entropy_avail > 0)?now - sutime_proc_sys_kernel_random_entropy_avail:0ULL); + sutime_proc_sys_kernel_random_entropy_avail = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_net_dev) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_dev()."); - sunow = time_usec(); - vdo_proc_net_dev = do_proc_net_dev(rrd_update_every, (sutime_proc_net_dev > 0)?sunow - sutime_proc_net_dev:0ULL); - sutime_proc_net_dev = sunow; + now = time_usec(); + vdo_proc_net_dev = do_proc_net_dev(rrd_update_every, (sutime_proc_net_dev > 0)?now - sutime_proc_net_dev:0ULL); + sutime_proc_net_dev = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_diskstats) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_diskstats()."); - sunow = time_usec(); - vdo_proc_diskstats = do_proc_diskstats(rrd_update_every, (sutime_proc_diskstats > 0)?sunow - sutime_proc_diskstats:0ULL); - sutime_proc_diskstats = sunow; + now = time_usec(); + vdo_proc_diskstats = do_proc_diskstats(rrd_update_every, (sutime_proc_diskstats > 0)?now - sutime_proc_diskstats:0ULL); + sutime_proc_diskstats = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_net_snmp) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_snmp()."); - sunow = time_usec(); - vdo_proc_net_snmp = do_proc_net_snmp(rrd_update_every, (sutime_proc_net_snmp > 0)?sunow - sutime_proc_net_snmp:0ULL); - sutime_proc_net_snmp = sunow; + now = time_usec(); + vdo_proc_net_snmp = do_proc_net_snmp(rrd_update_every, (sutime_proc_net_snmp > 0)?now - sutime_proc_net_snmp:0ULL); + sutime_proc_net_snmp = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_net_snmp6) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_snmp6()."); - sunow = time_usec(); - vdo_proc_net_snmp6 = do_proc_net_snmp6(rrd_update_every, (sutime_proc_net_snmp6 > 0)?sunow - sutime_proc_net_snmp6:0ULL); - sutime_proc_net_snmp6 = sunow; + now = time_usec(); + vdo_proc_net_snmp6 = do_proc_net_snmp6(rrd_update_every, (sutime_proc_net_snmp6 > 0)?now - sutime_proc_net_snmp6:0ULL); + sutime_proc_net_snmp6 = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_net_netstat) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_netstat()."); - sunow = time_usec(); - vdo_proc_net_netstat = do_proc_net_netstat(rrd_update_every, (sutime_proc_net_netstat > 0)?sunow - sutime_proc_net_netstat:0ULL); - sutime_proc_net_netstat = sunow; + now = time_usec(); + vdo_proc_net_netstat = do_proc_net_netstat(rrd_update_every, (sutime_proc_net_netstat > 0)?now - sutime_proc_net_netstat:0ULL); + sutime_proc_net_netstat = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_net_stat_conntrack) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_stat_conntrack()."); - sunow = time_usec(); - vdo_proc_net_stat_conntrack = do_proc_net_stat_conntrack(rrd_update_every, (sutime_proc_net_stat_conntrack > 0)?sunow - sutime_proc_net_stat_conntrack:0ULL); - sutime_proc_net_stat_conntrack = sunow; + now = time_usec(); + vdo_proc_net_stat_conntrack = do_proc_net_stat_conntrack(rrd_update_every, (sutime_proc_net_stat_conntrack > 0)?now - sutime_proc_net_stat_conntrack:0ULL); + sutime_proc_net_stat_conntrack = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_net_ip_vs_stats) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling vdo_proc_net_ip_vs_stats()."); - sunow = time_usec(); - vdo_proc_net_ip_vs_stats = do_proc_net_ip_vs_stats(rrd_update_every, (sutime_proc_net_ip_vs_stats > 0)?sunow - sutime_proc_net_ip_vs_stats:0ULL); - sutime_proc_net_ip_vs_stats = sunow; + now = time_usec(); + vdo_proc_net_ip_vs_stats = do_proc_net_ip_vs_stats(rrd_update_every, (sutime_proc_net_ip_vs_stats > 0)?now - sutime_proc_net_ip_vs_stats:0ULL); + sutime_proc_net_ip_vs_stats = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_net_stat_synproxy) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling vdo_proc_net_stat_synproxy()."); - sunow = time_usec(); - vdo_proc_net_stat_synproxy = do_proc_net_stat_synproxy(rrd_update_every, (sutime_proc_net_stat_synproxy > 0)?sunow - sutime_proc_net_stat_synproxy:0ULL); - sutime_proc_net_stat_synproxy = sunow; + now = time_usec(); + vdo_proc_net_stat_synproxy = do_proc_net_stat_synproxy(rrd_update_every, (sutime_proc_net_stat_synproxy > 0)?now - sutime_proc_net_stat_synproxy:0ULL); + sutime_proc_net_stat_synproxy = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_stat) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_stat()."); - sunow = time_usec(); - vdo_proc_stat = do_proc_stat(rrd_update_every, (sutime_proc_stat > 0)?sunow - sutime_proc_stat:0ULL); - sutime_proc_stat = sunow; + now = time_usec(); + vdo_proc_stat = do_proc_stat(rrd_update_every, (sutime_proc_stat > 0)?now - sutime_proc_stat:0ULL); + sutime_proc_stat = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_meminfo) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling vdo_proc_meminfo()."); - sunow = time_usec(); - vdo_proc_meminfo = do_proc_meminfo(rrd_update_every, (sutime_proc_meminfo > 0)?sunow - sutime_proc_meminfo:0ULL); - sutime_proc_meminfo = sunow; + now = time_usec(); + vdo_proc_meminfo = do_proc_meminfo(rrd_update_every, (sutime_proc_meminfo > 0)?now - sutime_proc_meminfo:0ULL); + sutime_proc_meminfo = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_vmstat) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling vdo_proc_vmstat()."); - sunow = time_usec(); - vdo_proc_vmstat = do_proc_vmstat(rrd_update_every, (sutime_proc_vmstat > 0)?sunow - sutime_proc_vmstat:0ULL); - sutime_proc_vmstat = sunow; + now = time_usec(); + vdo_proc_vmstat = do_proc_vmstat(rrd_update_every, (sutime_proc_vmstat > 0)?now - sutime_proc_vmstat:0ULL); + sutime_proc_vmstat = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_net_rpc_nfsd) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_rpc_nfsd()."); - sunow = time_usec(); - vdo_proc_net_rpc_nfsd = do_proc_net_rpc_nfsd(rrd_update_every, (sutime_proc_net_rpc_nfsd > 0)?sunow - sutime_proc_net_rpc_nfsd:0ULL); - sutime_proc_net_rpc_nfsd = sunow; + now = time_usec(); + vdo_proc_net_rpc_nfsd = do_proc_net_rpc_nfsd(rrd_update_every, (sutime_proc_net_rpc_nfsd > 0)?now - sutime_proc_net_rpc_nfsd:0ULL); + sutime_proc_net_rpc_nfsd = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_net_rpc_nfs) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_rpc_nfs()."); - sunow = time_usec(); - vdo_proc_net_rpc_nfs = do_proc_net_rpc_nfs(rrd_update_every, (sutime_proc_net_rpc_nfs > 0)?sunow - sutime_proc_net_rpc_nfs:0ULL); - sutime_proc_net_rpc_nfs = sunow; + now = time_usec(); + vdo_proc_net_rpc_nfs = do_proc_net_rpc_nfs(rrd_update_every, (sutime_proc_net_rpc_nfs > 0)?now - sutime_proc_net_rpc_nfs:0ULL); + sutime_proc_net_rpc_nfs = now; } if(unlikely(netdata_exit)) break; diff --git a/src/proc_loadavg.c b/src/proc_loadavg.c index 3e97dcdb..a3d75ac5 100644 --- a/src/proc_loadavg.c +++ b/src/proc_loadavg.c @@ -8,6 +8,8 @@ int do_proc_loadavg(int update_every, unsigned long long dt) { static procfile *ff = NULL; static int do_loadavg = -1, do_all_processes = -1; + static unsigned long long last_loadavg_usec = 0; + static RRDSET *load_chart = NULL, *processes_chart = NULL; if(unlikely(!ff)) { char filename[FILENAME_MAX + 1]; @@ -21,8 +23,10 @@ int do_proc_loadavg(int update_every, unsigned long long dt) { if(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time - if(unlikely(do_loadavg == -1)) do_loadavg = config_get_boolean("plugin:proc:/proc/loadavg", "enable load average", 1); - if(unlikely(do_all_processes == -1)) do_all_processes = config_get_boolean("plugin:proc:/proc/loadavg", "enable total processes", 1); + if(unlikely(do_loadavg == -1)) { + do_loadavg = config_get_boolean("plugin:proc:/proc/loadavg", "enable load average", 1); + do_all_processes = config_get_boolean("plugin:proc:/proc/loadavg", "enable total processes", 1); + } if(unlikely(procfile_lines(ff) < 1)) { error("/proc/loadavg has no lines."); @@ -39,43 +43,49 @@ int do_proc_loadavg(int update_every, unsigned long long dt) { //unsigned long long running_processes = strtoull(procfile_lineword(ff, 0, 3), NULL, 10); unsigned long long active_processes = strtoull(procfile_lineword(ff, 0, 4), NULL, 10); - //unsigned long long next_pid = strtoull(procfile_lineword(ff, 0, 5), NULL, 10); - + //unsigned long long next_pid = strtoull(procfile_lineword(ff, 0, 5), NULL, 10); - RRDSET *st; // -------------------------------------------------------------------- - if(likely(do_loadavg)) { - st = rrdset_find_byname("system.load"); - if(unlikely(!st)) { - st = rrdset_create("system", "load", NULL, "load", NULL, "System Load Average", "load", 100, (update_every < MIN_LOADAVG_UPDATE_EVERY)?MIN_LOADAVG_UPDATE_EVERY:update_every, RRDSET_TYPE_LINE); - - rrddim_add(st, "load1", NULL, 1, 1000, RRDDIM_ABSOLUTE); - rrddim_add(st, "load5", NULL, 1, 1000, RRDDIM_ABSOLUTE); - rrddim_add(st, "load15", NULL, 1, 1000, RRDDIM_ABSOLUTE); + if(last_loadavg_usec <= dt) { + if(likely(do_loadavg)) { + if(unlikely(!load_chart)) { + load_chart = rrdset_find_byname("system.load"); + if(unlikely(!load_chart)) { + load_chart = rrdset_create("system", "load", NULL, "load", NULL, "System Load Average", "load", 100, (update_every < MIN_LOADAVG_UPDATE_EVERY) ? MIN_LOADAVG_UPDATE_EVERY : update_every, RRDSET_TYPE_LINE); + rrddim_add(load_chart, "load1", NULL, 1, 1000, RRDDIM_ABSOLUTE); + rrddim_add(load_chart, "load5", NULL, 1, 1000, RRDDIM_ABSOLUTE); + rrddim_add(load_chart, "load15", NULL, 1, 1000, RRDDIM_ABSOLUTE); + } + } + else + rrdset_next(load_chart); + + rrddim_set(load_chart, "load1", (collected_number) (load1 * 1000)); + rrddim_set(load_chart, "load5", (collected_number) (load5 * 1000)); + rrddim_set(load_chart, "load15", (collected_number) (load15 * 1000)); + rrdset_done(load_chart); } - else rrdset_next(st); - rrddim_set(st, "load1", (collected_number)(load1 * 1000)); - rrddim_set(st, "load5", (collected_number)(load5 * 1000)); - rrddim_set(st, "load15", (collected_number)(load15 * 1000)); - rrdset_done(st); + last_loadavg_usec = load_chart->update_every * 1000000ULL; } + else last_loadavg_usec -= dt; // -------------------------------------------------------------------- if(likely(do_all_processes)) { - st = rrdset_find_byname("system.active_processes"); - if(unlikely(!st)) { - st = rrdset_create("system", "active_processes", NULL, "processes", NULL, "System Active Processes", "processes", 750, update_every, RRDSET_TYPE_LINE); - - rrddim_add(st, "active", NULL, 1, 1, RRDDIM_ABSOLUTE); + if(unlikely(!processes_chart)) { + processes_chart = rrdset_find_byname("system.active_processes"); + if(unlikely(!processes_chart)) { + processes_chart = rrdset_create("system", "active_processes", NULL, "processes", NULL, "System Active Processes", "processes", 750, update_every, RRDSET_TYPE_LINE); + rrddim_add(processes_chart, "active", NULL, 1, 1, RRDDIM_ABSOLUTE); + } } - else rrdset_next(st); + else rrdset_next(processes_chart); - rrddim_set(st, "active", active_processes); - rrdset_done(st); + rrddim_set(processes_chart, "active", active_processes); + rrdset_done(processes_chart); } return 0; diff --git a/src/rrd.c b/src/rrd.c index 8e2d76af..7d8bf394 100644 --- a/src/rrd.c +++ b/src/rrd.c @@ -525,6 +525,12 @@ RRDSET *rrdset_create(const char *type, const char *id, const char *name, const error("File %s is too old. Clearing it.", fullfilename); memset(st, 0, size); } + + // make sure the database is aligned + if(st->last_updated.tv_sec % update_every) { + st->last_updated.tv_sec -= st->last_updated.tv_sec % update_every; + st->last_updated.tv_usec = 0; + } } if(st) { @@ -1094,6 +1100,11 @@ unsigned long long rrdset_done(RRDSET *st) // it is the first entry // set the last_collected_time to now gettimeofday(&st->last_collected_time, NULL); + + // align it to update_every + st->last_collected_time.tv_sec -= st->last_collected_time.tv_sec % st->update_every; + st->last_collected_time.tv_usec = 0; + last_collect_ut = st->last_collected_time.tv_sec * 1000000ULL + st->last_collected_time.tv_usec - update_every_ut; // the first entry should not be stored @@ -1136,6 +1147,10 @@ unsigned long long rrdset_done(RRDSET *st) gettimeofday(&st->last_collected_time, NULL); + // align it to update_every + st->last_collected_time.tv_sec -= st->last_collected_time.tv_sec % st->update_every; + st->last_collected_time.tv_usec = 0; + unsigned long long ut = st->last_collected_time.tv_sec * 1000000ULL + st->last_collected_time.tv_usec - st->usec_since_last_update; st->last_updated.tv_sec = (time_t) (ut / 1000000ULL); st->last_updated.tv_usec = (suseconds_t) (ut % 1000000ULL); @@ -1349,6 +1364,9 @@ unsigned long long rrdset_done(RRDSET *st) if(unlikely(now_collect_ut < next_store_ut)) { // this is collected in the same interpolation point if(unlikely(st->debug)) debug(D_RRD_STATS, "%s: THIS IS IN THE SAME INTERPOLATION POINT", st->name); +#ifdef NETDATA_INTERNAL_CHECKS + info("%s is collected in the same interpolation point: short by %llu microseconds", st->name, next_store_ut - now_collect_ut); +#endif } unsigned long long first_ut = last_stored_ut; diff --git a/src/rrd2json.c b/src/rrd2json.c index b2c1a055..ac04ca72 100644 --- a/src/rrd2json.c +++ b/src/rrd2json.c @@ -1209,19 +1209,32 @@ RRDR *rrd2rrdr(RRDSET *st, long points, long long after, long long before, int g time_t last_entry_t = rrdset_last_entry_t(st); if(before == 0 && after == 0) { + // dump the all the data before = last_entry_t; after = first_entry_t; absolute_period_requested = 0; } - // allow relative for before and after (smaller than 3 years) - if(((before < 0)?-before:before) <= (3 * 365 * 86400)) { - before = last_entry_t + before; + // allow relative for before (smaller than API_RELATIVE_TIME_MAX) + if(((before < 0)?-before:before) <= API_RELATIVE_TIME_MAX) { + if(abs(before) % st->update_every) { + // make sure it is multiple of st->update_every + if(before < 0) before = before - st->update_every - before % st->update_every; + else before = before + st->update_every - before % st->update_every; + } + if(before > 0) before = first_entry_t + before; + else before = last_entry_t + before; absolute_period_requested = 0; } - if(((after < 0)?-after:after) <= (3 * 365 * 86400)) { + // allow relative for after (smaller than API_RELATIVE_TIME_MAX) + if(((after < 0)?-after:after) <= API_RELATIVE_TIME_MAX) { if(after == 0) after = -st->update_every; + if(abs(after) % st->update_every) { + // make sure it is multiple of st->update_every + if(after < 0) after = after - st->update_every - after % st->update_every; + else after = after + st->update_every - after % st->update_every; + } after = before + after; absolute_period_requested = 0; } diff --git a/src/rrd2json.h b/src/rrd2json.h index e3e5cb69..d3dc44e0 100644 --- a/src/rrd2json.h +++ b/src/rrd2json.h @@ -4,6 +4,8 @@ #define HOSTNAME_MAX 1024 extern char *hostname; +#define API_RELATIVE_TIME_MAX (3 * 365 * 86400) + // type of JSON generations #define DATASOURCE_INVALID -1 #define DATASOURCE_JSON 0