Code

prepare for the release of rrdtool-1.2.30
[rrdtool-all.git] / program / src / rrd_restore.c
index 3246047ce8677fd1d9ea7f2ad098e4c611911003..fa0a3b801c71ddc46649a78ddaaa67cfec162ece 100644 (file)
@@ -1,5 +1,5 @@
 /*****************************************************************************
- * RRDtool 1.2.12  Copyright by Tobi Oetiker, 1997-2005
+ * RRDtool 1.2.30  Copyright by Tobi Oetiker, 1997-2009
  *****************************************************************************
  * rrd_restore.c  creates new rrd from data dumped by rrd_dump.c
  *****************************************************************************/
@@ -18,6 +18,7 @@
 
 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);
@@ -25,6 +26,7 @@ int rrd_write(char *, rrd_t *, char);
 void parse_patch1028_RRA_params(char **buf, rrd_t *rrd, int rra_index);
 void parse_patch1028_CDP_params(char **buf, rrd_t *rrd, int rra_index, int ds_index);
 void parse_FAILURES_history(char **buf, rrd_t *rrd, int rra_index, int ds_index);
+long int rra_random_row(rra_def_t *);
 
 /* convert all occurrences of <BlaBlaBla> to <blablabla> */
 
@@ -44,9 +46,29 @@ void xml_lc(char* buf){
   }
 }
 
-int skip(char **buf){
+int skipxml(char **buf){
   char *ptr;  
   ptr=(*buf);
+  do {
+    (*buf)=ptr;
+    while((*(ptr+1)) && ((*ptr)==' ' ||  (*ptr)=='\r' || (*ptr)=='\n' || (*ptr)=='\t')) ptr++;
+    if (strncmp(ptr,"<?xml",4) == 0) {
+      ptr= strstr(ptr,"?>");
+      if (ptr) ptr+=2; else {
+       rrd_set_error("Dangling XML header");
+       (*buf) = NULL;
+       return -1;
+      }
+    }
+  } while ((*buf)!=ptr);  
+  return 1;
+}
+
+int skip(char **buf){
+  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++;
@@ -118,6 +140,8 @@ int xml2rrd(char* buf, rrd_t* rrd, char rc){
   ptr2=buf;
   ptr3=buf;
   /* start with an RRD tag */
+  
+  skipxml(&ptr);
 
   eat_tag(&ptr,"rrd");
   /* allocate static header */
@@ -130,10 +154,12 @@ int xml2rrd(char* buf, rrd_t* rrd, char rc){
   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) )
+  if (input_version > atoi(RRD_VERSION) || input_version < 1)
   {
-    rrd_set_error("Incompatible file version, detected version %s is bigger than supported version %s\n",
+    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 */
@@ -189,8 +215,9 @@ int xml2rrd(char* buf, rrd_t* rrd, char rc){
       read_tag(&ptr2,"max","%lf",&(rrd->ds_def[rrd->stat_head->ds_cnt-1].par[DS_max_val].u_val));
          } else { /* DST_CDEF */
                 char buffer[1024];
-            read_tag(&ptr2,"cdef","%s",buffer);
+                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);
@@ -213,7 +240,7 @@ int xml2rrd(char* buf, rrd_t* rrd, char rc){
       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; }
+         rrd_set_error("allocating cdp_prep"); return -1; }
 
       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));
@@ -230,7 +257,10 @@ int xml2rrd(char* buf, rrd_t* rrd, char rc){
          read_tag(&ptr2, "xff","%lf",
             &(rrd->rra_def[rra_index].par[RRA_cdp_xff_val].u_val));
       } else {
-        eat_tag(&ptr2, "params");
+        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, "<value>",7) == 0) {
@@ -284,7 +314,10 @@ int xml2rrd(char* buf, rrd_t* rrd, char rc){
       eat_tag(&ptr2,"cdp_prep");
       for(i=0;i< (int)rrd->stat_head->ds_cnt;i++)
       {
-      eat_tag(&ptr2,"ds");
+         if (eat_tag(&ptr2, "ds") != 1){
+            rrd_set_error("expected to find %lu <ds> entries in <cdp_prep>",rrd->stat_head->ds_cnt);
+            return -1;
+         }
       /* support to read CDP parameters */
       rra_index = rrd->stat_head->rra_cnt-1; 
       skip(&ptr2);
@@ -414,12 +447,6 @@ int xml2rrd(char* buf, rrd_t* rrd, char rc){
       return(-1);
   }
 
-  for(i=0; i < (int)rrd->stat_head->rra_cnt; i++) {
-         /* last row in the xml file is the most recent; as
-          * rrd_update increments the current row pointer, set cur_row
-          * here to the last row. */
-      rrd->rra_ptr[i].cur_row = rrd->rra_def[i].row_cnt-1;
-  }
   if (ptr==NULL)
       return -1;
   return 1;
@@ -434,7 +461,7 @@ int xml2rrd(char* buf, rrd_t* rrd, char rc){
 int
 rrd_write(char *file_name, rrd_t *rrd, char force_overwrite)
 {
-    unsigned long    i,ii,val_cnt;
+    unsigned long    i,ii,rra_offset;
     FILE             *rrd_file=NULL;
     int                        fdflags;
     int                        fd;
@@ -473,16 +500,30 @@ rrd_write(char *file_name, rrd_t *rrd, char force_overwrite)
     
     fwrite( rrd->cdp_prep, sizeof(cdp_prep_t),rrd->stat_head->rra_cnt*
            rrd->stat_head->ds_cnt,rrd_file);
+
+    for(i=0; i < rrd->stat_head->rra_cnt; i++)
+      rrd->rra_ptr[i].cur_row = rra_random_row(&rrd->rra_def[i]);
+
     fwrite( rrd->rra_ptr, sizeof(rra_ptr_t), rrd->stat_head->rra_cnt,rrd_file);
 
 
 
-    /* calculate the number of rrd_values to dump */
-    val_cnt=0;
+    /* Dump RRD values */
+    rra_offset=0;
     for(i=0; i <  rrd->stat_head->rra_cnt; i++)
-       for(ii=0; ii <  rrd->rra_def[i].row_cnt * rrd->stat_head->ds_cnt;ii++)
-           val_cnt++;
-    fwrite( rrd->rrd_value, sizeof(rrd_value_t),val_cnt,rrd_file);
+    {
+        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, rrd_file);
+
+        fwrite(rrd->rrd_value + rra_offset * ds_cnt,
+               sizeof(rrd_value_t), (num_rows-1 - cur_row)*ds_cnt, rrd_file);
+
+        rra_offset += num_rows;
+    }
 
     /* lets see if we had an error */
     if(ferror(rrd_file)){