From 54dff093c77402db1efdbdbda21c331ca3f6d2cd Mon Sep 17 00:00:00 2001 From: Peter Stamfest Date: Mon, 17 Mar 2014 08:39:00 +0100 Subject: [PATCH] First step to really integrate modify into tune. Currently implemented by doing all the "tune" conversions in place and doing the "modify" operations through a temporary RRD file with a followed move to the original file --- src/rrd_modify.c | 188 +++++++++++++++++++++++++++++++++++++++++++---- src/rrd_modify.h | 39 ++++++++++ src/rrd_tune.c | 22 +++++- 3 files changed, 232 insertions(+), 17 deletions(-) create mode 100644 src/rrd_modify.h diff --git a/src/rrd_modify.c b/src/rrd_modify.c index 360f56fc..d2d35f97 100644 --- a/src/rrd_modify.c +++ b/src/rrd_modify.c @@ -12,27 +12,13 @@ #include "rrd_restore.h" /* write_file */ #include "rrd_create.h" /* parseDS */ #include "rrd_update.h" /* update_cdp */ +#include "rrd_modify.h" #include "unused.h" #include "fnv.h" #include -typedef struct { - /* the index of the RRA to be changed or -1 if there is no current - RRA */ - int index; - /* what operation */ - char op; // '+', '-', '=', 'a' - /* the number originally specified with the operation (eg. rows to - be added) */ - unsigned int row_count; - /* the resulting final row count for the RRA */ - unsigned int final_row_count; - /* An RRA definition in case of an addition */ - char *def; -} rra_mod_op_t; - // calculate a % b, guaranteeing a positive result... static int positive_mod(int a, int b) { int x = a % b; @@ -1519,6 +1505,178 @@ done: return rc; } + +int handle_modify(const rrd_t *in, const char *outfilename, + int argc, char **argv, int optind, + int newstep) { + // parse add/remove options + int rc = -1; + int i; + + const char **remove = NULL, **add = NULL; + rra_mod_op_t *rra_ops = NULL; + int rcnt = 0, acnt = 0, rraopcnt = 0; + + for (i = optind ; i < argc ; i++) { + if (strncmp("DEL:", argv[i], 4) == 0 && strlen(argv[i]) > 4) { + remove = realloc(remove, (rcnt + 2) * sizeof(char*)); + if (remove == NULL) { + rrd_set_error("out of memory"); + rc = -1; + goto done; + } + + remove[rcnt] = strdup(argv[i] + 4); + if (remove[rcnt] == NULL) { + rrd_set_error("out of memory"); + rc = -1; + goto done; + } + + rcnt++; + remove[rcnt] = NULL; + } else if (strncmp("DS:", argv[i], 3) == 0 && strlen(argv[i]) > 3) { + add = realloc(add, (acnt + 2) * sizeof(char*)); + if (add == NULL) { + rrd_set_error("out of memory"); + rc = -1; + goto done; + } + + add[acnt] = strdup(argv[i]); + if (add[acnt] == NULL) { + rrd_set_error("out of memory"); + rc = -1; + goto done; + } + + acnt++; + add[acnt] = NULL; + } else if (strncmp("RRA#", argv[i], 4) == 0 && strlen(argv[i]) > 4) { + rra_mod_op_t rra_mod = { .def = NULL }; + char sign; + unsigned int number; + unsigned int index; + + if (sscanf(argv[i] + 4, "%u:%c%u", &index, &sign, &number) != 3) { + rrd_set_error("Failed to parse RRA# command"); + rc = -1; + goto done; + } + + rra_mod.index = index; + switch (sign) { + case '=': + case '-': + case '+': + rra_mod.index = index; + rra_mod.op = sign; + rra_mod.row_count = number; + rra_mod.final_row_count = 0; + break; + default: + rrd_set_error("Failed to parse RRA# command: invalid operation: %c", sign); + rc = -1; + goto done; + } + + rra_ops = copy_over_realloc(rra_ops, rraopcnt, + &rra_mod, 0, sizeof(rra_mod)); + if (rra_ops == NULL) { + rrd_set_error("out of memory"); + rc = -1; + goto done; + } + rraopcnt++; + } else if (strncmp("RRA:", argv[i], 4) == 0 && strlen(argv[i]) > 4) { + rra_mod_op_t rra_mod; + rra_mod.op = 'a'; + rra_mod.index = -1; + rra_mod.def = strdup(argv[i]); + + if (rra_mod.def == NULL) { + rrd_set_error("out of memory"); + rc = -1; + goto done; + } + + rra_ops = copy_over_realloc(rra_ops, rraopcnt, + &rra_mod, 0, sizeof(rra_mod)); + if (rra_ops == NULL) { + rrd_set_error("out of memory"); + rc = -1; + goto done; + } + rraopcnt++; + } else if (strncmp("DELRRA:", argv[i], 7) == 0 && strlen(argv[i]) > 7) { + rra_mod_op_t rra_mod = { .def = NULL, + .op = '=', + .row_count = 0 // eg. deletion + }; + + rra_mod.index = atoi(argv[i] + 7); + if (rra_mod.index < 0 ) { + rrd_set_error("DELRRA requires a non-negative, integer argument"); + rc = -1; + goto done; + } + + rra_ops = copy_over_realloc(rra_ops, rraopcnt, + &rra_mod, 0, sizeof(rra_mod)); + if (rra_ops == NULL) { + rrd_set_error("out of memory"); + rc = -1; + goto done; + } + rraopcnt++; + } else { + rrd_set_error("unparseable argument: %s", argv[i]); + rc = -1; + goto done; + } + } + + if (rcnt > 0 || acnt > 0 || rraopcnt > 0) { + unsigned long hashed_name = FnvHash(outfilename); + rrd_t *out = rrd_modify_r2(in, remove, add, rra_ops, rraopcnt, newstep, hashed_name); + + if (out == NULL) { + goto done; + } + + rc = write_rrd(outfilename, out); + rrd_free(out); + free(out); + + if (rc < 0) goto done; + } + + rc = argc; + +done: + if (remove) { + for (const char **c = remove ; *c ; c++) { + free((void*) *c); + } + free(remove); + } + if (add) { + for (const char **c = add ; *c ; c++) { + free((void*) *c); + } + free(add); + } + if (rra_ops) { + for (i = 0 ; i < rraopcnt ; i++) { + if (rra_ops[i].def) free(rra_ops[i].def); + } + free(rra_ops); + } + + return rc; +} + + int rrd_modify ( int argc, char **argv) diff --git a/src/rrd_modify.h b/src/rrd_modify.h new file mode 100644 index 00000000..6ef906a5 --- /dev/null +++ b/src/rrd_modify.h @@ -0,0 +1,39 @@ +/**************************************************************************** + * RRDtool 1.4.8 Copyright by Tobi Oetiker, 1997-2013 + **************************************************************************** + * rrd_create.h + ****************************************************************************/ +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _RRD_MODIFY_H +#define _RRD_MODIFY_H + +#include "rrd.h" + +typedef struct { + /* the index of the RRA to be changed or -1 if there is no current + * RRA */ + int index; + /* what operation */ + char op; // '+', '-', '=', 'a' + /* the number originally specified with the operation (eg. rows to + * be added) */ + unsigned int row_count; + /* the resulting final row count for the RRA */ + unsigned int final_row_count; + /* An RRA definition in case of an addition */ + char *def; +} rra_mod_op_t; + +int handle_modify(const rrd_t *in, const char *outfilename, + int argc, char **argv, int optind, + int newstep); + +#endif + + +#ifdef __cplusplus +} +#endif diff --git a/src/rrd_tune.c b/src/rrd_tune.c index 0c2a998b..bdb1cb6a 100644 --- a/src/rrd_tune.c +++ b/src/rrd_tune.c @@ -45,6 +45,7 @@ #include "rrd_tool.h" #include "rrd_rpncalc.h" #include "rrd_hw.h" +#include "rrd_modify.h" int set_hwarg( rrd_t *rrd, @@ -81,6 +82,7 @@ int rrd_tune( double max; char dst[DST_SIZE]; int rc = -1; + int opt_newstep = -1; rrd_file_t *rrd_file; struct option long_options[] = { {"heartbeat", required_argument, 0, 'h'}, @@ -112,7 +114,7 @@ int rrd_tune( opterr = 0; /* initialize getopt */ rrd_init(&rrd); - rrd_file = rrd_open(argv[1], &rrd, RRD_READWRITE); + rrd_file = rrd_open(argv[1], &rrd, RRD_READWRITE | RRD_READVALUES); if (rrd_file == NULL) { goto done; } @@ -282,6 +284,9 @@ int rrd_tune( goto done; } break; + case 't': + opt_newstep = atoi(optarg); + break; case '?': if (optopt != 0) rrd_set_error("unknown option '%c'", optopt); @@ -298,7 +303,20 @@ int rrd_tune( /* need to write rra_defs for RRA parameter changes */ rrd_write(rrd_file, rrd.rra_def, sizeof(rra_def_t) * rrd.stat_head->rra_cnt); - } else { + } + + // rrd modify functionality + rrd_t in; + rrd_init(&in); + + rrd_file = rrd_open(argv[1], &in, RRD_READWRITE | RRD_READAHEAD | RRD_READVALUES); + + optind = handle_modify(&in, argv[1], argc, argv, optind + 1, opt_newstep); + if (optind < 0) { + goto done; + } + + if (optcnt == 0) { int i; for (i = 0; i < (int) rrd.stat_head->ds_cnt; i++) -- 2.47.3