From: oetiker Date: Sat, 15 Mar 2008 10:39:48 +0000 (+0000) Subject: reindent X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=9dba554e59319d13076a8184c7889cca868b4c85;p=rrdtool.git reindent aded id keyword substitution git-svn-id: svn://svn.oetiker.ch/rrdtool/trunk/program@1306 a5681a0c-68f1-0310-ab6d-d61299d08faa --- diff --git a/configure.ac b/configure.ac index 93b2794..f92c559 100644 --- a/configure.ac +++ b/configure.ac @@ -612,6 +612,7 @@ EX_CHECK_ALL(cairo, cairo_pdf_surface_create, cairo-pdf.h, EX_CHECK_ALL(cairo, cairo_ps_surface_create, cairo-ps.h, cairo-ps, 1.4.6, http://cairographics.org/releases/, "") dnl EX_CHECK_ALL(glib-2.0, glib_check_version, glib.h, glib-2.0, 2.12.12, ftp://ftp.gtk.org/pub/glib/2.12/, "") EX_CHECK_ALL(pango-1.0, pango_cairo_context_set_font_options, pango/pango.h, pangocairo, 1.17, http://ftp.gnome.org/pub/GNOME/sources/pango/1.17, "") +EX_CHECK_ALL(xml2, xmlParseFile, libxml/parser.h, xml2, 2.6.31, http://xmlsoft.org/downloads.html, /usr/include/libxml2) if test "$EX_CHECK_ALL_ERR" = "YES"; then AC_MSG_ERROR([Please fix the library issues listed above and try again.]) diff --git a/doc/rrdbuild.pod b/doc/rrdbuild.pod index 64df754..5fe138d 100644 --- a/doc/rrdbuild.pod +++ b/doc/rrdbuild.pod @@ -239,6 +239,16 @@ config file. $MAKE $MAKE install +=item Building LibXML2 + + cd $BUILD_DIR + wget http://oss.oetiker.ch/rrdtool/pub/libs/libxml2-sources-2.6.31.tar.gz + gunzip -c libxml2-sources-2.6.31.tar.gz | tar xf - + cd libxml2-sources-2.6.31 + ./configure --prefix=$INSTALL_DIR CFLAGS="-O3 -fPIC" + $MAKE + $MAKE install + =back Now all the dependent libraries are built and you can try again. This time diff --git a/src/rrd_graph.c b/src/rrd_graph.c index 56f509a..6e1154a 100644 --- a/src/rrd_graph.c +++ b/src/rrd_graph.c @@ -3345,38 +3345,36 @@ int graph_paint( switch (im->gdes[i].gf) { case GF_HRULE: if (im->gdes[i].yrule >= im->minval - && im->gdes[i].yrule <= im->maxval) - { + && im->gdes[i].yrule <= im->maxval) { cairo_save(im->cr); - if (im->gdes[i].dash) { - cairo_set_dash(im->cr, im->gdes[i].p_dashes, - im->gdes[i].ndash, im->gdes[i].offset); + if (im->gdes[i].dash) { + cairo_set_dash(im->cr, im->gdes[i].p_dashes, + im->gdes[i].ndash, im->gdes[i].offset); + } + gfx_line(im, + im->xorigin, ytr(im, im->gdes[i].yrule), + im->xorigin + im->xsize, ytr(im, + im->gdes[i].yrule), + 1.0, im->gdes[i].col); + cairo_stroke(im->cr); + cairo_restore(im->cr); } - gfx_line(im, - im->xorigin, ytr(im, im->gdes[i].yrule), - im->xorigin + im->xsize, ytr(im, - im->gdes[i].yrule), - 1.0, im->gdes[i].col); - cairo_stroke(im->cr); - cairo_restore(im->cr); - } break; case GF_VRULE: if (im->gdes[i].xrule >= im->start - && im->gdes[i].xrule <= im->end) - { + && im->gdes[i].xrule <= im->end) { cairo_save(im->cr); - if (im->gdes[i].dash) { - cairo_set_dash(im->cr, im->gdes[i].p_dashes, - im->gdes[i].ndash, im->gdes[i].offset); + if (im->gdes[i].dash) { + cairo_set_dash(im->cr, im->gdes[i].p_dashes, + im->gdes[i].ndash, im->gdes[i].offset); + } + gfx_line(im, + xtr(im, im->gdes[i].xrule), im->yorigin, + xtr(im, im->gdes[i].xrule), + im->yorigin - im->ysize, 1.0, im->gdes[i].col); + cairo_stroke(im->cr); + cairo_restore(im->cr); } - gfx_line(im, - xtr(im, im->gdes[i].xrule), im->yorigin, - xtr(im, im->gdes[i].xrule), - im->yorigin - im->ysize, 1.0, im->gdes[i].col); - cairo_stroke(im->cr); - cairo_restore(im->cr); - } break; default: break; diff --git a/src/rrd_restore.c b/src/rrd_restore.c index b2d1193..fa8493a 100644 --- a/src/rrd_restore.c +++ b/src/rrd_restore.c @@ -1,742 +1,1073 @@ /***************************************************************************** * RRDtool 1.2.99907080300 Copyright by Tobi Oetiker, 1997-2007 + * This file: Copyright 2008 Florian octo Forster + * Distributed under the GPL ***************************************************************************** - * rrd_restore.c creates new rrd from data dumped by rrd_dump.c - *****************************************************************************/ - -#include "rrd_tool.h" -#include "rrd_rpncalc.h" + * rrd_thread_safe.c Contains routines used when thread safety is required + ***************************************************************************** + * $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 > **/ +#include +#include +#include +#include +#include #include - #if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__CYGWIN32__) -#include -#define open _open -#define close _close +# 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 + */ + static int get_string_from_node( + xmlDoc * doc, + xmlNode * node, + char *buffer, + size_t buffer_size) +{ + xmlChar *temp0; + char *begin_ptr; + char *end_ptr; -/* Prototypes */ - -void xml_lc( - char *); -int skip( - char **); -int skipxml( - char **); -int eat_tag( - char **, - char *); -int read_tag( - char **, - char *, - char *, - void *); -int xml2rrd( - char *, - rrd_t *, - char); -int rrd_creat( - 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); -long int rra_random_row( - rra_def_t *); + temp0 = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); + if (temp0 == NULL) { + rrd_set_error("get_string_from_node: xmlNodeListGetString failed."); + return (-1); + } + + begin_ptr = (char *) temp0; + while ((begin_ptr[0] != 0) && (isspace(begin_ptr[0]))) + begin_ptr++; -/* convert all occurrences of to */ + if (begin_ptr[0] == 0) { + xmlFree(temp0); + buffer[0] = 0; + return (0); + } + + 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); -void xml_lc( - char *buf) + return (0); +} /* int get_string_from_node */ + +static int get_int_from_node( + xmlDoc * doc, + xmlNode * node, + int *value) { - int intag = 0; - - while ((*buf)) { - if (intag == 0 && (*buf) == '<') { - intag = 1; - } else if (intag == 1 && (*buf) == '>') { - intag = 0; - continue; - } else if (intag == 1) { - *buf = tolower(*buf); - } - buf++; + 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); } -} -int skipxml( - char **buf) + 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); + } + + *value = temp; + + return (0); +} /* int get_int_from_node */ + +static int get_double_from_node( + xmlDoc * doc, + xmlNode * node, + double *value) { - char *ptr; - - ptr = (*buf); - do { - (*buf) = ptr; - while ((*(ptr + 1)) - && ((*ptr) == ' ' || (*ptr) == '\r' || (*ptr) == '\n' - || (*ptr) == '\t')) - ptr++; - if (strncmp(ptr, ""); - if (ptr) - ptr += 2; - else { - rrd_set_error("Dangling XML header"); - (*buf) = NULL; - return -1; + double temp; + char *str_ptr; + char *end_ptr; + + str_ptr = (char *) xmlNodeListGetString(doc, node->xmlChildrenNode, 1); + if (str_ptr == NULL) { + rrd_set_error("get_double_from_node: xmlNodeListGetString failed."); + return (-1); + } + + end_ptr = NULL; + temp = strtod(str_ptr, &end_ptr); + xmlFree(str_ptr); + + if (str_ptr == end_ptr) { + rrd_set_error + ("get_double_from_node: Cannot parse buffer as double: %s", + str_ptr); + return (-1); + } + + *value = temp; + + return (0); +} /* int get_double_from_node */ + +static int value_check_range( + rrd_value_t *rrd_value, + const ds_def_t *ds_def) +{ + double min; + double max; + + if (opt_range_check == 0) + return (0); + + min = ds_def->par[DS_min_val].u_val; + max = ds_def->par[DS_max_val].u_val; + + if (((!isnan(min)) && (*rrd_value < min)) + || ((!isnan(max)) && (*rrd_value > max))) + *rrd_value = NAN; + + return (0); +} /* int value_check_range */ + +/* + * Parse the block within an RRA definition + */ +static int parse_tag_rra_database_row( + xmlDoc * doc, + xmlNode * node, + 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; } - } while ((*buf) != ptr); - return 1; -} -int skip( - char **buf) + 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); +} /* int parse_tag_rra_database_row */ + +static int parse_tag_rra_database( + xmlDoc * doc, + xmlNode * node, + rrd_t *rrd) { - char *ptr; - - if ((buf == NULL) || (*buf == NULL)) - return -1; - ptr = (*buf); - do { - (*buf) = ptr; - while ((*(ptr + 1)) - && ((*ptr) == ' ' || (*ptr) == '\r' || (*ptr) == '\n' - || (*ptr) == '\t')) - ptr++; - if (strncmp(ptr, ""); - if (ptr) - ptr += 3; - else { - rrd_set_error("Dangling Comment"); - (*buf) = NULL; - return -1; + rra_def_t *cur_rra_def; + unsigned int total_row_cnt; + xmlNode *child; + int status; + int i; + + total_row_cnt = 0; + for (i = 0; i < (((int) rrd->stat_head->rra_cnt) - 1); i++) + total_row_cnt += rrd->rra_def[i].row_cnt; + + 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); + + /* Allocate space for the new values.. */ + temp = (rrd_value_t *) realloc(rrd->rrd_value, + sizeof(rrd_value_t) * + total_values_count); + if (temp == NULL) { + rrd_set_error("parse_tag_rra_database: realloc failed."); + status = -1; + break; } + rrd->rrd_value = temp; + cur_rrd_value = rrd->rrd_value + + (rrd->stat_head->ds_cnt * total_row_cnt); + memset(cur_rrd_value, '\0', + sizeof(rrd_value_t) * rrd->stat_head->ds_cnt); + total_row_cnt++; + 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) */ + else { + rrd_set_error("parse_tag_rra_database: Unknown tag: %s", + child->name); + status = -1; } - } while ((*buf) != ptr); - return 1; -} -int eat_tag( - char **buf, - char *tag) + if (status != 0) + break; + } /* for (child = node->xmlChildrenNode) */ + + return (status); +} /* 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, + cdp_prep_t *cdp_prep) { - if ((*buf) == NULL) - return -1; /* fall though clause */ - - rrd_clear_error(); - skip(buf); - if ((**buf) == '<' - && strncmp((*buf) + 1, tag, strlen(tag)) == 0 - && *((*buf) + strlen(tag) + 1) == '>') { - (*buf) += strlen(tag) + 2; - } else { - rrd_set_error("No <%s> tag found", tag); - (*buf) = NULL; - return -1; - } - skip(buf); - return 1; -} - -int read_tag( - char **buf, - char *tag, - char *format, - void *value) + /* 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]; + 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 */ + +static int parse_tag_rra_cdp_prep_ds( + xmlDoc * doc, + xmlNode * node, + rrd_t *rrd, + cdp_prep_t *cdp_prep) { - char *end_tag; - int matches; - - if ((*buf) == NULL) - return -1; /* fall though clause */ - rrd_clear_error(); - if (eat_tag(buf, tag) == 1) { - char *temp; - - temp = (*buf); - while (*((*buf) + 1) && (*(*buf) != '<')) - (*buf)++; /*find start of endtag */ - *(*buf) = '\0'; - matches = sscanf(temp, format, value); - *(*buf) = '<'; - end_tag = malloc((strlen(tag) + 2) * sizeof(char)); - sprintf(end_tag, "/%s", tag); - eat_tag(buf, end_tag); - free(end_tag); - if (matches == 0 && strcmp(format, "%lf") == 0) - (*((double *) (value))) = DNAN; - if (matches != 1) - return 0; - return 1; + xmlNode *child; + int status; + + 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 = + get_double_from_node(doc, child, + &cdp_prep->scratch[CDP_primary_val]. + u_val); + else if (xmlStrcmp(child->name, (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, + &cdp_prep-> + scratch[CDP_hw_intercept].u_val); + else if (xmlStrcmp(child->name, (const xmlChar *) "last_intercept") == + 0) + status = + get_double_from_node(doc, child, + &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") == + 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") == + 0) + status = + get_double_from_node(doc, child, + &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-> + 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, + (const xmlChar *) "unknown_datapoints") == 0) + status = get_int_from_node(doc, child, + (int *) &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); + status = -1; + } + + if (status != 0) + break; } - return -1; -} + return (status); +} /* int parse_tag_rra_cdp_prep_ds */ -/* parse the data stored in buf and return a filled rrd structure */ -int xml2rrd( - char *buf, +static int parse_tag_rra_cdp_prep( + xmlDoc * doc, + xmlNode * node, rrd_t *rrd, - char rc) + cdp_prep_t *cdp_prep) { - /* 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; - ptr3 = buf; - /* start with an RRD tag */ - - skipxml(&ptr); - - eat_tag(&ptr, "rrd"); - /* allocate static header */ - if ((rrd->stat_head = calloc(1, sizeof(stat_head_t))) == NULL) { - rrd_set_error("allocating rrd.stat_head"); - return -1; - }; - - 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) || input_version < 1) { - rrd_set_error - ("Incompatible file version, detected version %s. This is not supported by the version %s restore tool.\n", - rrd->stat_head->version, RRD_VERSION); - free(rrd->stat_head); - rrd->stat_head = NULL; - return -1; - } - /* make sure we output the right version only go over 3 if input is over 3 too */ - if (input_version > 3) { - strcpy(rrd->stat_head->version, RRD_VERSION); - } else { - strcpy(rrd->stat_head->version, RRD_VERSION3); - } + xmlNode *child; + int status; + + unsigned int ds_count = 0; + + 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++; + } + } else { + rrd_set_error("parse_tag_rra_cdp_prep: Unknown tag: %s", + child->name); + status = -1; + } - rrd->stat_head->float_cookie = FLOAT_COOKIE; - rrd->stat_head->ds_cnt = 0; - rrd->stat_head->rra_cnt = 0; - read_tag(&ptr, "step", "%lu", &(rrd->stat_head->pdp_step)); - - /* allocate live head */ - if ((rrd->live_head = calloc(1, sizeof(live_head_t))) == NULL) { - rrd_set_error("allocating rrd.live_head"); - return -1; + if (status != 0) + break; } - read_tag(&ptr, "lastupdate", "%lu", &(rrd->live_head->last_up)); - - /* Data Source Definition Part */ - ptr2 = ptr; - while (eat_tag(&ptr2, "ds") == 1) { - rrd->stat_head->ds_cnt++; - if ((rrd->ds_def = - rrd_realloc(rrd->ds_def, - rrd->stat_head->ds_cnt * sizeof(ds_def_t))) == - NULL) { - rrd_set_error("allocating rrd.ds_def"); - return -1; - }; - /* clean out memory to make sure no data gets stored from previous tasks */ - memset(&(rrd->ds_def[rrd->stat_head->ds_cnt - 1]), 0, - sizeof(ds_def_t)); - if ((rrd->pdp_prep = - rrd_realloc(rrd->pdp_prep, - rrd->stat_head->ds_cnt * sizeof(pdp_prep_t))) == - NULL) { - rrd_set_error("allocating pdp_prep"); - return (-1); - } - /* clean out memory to make sure no data gets stored from previous tasks */ - memset(&(rrd->pdp_prep[rrd->stat_head->ds_cnt - 1]), 0, - sizeof(pdp_prep_t)); - - read_tag(&ptr2, "name", DS_NAM_FMT, - rrd->ds_def[rrd->stat_head->ds_cnt - 1].ds_nam); - - read_tag(&ptr2, "type", DST_FMT, - rrd->ds_def[rrd->stat_head->ds_cnt - 1].dst); - /* test for valid type */ - 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", "%1000s", buffer); - parseCDEF_DS(buffer, rrd, rrd->stat_head->ds_cnt - 1); - if (rrd_test_error()) - return -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[rrd->stat_head->ds_cnt - 1]. - scratch[PDP_unkn_sec_cnt].u_cnt)); - eat_tag(&ptr2, "/ds"); - ptr = ptr2; + 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; } - ptr2 = ptr; - while (eat_tag(&ptr2, "rra") == 1) { - rrd->stat_head->rra_cnt++; - - /* 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)); - - /* 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) { - rrd_set_error("allocating cdp_prep"); - return -1; - } + return (status); +} /* int parse_tag_rra_cdp_prep */ - memset(& - (rrd-> - cdp_prep[rrd->stat_head->ds_cnt * - (rrd->stat_head->rra_cnt - 1)]), 0, - rrd->stat_head->ds_cnt * sizeof(cdp_prep_t)); - - - read_tag(&ptr2, "cf", CF_NAM_FMT, - rrd->rra_def[rrd->stat_head->rra_cnt - 1].cf_nam); - /* test for valid type */ - 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)); - /* 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 { - if (eat_tag(&ptr2, "params") != 1) { - rrd_set_error("could not find params tag to eat and skip"); - return -1; - } - 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: - case CF_MHWPREDICT: - 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)); +/* + * Parse the block within an RRA definition + */ +static int parse_tag_rra_params( + xmlDoc * doc, + xmlNode * node, + rra_def_t *rra_def) +{ + 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 */ ; + /* + * Parameters for CF_HWPREDICT + */ + else if (xmlStrcmp(child->name, (const xmlChar *) "hw_alpha") == 0) + status = get_double_from_node(doc, child, + &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, + &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-> + par[RRA_dependent_rra_idx].u_cnt); + /* + * Parameters for CF_SEASONAL and CF_DEVSEASONAL + */ + else if (xmlStrcmp(child->name, (const xmlChar *) "seasonal_gamma") == + 0) + status = + get_double_from_node(doc, child, + &rra_def->par[RRA_seasonal_gamma].u_val); + else if (xmlStrcmp + (child->name, (const xmlChar *) "seasonal_smooth_idx") == 0) + status = + get_int_from_node(doc, child, + (int *) &rra_def-> + par[RRA_seasonal_smooth_idx].u_cnt); + else if (xmlStrcmp(child->name, (const xmlChar *) "smoothing_window") + == 0) + status = + get_double_from_node(doc, child, + &rra_def-> + par[RRA_seasonal_smoothing_window]. + u_val); + /* else if (dependent_rra_idx) ...; */ + /* + * Parameters for CF_FAILURES + */ + else if (xmlStrcmp(child->name, (const xmlChar *) "delta_pos") == 0) + status = get_double_from_node(doc, child, + &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, + &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]. + u_cnt); + else if (xmlStrcmp(child->name, (const xmlChar *) "failure_threshold") + == 0) + status = + get_int_from_node(doc, child, + (int *) &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, + &rra_def->par[RRA_cdp_xff_val]. + u_val); + /* + * Compatibility code for 1.0.49 + */ + else if (xmlStrcmp(child->name, (const xmlChar *) "value") == 0) { /* {{{ */ + unsigned int i = 0; + + while (42) { + if (i >= ARRAY_LENGTH(rra_def->par)) { + status = -1; 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)); - if (atoi(rrd->stat_head->version) >= 4) { - read_tag(&ptr2, "smoothing_window", "%lf", - &(rrd->rra_def[rra_index]. - par[RRA_seasonal_smoothing_window].u_val)); - } - read_tag(&ptr2, "dependent_rra_idx", "%lu", - &(rrd->rra_def[rra_index]. - par[RRA_dependent_rra_idx].u_cnt)); + } + + 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]. + u_cnt); + else + status = get_double_from_node(doc, child, + &rra_def->par[i].u_val); + + if (status != 0) 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)); + + /* 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; - 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)); - } + + child = child->next; + i++; } - eat_tag(&ptr2, "/params"); + } /* }}} */ + else { + rrd_set_error("parse_tag_rra_params: Unknown tag: %s", + child->name); + status = -1; } + if (status != 0) + break; + } - eat_tag(&ptr2, "cdp_prep"); - for (i = 0; i < (int) rrd->stat_head->ds_cnt; i++) { - if (eat_tag(&ptr2, "ds") != 1) { - rrd_set_error - ("expected to find %lu entries in ", - rrd->stat_head->ds_cnt); - return -1; - } - /* 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: - case CF_MHWPREDICT: - 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"); + return (status); +} /* int parse_tag_rra_params */ + +/* + * Parse an RRA definition + */ +static int parse_tag_rra_cf( + xmlDoc * doc, + xmlNode * node, + rra_def_t *rra_def) +{ + int status; + + status = get_string_from_node(doc, node, + rra_def->cf_nam, sizeof(rra_def->cf_nam)); + if (status != 0) + return (-1); + + 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 (0); +} /* int parse_tag_rra_cf */ + +static int parse_tag_rra( + xmlDoc * doc, + xmlNode * node, + rrd_t *rrd) +{ + xmlNode *child; + int status; + + rra_def_t *cur_rra_def; + cdp_prep_t *cur_cdp_prep; + rra_ptr_t *cur_rra_ptr; + + /* Allocate more rra_def space for this RRA */ + { /* {{{ */ + rra_def_t *temp; + + temp = (rra_def_t *) realloc(rrd->rra_def, + sizeof(rra_def_t) * + (rrd->stat_head->rra_cnt + 1)); + if (temp == NULL) { + rrd_set_error("parse_tag_rra: realloc failed."); + return (-1); } - eat_tag(&ptr2, "/cdp_prep"); - rrd->rra_def[rrd->stat_head->rra_cnt - 1].row_cnt = 0; - eat_tag(&ptr2, "database"); - ptr3 = ptr2; - while (eat_tag(&ptr3, "row") == 1) { - - if (mempool == 0) { - mempool = 1000; - if ((rrd->rrd_value = rrd_realloc(rrd->rrd_value, - (rows + - mempool) * - (rrd->stat_head->ds_cnt) - * sizeof(rrd_value_t))) == - NULL) { - rrd_set_error("allocating rrd_values"); - return -1; - } - } - rows++; - mempool--; - rrd->rra_def[rrd->stat_head->rra_cnt - 1].row_cnt++; - 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]); - - read_tag(&ptr3, "v", "%lf", value); - - if ((rc == 1) /* do we have to check for the ranges */ - &&(!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)) - || /* max defined and in the range ? */ - (!isnan(rrd->ds_def[i].par[DS_max_val].u_val) - && (*value > - rrd->ds_def[i].par[DS_max_val].u_val)) - ) - ) { - fprintf(stderr, - "out of range found [ds: %lu], [value : %0.10e]\n", - i, *value); - *value = DNAN; - } - } - eat_tag(&ptr3, "/row"); - ptr2 = ptr3; + rrd->rra_def = temp; + cur_rra_def = rrd->rra_def + rrd->stat_head->rra_cnt; + memset(cur_rra_def, '\0', sizeof(rra_def_t)); + } /* }}} */ + + /* allocate cdp_prep_t */ + { /* {{{ */ + cdp_prep_t *temp; + + temp = (cdp_prep_t *) realloc(rrd->cdp_prep, sizeof(cdp_prep_t) + * rrd->stat_head->ds_cnt + * (rrd->stat_head->rra_cnt + 1)); + if (temp == NULL) { + rrd_set_error("parse_tag_rra: realloc failed."); + return (-1); + } + rrd->cdp_prep = temp; + cur_cdp_prep = rrd->cdp_prep + + (rrd->stat_head->ds_cnt * rrd->stat_head->rra_cnt); + memset(cur_cdp_prep, '\0', + sizeof(cdp_prep_t) * rrd->stat_head->ds_cnt); + } /* }}} */ + + /* allocate rra_ptr_t */ + { /* {{{ */ + rra_ptr_t *temp; + + temp = (rra_ptr_t *) realloc(rrd->rra_ptr, + sizeof(rra_ptr_t) * + (rrd->stat_head->rra_cnt + 1)); + if (temp == NULL) { + rrd_set_error("parse_tag_rra: realloc failed."); + return (-1); + } + rrd->rra_ptr = temp; + cur_rra_ptr = rrd->rra_ptr + rrd->stat_head->rra_cnt; + memset(cur_rra_ptr, '\0', sizeof(rra_ptr_t)); + } /* }}} */ + + /* All space successfully allocated, increment number of RRAs. */ + 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; } - eat_tag(&ptr2, "/database"); - eat_tag(&ptr2, "/rra"); - ptr = ptr2; + + if (status != 0) + break; } - eat_tag(&ptr, "/rrd"); - if ((rrd->rra_ptr = - calloc(1, sizeof(rra_ptr_t) * rrd->stat_head->rra_cnt)) == NULL) { - rrd_set_error("allocating rra_ptr"); + /* Set the RRA pointer to the last value in the archive */ + cur_rra_ptr->cur_row = cur_rra_def->row_cnt - 1; + + return (status); +} /* int parse_tag_rra */ + +/* + * Parse a DS definition + */ +static int parse_tag_ds_cdef( + xmlDoc * doc, + xmlNode * node, + rrd_t *rrd) +{ + char buffer[1024]; + int status; + + status = get_string_from_node(doc, node, buffer, sizeof(buffer)); + if (status != 0) return (-1); - } - if (ptr == NULL) - return -1; - 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); +} /* int parse_tag_ds_cdef */ +static int parse_tag_ds_type( + xmlDoc * doc, + xmlNode * node, + 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); + } -/* create and empty rrd file according to the specs given */ + return (0); +} /* int parse_tag_ds_type */ -int rrd_creat( - char *file_name, - rrd_t *rrd, - char force_overwrite) +static int parse_tag_ds( + xmlDoc * doc, + xmlNode * node, + rrd_t *rrd) { - unsigned long i, ii, rra_offset; - FILE *rrd_file = NULL; - int fdflags; - int fd; - - if (strcmp("-", file_name) == 0) { - rrd_file = stdout; - } else { -#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; + xmlNode *child; + int status; + + ds_def_t *cur_ds_def; + pdp_prep_t *cur_pdp_prep; + + /* + * If there are DS definitions after RRA definitions the number of values, + * cdp_prep areas and so on will be calculated wrong. Thus, enforce a + * specific order in this case. + */ + if (rrd->stat_head->rra_cnt > 0) { + rrd_set_error("parse_tag_ds: All data source definitions MUST " + "precede the RRA definitions!"); + return (-1); + } + + /* Allocate space for the new DS definition */ + { /* {{{ */ + ds_def_t *temp; + + temp = (ds_def_t *) realloc(rrd->ds_def, + sizeof(ds_def_t) * + (rrd->stat_head->ds_cnt + 1)); + if (temp == NULL) { + rrd_set_error("parse_tag_ds: malloc failed."); + return (-1); } - 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); + rrd->ds_def = temp; + cur_ds_def = rrd->ds_def + rrd->stat_head->ds_cnt; + memset(cur_ds_def, '\0', sizeof(ds_def_t)); + } /* }}} */ + + /* Allocate pdp_prep space for the new DS definition */ + { /* {{{ */ + pdp_prep_t *temp; + + temp = (pdp_prep_t *) realloc(rrd->pdp_prep, + sizeof(pdp_prep_t) * + (rrd->stat_head->ds_cnt + 1)); + if (temp == NULL) { + rrd_set_error("parse_tag_ds: malloc failed."); return (-1); } + rrd->pdp_prep = temp; + cur_pdp_prep = rrd->pdp_prep + rrd->stat_head->ds_cnt; + memset(cur_pdp_prep, '\0', sizeof(pdp_prep_t)); + } /* }}} */ + + /* All allocations successful, let's increment the number of DSes. */ + 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, + (const xmlChar *) "minimal_heartbeat") == 0) + status = get_int_from_node(doc, child, + (int *) &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, + &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, + &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, + 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, + &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-> + scratch[PDP_unkn_sec_cnt].u_cnt); + else { + rrd_set_error("parse_tag_ds: Unknown tag: %s", child->name); + status = -1; + } + + if (status != 0) + break; } - fwrite(rrd->stat_head, sizeof(stat_head_t), 1, rrd_file); - fwrite(rrd->ds_def, sizeof(ds_def_t), rrd->stat_head->ds_cnt, rrd_file); + return (status); +} /* int parse_tag_ds */ - fwrite(rrd->rra_def, - sizeof(rra_def_t), rrd->stat_head->rra_cnt, rrd_file); +/* + * Parse root nodes + */ +static int parse_tag_rrd( + xmlDoc * doc, + xmlNode * node, + rrd_t *rrd) +{ + 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 *) "version") == 0) + status = get_string_from_node(doc, child, + 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 { + rrd_set_error("parse_tag_rrd: Unknown tag: %s", child->name); + status = -1; + } - fwrite(rrd->live_head, sizeof(live_head_t), 1, rrd_file); + if (status != 0) + break; + } - fwrite(rrd->pdp_prep, sizeof(pdp_prep_t), rrd->stat_head->ds_cnt, - rrd_file); + return (status); +} /* int parse_tag_rrd */ - fwrite(rrd->cdp_prep, sizeof(cdp_prep_t), rrd->stat_head->rra_cnt * - rrd->stat_head->ds_cnt, rrd_file); +static rrd_t *parse_file( + const char *filename) +{ + xmlDoc *doc; + xmlNode *cur; + int status; - for (i = 0; i < rrd->stat_head->rra_cnt; i++) - rrd->rra_ptr[i].cur_row = rra_random_row(&rrd->rra_def[i]); + 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); + 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); + return (NULL); + } + + rrd = (rrd_t *) malloc(sizeof(rrd_t)); + if (rrd == NULL) { + rrd_set_error("parse_file: malloc failed."); + xmlFreeDoc(doc); + return (NULL); + } + memset(rrd, '\0', sizeof(rrd_t)); + + 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); + free(rrd); + return (NULL); + } + memset(rrd->stat_head, '\0', sizeof(stat_head_t)); + + strncpy(rrd->stat_head->cookie, "RRD", sizeof(rrd->stat_head->cookie)); + rrd->stat_head->float_cookie = FLOAT_COOKIE; + + 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); + free(rrd->stat_head); + free(rrd); + return (NULL); + } + memset(rrd->live_head, '\0', sizeof(live_head_t)); + + status = parse_tag_rrd(doc, cur, rrd); - fwrite(rrd->rra_ptr, sizeof(rra_ptr_t), rrd->stat_head->rra_cnt, - rrd_file); + xmlFreeDoc(doc); + if (status != 0) { + rrd_free(rrd); + rrd = NULL; + } + return (rrd); +} /* rrd_t *parse_file */ - /* Dump RRD values */ - 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; +static int write_file( + const char *file_name, + rrd_t *rrd) +{ + FILE *fh; + unsigned int i; + unsigned int value_count; - fwrite(rrd->rrd_value + - (rra_offset + num_rows - 1 - cur_row) * ds_cnt, - sizeof(rrd_value_t), (cur_row + 1) * ds_cnt, rrd_file); + if (strcmp("-", file_name) == 0) + fh = stdout; + else { + int fd_flags = O_WRONLY | O_CREAT; + int fd; - fwrite(rrd->rrd_value + rra_offset * ds_cnt, - sizeof(rrd_value_t), (num_rows - 1 - cur_row) * ds_cnt, - rrd_file); +#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__CYGWIN32__) + fd_flags |= O_BINARY; +#endif + + if (opt_force_overwrite == 0) + fd_flags |= O_EXCL; + + fd = open(file_name, fd_flags, 0666); + if (fd == -1) { + rrd_set_error("creating '%s': %s", file_name, + rrd_strerror(errno)); + return (-1); + } - rra_offset += num_rows; + fh = fdopen(fd, "wb"); + if (fh == NULL) { + rrd_set_error("fdopen failed: %s", rrd_strerror(errno)); + close(fd); + return (-1); + } } + 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); + fwrite(rrd->live_head, sizeof(live_head_t), 1, fh); + fwrite(rrd->pdp_prep, sizeof(pdp_prep_t), rrd->stat_head->ds_cnt, fh); + fwrite(rrd->cdp_prep, sizeof(cdp_prep_t), + rrd->stat_head->rra_cnt * rrd->stat_head->ds_cnt, fh); + 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); + + fwrite(rrd->rrd_value, sizeof(rrd_value_t), value_count, fh); + /* lets see if we had an error */ - if (ferror(rrd_file)) { + if (ferror(fh)) { rrd_set_error("a file error occurred while creating '%s'", file_name); - fclose(rrd_file); + fclose(fh); return (-1); } - fclose(rrd_file); - return 0; -} - + fclose(fh); + return (0); +} /* int write_file */ int rrd_restore( int argc, char **argv) { - rrd_t rrd; - char *buf; - char rc = 0; - char force_overwrite = 0; - struct option long_options[] = { - {"range-check", no_argument, 0, 'r'}, - {"force-overwrite", no_argument, 0, 'f'}, - {0, 0, 0, 0} - }; + rrd_t *rrd; /* init rrd clean */ optind = 0; opterr = 0; /* initialize getopt */ - while (1) { - int option_index = 0; + while (42) { int opt; + int option_index = 0; + static struct option long_options[] = { + {"range-check", no_argument, 0, 'r'}, + {"force-overwrite", no_argument, 0, 'f'}, + {0, 0, 0, 0} + }; opt = getopt_long(argc, argv, "rf", long_options, &option_index); @@ -745,114 +1076,39 @@ int rrd_restore( switch (opt) { case 'r': - rc = 1; + opt_range_check = 1; break; + case 'f': - force_overwrite = 1; + opt_force_overwrite = 1; break; + default: - rrd_set_error - ("usage rrdtool %s [--range-check|-r] [--force-overwrite/-f] 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; - } + } /* while (42) */ - rrd_init(&rrd); - - if (xml2rrd(buf, &rrd, rc) == -1) { - rrd_free(&rrd); - free(buf); - return -1; + if ((argc - optind) != 2) { + rrd_set_error("usage rrdtool %s [--range-check/-r] " + "[--force-overwrite/-f] file.xml file.rrd", argv[0]); + return (-1); } - free(buf); - - if (rrd_creat(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)); - } -} + rrd = parse_file(argv[optind]); + if (rrd == NULL) + return (-1); -/* 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)); - } + if (write_file(argv[optind + 1], rrd) != 0) { + rrd_free(rrd); + return (-1); } -} - -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; + rrd_free(rrd); + return (0); +} /* int rrd_restore */ -} +/* vim: set sw=2 sts=2 ts=8 et fdm=marker : */ diff --git a/src/rrd_rpncalc.c b/src/rrd_rpncalc.c index 1f86f2e..d98008d 100644 --- a/src/rrd_rpncalc.c +++ b/src/rrd_rpncalc.c @@ -547,14 +547,14 @@ short rpn_calc( break; case OP_ADDNAN: stackunderflow(1); - if (isnan(rpnstack->s[stptr - 1])) { - rpnstack->s[stptr - 1] = rpnstack->s[stptr]; - } else if (isnan(rpnstack->s[stptr])) { - //rpnstack->s[stptr - 1] = rpnstack->s[stptr - 1]; - } else { - rpnstack->s[stptr - 1] = rpnstack->s[stptr - 1] - + rpnstack->s[stptr]; - } + if (isnan(rpnstack->s[stptr - 1])) { + rpnstack->s[stptr - 1] = rpnstack->s[stptr]; + } else if (isnan(rpnstack->s[stptr])) { + //rpnstack->s[stptr - 1] = rpnstack->s[stptr - 1]; + } else { + rpnstack->s[stptr - 1] = rpnstack->s[stptr - 1] + + rpnstack->s[stptr]; + } stptr--; break; @@ -705,8 +705,10 @@ short rpn_calc( break; case OP_IF: stackunderflow(2); - rpnstack->s[stptr - 2] = ( isnan(rpnstack->s[stptr - 2]) || rpnstack->s[stptr - 2] == 0.0 ) ? - rpnstack->s[stptr] : rpnstack->s[stptr - 1]; + rpnstack->s[stptr - 2] = (isnan(rpnstack->s[stptr - 2]) + || rpnstack->s[stptr - 2] == + 0.0) ? rpnstack->s[stptr] : rpnstack-> + s[stptr - 1]; stptr--; stptr--; break;