X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Frrd_restore.c;h=369f7bdf290047d6c874cca16841d4500d283a57;hb=ac80502874611b14e8d7361ab8af22e252c0385b;hp=fa8493adf893b45ca91040fb18138fe8e7583004;hpb=9dba554e59319d13076a8184c7889cca868b4c85;p=rrdtool.git diff --git a/src/rrd_restore.c b/src/rrd_restore.c index fa8493a..369f7bd 100644 --- a/src/rrd_restore.c +++ b/src/rrd_restore.c @@ -1,35 +1,45 @@ /***************************************************************************** - * RRDtool 1.2.99907080300 Copyright by Tobi Oetiker, 1997-2007 + * RRDtool 1.3.2 Copyright by Tobi Oetiker, 1997-2008 * This file: Copyright 2008 Florian octo Forster * Distributed under the GPL ***************************************************************************** - * rrd_thread_safe.c Contains routines used when thread safety is required + * rrd_restore.c Contains logic to parse XML input and create an RRD file ***************************************************************************** * $Id$ *************************************************************************** */ -* *This program is free software; -you can redistribute it and / or modify it - * - under the terms of the GNU General Public License as published by the Free - * Software Foundation; -either version 2 of the License, or( - at your option) -* any later version. - * *This program is distributed in the hope that it will be useful, -but WITHOUT * ANY WARRANTY; - without even the implied warranty of MERCHANTABILITY or - * - FITNESS FOR A PARTICULAR PURPOSE. - See the GNU General Public License for *more details. * - *You should have received a copy of the GNU General Public License - along * with this program; if not - , write to the Free Software Foundation, Inc., *51 Franklin St, Fifth Floor, Boston, MA 02110 - 1301 USA * *Authors: - *Florian octo Forster < octo at verplant.org > **/ + +/* + * This program is free software; you can redistribute it and / or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (t your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110 - 1301 USA + * + * Authors: + * Florian octo Forster + **/ + #include #include #include #include -#include + + +#ifndef WIN32 +# include /* for off_t */ +#else + typedef size_t ssize_t; + typedef long off_t; +#endif + #include #if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__CYGWIN32__) # include @@ -40,13 +50,13 @@ but WITHOUT * ANY WARRANTY; #include "rrd_tool.h" #include "rrd_rpncalc.h" #define ARRAY_LENGTH(a) (sizeof (a) / sizeof ((a)[0])) - static int opt_range_check = 0; - static int opt_force_overwrite = 0; +static int opt_range_check = 0; +static int opt_force_overwrite = 0; /* * Auxiliary functions */ - static int get_string_from_node( +static int get_string_from_node( xmlDoc * doc, xmlNode * node, char *buffer, @@ -85,18 +95,18 @@ but WITHOUT * ANY WARRANTY; return (0); } /* int get_string_from_node */ -static int get_int_from_node( +static int get_long_from_node( xmlDoc * doc, xmlNode * node, - int *value) + long *value) { - int temp; + long temp; char *str_ptr; char *end_ptr; str_ptr = (char *) xmlNodeListGetString(doc, node->xmlChildrenNode, 1); if (str_ptr == NULL) { - rrd_set_error("get_int_from_node: xmlNodeListGetString failed."); + rrd_set_error("get_long_from_node: xmlNodeListGetString failed."); return (-1); } @@ -105,7 +115,37 @@ static int get_int_from_node( xmlFree(str_ptr); if (str_ptr == end_ptr) { - rrd_set_error("get_int_from_node: Cannot parse buffer as int: %s", + rrd_set_error("get_long_from_node: Cannot parse buffer as long: %s", + str_ptr); + return (-1); + } + + *value = temp; + + return (0); +} /* int get_long_from_node */ + +static int get_ulong_from_node( + xmlDoc * doc, + xmlNode * node, + unsigned long *value) +{ + unsigned long temp; + char *str_ptr; + char *end_ptr; + + str_ptr = (char *) xmlNodeListGetString(doc, node->xmlChildrenNode, 1); + if (str_ptr == NULL) { + rrd_set_error("get_ulong_from_node: xmlNodeListGetString failed."); + return (-1); + } + + end_ptr = NULL; + temp = strtoul(str_ptr, &end_ptr, 0); + xmlFree(str_ptr); + + if (str_ptr == end_ptr) { + rrd_set_error("get_ulong_from_node: Cannot parse buffer as unsigned long: %s", str_ptr); return (-1); } @@ -113,7 +153,7 @@ static int get_int_from_node( *value = temp; return (0); -} /* int get_int_from_node */ +} /* int get_ulong_from_node */ static int get_double_from_node( xmlDoc * doc, @@ -130,6 +170,13 @@ static int get_double_from_node( return (-1); } + if (strstr(str_ptr, "NaN") != NULL) + { + *value = DNAN; + xmlFree(str_ptr); + return 0; + } + end_ptr = NULL; temp = strtod(str_ptr, &end_ptr); xmlFree(str_ptr); @@ -161,7 +208,7 @@ static int value_check_range( if (((!isnan(min)) && (*rrd_value < min)) || ((!isnan(max)) && (*rrd_value > max))) - *rrd_value = NAN; + *rrd_value = DNAN; return (0); } /* int value_check_range */ @@ -316,6 +363,10 @@ static int parse_tag_rra_cdp_prep_ds( status = 0; for (child = node->xmlChildrenNode; child != NULL; child = child->next) { + if (atoi(rrd->stat_head->version) == 1) { + cdp_prep->scratch[CDP_primary_val].u_val = 0.0; + cdp_prep->scratch[CDP_secondary_val].u_val = 0.0; + } if ((xmlStrcmp(child->name, (const xmlChar *) "comment") == 0) || (xmlStrcmp(child->name, (const xmlChar *) "text") == 0)) /* ignore */ ; @@ -350,14 +401,14 @@ static int parse_tag_rra_cdp_prep_ds( &cdp_prep-> scratch[CDP_hw_last_slope].u_val); else if (xmlStrcmp(child->name, (const xmlChar *) "nan_count") == 0) - status = get_int_from_node(doc, child, - (int *) &cdp_prep-> + status = get_ulong_from_node(doc, child, + &cdp_prep-> scratch[CDP_null_count].u_cnt); else if (xmlStrcmp(child->name, (const xmlChar *) "last_nan_count") == 0) status = - get_int_from_node(doc, child, - (int *) &cdp_prep-> + get_ulong_from_node(doc, child, + &cdp_prep-> scratch[CDP_last_null_count].u_cnt); else if (xmlStrcmp(child->name, (const xmlChar *) "seasonal") == 0) status = get_double_from_node(doc, child, @@ -370,8 +421,8 @@ static int parse_tag_rra_cdp_prep_ds( &cdp_prep->scratch[CDP_hw_last_seasonal]. u_val); else if (xmlStrcmp(child->name, (const xmlChar *) "init_flag") == 0) - status = get_int_from_node(doc, child, - (int *) &cdp_prep-> + status = get_ulong_from_node(doc, child, + &cdp_prep-> scratch[CDP_init_seasonal].u_cnt); else if (xmlStrcmp(child->name, (const xmlChar *) "history") == 0) status = parse_tag_rra_cdp_prep_ds_history(doc, child, cdp_prep); @@ -380,48 +431,9 @@ static int parse_tag_rra_cdp_prep_ds( &cdp_prep->scratch[CDP_val].u_val); else if (xmlStrcmp(child->name, (const xmlChar *) "unknown_datapoints") == 0) - status = get_int_from_node(doc, child, - (int *) &cdp_prep-> + status = get_ulong_from_node(doc, child, + &cdp_prep-> scratch[CDP_unkn_pdp_cnt].u_cnt); - /* - * Compatibility code for 1.0.49 - */ - else if (xmlStrcmp(child->name, (const xmlChar *) "value") == 0) { /* {{{ */ - unsigned int i = 0; - rra_def_t *rra_def = rrd->rra_def + (rrd->stat_head->rra_cnt - 1); - - while (42) { - if (i >= ARRAY_LENGTH(cdp_prep->scratch)) { - status = -1; - break; - } - - if ((cf_conv(rra_def->cf_nam) == CF_FAILURES) - || (i == CDP_unkn_pdp_cnt) - || (i == CDP_null_count) - || (i == CDP_last_null_count)) - status = get_int_from_node(doc, child, - (int *) &cdp_prep->scratch[i]. - u_cnt); - else - status = get_double_from_node(doc, child, - &cdp_prep->scratch[i]. - u_val); - - if (status != 0) - break; - - /* When this loops exits (sucessfully) `child' points to the last - * `value' tag in the list. */ - if ((child->next == NULL) - || (xmlStrcmp(child->name, (const xmlChar *) "value") != - 0)) - break; - - child = child->next; - i++; - } - } /* }}} */ else { rrd_set_error("parse_tag_rra_cdp_prep: Unknown tag: %s", child->name); @@ -506,8 +518,8 @@ static int parse_tag_rra_params( &rra_def->par[RRA_hw_beta].u_val); else if (xmlStrcmp(child->name, (const xmlChar *) "dependent_rra_idx") == 0) - status = get_int_from_node(doc, child, - (int *) &rra_def-> + status = get_ulong_from_node(doc, child, + &rra_def-> par[RRA_dependent_rra_idx].u_cnt); /* * Parameters for CF_SEASONAL and CF_DEVSEASONAL @@ -520,8 +532,8 @@ static int parse_tag_rra_params( else if (xmlStrcmp (child->name, (const xmlChar *) "seasonal_smooth_idx") == 0) status = - get_int_from_node(doc, child, - (int *) &rra_def-> + get_ulong_from_node(doc, child, + &rra_def-> par[RRA_seasonal_smooth_idx].u_cnt); else if (xmlStrcmp(child->name, (const xmlChar *) "smoothing_window") == 0) @@ -541,14 +553,14 @@ static int parse_tag_rra_params( status = get_double_from_node(doc, child, &rra_def->par[RRA_delta_neg].u_val); else if (xmlStrcmp(child->name, (const xmlChar *) "window_len") == 0) - status = get_int_from_node(doc, child, - (int *) &rra_def->par[RRA_window_len]. + status = get_ulong_from_node(doc, child, + &rra_def->par[RRA_window_len]. u_cnt); else if (xmlStrcmp(child->name, (const xmlChar *) "failure_threshold") == 0) status = - get_int_from_node(doc, child, - (int *) &rra_def-> + get_ulong_from_node(doc, child, + &rra_def-> par[RRA_failure_threshold].u_cnt); /* * Parameters for CF_AVERAGE, CF_MAXIMUM, CF_MINIMUM, and CF_LAST @@ -572,8 +584,8 @@ static int parse_tag_rra_params( if ((i == RRA_dependent_rra_idx) || (i == RRA_seasonal_smooth_idx) || (i == RRA_failure_threshold)) - status = get_int_from_node(doc, child, - (int *) &rra_def->par[i]. + status = get_ulong_from_node(doc, child, + &rra_def->par[i]. u_cnt); else status = get_double_from_node(doc, child, @@ -704,9 +716,15 @@ static int parse_tag_rra( else if (xmlStrcmp(child->name, (const xmlChar *) "cf") == 0) status = parse_tag_rra_cf(doc, child, cur_rra_def); else if (xmlStrcmp(child->name, (const xmlChar *) "pdp_per_row") == 0) - status = get_int_from_node(doc, child, - (int *) &cur_rra_def->pdp_cnt); - else if (xmlStrcmp(child->name, (const xmlChar *) "params") == 0) + status = get_ulong_from_node(doc, child, + &cur_rra_def->pdp_cnt); + else if (atoi(rrd->stat_head->version) == 1 + && xmlStrcmp(child->name, (const xmlChar *) "xff") == 0) + status = get_double_from_node(doc, child, + (double *) &cur_rra_def-> + par[RRA_cdp_xff_val].u_val); + else if (atoi(rrd->stat_head->version) >= 2 + && xmlStrcmp(child->name, (const xmlChar *) "params") == 0) status = parse_tag_rra_params(doc, child, cur_rra_def); else if (xmlStrcmp(child->name, (const xmlChar *) "cdp_prep") == 0) status = parse_tag_rra_cdp_prep(doc, child, rrd, cur_cdp_prep); @@ -721,8 +739,8 @@ static int parse_tag_rra( break; } - /* Set the RRA pointer to the last value in the archive */ - cur_rra_ptr->cur_row = cur_rra_def->row_cnt - 1; + /* Set the RRA pointer to a random location */ + cur_rra_ptr->cur_row = rrd_random() % cur_rra_def->row_cnt; return (status); } /* int parse_tag_rra */ @@ -841,8 +859,8 @@ static int parse_tag_ds( status = parse_tag_ds_type(doc, child, cur_ds_def); else if (xmlStrcmp(child->name, (const xmlChar *) "minimal_heartbeat") == 0) - status = get_int_from_node(doc, child, - (int *) &cur_ds_def->par[DS_mrhb_cnt]. + status = get_ulong_from_node(doc, child, + &cur_ds_def->par[DS_mrhb_cnt]. u_cnt); else if (xmlStrcmp(child->name, (const xmlChar *) "min") == 0) status = get_double_from_node(doc, child, @@ -861,8 +879,8 @@ static int parse_tag_ds( &cur_pdp_prep->scratch[PDP_val]. u_val); else if (xmlStrcmp(child->name, (const xmlChar *) "unknown_sec") == 0) - status = get_int_from_node(doc, child, - (int *) &cur_pdp_prep-> + status = get_ulong_from_node(doc, child, + &cur_pdp_prep-> scratch[PDP_unkn_sec_cnt].u_cnt); else { rrd_set_error("parse_tag_ds: Unknown tag: %s", child->name); @@ -897,11 +915,11 @@ static int parse_tag_rrd( rrd->stat_head->version, sizeof(rrd->stat_head->version)); else if (xmlStrcmp(child->name, (const xmlChar *) "step") == 0) - status = get_int_from_node(doc, child, - (int *) &rrd->stat_head->pdp_step); + status = get_ulong_from_node(doc, child, + &rrd->stat_head->pdp_step); else if (xmlStrcmp(child->name, (const xmlChar *) "lastupdate") == 0) - status = get_int_from_node(doc, child, - (int *) &rrd->live_head->last_up); + status = get_long_from_node(doc, child, + &rrd->live_head->last_up); else if (xmlStrcmp(child->name, (const xmlChar *) "ds") == 0) status = parse_tag_ds(doc, child, rrd); else if (xmlStrcmp(child->name, (const xmlChar *) "rra") == 0) @@ -994,7 +1012,7 @@ static int write_file( { FILE *fh; unsigned int i; - unsigned int value_count; + unsigned int rra_offset; if (strcmp("-", file_name) == 0) fh = stdout; @@ -1023,7 +1041,10 @@ static int write_file( return (-1); } } - + if (atoi(rrd->stat_head->version) < 3) { + /* we output 3 or higher */ + strcpy(rrd->stat_head->version, "0003"); + } fwrite(rrd->stat_head, sizeof(stat_head_t), 1, fh); fwrite(rrd->ds_def, sizeof(ds_def_t), rrd->stat_head->ds_cnt, fh); fwrite(rrd->rra_def, sizeof(rra_def_t), rrd->stat_head->rra_cnt, fh); @@ -1034,11 +1055,21 @@ static int write_file( fwrite(rrd->rra_ptr, sizeof(rra_ptr_t), rrd->stat_head->rra_cnt, fh); /* calculate the number of rrd_values to dump */ - value_count = 0; - for (i = 0; i < rrd->stat_head->rra_cnt; i++) - value_count += (rrd->rra_def[i].row_cnt * rrd->stat_head->ds_cnt); + rra_offset = 0; + for (i = 0; i < rrd->stat_head->rra_cnt; i++) { + unsigned long num_rows = rrd->rra_def[i].row_cnt; + unsigned long cur_row = rrd->rra_ptr[i].cur_row; + unsigned long ds_cnt = rrd->stat_head->ds_cnt; + + fwrite(rrd->rrd_value + + (rra_offset + num_rows - 1 - cur_row) * ds_cnt, + sizeof(rrd_value_t), (cur_row + 1) * ds_cnt, fh); - fwrite(rrd->rrd_value, sizeof(rrd_value_t), value_count, fh); + fwrite(rrd->rrd_value + rra_offset * ds_cnt, + sizeof(rrd_value_t), (num_rows - 1 - cur_row) * ds_cnt, fh); + + rra_offset += num_rows; + } /* lets see if we had an error */ if (ferror(fh)) {