prepare for the release of rrdtool-1.2.9
[rrdtool.git] / src / rrd_create.c
index a3bfafe..3e9c68c 100644 (file)
@@ -1,5 +1,5 @@
 /*****************************************************************************
- * RRDtool 1.1.x  Copyright Tobias Oetiker, 1997 - 2002
+ * RRDtool 1.2.9  Copyright by Tobi Oetiker, 1997-2005
  *****************************************************************************
  * rrd_create.c  creates new rrds
  *****************************************************************************/
@@ -19,10 +19,11 @@ rrd_create(int argc, char **argv)
 {
     time_t            last_up = time(NULL)-10;
     unsigned long     pdp_step = 300;
-    struct time_value last_up_tv;
+    struct rrd_time_value last_up_tv;
     char *parsetime_error = NULL;
     long              long_tmp;
     int               rc;
+    optind = 0; opterr = 0;  /* initialize getopt */
 
     while (1){
        static struct option long_options[] =
@@ -95,6 +96,7 @@ rrd_create_r(char *filename,
     long              i;
     int               offset;
     char *token;
+    unsigned short dummychar1,dummychar2;
     unsigned short token_idx, error_flag, period=0;
     unsigned long hashed_name;
 
@@ -103,12 +105,14 @@ rrd_create_r(char *filename,
     /* static header */
     if((rrd.stat_head = calloc(1,sizeof(stat_head_t)))==NULL){
        rrd_set_error("allocating rrd.stat_head");
+       rrd_free(&rrd);
        return(-1);
     }
 
     /* live header */
     if((rrd.live_head = calloc(1,sizeof(live_head_t)))==NULL){
        rrd_set_error("allocating rrd.live_head");
+       rrd_free(&rrd);
        return(-1);
     }
 
@@ -143,19 +147,31 @@ rrd_create_r(char *filename,
            }
            memset(&rrd.ds_def[rrd.stat_head->ds_cnt], 0, sizeof(ds_def_t));
             /* extract the name and type */
-           if (sscanf(&argv[i][3],
-                      DS_NAM_FMT ":" DST_FMT ":%n",
-                      rrd.ds_def[rrd.stat_head->ds_cnt].ds_nam,
-                      rrd.ds_def[rrd.stat_head->ds_cnt].dst,&offset) == 2)
-            {
-                /* check for duplicate datasource names */
-                for(ii=0;ii<rrd.stat_head->ds_cnt;ii++)
-                    if(strcmp(rrd.ds_def[rrd.stat_head->ds_cnt].ds_nam,
-                              rrd.ds_def[ii].ds_nam) == 0){
-                        rrd_set_error("Duplicate DS name: %s",rrd.ds_def[ii].ds_nam);
-                    }                                                          
-            } else {
-                rrd_set_error("invalid DS format");
+           switch (sscanf(&argv[i][3],
+                       DS_NAM_FMT "%1[:]" DST_FMT "%1[:]%n",
+                       rrd.ds_def[rrd.stat_head->ds_cnt].ds_nam,
+                       &dummychar1,
+                       rrd.ds_def[rrd.stat_head->ds_cnt].dst,
+                       &dummychar2,
+                       &offset)) {
+               case 0:
+               case 1: rrd_set_error("Invalid DS name"); break;
+               case 2:
+               case 3: rrd_set_error("Invalid DS type"); break;
+               case 4: /* (%n may or may not be counted) */
+               case 5: /* check for duplicate datasource names */
+                   for (ii=0;ii<rrd.stat_head->ds_cnt;ii++)
+                       if(strcmp(rrd.ds_def[rrd.stat_head->ds_cnt].ds_nam,
+                               rrd.ds_def[ii].ds_nam) == 0)
+                           rrd_set_error("Duplicate DS name: %s",
+                                       rrd.ds_def[ii].ds_nam);
+                   /* DS_type may be valid or not. Checked later */
+                   break;
+               default: rrd_set_error("invalid DS format");
+            }
+           if (rrd_test_error()) {
+                rrd_free(&rrd);
+                return -1;
             }
             
             /* parse the remainder of the arguments */
@@ -180,7 +196,8 @@ rrd_create_r(char *filename,
                 return -1;
             }
             rrd.stat_head -> ds_cnt++;
-       } else if (strncmp(argv[i],"RRA:",3)==0){
+       } else if (strncmp(argv[i],"RRA:",4)==0){
+            char *argvcopy;
            char *tokptr;
            size_t old_size = sizeof(rra_def_t)*(rrd.stat_head->rra_cnt);
            if((rrd.rra_def = rrd_realloc(rrd.rra_def,
@@ -191,8 +208,9 @@ rrd_create_r(char *filename,
                 return(-1);    
            }
            memset(&rrd.rra_def[rrd.stat_head->rra_cnt], 0, sizeof(rra_def_t));
-            
-           token = strtok_r(&argv[i][4],":", &tokptr);
+
+            argvcopy = strdup(argv[i]);
+           token = strtok_r(&argvcopy[4],":", &tokptr);
            token_idx = error_flag = 0;
            while (token != NULL)
            {
@@ -367,12 +385,14 @@ rrd_create_r(char *filename,
                 if (rrd_test_error())
                 {
                     /* all errors are unrecoverable */
+                    free(argvcopy);
                     rrd_free(&rrd);
                     return (-1);
                 }
                 token = strtok_r(NULL,":", &tokptr);
                 token_idx++;
            } /* end while */
+           free(argvcopy);
 #ifdef DEBUG
            fprintf(stderr,"Creating RRA CF: %s, dep idx %lu, current idx %lu\n",
                    rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam,
@@ -388,6 +408,7 @@ rrd_create_r(char *filename,
                 fprintf(stderr,"Creating HW contingent RRAs\n");
 #endif
                 if (create_hw_contingent_rras(&rrd,period,hashed_name) == -1) {
+                    rrd_set_error("creating contingent RRA");
                     rrd_free(&rrd);
                     return -1;
                 }
@@ -527,7 +548,8 @@ rrd_create_fn(char *file_name, rrd_t *rrd)
 {
     unsigned long    i,ii;
     FILE             *rrd_file;
-    rrd_value_t       unknown = DNAN ;
+    rrd_value_t      *unknown;
+    int        unkn_cnt;
     
     if ((rrd_file = fopen(file_name,"wb")) == NULL ) {
        rrd_set_error("creating '%s': %s",file_name, rrd_strerror(errno));
@@ -632,17 +654,24 @@ rrd_create_fn(char *file_name, rrd_t *rrd)
     }
     
     /* write the empty data area */
-    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++){
-            fwrite(&unknown,sizeof(rrd_value_t),1,rrd_file);
-        }
+    if ((unknown = (rrd_value_t *)malloc(512 * sizeof(rrd_value_t))) == NULL) {
+       rrd_set_error("allocating unknown");
+       rrd_free(rrd);
+       fclose(rrd_file);
+       return(-1);
     }
+    for (i = 0; i < 512; ++i)
+       unknown[i] = DNAN;
+    
+    unkn_cnt = 0;
+    for (i = 0; i < rrd->stat_head->rra_cnt; i++)
+        unkn_cnt += rrd->stat_head->ds_cnt * rrd->rra_def[i].row_cnt;
+                     
+    while (unkn_cnt > 0) {
+       fwrite(unknown, sizeof(rrd_value_t), min(unkn_cnt, 512), rrd_file);
+       unkn_cnt -= 512;
+     }
+    free(unknown);
     
     /* lets see if we had an error */
     if(ferror(rrd_file)){