X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Frrd_restore.c;h=3246047ce8677fd1d9ea7f2ad098e4c611911003;hb=291d201f087974f6e2b717aea983cf6c7b0d67e7;hp=4e2b6c311a7d02a11f25b776a012064a6a8ece04;hpb=5837606887a6d81e8b1f7588525cb1c8783fb62b;p=rrdtool.git diff --git a/src/rrd_restore.c b/src/rrd_restore.c index 4e2b6c3..3246047 100644 --- a/src/rrd_restore.c +++ b/src/rrd_restore.c @@ -1,10 +1,18 @@ /***************************************************************************** - * RRDtool 1.0.33 Copyright Tobias Oetiker, 1997 - 2000 + * RRDtool 1.2.12 Copyright by Tobi Oetiker, 1997-2005 ***************************************************************************** * rrd_restore.c creates new rrd from data dumped by rrd_dump.c *****************************************************************************/ #include "rrd_tool.h" +#include "rrd_rpncalc.h" +#include + +#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__CYGWIN32__) +#include +#define open _open +#define close _close +#endif /* Prototypes */ @@ -13,9 +21,12 @@ int skip(char **); int eat_tag(char **, char *); int read_tag(char **, char *, char *, void *); int xml2rrd(char*, rrd_t*, char); -int rrd_write(char *, rrd_t *); +int rrd_write(char *, rrd_t *, char); +void parse_patch1028_RRA_params(char **buf, rrd_t *rrd, int rra_index); +void parse_patch1028_CDP_params(char **buf, rrd_t *rrd, int rra_index, int ds_index); +void parse_FAILURES_history(char **buf, rrd_t *rrd, int rra_index, int ds_index); -/* convert all ocurances of to */ +/* convert all occurrences of to */ void xml_lc(char* buf){ int intag=0; @@ -100,6 +111,8 @@ int xml2rrd(char* buf, rrd_t* rrd, char rc){ /* pass 1 identify number of RRAs */ char *ptr,*ptr2,*ptr3; /* walks thought the buffer */ long rows=0,mempool=0,i=0; + int rra_index; + int input_version; xml_lc(buf); /* lets lowercase all active parts of the xml */ ptr=buf; ptr2=buf; @@ -115,6 +128,23 @@ int xml2rrd(char* buf, rrd_t* rrd, char rc){ strcpy(rrd->stat_head->cookie,RRD_COOKIE); read_tag(&ptr,"version","%4[0-9]",rrd->stat_head->version); + input_version = atoi(rrd->stat_head->version); + /* added primitive version checking */ + if (input_version > atoi(RRD_VERSION) ) + { + rrd_set_error("Incompatible file version, detected version %s is bigger than supported version %s\n", + rrd -> stat_head -> version, RRD_VERSION ); + return -1; + } + /* make sure we output the right version */ + strcpy(rrd->stat_head->version,RRD_VERSION); + + /* if (atoi(rrd -> stat_head -> version) < 2) + { + rrd_set_error("Can only restore version >= 2 (Not %s). Dump your old rrd using a current rrdtool dump.", rrd -> stat_head -> version ); + return -1; + } */ + rrd->stat_head->float_cookie = FLOAT_COOKIE; rrd->stat_head->ds_cnt = 0; rrd->stat_head->rra_cnt = 0; @@ -149,16 +179,23 @@ int xml2rrd(char* buf, rrd_t* rrd, char rc){ read_tag(&ptr2,"type",DST_FMT,rrd->ds_def[rrd->stat_head->ds_cnt-1].dst); /* test for valid type */ - if(dst_conv(rrd->ds_def[rrd->stat_head->ds_cnt-1].dst) == -1) return -1; + if( (int)dst_conv(rrd->ds_def[rrd->stat_head->ds_cnt-1].dst) == -1) return -1; + if (dst_conv(rrd->ds_def[rrd->stat_head->ds_cnt-1].dst) != DST_CDEF) + { read_tag(&ptr2,"minimal_heartbeat","%lu", &(rrd->ds_def[rrd->stat_head->ds_cnt-1].par[DS_mrhb_cnt].u_cnt)); read_tag(&ptr2,"min","%lf",&(rrd->ds_def[rrd->stat_head->ds_cnt-1].par[DS_min_val].u_val)); read_tag(&ptr2,"max","%lf",&(rrd->ds_def[rrd->stat_head->ds_cnt-1].par[DS_max_val].u_val)); + } else { /* DST_CDEF */ + char buffer[1024]; + read_tag(&ptr2,"cdef","%s",buffer); + parseCDEF_DS(buffer,rrd,rrd -> stat_head -> ds_cnt - 1); + } read_tag(&ptr2,"last_ds","%30s",rrd->pdp_prep[rrd->stat_head->ds_cnt-1].last_ds); read_tag(&ptr2,"value","%lf",&(rrd->pdp_prep[rrd->stat_head->ds_cnt-1].scratch[PDP_val].u_val)); - read_tag(&ptr2,"unknown_sec","%lu",&(rrd->pdp_prep[i].scratch[PDP_unkn_sec_cnt].u_cnt)); + read_tag(&ptr2,"unknown_sec","%lu",&(rrd->pdp_prep[rrd->stat_head->ds_cnt-1].scratch[PDP_unkn_sec_cnt].u_cnt)); eat_tag(&ptr2,"/ds"); ptr=ptr2; } @@ -167,12 +204,12 @@ int xml2rrd(char* buf, rrd_t* rrd, char rc){ while (eat_tag(&ptr2,"rra") == 1){ rrd->stat_head->rra_cnt++; - /* alocate and reset rra definition areas */ + /* allocate and reset rra definition areas */ if((rrd->rra_def = rrd_realloc(rrd->rra_def,rrd->stat_head->rra_cnt*sizeof(rra_def_t)))==NULL){ rrd_set_error("allocating rra_def"); return -1; } memset(&(rrd->rra_def[rrd->stat_head->rra_cnt-1]), 0, sizeof(rra_def_t)); - /* alocate and reset consolidation point areas */ + /* allocate and reset consolidation point areas */ if((rrd->cdp_prep = rrd_realloc(rrd->cdp_prep, rrd->stat_head->rra_cnt *rrd->stat_head->ds_cnt*sizeof(cdp_prep_t)))==NULL){ @@ -184,24 +221,143 @@ int xml2rrd(char* buf, rrd_t* rrd, char rc){ read_tag(&ptr2,"cf",CF_NAM_FMT,rrd->rra_def[rrd->stat_head->rra_cnt-1].cf_nam); /* test for valid type */ - if(cf_conv(rrd->rra_def[rrd->stat_head->rra_cnt-1].cf_nam) == -1) return -1; + if( (int)cf_conv(rrd->rra_def[rrd->stat_head->rra_cnt-1].cf_nam) == -1) return -1; read_tag(&ptr2,"pdp_per_row","%lu",&(rrd->rra_def[rrd->stat_head->rra_cnt-1].pdp_cnt)); - read_tag(&ptr2,"xff","%lf",&(rrd->rra_def[rrd->stat_head->rra_cnt-1].par[RRA_cdp_xff_val].u_val)); - if(rrd->rra_def[rrd->stat_head->rra_cnt-1].par[RRA_cdp_xff_val].u_val > 1 || - rrd->rra_def[rrd->stat_head->rra_cnt-1].par[RRA_cdp_xff_val].u_val < 0) - return -1; - + /* support to read RRA parameters */ + rra_index = rrd->stat_head->rra_cnt - 1; + if ( input_version < 2 ){ + read_tag(&ptr2, "xff","%lf", + &(rrd->rra_def[rra_index].par[RRA_cdp_xff_val].u_val)); + } else { + eat_tag(&ptr2, "params"); + skip(&ptr2); + /* backwards compatibility w/ old patch */ + if (strncmp(ptr2, "",7) == 0) { + parse_patch1028_RRA_params(&ptr2,rrd,rra_index); + } else { + switch(cf_conv(rrd -> rra_def[rra_index].cf_nam)) { + case CF_HWPREDICT: + read_tag(&ptr2, "hw_alpha", "%lf", + &(rrd->rra_def[rra_index].par[RRA_hw_alpha].u_val)); + read_tag(&ptr2, "hw_beta", "%lf", + &(rrd->rra_def[rra_index].par[RRA_hw_beta].u_val)); + read_tag(&ptr2, "dependent_rra_idx", "%lu", + &(rrd->rra_def[rra_index].par[RRA_dependent_rra_idx].u_cnt)); + break; + case CF_SEASONAL: + case CF_DEVSEASONAL: + read_tag(&ptr2, "seasonal_gamma", "%lf", + &(rrd->rra_def[rra_index].par[RRA_seasonal_gamma].u_val)); + read_tag(&ptr2, "seasonal_smooth_idx", "%lu", + &(rrd->rra_def[rra_index].par[RRA_seasonal_smooth_idx].u_cnt)); + read_tag(&ptr2, "dependent_rra_idx", "%lu", + &(rrd->rra_def[rra_index].par[RRA_dependent_rra_idx].u_cnt)); + break; + case CF_FAILURES: + read_tag(&ptr2, "delta_pos", "%lf", + &(rrd->rra_def[rra_index].par[RRA_delta_pos].u_val)); + read_tag(&ptr2, "delta_neg", "%lf", + &(rrd->rra_def[rra_index].par[RRA_delta_neg].u_val)); + read_tag(&ptr2, "window_len", "%lu", + &(rrd->rra_def[rra_index].par[RRA_window_len].u_cnt)); + read_tag(&ptr2, "failure_threshold", "%lu", + &(rrd->rra_def[rra_index].par[RRA_failure_threshold].u_cnt)); + /* fall thru */ + case CF_DEVPREDICT: + read_tag(&ptr2, "dependent_rra_idx", "%lu", + &(rrd->rra_def[rra_index].par[RRA_dependent_rra_idx].u_cnt)); + break; + case CF_AVERAGE: + case CF_MAXIMUM: + case CF_MINIMUM: + case CF_LAST: + default: + read_tag(&ptr2, "xff","%lf", + &(rrd->rra_def[rra_index].par[RRA_cdp_xff_val].u_val)); + } + } + eat_tag(&ptr2, "/params"); + } + + eat_tag(&ptr2,"cdp_prep"); - for(i=0;istat_head->ds_cnt;i++){ - eat_tag(&ptr2,"ds"); - read_tag(&ptr2,"value","%lf",&(rrd->cdp_prep[rrd->stat_head->ds_cnt* - (rrd->stat_head->rra_cnt-1) - +i].scratch[CDP_val].u_val)); - read_tag(&ptr2,"unknown_datapoints","%lu",&(rrd->cdp_prep[rrd->stat_head->ds_cnt - *(rrd->stat_head->rra_cnt-1) - +i].scratch[CDP_unkn_pdp_cnt].u_cnt)); - eat_tag(&ptr2,"/ds"); + for(i=0;i< (int)rrd->stat_head->ds_cnt;i++) + { + eat_tag(&ptr2,"ds"); + /* support to read CDP parameters */ + rra_index = rrd->stat_head->rra_cnt-1; + skip(&ptr2); + if ( input_version < 2 ){ + rrd->cdp_prep[rrd->stat_head->ds_cnt*(rra_index)+i].scratch[CDP_primary_val].u_val = 0.0; + rrd->cdp_prep[rrd->stat_head->ds_cnt*(rra_index)+i].scratch[CDP_secondary_val].u_val = 0.0; + read_tag(&ptr2,"value","%lf",&(rrd->cdp_prep[rrd->stat_head->ds_cnt + *(rra_index) +i].scratch[CDP_val].u_val)); + read_tag(&ptr2,"unknown_datapoints","%lu",&(rrd->cdp_prep[rrd->stat_head->ds_cnt + *(rra_index) +i].scratch[CDP_unkn_pdp_cnt].u_cnt)); + } else { + + if (strncmp(ptr2, "",7) == 0) { + parse_patch1028_CDP_params(&ptr2,rrd,rra_index,i); + } else { + read_tag(&ptr2, "primary_value","%lf", + &(rrd->cdp_prep[rrd->stat_head->ds_cnt*(rra_index) + +i].scratch[CDP_primary_val].u_val)); + read_tag(&ptr2, "secondary_value","%lf", + &(rrd->cdp_prep[rrd->stat_head->ds_cnt*(rra_index) + +i].scratch[CDP_secondary_val].u_val)); + switch(cf_conv(rrd->rra_def[rra_index].cf_nam)) { + case CF_HWPREDICT: + read_tag(&ptr2,"intercept","%lf", + &(rrd->cdp_prep[rrd->stat_head->ds_cnt*(rra_index) + +i].scratch[CDP_hw_intercept].u_val)); + read_tag(&ptr2,"last_intercept","%lf", + &(rrd->cdp_prep[rrd->stat_head->ds_cnt*(rra_index) + +i].scratch[CDP_hw_last_intercept].u_val)); + read_tag(&ptr2,"slope","%lf", + &(rrd->cdp_prep[rrd->stat_head->ds_cnt*(rra_index) + +i].scratch[CDP_hw_slope].u_val)); + read_tag(&ptr2,"last_slope","%lf", + &(rrd->cdp_prep[rrd->stat_head->ds_cnt*(rra_index) + +i].scratch[CDP_hw_last_slope].u_val)); + read_tag(&ptr2,"nan_count","%lu", + &(rrd->cdp_prep[rrd->stat_head->ds_cnt*(rra_index) + +i].scratch[CDP_null_count].u_cnt)); + read_tag(&ptr2,"last_nan_count","%lu", + &(rrd->cdp_prep[rrd->stat_head->ds_cnt*(rra_index) + +i].scratch[CDP_last_null_count].u_cnt)); + break; + case CF_SEASONAL: + case CF_DEVSEASONAL: + read_tag(&ptr2,"seasonal","%lf", + &(rrd->cdp_prep[rrd->stat_head->ds_cnt*(rra_index) + +i].scratch[CDP_hw_seasonal].u_val)); + read_tag(&ptr2,"last_seasonal","%lf", + &(rrd->cdp_prep[rrd->stat_head->ds_cnt*(rra_index) + +i].scratch[CDP_hw_last_seasonal].u_val)); + read_tag(&ptr2,"init_flag","%lu", + &(rrd->cdp_prep[rrd->stat_head->ds_cnt*(rra_index) + +i].scratch[CDP_init_seasonal].u_cnt)); + break; + case CF_DEVPREDICT: + break; + case CF_FAILURES: + parse_FAILURES_history(&ptr2,rrd,rra_index,i); + break; + case CF_AVERAGE: + case CF_MAXIMUM: + case CF_MINIMUM: + case CF_LAST: + default: + read_tag(&ptr2,"value","%lf",&(rrd->cdp_prep[rrd->stat_head->ds_cnt + *(rra_index) +i].scratch[CDP_val].u_val)); + read_tag(&ptr2,"unknown_datapoints","%lu",&(rrd->cdp_prep[rrd->stat_head->ds_cnt + *(rra_index) +i].scratch[CDP_unkn_pdp_cnt].u_cnt)); + break; + } + } + } + eat_tag(&ptr2,"/ds"); } eat_tag(&ptr2,"/cdp_prep"); rrd->rra_def[rrd->stat_head->rra_cnt-1].row_cnt=0; @@ -219,7 +375,7 @@ int xml2rrd(char* buf, rrd_t* rrd, char rc){ rows++; mempool--; rrd->rra_def[rrd->stat_head->rra_cnt-1].row_cnt++; - for(i=0;istat_head->ds_cnt;i++){ + for(i=0;i< (int)rrd->stat_head->ds_cnt;i++){ rrd_value_t * value = &(rrd->rrd_value[(rows-1)*rrd->stat_head->ds_cnt+i]); @@ -230,6 +386,8 @@ int xml2rrd(char* buf, rrd_t* rrd, char rc){ && (!isnan(*value)) /* not a NAN value */ && + (dst_conv(rrd->ds_def[i].dst) != DST_CDEF) + && ( /* min defined and in the range ? */ (!isnan(rrd->ds_def[i].par[DS_min_val].u_val) && (*value < rrd->ds_def[i].par[DS_min_val].u_val)) @@ -256,7 +414,10 @@ int xml2rrd(char* buf, rrd_t* rrd, char rc){ return(-1); } - for(i=0; i stat_head->rra_cnt; i++) { + for(i=0; i < (int)rrd->stat_head->rra_cnt; i++) { + /* last row in the xml file is the most recent; as + * rrd_update increments the current row pointer, set cur_row + * here to the last row. */ rrd->rra_ptr[i].cur_row = rrd->rra_def[i].row_cnt-1; } if (ptr==NULL) @@ -271,17 +432,29 @@ int xml2rrd(char* buf, rrd_t* rrd, char rc){ /* create and empty rrd file according to the specs given */ int -rrd_write(char *file_name, rrd_t *rrd) +rrd_write(char *file_name, rrd_t *rrd, char force_overwrite) { unsigned long i,ii,val_cnt; FILE *rrd_file=NULL; + int fdflags; + int fd; if (strcmp("-",file_name)==0){ - *rrd_file= *stdout; + rrd_file= stdout; } else { - if ((rrd_file = fopen(file_name,"wb")) == NULL ) { - rrd_set_error("creating '%s': %s",file_name,strerror(errno)); - rrd_free(rrd); +#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__CYGWIN32__) + fdflags = O_RDWR|O_BINARY|O_CREAT; +#else + fdflags = O_WRONLY|O_CREAT; +#endif + if (force_overwrite == 0) { + fdflags |= O_EXCL; + } + fd = open(file_name,fdflags,0666); + if (fd == -1 || (rrd_file = fdopen(fd,"wb")) == NULL) { + rrd_set_error("creating '%s': %s",file_name,rrd_strerror(errno)); + if (fd != -1) + close(fd); return(-1); } } @@ -293,7 +466,7 @@ rrd_write(char *file_name, rrd_t *rrd) fwrite(rrd->rra_def, sizeof(rra_def_t), rrd->stat_head->rra_cnt, rrd_file); - + fwrite(rrd->live_head, sizeof(live_head_t),1, rrd_file); fwrite( rrd->pdp_prep, sizeof(pdp_prep_t),rrd->stat_head->ds_cnt,rrd_file); @@ -329,25 +502,22 @@ rrd_restore(int argc, char **argv) rrd_t rrd; char *buf; char rc = 0; + char force_overwrite = 0; /* init rrd clean */ - rrd_init(&rrd); - if (argc<3) { - rrd_set_error("usage rrdtool %s [--range-check/-r] file.xml file.rrd",argv[0]); - return -1; - } - + optind = 0; opterr = 0; /* initialize getopt */ while (1) { static struct option long_options[] = { - {"range-check", required_argument, 0, 'r'}, + {"range-check", no_argument, 0, 'r'}, + {"force-overwrite", no_argument, 0, 'f'}, {0,0,0,0} }; int option_index = 0; int opt; - opt = getopt_long(argc, argv, "r", long_options, &option_index); + opt = getopt_long(argc, argv, "rf", long_options, &option_index); if (opt == EOF) break; @@ -356,26 +526,98 @@ rrd_restore(int argc, char **argv) case 'r': rc=1; break; + case 'f': + force_overwrite=1; + break; default: - rrd_set_error("usage rrdtool %s [--range-check|-r] file.xml file.rrd",argv[0]); - return -1; + rrd_set_error("usage rrdtool %s [--range-check|-r] [--force-overwrite/-f] file.xml file.rrd",argv[0]); + return -1; break; } } + + if (argc-optind != 2) { + rrd_set_error("usage rrdtool %s [--range-check/-r] [--force-overwrite/-f] file.xml file.rrd",argv[0]); + return -1; + } if (readfile(argv[optind],&buf,0)==-1){ return -1; } + + rrd_init(&rrd); + if (xml2rrd(buf,&rrd,rc)==-1) { rrd_free(&rrd); free(buf); return -1; } + free(buf); - if(rrd_write(argv[optind+1],&rrd)==-1){ + + if(rrd_write(argv[optind+1],&rrd,force_overwrite)==-1){ rrd_free(&rrd); return -1; }; rrd_free(&rrd); return 0; } + +/* a backwards compatibility routine that will parse the RRA params section + * generated by the aberrant patch to 1.0.28. */ + +void +parse_patch1028_RRA_params(char **buf, rrd_t *rrd, int rra_index) +{ + int i; + for (i = 0; i < MAX_RRA_PAR_EN; i++) + { + if (i == RRA_dependent_rra_idx || + i == RRA_seasonal_smooth_idx || + i == RRA_failure_threshold) + read_tag(buf, "value","%lu", + &(rrd->rra_def[rra_index].par[i].u_cnt)); + else + read_tag(buf, "value","%lf", + &(rrd->rra_def[rra_index].par[i].u_val)); + } +} + +/* a backwards compatibility routine that will parse the CDP params section + * generated by the aberrant patch to 1.0.28. */ +void +parse_patch1028_CDP_params(char **buf, rrd_t *rrd, int rra_index, int ds_index) +{ + int ii; + for (ii = 0; ii < MAX_CDP_PAR_EN; ii++) + { + if (cf_conv(rrd->rra_def[rra_index].cf_nam) == CF_FAILURES || + ii == CDP_unkn_pdp_cnt || + ii == CDP_null_count || + ii == CDP_last_null_count) + { + read_tag(buf,"value","%lu", + &(rrd->cdp_prep[rrd->stat_head->ds_cnt*(rra_index) + ds_index].scratch[ii].u_cnt)); + } else { + read_tag(buf,"value","%lf",&(rrd->cdp_prep[rrd->stat_head->ds_cnt* + (rra_index) + ds_index].scratch[ii].u_val)); + } + } +} + +void +parse_FAILURES_history(char **buf, rrd_t *rrd, int rra_index, int ds_index) +{ + char history[MAX_FAILURES_WINDOW_LEN + 1]; + char *violations_array; + unsigned short i; + + /* 28 = MAX_FAILURES_WINDOW_LEN */ + read_tag(buf, "history", "%28[0-1]", history); + violations_array = (char*) rrd -> cdp_prep[rrd->stat_head->ds_cnt*(rra_index) + + ds_index].scratch; + + for (i = 0; i < rrd -> rra_def[rra_index].par[RRA_window_len].u_cnt; ++i) + violations_array[i] = (history[i] == '1') ? 1 : 0; + +}