fix from alex
[rrdtool.git] / src / rrd_restore.c
index fa8493a..ab8b138 100644 (file)
@@ -1,30 +1,32 @@
 /*****************************************************************************
- * RRDtool 1.2.99907080300  Copyright by Tobi Oetiker, 1997-2007
+ * RRDtool 1.3.2  Copyright by Tobi Oetiker, 1997-2008
  * This file:     Copyright 2008 Florian octo Forster
  * Distributed under the GPL
  *****************************************************************************
- * rrd_thread_safe.c   Contains routines used when thread safety is required
+ * rrd_restore.c   Contains logic to parse XML input and create an RRD file
  *****************************************************************************
  * $Id$
  *************************************************************************** */
-* *This program is free software;
-you can redistribute it and / or modify it
-    *
-    under the terms of the GNU General Public License as published by the Free
-    * Software Foundation;
-either    version 2 of the License, or(
-    at your option)
-* any later version.
-    * *This program is distributed in the hope that it will be useful,
-but WITHOUT * ANY WARRANTY;
-    without even the implied warranty of MERCHANTABILITY or
-        *
-        FITNESS FOR A PARTICULAR PURPOSE.
-        See the GNU General Public License for *more details. *
-        *You should have received a copy of the GNU General Public License
-        along * with this program; if not
-      , write to the Free Software Foundation, Inc., *51 Franklin St, Fifth Floor, Boston, MA 02110 - 1301 USA * *Authors:
-        *Florian octo Forster < octo at verplant.org > **/
+
+/*
+ * This program is free software; you can redistribute it and / or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (t your option)
+ * any later version.
+ * 
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110 - 1301 USA
+ *
+ * Authors:
+ *   Florian octo Forster <octo at verplant.org>
+ **/
+
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -40,13 +42,13 @@ but WITHOUT * ANY WARRANTY;
 #include "rrd_tool.h"
 #include "rrd_rpncalc.h"
 #define ARRAY_LENGTH(a) (sizeof (a) / sizeof ((a)[0]))
-    static int opt_range_check = 0;
-    static int opt_force_overwrite = 0;
+static int opt_range_check = 0;
+static int opt_force_overwrite = 0;
 
 /*
  * Auxiliary functions
  */
-    static int get_string_from_node(
+static int get_string_from_node(
     xmlDoc * doc,
     xmlNode * node,
     char *buffer,
@@ -161,7 +163,7 @@ static int value_check_range(
 
     if (((!isnan(min)) && (*rrd_value < min))
         || ((!isnan(max)) && (*rrd_value > max)))
-        *rrd_value = NAN;
+        *rrd_value = DNAN;
 
     return (0);
 }                       /* int value_check_range */
@@ -316,6 +318,10 @@ static int parse_tag_rra_cdp_prep_ds(
 
     status = 0;
     for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
+        if (atoi(rrd->stat_head->version) == 1) {
+            cdp_prep->scratch[CDP_primary_val].u_val = 0.0;
+            cdp_prep->scratch[CDP_secondary_val].u_val = 0.0;
+        }
         if ((xmlStrcmp(child->name, (const xmlChar *) "comment") == 0)
             || (xmlStrcmp(child->name, (const xmlChar *) "text") == 0))
             /* ignore */ ;
@@ -383,45 +389,6 @@ static int parse_tag_rra_cdp_prep_ds(
             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);
@@ -706,7 +673,13 @@ static int parse_tag_rra(
         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)
+        else if (atoi(rrd->stat_head->version) == 1
+                 && xmlStrcmp(child->name, (const xmlChar *) "xff") == 0)
+            status = get_double_from_node(doc, child,
+                                          (double *) &cur_rra_def->
+                                          par[RRA_cdp_xff_val].u_val);
+        else if (atoi(rrd->stat_head->version) >= 2
+                 && xmlStrcmp(child->name, (const xmlChar *) "params") == 0)
             status = parse_tag_rra_params(doc, child, cur_rra_def);
         else if (xmlStrcmp(child->name, (const xmlChar *) "cdp_prep") == 0)
             status = parse_tag_rra_cdp_prep(doc, child, rrd, cur_cdp_prep);
@@ -721,8 +694,8 @@ static int parse_tag_rra(
             break;
     }
 
-    /* Set the RRA pointer to the last value in the archive */
-    cur_rra_ptr->cur_row = cur_rra_def->row_cnt - 1;
+    /* Set the RRA pointer to a random location */
+    cur_rra_ptr->cur_row = random() % cur_rra_def->row_cnt;
 
     return (status);
 }                       /* int parse_tag_rra */
@@ -994,7 +967,7 @@ static int write_file(
 {
     FILE     *fh;
     unsigned int i;
-    unsigned int value_count;
+    unsigned int rra_offset;
 
     if (strcmp("-", file_name) == 0)
         fh = stdout;
@@ -1023,7 +996,10 @@ static int write_file(
             return (-1);
         }
     }
-
+    if (atoi(rrd->stat_head->version) < 3) {
+        /* we output 3 or higher */
+        strcpy(rrd->stat_head->version, "0003");
+    }
     fwrite(rrd->stat_head, sizeof(stat_head_t), 1, fh);
     fwrite(rrd->ds_def, sizeof(ds_def_t), rrd->stat_head->ds_cnt, fh);
     fwrite(rrd->rra_def, sizeof(rra_def_t), rrd->stat_head->rra_cnt, fh);
@@ -1034,11 +1010,21 @@ static int write_file(
     fwrite(rrd->rra_ptr, sizeof(rra_ptr_t), rrd->stat_head->rra_cnt, fh);
 
     /* calculate the number of rrd_values to dump */
-    value_count = 0;
-    for (i = 0; i < rrd->stat_head->rra_cnt; i++)
-        value_count += (rrd->rra_def[i].row_cnt * rrd->stat_head->ds_cnt);
+    rra_offset = 0;
+    for (i = 0; i < rrd->stat_head->rra_cnt; i++) {
+        unsigned long num_rows = rrd->rra_def[i].row_cnt;
+        unsigned long cur_row = rrd->rra_ptr[i].cur_row;
+        unsigned long ds_cnt = rrd->stat_head->ds_cnt;
+
+        fwrite(rrd->rrd_value +
+               (rra_offset + num_rows - 1 - cur_row) * ds_cnt,
+               sizeof(rrd_value_t), (cur_row + 1) * ds_cnt, fh);
 
-    fwrite(rrd->rrd_value, sizeof(rrd_value_t), value_count, fh);
+        fwrite(rrd->rrd_value + rra_offset * ds_cnt,
+               sizeof(rrd_value_t), (num_rows - 1 - cur_row) * ds_cnt, fh);
+
+        rra_offset += num_rows;
+    }
 
     /* lets see if we had an error */
     if (ferror(fh)) {
@@ -1057,6 +1043,7 @@ int rrd_restore(
 {
     rrd_t    *rrd;
 
+    srandom((unsigned int) time(NULL) + (unsigned int) getpid());
     /* init rrd clean */
     optind = 0;
     opterr = 0;         /* initialize getopt */