X-Git-Url: https://git.octo.it/?p=rrdtool.git;a=blobdiff_plain;f=src%2Frrd_restore.c;h=46a79b5a59e04d1c8510159a16d7fc3d16a3dac5;hp=d6b0d5aec108eeb0fa318656b6bdea4b4c24f890;hb=a7066853475167aeeaec21a2405189c5afd231f9;hpb=f75c19b15bd7f3aae3c48d9c1ab1036d5e201baa diff --git a/src/rrd_restore.c b/src/rrd_restore.c index d6b0d5a..46a79b5 100644 --- a/src/rrd_restore.c +++ b/src/rrd_restore.c @@ -1,152 +1,313 @@ /***************************************************************************** - * RRDtool 1.2.99907080300 Copyright by Tobi Oetiker, 1997-2007 - * This file: Copyright 2008 Florian octo Forster - * Distributed under the GPL + * RRDtool 1.3.2 Copyright by Tobi Oetiker, 1997-2009 ***************************************************************************** - * rrd_restore.c Contains logic to parse XML input and create an RRD file + * rrd_restore.c Contains logic to parse XML input and create an RRD file + * initial libxml2 version of rrd_restore (c) by Florian octo Forster ***************************************************************************** * $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 (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 -#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 # define open _open # define close _close #endif -#include + #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; /* - * Auxiliary functions + * Helpers */ -static int get_string_from_node( - xmlDoc * doc, - xmlNode * node, - char *buffer, - size_t buffer_size) -{ - xmlChar *temp0; - char *begin_ptr; - char *end_ptr; - temp0 = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); - if (temp0 == NULL) { - rrd_set_error("get_string_from_node: xmlNodeListGetString failed."); - return (-1); +/* skip all but tags. complain if we do not get the right tag */ +/* dept -1 causes depth to be ignored */ +static xmlChar* get_xml_element ( + xmlTextReaderPtr reader + ) +{ + while(xmlTextReaderRead(reader)){ + int type; + xmlChar *name; + type = xmlTextReaderNodeType(reader); + if (type == XML_READER_TYPE_TEXT){ + xmlChar *value; + value = xmlTextReaderValue(reader); + rrd_set_error("line %d: expected element but found text '%s'", + xmlTextReaderGetParserLineNumber(reader),value); + xmlFree(value); + return NULL; + } + /* skip all other non-elements */ + if (type != XML_READER_TYPE_ELEMENT && type != XML_READER_TYPE_END_ELEMENT) + continue; + + name = xmlTextReaderName(reader); + if (type == XML_READER_TYPE_END_ELEMENT){ + xmlChar *temp; + xmlChar *temp2; + temp = (xmlChar*)sprintf_alloc("/%s",name); + temp2 = xmlStrdup(temp); + free(temp); + xmlFree(name); + return temp2; + } + /* all seems well, return the happy news */ + return name; } - - begin_ptr = (char *) temp0; - while ((begin_ptr[0] != 0) && (isspace(begin_ptr[0]))) - begin_ptr++; - - if (begin_ptr[0] == 0) { - xmlFree(temp0); - buffer[0] = 0; - return (0); + rrd_set_error("the xml ended while we were looking for an element"); + return NULL; +} /* get_xml_element */ + +static void local_rrd_free (rrd_t *rrd) +{ + free(rrd->live_head); + free(rrd->stat_head); + free(rrd->ds_def); + free(rrd->rra_def); + free(rrd->rra_ptr); + free(rrd->pdp_prep); + free(rrd->cdp_prep); + free(rrd->rrd_value); + free(rrd); +} + + +static int expect_element ( + xmlTextReaderPtr reader, + char *exp_name) +{ + xmlChar *name; + name = get_xml_element(reader); + if (!name) + return -1; + if (xmlStrcasecmp(name,(xmlChar *)exp_name) != 0){ + rrd_set_error("line %d: expected <%s> element but found <%s>", + xmlTextReaderGetParserLineNumber(reader),name,exp_name); + xmlFree(name); + return -1; } + xmlFree(name); + return 0; +} /* expect_element */ - end_ptr = begin_ptr; - while ((end_ptr[0] != 0) && (!isspace(end_ptr[0]))) - end_ptr++; - end_ptr[0] = 0; - - strncpy(buffer, begin_ptr, buffer_size); - buffer[buffer_size - 1] = 0; - - xmlFree(temp0); - - return (0); -} /* int get_string_from_node */ - -static int get_int_from_node( - xmlDoc * doc, - xmlNode * node, - int *value) +static int expect_element_end ( + xmlTextReaderPtr reader, + char *exp_name) { - int 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."); - return (-1); + xmlChar *name; + name = get_xml_element(reader); + if (name == NULL) + return -1; + if (xmlStrcasecmp(name+1,(xmlChar *)exp_name) != 0 || name[0] != '/'){ + rrd_set_error("line %d: expected end element but found <%s>", + xmlTextReaderGetParserLineNumber(reader),exp_name,name); + xmlFree(name); + return -1; } + xmlFree(name); + return 0; +} /* expect_element_end */ - end_ptr = NULL; - temp = strtol(str_ptr, &end_ptr, 0); - xmlFree(str_ptr); - if (str_ptr == end_ptr) { - rrd_set_error("get_int_from_node: Cannot parse buffer as int: %s", - str_ptr); - return (-1); +static xmlChar* get_xml_text ( + xmlTextReaderPtr reader + ) +{ + while(xmlTextReaderRead(reader)){ + xmlChar *ret; + xmlChar *text; + xmlChar *begin_ptr; + xmlChar *end_ptr; + int type; + type = xmlTextReaderNodeType(reader); + if (type == XML_READER_TYPE_ELEMENT){ + xmlChar *name; + name = xmlTextReaderName(reader); + rrd_set_error("line %d: expected a value but found an <%s> element", + xmlTextReaderGetParserLineNumber(reader), + name); + xmlFree(name); + return NULL; + } + /* skip all other non-text */ + if (xmlTextReaderNodeType(reader) != XML_READER_TYPE_TEXT) + continue; + + text = xmlTextReaderValue(reader); + + begin_ptr = text; + while ((begin_ptr[0] != 0) && (isspace(begin_ptr[0]))) + begin_ptr++; + if (begin_ptr[0] == 0) { + xmlFree(text); + return xmlStrdup(BAD_CAST ""); + } + end_ptr = begin_ptr; + while ((end_ptr[0] != 0) && (!isspace(end_ptr[0]))) + end_ptr++; + end_ptr[0] = 0; + + ret = xmlStrdup(begin_ptr); + xmlFree(text); + return ret; } + rrd_set_error("file ended while looking for text"); + return NULL; +} /* get_xml_text */ - *value = temp; - return (0); -} /* int get_int_from_node */ +static int get_xml_string( + xmlTextReaderPtr reader, + char *value, + int max_len) +{ + xmlChar *str; + str = get_xml_text(reader); + if (str != NULL){ + strncpy(value,(char *)str,max_len); + xmlFree(str); + return 0; + } + else + return -1; +} + + +static int get_xml_long( + xmlTextReaderPtr reader, + long *value) +{ + xmlChar *text; + long temp; + if ((text = get_xml_text(reader)) != NULL){ + errno = 0; + temp = strtol((char *)text,NULL, 0); + if (errno>0){ + rrd_set_error("ling %d: get_xml_long from '%s' %s", + xmlTextReaderGetParserLineNumber(reader), + text,rrd_strerror(errno)); + xmlFree(text); + return -1; + } + xmlFree(text); + *value = temp; + return 0; + } + return -1; +} /* get_xml_long */ -static int get_double_from_node( - xmlDoc * doc, - xmlNode * node, - double *value) +static int get_xml_ulong( + xmlTextReaderPtr reader, + unsigned long *value) { - double temp; - char *str_ptr; - char *end_ptr; + + xmlChar *text; + unsigned long temp; + if ((text = get_xml_text(reader)) != NULL){ + errno = 0; + temp = strtoul((char *)text,NULL, 0); + if (errno>0){ + rrd_set_error("ling %d: get_xml_ulong from '%s' %s", + xmlTextReaderGetParserLineNumber(reader), + text,rrd_strerror(errno)); + xmlFree(text); + return -1; + } + xmlFree(text); + *value = temp; + return 0; + } + return -1; +} /* get_xml_ulong */ - str_ptr = (char *) xmlNodeListGetString(doc, node->xmlChildrenNode, 1); - if (str_ptr == NULL) { - rrd_set_error("get_double_from_node: xmlNodeListGetString failed."); - return (-1); +#ifndef TIME_T_IS_LONG +static int get_xml_llong( + xmlTextReaderPtr reader, + long long *value) +{ + + xmlChar *text; + long long temp; + if ((text = get_xml_text(reader)) != NULL){ + errno = 0; + temp = strtoll((char *)text,NULL, 0); + if (errno>0){ + rrd_set_error("ling %d: get_xml_llong from '%s' %s", + xmlTextReaderGetParserLineNumber(reader), + text,rrd_strerror(errno)); + xmlFree(text); + return -1; + } + xmlFree(text); + *value = temp; + return 0; } + return -1; +} /* get_xml_llong */ - end_ptr = NULL; - temp = strtod(str_ptr, &end_ptr); - xmlFree(str_ptr); +#endif - if (str_ptr == end_ptr) { - rrd_set_error - ("get_double_from_node: Cannot parse buffer as double: %s", - str_ptr); - return (-1); +static int get_xml_double( + xmlTextReaderPtr reader, + double *value) +{ + + char *text; + double temp; + if ((text = (char *)get_xml_text(reader))!= NULL){ + if (strcasestr(text,"nan")){ + *value = DNAN; + xmlFree(text); + return 0; + } + else if (strcasestr(text,"-inf")){ + *value = -DINF; + xmlFree(text); + return 0; + } + else if (strcasestr(text,"+inf") + || strcasestr(text,"inf")){ + *value = DINF; + xmlFree(text); + return 0; + } + errno = 0; + temp = strtod((char *)text,NULL); + if (errno>0){ + rrd_set_error("ling %d: get_xml_double from '%s' %s", + xmlTextReaderGetParserLineNumber(reader), + text,rrd_strerror(errno)); + xmlFree(text); + return -1; + } + xmlFree(text); + *value = temp; + return 0; } + return -1; +} /* get_xml_double */ - *value = temp; - - return (0); -} /* int get_double_from_node */ static int value_check_range( rrd_value_t *rrd_value, @@ -163,70 +324,50 @@ 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 */ +} /* int value_check_range */ /* * Parse the block within an RRA definition */ + static int parse_tag_rra_database_row( - xmlDoc * doc, - xmlNode * node, + xmlTextReaderPtr reader, rrd_t *rrd, rrd_value_t *rrd_value) { unsigned int values_count = 0; - xmlNode *child; int status; - + status = 0; - for (child = node->xmlChildrenNode; child != NULL; child = child->next) { - if ((xmlStrcmp(child->name, (const xmlChar *) "comment") == 0) - || (xmlStrcmp(child->name, (const xmlChar *) "text") == 0)) - /* ignore */ ; - else if (xmlStrcmp(child->name, (const xmlChar *) "v") == 0) { - if (values_count < rrd->stat_head->ds_cnt) { - status = - get_double_from_node(doc, child, - rrd_value + values_count); - if (status == 0) - value_check_range(rrd_value + values_count, - rrd->ds_def + values_count); - } - - values_count++; - } else { - rrd_set_error("parse_tag_rra_database_row: Unknown tag: %s", - child->name); - status = -1; + for (values_count = 0;values_count < rrd->stat_head->ds_cnt;values_count++){ + if (expect_element(reader,"v") == 0){ + status = get_xml_double(reader,rrd_value + values_count); + if (status == 0) + value_check_range(rrd_value + values_count, + rrd->ds_def + values_count); + else + break; + } else + return -1; + if (expect_element(reader,"/v") == -1){ + return -1; } - - if (status != 0) - break; - } /* for (child = node->xmlChildrenNode) */ - - if (values_count != rrd->stat_head->ds_cnt) { - rrd_set_error("parse_tag_rra_database_row: Row has %u values " - "and RRD has %lu data sources.", - values_count, rrd->stat_head->ds_cnt); - status = -1; } - - return (status); + return status; } /* int parse_tag_rra_database_row */ static int parse_tag_rra_database( - xmlDoc * doc, - xmlNode * node, - rrd_t *rrd) + xmlTextReaderPtr reader, + rrd_t *rrd ) { rra_def_t *cur_rra_def; unsigned int total_row_cnt; - xmlNode *child; int status; int i; + xmlChar *element; total_row_cnt = 0; for (i = 0; i < (((int) rrd->stat_head->rra_cnt) - 1); i++) @@ -235,15 +376,12 @@ static int parse_tag_rra_database( cur_rra_def = rrd->rra_def + i; status = 0; - for (child = node->xmlChildrenNode; child != NULL; child = child->next) { - if ((xmlStrcmp(child->name, (const xmlChar *) "comment") == 0) - || (xmlStrcmp(child->name, (const xmlChar *) "text") == 0)) - /* ignore */ ; - else if (xmlStrcmp(child->name, (const xmlChar *) "row") == 0) { - rrd_value_t *temp; - rrd_value_t *cur_rrd_value; - unsigned int total_values_count = rrd->stat_head->ds_cnt - * (total_row_cnt + 1); + while ((element = get_xml_element(reader)) != NULL){ + if (xmlStrcasecmp(element,(const xmlChar *)"row") == 0){ + rrd_value_t *temp; + rrd_value_t *cur_rrd_value; + unsigned int total_values_count = rrd->stat_head->ds_cnt + * (total_row_cnt + 1); /* Allocate space for the new values.. */ temp = (rrd_value_t *) realloc(rrd->rrd_value, @@ -252,7 +390,7 @@ static int parse_tag_rra_database( if (temp == NULL) { rrd_set_error("parse_tag_rra_database: realloc failed."); status = -1; - break; + break; } rrd->rrd_value = temp; cur_rrd_value = rrd->rrd_value @@ -263,18 +401,25 @@ static int parse_tag_rra_database( cur_rra_def->row_cnt++; status = - parse_tag_rra_database_row(doc, child, rrd, cur_rrd_value); - } /* if (xmlStrcmp (child->name, (const xmlChar *) "row") == 0) */ + parse_tag_rra_database_row(reader, rrd, cur_rrd_value); + if (status == 0) + status = expect_element(reader,"/row"); + } /* if (xmlStrcasecmp(element,"row")) */ else { - rrd_set_error("parse_tag_rra_database: Unknown tag: %s", - child->name); - status = -1; + if ( xmlStrcasecmp(element,(const xmlChar *)"/database") == 0){ + xmlFree(element); + break; + } + else { + rrd_set_error("line %d: found unexpected tag: %s", + xmlTextReaderGetParserLineNumber(reader),element); + status = -1; + } } - + xmlFree(element); if (status != 0) - break; - } /* for (child = node->xmlChildrenNode) */ - + break; + } return (status); } /* int parse_tag_rra_database */ @@ -282,202 +427,146 @@ static int parse_tag_rra_database( * Parse the block within an RRA definition */ static int parse_tag_rra_cdp_prep_ds_history( - xmlDoc * doc, - xmlNode * node, + xmlTextReaderPtr reader, cdp_prep_t *cdp_prep) { /* Make `history_buffer' the same size as the scratch area, plus the * terminating NULL byte. */ - char history_buffer[sizeof(((cdp_prep_t *)0)->scratch) + 1]; + xmlChar *history; char *history_ptr; - int status; int i; - - status = get_string_from_node(doc, node, - history_buffer, sizeof(history_buffer)); - if (status != 0) - return (-1); - - history_ptr = (char *) (&cdp_prep->scratch[0]); - for (i = 0; history_buffer[i] != '\0'; i++) - history_ptr[i] = (history_buffer[i] == '1') ? 1 : 0; - - return (0); -} /* int parse_tag_rra_cdp_prep_ds_history */ + if ((history = get_xml_text(reader)) != NULL){ + history_ptr = (char *) (&cdp_prep->scratch[0]); + for (i = 0; history[i] != '\0'; i++) + history_ptr[i] = (history[i] == '1') ? 1 : 0; + xmlFree(history); + return 0; + } + return -1; +} /* int parse_tag_rra_cdp_prep_ds_history */ static int parse_tag_rra_cdp_prep_ds( - xmlDoc * doc, - xmlNode * node, + xmlTextReaderPtr reader, rrd_t *rrd, cdp_prep_t *cdp_prep) { - xmlNode *child; int status; - + xmlChar *element; memset(cdp_prep, '\0', sizeof(cdp_prep_t)); - status = 0; - for (child = node->xmlChildrenNode; child != NULL; child = child->next) { - if ((xmlStrcmp(child->name, (const xmlChar *) "comment") == 0) - || (xmlStrcmp(child->name, (const xmlChar *) "text") == 0)) - /* ignore */ ; - else if (xmlStrcmp(child->name, (const xmlChar *) "primary_value") == - 0) + status = -1; + + 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; + } + + while ((element = get_xml_element(reader)) != NULL){ + if (xmlStrcasecmp(element, (const xmlChar *) "primary_value") == 0) status = - get_double_from_node(doc, child, - &cdp_prep->scratch[CDP_primary_val]. - u_val); - else if (xmlStrcmp(child->name, (const xmlChar *) "secondary_value") - == 0) + get_xml_double(reader,&cdp_prep->scratch[CDP_primary_val].u_val); + else if (xmlStrcasecmp(element, (const xmlChar *) "secondary_value") == 0) status = - get_double_from_node(doc, child, - &cdp_prep->scratch[CDP_secondary_val]. - u_val); - else if (xmlStrcmp(child->name, (const xmlChar *) "intercept") == 0) - status = get_double_from_node(doc, child, + get_xml_double(reader,&cdp_prep->scratch[CDP_secondary_val].u_val); + else if (xmlStrcasecmp(element, (const xmlChar *) "intercept") == 0) + status = get_xml_double(reader, &cdp_prep-> scratch[CDP_hw_intercept].u_val); - else if (xmlStrcmp(child->name, (const xmlChar *) "last_intercept") == + else if (xmlStrcasecmp(element, (const xmlChar *) "last_intercept") == 0) status = - get_double_from_node(doc, child, + get_xml_double(reader, &cdp_prep-> scratch[CDP_hw_last_intercept].u_val); - else if (xmlStrcmp(child->name, (const xmlChar *) "slope") == 0) - status = get_double_from_node(doc, child, - &cdp_prep->scratch[CDP_hw_slope]. - u_val); - else if (xmlStrcmp(child->name, (const xmlChar *) "last_slope") == 0) - status = get_double_from_node(doc, child, - &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-> - scratch[CDP_null_count].u_cnt); - else if (xmlStrcmp(child->name, (const xmlChar *) "last_nan_count") == + else if (xmlStrcasecmp(element, (const xmlChar *) "slope") == 0) + status = get_xml_double(reader, + &cdp_prep->scratch[CDP_hw_slope]. + u_val); + else if (xmlStrcasecmp(element, (const xmlChar *) "last_slope") == 0) + status = get_xml_double(reader, + &cdp_prep-> + scratch[CDP_hw_last_slope].u_val); + else if (xmlStrcasecmp(element, (const xmlChar *) "nan_count") == 0) + status = get_xml_ulong(reader, + &cdp_prep-> + scratch[CDP_null_count].u_cnt); + else if (xmlStrcasecmp(element, (const xmlChar *) "last_nan_count") == 0) status = - get_int_from_node(doc, child, - (int *) &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, - &cdp_prep->scratch[CDP_hw_seasonal]. - u_val); - else if (xmlStrcmp(child->name, (const xmlChar *) "last_seasonal") == + get_xml_ulong(reader, + &cdp_prep-> + scratch[CDP_last_null_count].u_cnt); + else if (xmlStrcasecmp(element, (const xmlChar *) "seasonal") == 0) + status = get_xml_double(reader, + &cdp_prep->scratch[CDP_hw_seasonal]. + u_val); + else if (xmlStrcasecmp(element, (const xmlChar *) "last_seasonal") == 0) status = - get_double_from_node(doc, child, + get_xml_double(reader, &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-> + else if (xmlStrcasecmp(element, (const xmlChar *) "init_flag") == 0) + status = get_xml_ulong(reader, + &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); - else if (xmlStrcmp(child->name, (const xmlChar *) "value") == 0) - status = get_double_from_node(doc, child, - &cdp_prep->scratch[CDP_val].u_val); - else if (xmlStrcmp(child->name, + else if (xmlStrcasecmp(element, (const xmlChar *) "history") == 0) + status = parse_tag_rra_cdp_prep_ds_history(reader, cdp_prep); + else if (xmlStrcasecmp(element, (const xmlChar *) "value") == 0) + status = get_xml_double(reader, + &cdp_prep->scratch[CDP_val].u_val); + else if (xmlStrcasecmp(element, (const xmlChar *) "unknown_datapoints") == 0) - status = get_int_from_node(doc, child, - (int *) &cdp_prep-> + status = get_xml_ulong(reader, + &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 if (xmlStrcasecmp(element, + (const xmlChar *) "/ds") == 0){ + xmlFree(element); + break; + } else { rrd_set_error("parse_tag_rra_cdp_prep: Unknown tag: %s", - child->name); + element); status = -1; + xmlFree(element); + break; } - + if (status != 0){ + xmlFree(element); + break; + } + status = expect_element_end(reader,(char *)element); + xmlFree(element); if (status != 0) break; - } - + } return (status); } /* int parse_tag_rra_cdp_prep_ds */ static int parse_tag_rra_cdp_prep( - xmlDoc * doc, - xmlNode * node, + xmlTextReaderPtr reader, rrd_t *rrd, cdp_prep_t *cdp_prep) { - xmlNode *child; int status; - unsigned int ds_count = 0; + unsigned int ds_count; status = 0; - for (child = node->xmlChildrenNode; child != NULL; child = child->next) { - if ((xmlStrcmp(child->name, (const xmlChar *) "comment") == 0) - || (xmlStrcmp(child->name, (const xmlChar *) "text") == 0)) - /* ignore */ ; - else if (xmlStrcmp(child->name, (const xmlChar *) "ds") == 0) { - if (ds_count >= rrd->stat_head->ds_cnt) - status = -1; - else { - status = parse_tag_rra_cdp_prep_ds(doc, child, rrd, - cdp_prep + ds_count); - ds_count++; - } + for ( ds_count = 0; ds_count < rrd->stat_head->ds_cnt;ds_count++){ + if (expect_element(reader,"ds") == 0) { + status = parse_tag_rra_cdp_prep_ds(reader, rrd, + cdp_prep + ds_count); + if (status != 0) + break; } else { - rrd_set_error("parse_tag_rra_cdp_prep: Unknown tag: %s", - child->name); - status = -1; - } - - if (status != 0) + status = -1; break; + } } - - if (ds_count != rrd->stat_head->ds_cnt) { - rrd_set_error("parse_tag_rra_cdp_prep: There are %i data sources in " - "the RRD file, but %i in this cdp_prep block!", - (int) rrd->stat_head->ds_cnt, ds_count); - status = -1; - } - + if (status == 0) + status = expect_element(reader,"/cdp_prep"); return (status); } /* int parse_tag_rra_cdp_prep */ @@ -485,50 +574,46 @@ static int parse_tag_rra_cdp_prep( * Parse the block within an RRA definition */ static int parse_tag_rra_params( - xmlDoc * doc, - xmlNode * node, + xmlTextReaderPtr reader, rra_def_t *rra_def) { - xmlNode *child; + xmlChar *element; int status; - status = 0; - for (child = node->xmlChildrenNode; child != NULL; child = child->next) { - if ((xmlStrcmp(child->name, (const xmlChar *) "comment") == 0) - || (xmlStrcmp(child->name, (const xmlChar *) "text") == 0)) - /* ignore */ ; + status = -1; + while ((element = get_xml_element(reader)) != NULL){ /* * Parameters for CF_HWPREDICT */ - else if (xmlStrcmp(child->name, (const xmlChar *) "hw_alpha") == 0) - status = get_double_from_node(doc, child, + if (xmlStrcasecmp(element, (const xmlChar *) "hw_alpha") == 0) + status = get_xml_double(reader, &rra_def->par[RRA_hw_alpha].u_val); - else if (xmlStrcmp(child->name, (const xmlChar *) "hw_beta") == 0) - status = get_double_from_node(doc, child, + else if (xmlStrcasecmp(element, (const xmlChar *) "hw_beta") == 0) + status = get_xml_double(reader, &rra_def->par[RRA_hw_beta].u_val); - else if (xmlStrcmp(child->name, + else if (xmlStrcasecmp(element, (const xmlChar *) "dependent_rra_idx") == 0) - status = get_int_from_node(doc, child, - (int *) &rra_def-> + status = get_xml_ulong(reader, + &rra_def-> par[RRA_dependent_rra_idx].u_cnt); /* * Parameters for CF_SEASONAL and CF_DEVSEASONAL */ - else if (xmlStrcmp(child->name, (const xmlChar *) "seasonal_gamma") == + else if (xmlStrcasecmp(element, (const xmlChar *) "seasonal_gamma") == 0) status = - get_double_from_node(doc, child, + get_xml_double(reader, &rra_def->par[RRA_seasonal_gamma].u_val); - else if (xmlStrcmp - (child->name, (const xmlChar *) "seasonal_smooth_idx") == 0) + else if (xmlStrcasecmp + (element, (const xmlChar *) "seasonal_smooth_idx") == 0) status = - get_int_from_node(doc, child, - (int *) &rra_def-> + get_xml_ulong(reader, + &rra_def-> par[RRA_seasonal_smooth_idx].u_cnt); - else if (xmlStrcmp(child->name, (const xmlChar *) "smoothing_window") + else if (xmlStrcasecmp(element, (const xmlChar *) "smoothing_window") == 0) status = - get_double_from_node(doc, child, + get_xml_double(reader, &rra_def-> par[RRA_seasonal_smoothing_window]. u_val); @@ -536,75 +621,73 @@ static int parse_tag_rra_params( /* * Parameters for CF_FAILURES */ - else if (xmlStrcmp(child->name, (const xmlChar *) "delta_pos") == 0) - status = get_double_from_node(doc, child, + else if (xmlStrcasecmp(element, (const xmlChar *) "delta_pos") == 0) + status = get_xml_double(reader, &rra_def->par[RRA_delta_pos].u_val); - else if (xmlStrcmp(child->name, (const xmlChar *) "delta_neg") == 0) - status = get_double_from_node(doc, child, + else if (xmlStrcasecmp(element, (const xmlChar *) "delta_neg") == 0) + status = get_xml_double(reader, &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]. + else if (xmlStrcasecmp(element, (const xmlChar *) "window_len") == 0) + status = get_xml_ulong(reader, + &rra_def->par[RRA_window_len]. u_cnt); - else if (xmlStrcmp(child->name, (const xmlChar *) "failure_threshold") + else if (xmlStrcasecmp(element, (const xmlChar *) "failure_threshold") == 0) status = - get_int_from_node(doc, child, - (int *) &rra_def-> + get_xml_ulong(reader, + &rra_def-> par[RRA_failure_threshold].u_cnt); /* * Parameters for CF_AVERAGE, CF_MAXIMUM, CF_MINIMUM, and CF_LAST */ - else if (xmlStrcmp(child->name, (const xmlChar *) "xff") == 0) - status = get_double_from_node(doc, child, + else if (xmlStrcasecmp(element, (const xmlChar *) "xff") == 0) + status = get_xml_double(reader, &rra_def->par[RRA_cdp_xff_val]. u_val); /* * Compatibility code for 1.0.49 */ - else if (xmlStrcmp(child->name, (const xmlChar *) "value") == 0) { /* {{{ */ + else if (xmlStrcasecmp(element, (const xmlChar *) "value") == 0) { /* {{{ */ unsigned int i = 0; - while (42) { - if (i >= ARRAY_LENGTH(rra_def->par)) { - status = -1; - break; - } - + for (i=0;ipar);i++){ 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_xml_ulong(reader, + &rra_def->par[i]. u_cnt); else - status = get_double_from_node(doc, child, + status = get_xml_double(reader, &rra_def->par[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++; + if ( i-1 < ARRAY_LENGTH(rra_def->par)){ + status = expect_element(reader,"/value"); + if (status == 0){ + status = expect_element(reader,"value"); + } + } + if (status != 0){ + break; + } } - } /* }}} */ + } /* }}} */ + else if (xmlStrcasecmp(element,(const xmlChar *) "/params") == 0){ + xmlFree(element); + return status; + } /* }}} */ else { - rrd_set_error("parse_tag_rra_params: Unknown tag: %s", - child->name); + rrd_set_error("line %d: parse_tag_rra_params: Unknown tag: %s", + xmlTextReaderGetParserLineNumber(reader),element); status = -1; } - + status = expect_element_end(reader,(char *)element); + xmlFree(element); if (status != 0) break; } - return (status); } /* int parse_tag_rra_params */ @@ -612,35 +695,33 @@ static int parse_tag_rra_params( * Parse an RRA definition */ static int parse_tag_rra_cf( - xmlDoc * doc, - xmlNode * node, + xmlTextReaderPtr reader, rra_def_t *rra_def) { int status; - status = get_string_from_node(doc, node, + status = get_xml_string(reader, rra_def->cf_nam, sizeof(rra_def->cf_nam)); if (status != 0) - return (-1); + return status; status = cf_conv(rra_def->cf_nam); if (status == -1) { rrd_set_error("parse_tag_rra_cf: Unknown consolidation function: %s", rra_def->cf_nam); - return (-1); + return -1; } - return (0); + return 0; } /* int parse_tag_rra_cf */ static int parse_tag_rra( - xmlDoc * doc, - xmlNode * node, + xmlTextReaderPtr reader, rrd_t *rrd) { - xmlNode *child; int status; - + xmlChar *element; + rra_def_t *cur_rra_def; cdp_prep_t *cur_cdp_prep; rra_ptr_t *cur_rra_ptr; @@ -699,32 +780,63 @@ static int parse_tag_rra( rrd->stat_head->rra_cnt++; status = 0; - for (child = node->xmlChildrenNode; child != NULL; child = child->next) { - if ((xmlStrcmp(child->name, (const xmlChar *) "comment") == 0) - || (xmlStrcmp(child->name, (const xmlChar *) "text") == 0)) - /* ignore */ ; - 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 = 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); - else if (xmlStrcmp(child->name, (const xmlChar *) "database") == 0) - status = parse_tag_rra_database(doc, child, rrd); - else { - rrd_set_error("parse_tag_rra: Unknown tag: %s", child->name); - status = -1; + while ((element = get_xml_element(reader)) != NULL){ + if (xmlStrcasecmp(element, (const xmlChar *) "cf") == 0) + status = parse_tag_rra_cf(reader, cur_rra_def); + else if (xmlStrcasecmp(element, (const xmlChar *) "pdp_per_row") == 0) + status = get_xml_ulong(reader, + &cur_rra_def->pdp_cnt); + else if (atoi(rrd->stat_head->version) == 1 + && xmlStrcasecmp(element, (const xmlChar *) "xff") == 0) + status = get_xml_double(reader, + (double *) &cur_rra_def-> + par[RRA_cdp_xff_val].u_val); + else if (atoi(rrd->stat_head->version) >= 2 + && xmlStrcasecmp(element, (const xmlChar *) "params") == 0){ + xmlFree(element); + status = parse_tag_rra_params(reader, cur_rra_def); + if (status == 0) + continue; + else + return status; } - - if (status != 0) - break; - } - - /* Set the RRA pointer to the last value in the archive */ - cur_rra_ptr->cur_row = cur_rra_def->row_cnt - 1; + else if (xmlStrcasecmp(element, (const xmlChar *) "cdp_prep") == 0){ + xmlFree(element); + status = parse_tag_rra_cdp_prep(reader, rrd, cur_cdp_prep); + if (status == 0) + continue; + else + return status; + } + else if (xmlStrcasecmp(element, (const xmlChar *) "database") == 0){ + xmlFree(element); + status = parse_tag_rra_database(reader, rrd); + if (status == 0) + continue; + else + return status; + } + else if (xmlStrcasecmp(element,(const xmlChar *) "/rra") == 0){ + xmlFree(element); + return status; + } /* }}} */ + else { + rrd_set_error("line %d: parse_tag_rra: Unknown tag: %s", + xmlTextReaderGetParserLineNumber(reader), element); + status = -1; + } + if (status != 0) { + xmlFree(element); + return status; + } + status = expect_element_end(reader,(char *)element); + xmlFree(element); + if (status != 0) { + return status; + } + } + /* 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 */ @@ -733,54 +845,54 @@ static int parse_tag_rra( * Parse a DS definition */ static int parse_tag_ds_cdef( - xmlDoc * doc, - xmlNode * node, + xmlTextReaderPtr reader, rrd_t *rrd) { - char buffer[1024]; - int status; - - status = get_string_from_node(doc, node, buffer, sizeof(buffer)); - if (status != 0) - return (-1); - - /* We're always working on the last DS that has been added to the structure - * when we get here */ - parseCDEF_DS(buffer, rrd, rrd->stat_head->ds_cnt - 1); - - return (0); + xmlChar *cdef; + + cdef = get_xml_text(reader); + if (cdef != NULL){ + /* We're always working on the last DS that has been added to the structure + * when we get here */ + parseCDEF_DS((char *)cdef, rrd, rrd->stat_head->ds_cnt - 1); + xmlFree(cdef); + if (rrd_test_error()) + return -1; + else + return 0; + } + return -1; } /* int parse_tag_ds_cdef */ static int parse_tag_ds_type( - xmlDoc * doc, - xmlNode * node, + xmlTextReaderPtr reader, ds_def_t *ds_def) { - int status; - - status = get_string_from_node(doc, node, - ds_def->dst, sizeof(ds_def->dst)); - if (status != 0) - return (-1); - - status = dst_conv(ds_def->dst); - if (status == -1) { - rrd_set_error("parse_tag_ds_type: Unknown data source type: %s", - ds_def->dst); - return (-1); + char *dst; + dst = (char *)get_xml_text(reader); + if (dst != NULL){ + int status; + status = dst_conv(dst); + if (status == -1) { + rrd_set_error("parse_tag_ds_type: Unknown data source type: %s", + dst); + return -1; + } + strncpy(ds_def->dst,dst,sizeof(ds_def->dst)-1); + ds_def->dst[sizeof(ds_def->dst)-1] = '\0'; + xmlFree(dst); + return 0; } - - return (0); + return -1; } /* int parse_tag_ds_type */ static int parse_tag_ds( - xmlDoc * doc, - xmlNode * node, + xmlTextReaderPtr reader, rrd_t *rrd) { - xmlNode *child; int status; - + xmlChar *element; + ds_def_t *cur_ds_def; pdp_prep_t *cur_pdp_prep; @@ -831,50 +943,55 @@ static int parse_tag_ds( rrd->stat_head->ds_cnt++; status = 0; - for (child = node->xmlChildrenNode; child != NULL; child = child->next) { - if ((xmlStrcmp(child->name, (const xmlChar *) "comment") == 0) - || (xmlStrcmp(child->name, (const xmlChar *) "text") == 0)) - /* ignore */ ; - else if (xmlStrcmp(child->name, (const xmlChar *) "name") == 0) - status = get_string_from_node(doc, child, - cur_ds_def->ds_nam, - sizeof(cur_ds_def->ds_nam)); - else if (xmlStrcmp(child->name, (const xmlChar *) "type") == 0) - status = parse_tag_ds_type(doc, child, cur_ds_def); - else if (xmlStrcmp(child->name, + while ((element = get_xml_element(reader)) != NULL){ + if (xmlStrcasecmp(element, (const xmlChar *) "name") == 0){ + status = get_xml_string(reader,cur_ds_def->ds_nam,sizeof(cur_ds_def->ds_nam)); + } + else if (xmlStrcasecmp(element, (const xmlChar *) "type") == 0) + status = parse_tag_ds_type(reader, cur_ds_def); + else if (xmlStrcasecmp(element, (const xmlChar *) "minimal_heartbeat") == 0) - status = get_int_from_node(doc, child, - (int *) &cur_ds_def->par[DS_mrhb_cnt]. + status = get_xml_ulong(reader, + &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, + else if (xmlStrcasecmp(element, (const xmlChar *) "min") == 0) + status = get_xml_double(reader, &cur_ds_def->par[DS_min_val].u_val); - else if (xmlStrcmp(child->name, (const xmlChar *) "max") == 0) - status = get_double_from_node(doc, child, + else if (xmlStrcasecmp(element, (const xmlChar *) "max") == 0) + status = get_xml_double(reader, &cur_ds_def->par[DS_max_val].u_val); - else if (xmlStrcmp(child->name, (const xmlChar *) "cdef") == 0) - status = parse_tag_ds_cdef(doc, child, rrd); - else if (xmlStrcmp(child->name, (const xmlChar *) "last_ds") == 0) - status = get_string_from_node(doc, child, + else if (xmlStrcasecmp(element, (const xmlChar *) "cdef") == 0) + status = parse_tag_ds_cdef(reader, rrd); + else if (xmlStrcasecmp(element, (const xmlChar *) "last_ds") == 0) + status = get_xml_string(reader, cur_pdp_prep->last_ds, sizeof(cur_pdp_prep->last_ds)); - else if (xmlStrcmp(child->name, (const xmlChar *) "value") == 0) - status = get_double_from_node(doc, child, + else if (xmlStrcasecmp(element, (const xmlChar *) "value") == 0) + status = get_xml_double(reader, &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-> + else if (xmlStrcasecmp(element, (const xmlChar *) "unknown_sec") == 0) + status = get_xml_ulong(reader, + &cur_pdp_prep-> scratch[PDP_unkn_sec_cnt].u_cnt); + else if (xmlStrcasecmp(element, (const xmlChar *) "/ds") == 0) { + xmlFree(element); + break; + } else { - rrd_set_error("parse_tag_ds: Unknown tag: %s", child->name); + rrd_set_error("parse_tag_ds: Unknown tag: %s", element); status = -1; + } + if (status != 0) { + xmlFree(element); + break; } - + status = expect_element_end(reader,(char *)element); + xmlFree(element); if (status != 0) - break; + break; } - + return (status); } /* int parse_tag_ds */ @@ -882,77 +999,100 @@ static int parse_tag_ds( * Parse root nodes */ static int parse_tag_rrd( - xmlDoc * doc, - xmlNode * node, + xmlTextReaderPtr reader, rrd_t *rrd) { - xmlNode *child; int status; - + xmlChar *element; + status = 0; - for (child = node->xmlChildrenNode; child != NULL; child = child->next) { - if ((xmlStrcmp(child->name, (const xmlChar *) "comment") == 0) - || (xmlStrcmp(child->name, (const xmlChar *) "text") == 0)) - /* ignore */ ; - else if (xmlStrcmp(child->name, (const xmlChar *) "version") == 0) - status = get_string_from_node(doc, child, + while ((element = get_xml_element(reader)) != NULL ){ + if (xmlStrcasecmp(element, (const xmlChar *) "version") == 0) + status = get_xml_string(reader, 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); - else if (xmlStrcmp(child->name, (const xmlChar *) "lastupdate") == 0) - status = get_int_from_node(doc, child, - (int *) &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) - status = parse_tag_rra(doc, child, rrd); + else if (xmlStrcasecmp(element, (const xmlChar *) "step") == 0) + status = get_xml_ulong(reader, + &rrd->stat_head->pdp_step); + else if (xmlStrcasecmp(element, (const xmlChar *) "lastupdate") == 0) { +#ifdef TIME_T_IS_LONG + status = get_xml_long(reader, &rrd->live_head->last_up); +#else +#ifdef TIME_T_IS_LONG_LONG + status = get_xml_llong(reader, &rrd->live_head->last_up); +#else + if (sizeof(time_t) == sizeof(long)) { + status = get_xml_long(reader, + (long *)&rrd->live_head->last_up); + } + else if (sizeof(time_t) == sizeof(long long)) { + status = get_xml_llong(reader, + (long long *)&rrd->live_head->last_up); + } +#endif +#endif + } + else if (xmlStrcasecmp(element, (const xmlChar *) "ds") == 0){ + xmlFree(element); + status = parse_tag_ds(reader, rrd); + /* as we come back the tag is already gone */ + if (status == 0) + continue; + else + return status; + } + else if (xmlStrcasecmp(element, (const xmlChar *) "rra") == 0){ + xmlFree(element); + status = parse_tag_rra(reader, rrd); + if (status == 0) + continue; + else + return status; + } + else if (xmlStrcasecmp(element, (const xmlChar *) "/rrd") == 0) { + xmlFree(element); + return status; + } else { - rrd_set_error("parse_tag_rrd: Unknown tag: %s", child->name); + rrd_set_error("parse_tag_rrd: Unknown tag: %s", element); status = -1; } - if (status != 0) + if (status != 0){ + xmlFree(element); break; + } + status = expect_element_end(reader,(char *)element); + xmlFree(element); + if (status != 0) + break; } - return (status); } /* int parse_tag_rrd */ static rrd_t *parse_file( const char *filename) { - xmlDoc *doc; - xmlNode *cur; + xmlTextReaderPtr reader; int status; rrd_t *rrd; - doc = xmlParseFile(filename); - if (doc == NULL) { - rrd_set_error("Document not parsed successfully."); - return (NULL); - } - - cur = xmlDocGetRootElement(doc); - if (cur == NULL) { - rrd_set_error("Document is empty."); - xmlFreeDoc(doc); + reader = xmlNewTextReaderFilename(filename); + if (reader == NULL) { + rrd_set_error("Could not create xml reader for: %s",filename); return (NULL); } - if (xmlStrcmp(cur->name, (const xmlChar *) "rrd") != 0) { - rrd_set_error - ("Document of the wrong type, root node is not \"rrd\"."); - xmlFreeDoc(doc); + if (expect_element(reader,"rrd") != 0) { + xmlFreeTextReader(reader); return (NULL); } rrd = (rrd_t *) malloc(sizeof(rrd_t)); if (rrd == NULL) { rrd_set_error("parse_file: malloc failed."); - xmlFreeDoc(doc); + xmlFreeTextReader(reader); return (NULL); } memset(rrd, '\0', sizeof(rrd_t)); @@ -960,7 +1100,7 @@ static rrd_t *parse_file( rrd->stat_head = (stat_head_t *) malloc(sizeof(stat_head_t)); if (rrd->stat_head == NULL) { rrd_set_error("parse_tag_rrd: malloc failed."); - xmlFreeDoc(doc); + xmlFreeTextReader(reader); free(rrd); return (NULL); } @@ -972,18 +1112,19 @@ static rrd_t *parse_file( rrd->live_head = (live_head_t *) malloc(sizeof(live_head_t)); if (rrd->live_head == NULL) { rrd_set_error("parse_tag_rrd: malloc failed."); - xmlFreeDoc(doc); + xmlFreeTextReader(reader); free(rrd->stat_head); free(rrd); return (NULL); } memset(rrd->live_head, '\0', sizeof(live_head_t)); - status = parse_tag_rrd(doc, cur, rrd); + status = parse_tag_rrd(reader, rrd); + + xmlFreeTextReader(reader); - xmlFreeDoc(doc); if (status != 0) { - rrd_free(rrd); + local_rrd_free(rrd); rrd = NULL; } @@ -996,7 +1137,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; @@ -1025,7 +1166,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); @@ -1036,11 +1180,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 + rra_offset * ds_cnt, + sizeof(rrd_value_t), (num_rows - 1 - cur_row) * ds_cnt, fh); - fwrite(rrd->rrd_value, sizeof(rrd_value_t), value_count, fh); + rra_offset += num_rows; + } /* lets see if we had an error */ if (ferror(fh)) { @@ -1103,13 +1257,14 @@ int rrd_restore( rrd = parse_file(argv[optind]); if (rrd == NULL) return (-1); - + if (write_file(argv[optind + 1], rrd) != 0) { - rrd_free(rrd); + local_rrd_free(rrd); return (-1); } + local_rrd_free(rrd); + - rrd_free(rrd); return (0); } /* int rrd_restore */