From e6b9363c11cf587b1e9fc0e6068e217eb1279f4f Mon Sep 17 00:00:00 2001 From: Tobias Oetiker Date: Tue, 13 Nov 2012 15:56:47 +0100 Subject: [PATCH] New rrd_update switch --skip-past-updates When updateing an rrd file with data earlier than the latest update already applied, rrdtool will issue an error message an abort. This option instructs rrdtool to silently skip such data. It can be useful when re-playing old data into an rrd file and you are not sure how many updates have already been applied. --- doc/rrdupdate.pod | 8 ++++ src/librrd.sym.in.in | 1 + src/rrd.h | 17 +++++++++ src/rrd_tool.c | 2 + src/rrd_update.c | 87 +++++++++++++++++++++++++++++++------------- src/rrdupdate.c | 1 + 6 files changed, 90 insertions(+), 26 deletions(-) diff --git a/doc/rrdupdate.pod b/doc/rrdupdate.pod index 67908d01..a7d65199 100644 --- a/doc/rrdupdate.pod +++ b/doc/rrdupdate.pod @@ -60,6 +60,14 @@ function. If this is done accidentally (and this can only be done using the template switch), B will ignore the value specified for the COMPUTE B. +=item B<--skip-past-updates> + +When updateing an rrd file with data earlier than the latest update already +applied, rrdtool will issue an error message an abort. This option instructs +rrdtool to silently skip such data. It can be useful when re-playing old +data into an rrd file and you are not sure how many updates have already +been applied. + =item B<--daemon> I
If given, B will try to connect to the caching daemon L diff --git a/src/librrd.sym.in.in b/src/librrd.sym.in.in index 442c8b35..dd31b627 100644 --- a/src/librrd.sym.in.in +++ b/src/librrd.sym.in.in @@ -56,6 +56,7 @@ rrd_test_error rrd_tune rrd_update rrd_update_r +rrd_updatex_r rrd_update_v rrd_update_v_r rrd_version diff --git a/src/rrd.h b/src/rrd.h index dc996695..256d9fa3 100644 --- a/src/rrd.h +++ b/src/rrd.h @@ -254,6 +254,23 @@ extern "C" { int argc, const char **argv, rrd_info_t * pcdp_summary); + +/* extra flags */ +#define RRD_SKIP_PAST_UPDATES 0x01 + + int rrd_updatex_r( + const char *filename, + const char *_template, + int extra_flags, + int argc, + const char **argv); + int rrd_updatex_v_r( + const char *filename, + const char *_template, + int extra_flags, + int argc, + const char **argv, + rrd_info_t * pcdp_summary); int rrd_fetch_r ( const char *filename, const char *cf, diff --git a/src/rrd_tool.c b/src/rrd_tool.c index 24abcdce..8c1b6747 100644 --- a/src/rrd_tool.c +++ b/src/rrd_tool.c @@ -99,6 +99,7 @@ void PrintUsage( N_("* update - update an RRD\n\n" "\trrdtool update filename\n" "\t\t[--template|-t ds-name:ds-name:...]\n" + "\t\t[--skip-past-updates]\n" "\t\t[--daemon
]\n" "\t\ttime|N:value[:value...]\n\n" "\t\tat-time@value[:value...]\n\n" @@ -109,6 +110,7 @@ void PrintUsage( "\treturns information about values, RRAs, and datasources updated\n\n" "\trrdtool updatev filename\n" "\t\t[--template|-t ds-name:ds-name:...]\n" + "\t\t[--skip-past-updates]\n" "\t\ttime|N:value[:value...]\n\n" "\t\tat-time@value[:value...]\n\n" "\t\t[ time:value[:value...] ..]\n"); diff --git a/src/rrd_update.c b/src/rrd_update.c index c5917c0b..9e28b2dd 100644 --- a/src/rrd_update.c +++ b/src/rrd_update.c @@ -3,8 +3,6 @@ * Copyright by Florian Forster, 2008 ***************************************************************************** * rrd_update.c RRD Update Function - ***************************************************************************** - * $Id$ *****************************************************************************/ #include "rrd_tool.h" @@ -17,6 +15,9 @@ #include +#include +#include + #include "rrd_hw.h" #include "rrd_rpncalc.h" @@ -26,6 +27,7 @@ #include "rrd_client.h" #if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__CYGWIN32__) + /* * WIN32 does not have gettimeofday and struct timeval. This is a quick and dirty * replacement. @@ -68,9 +70,10 @@ int rrd_update_r( const char *tmplt, int argc, const char **argv); -int _rrd_update( +int _rrd_updatex( const char *filename, const char *tmplt, + int extra_flags, int argc, const char **argv, rrd_info_t *); @@ -319,11 +322,13 @@ rrd_info_t *rrd_update_v( char **argv) { char *tmplt = NULL; + int extra_flags = 0; rrd_info_t *result = NULL; rrd_infoval_t rc; char *opt_daemon = NULL; struct option long_options[] = { {"template", required_argument, 0, 't'}, + {"skip-past-updates", no_argument, 0, 's'}, {0, 0, 0, 0} }; @@ -335,7 +340,7 @@ rrd_info_t *rrd_update_v( int option_index = 0; int opt; - opt = getopt_long(argc, argv, "t:", long_options, &option_index); + opt = getopt_long(argc, argv, "st:", long_options, &option_index); if (opt == EOF) break; @@ -367,7 +372,7 @@ rrd_info_t *rrd_update_v( } rc.u_int = 0; result = rrd_info_push(NULL, sprintf_alloc("return_value"), RD_I_INT, rc); - rc.u_int = _rrd_update(argv[optind], tmplt, + rc.u_int = _rrd_updatex(argv[optind], tmplt,extra_flags, argc - optind - 1, (const char **) (argv + optind + 1), result); result->value.u_int = rc.u_int; @@ -382,11 +387,13 @@ int rrd_update( struct option long_options[] = { {"template", required_argument, 0, 't'}, {"daemon", required_argument, 0, 'd'}, + {"skip-past-updates", no_argument, 0, 's'}, {0, 0, 0, 0} }; int option_index = 0; int opt; - char *tmplt = NULL; + int extra_flags = 0; + char *tmplt = NULL; int rc = -1; char *opt_daemon = NULL; @@ -394,7 +401,7 @@ int rrd_update( opterr = 0; /* initialize getopt */ while (1) { - opt = getopt_long(argc, argv, "t:d:", long_options, &option_index); + opt = getopt_long(argc, argv, "t:d:s", long_options, &option_index); if (opt == EOF) break; @@ -404,6 +411,10 @@ int rrd_update( tmplt = strdup(optarg); break; + case 's': + extra_flags |= RRD_SKIP_PAST_UPDATES; + break; + case 'd': if (opt_daemon != NULL) free (opt_daemon); @@ -435,16 +446,16 @@ int rrd_update( } } - if ((tmplt != NULL) && rrdc_is_connected(opt_daemon)) + if (((tmplt != NULL) || (extra_flags != 0)) && rrdc_is_connected(opt_daemon)) { rrd_set_error("The caching daemon cannot be used together with " - "templates yet."); + "templates and skip-past-updates yet."); goto out; } if (! rrdc_is_connected(opt_daemon)) { - rc = rrd_update_r(argv[optind], tmplt, + rc = rrd_updatex_r(argv[optind], tmplt,extra_flags, argc - optind - 1, (const char **) (argv + optind + 1)); } else /* we are connected */ @@ -477,7 +488,7 @@ int rrd_update_r( int argc, const char **argv) { - return _rrd_update(filename, tmplt, argc, argv, NULL); + return _rrd_updatex(filename, tmplt, 0, argc, argv, NULL); } int rrd_update_v_r( @@ -487,12 +498,34 @@ int rrd_update_v_r( const char **argv, rrd_info_t * pcdp_summary) { - return _rrd_update(filename, tmplt, argc, argv, pcdp_summary); + return _rrd_updatex(filename, tmplt, 0, argc, argv, pcdp_summary); } -int _rrd_update( +int rrd_updatex_r( const char *filename, const char *tmplt, + int extra_flags, + int argc, + const char **argv) +{ + return _rrd_updatex(filename, tmplt, extra_flags, argc, argv, NULL); +} + +int rrd_updatex_v_r( + const char *filename, + const char *tmplt, + int extra_flags, + int argc, + const char **argv, + rrd_info_t * pcdp_summary) +{ + return _rrd_updatex(filename, tmplt, extra_flags, argc, argv, pcdp_summary); +} + +int _rrd_updatex( + const char *filename, + const char *tmplt, + int extra_flags, int argc, const char **argv, rrd_info_t * pcdp_summary) @@ -524,6 +557,7 @@ int _rrd_update( rrd_file_t *rrd_file; char *arg_copy; /* for processing the argv */ unsigned long *skip_update; /* RRAs to advance but not write */ + int process_ret; /* need at least 1 arguments: data. */ if (argc < 1) { @@ -563,11 +597,12 @@ int _rrd_update( rrd_set_error("failed duplication argv entry"); break; } - if (process_arg(arg_copy, &rrd, rrd_file, rra_begin, + process_ret = process_arg(arg_copy, &rrd, rrd_file, rra_begin, ¤t_time, ¤t_time_usec, pdp_temp, pdp_new, rra_step_cnt, updvals, tmpl_idx, tmpl_cnt, &pcdp_summary, version, skip_update, - &schedule_smooth) == -1) { + &schedule_smooth); + if ( ( process_ret == -1 ) || ( ! (extra_flags & RRD_SKIP_PAST_UPDATES) && process_ret == -2 ) ) { if (rrd_test_error()) { /* Should have error string always here */ char *save_error; @@ -580,6 +615,9 @@ int _rrd_update( free(arg_copy); break; } + if ( process_ret == -2 ){ + rrd_clear_error(); + } free(arg_copy); } @@ -774,7 +812,7 @@ static int parse_template( * Parse an update string, updates the primary data points (PDPs) * and consolidated data points (CDPs), and writes changes to the RRAs. * - * Returns 0 on success, -1 on error. + * Returns 0 on success, -1 on error, -2 on time stamp error. */ static int process_arg( char *step_start, @@ -802,10 +840,10 @@ static int process_arg( double interval, pre_int, post_int; /* interval between this and * the last run */ unsigned long proc_pdp_cnt; - - if (parse_ds(rrd, updvals, tmpl_idx, step_start, tmpl_cnt, - current_time, current_time_usec, version) == -1) { - return -1; + int ds_ret; + if ((ds_ret = parse_ds(rrd, updvals, tmpl_idx, step_start, tmpl_cnt, + current_time, current_time_usec, version)) != 0) { + return ds_ret; } interval = (double) (*current_time - rrd->live_head->last_up) @@ -931,12 +969,9 @@ static int parse_ds( return -1; } - if (get_time_from_reading(rrd, timesyntax, updvals, + return get_time_from_reading(rrd, timesyntax, updvals, current_time, current_time_usec, - version) == -1) { - return -1; - } - return 0; + version); } /* @@ -1008,7 +1043,7 @@ static int get_time_from_reading( rrd_set_error("illegal attempt to update using time %ld when " "last update time is %ld (minimum one second step)", *current_time, rrd->live_head->last_up); - return -1; + return -2; } return 0; } diff --git a/src/rrdupdate.c b/src/rrdupdate.c index 5a6301ed..cfd1894c 100644 --- a/src/rrdupdate.c +++ b/src/rrdupdate.c @@ -53,6 +53,7 @@ int main( else { printf("Usage: rrdupdate \n" "\t\t\t[--template|-t ds-name[:ds-name]...]\n" + "\t\t\t[--skip-past-updates]\n" "\t\t\ttime|N:value[:value...]\n\n" "\t\t\tat-time@value[:value...]\n\n" "\t\t\t[ time:value[:value...] ..]\n\n"); -- 2.47.3