/*****************************************************************************
- * RRDtool 1.2rc2 Copyright by Tobi Oetiker, 1997-2005
+ * RRDtool 1.3.2 Copyright by Tobi Oetiker, 1997-2008
*****************************************************************************
* rrd_resize.c Alters size of an RRA
*****************************************************************************
* Initial version by Alex van den Bogaerdt
*****************************************************************************/
+#include <stdlib.h>
+
#include "rrd_tool.h"
-int
-rrd_resize(int argc, char **argv)
+int rrd_resize(
+ int argc,
+ char **argv)
{
- char *infilename,outfilename[11]="resize.rrd";
- FILE *infile,*outfile;
- rrd_t rrdold,rrdnew;
- rrd_value_t buffer;
- unsigned long l,rra;
- long modify;
- unsigned long target_rra;
- int grow=0,shrink=0;
- char *endptr;
-
- infilename=argv[1];
- if (!strcmp(infilename,"resize.rrd")) {
+ char *infilename, outfilename[11] = "resize.rrd";
+ rrd_t rrdold, rrdnew;
+ rrd_value_t buffer;
+ int version;
+ unsigned long l, rra;
+ long modify;
+ unsigned long target_rra;
+ int grow = 0, shrink = 0;
+ char *endptr;
+ rrd_file_t *rrd_file, *rrd_out_file;
+
+ infilename = argv[1];
+ if (!strcmp(infilename, "resize.rrd")) {
rrd_set_error("resize.rrd is a reserved name");
- return(-1);
+ return (-1);
}
- if (argc!=5) {
+ if (argc != 5) {
rrd_set_error("wrong number of parameters");
- return(-1);
+ return (-1);
}
- target_rra=strtol(argv[2],&endptr,0);
+ target_rra = strtol(argv[2], &endptr, 0);
- if (!strcmp(argv[3],"GROW")) grow=1;
- else if (!strcmp(argv[3],"SHRINK")) shrink=1;
+ if (!strcmp(argv[3], "GROW"))
+ grow = 1;
+ else if (!strcmp(argv[3], "SHRINK"))
+ shrink = 1;
else {
rrd_set_error("I can only GROW or SHRINK");
- return(-1);
+ return (-1);
}
- modify=strtol(argv[4],&endptr,0);
+ modify = strtol(argv[4], &endptr, 0);
- if ((modify<1)) {
+ if ((modify < 1)) {
rrd_set_error("Please grow or shrink with at least 1 row");
- return(-1);
+ return (-1);
}
- if (shrink) modify = -modify;
+ if (shrink)
+ modify = -modify;
- if (rrd_open(infilename, &infile, &rrdold, RRD_READWRITE)==-1) {
- rrd_set_error("could not open RRD");
- return(-1);
+ rrd_init(&rrdold);
+ rrd_file = rrd_open(infilename, &rrdold, RRD_READWRITE | RRD_COPY);
+ if (rrd_file == NULL) {
+ rrd_free(&rrdold);
+ return (-1);
}
- if (LockRRD(infile) != 0) {
+
+ if (rrd_lock(rrd_file) != 0) {
rrd_set_error("could not lock original RRD");
rrd_free(&rrdold);
- fclose(infile);
- return(-1);
+ rrd_close(rrd_file);
+ return (-1);
}
+
if (target_rra >= rrdold.stat_head->rra_cnt) {
rrd_set_error("no such RRA in this RRD");
rrd_free(&rrdold);
- fclose(infile);
- return(-1);
+ rrd_close(rrd_file);
+ return (-1);
}
if (modify < 0)
- if ((long)rrdold.rra_def[target_rra].row_cnt <= -modify) {
- rrd_set_error("This RRA is not that big");
- rrd_free(&rrdold);
- fclose(infile);
- return(-1);
- }
-
- rrdnew.stat_head = rrdold.stat_head;
- rrdnew.ds_def = rrdold.ds_def;
- rrdnew.rra_def = rrdold.rra_def;
- rrdnew.live_head = rrdold.live_head;
- rrdnew.pdp_prep = rrdold.pdp_prep;
- rrdnew.cdp_prep = rrdold.cdp_prep;
- rrdnew.rra_ptr = rrdold.rra_ptr;
+ if ((long) rrdold.rra_def[target_rra].row_cnt <= -modify) {
+ rrd_set_error("This RRA is not that big");
+ rrd_free(&rrdold);
+ rrd_close(rrd_file);
+ return (-1);
+ }
+
+ rrd_init(&rrdnew);
+ /* These need to be initialised before calling rrd_open() with
+ the RRD_CREATE flag */
+
+ if ((rrdnew.stat_head = (stat_head_t*)calloc(1, sizeof(stat_head_t))) == NULL) {
+ rrd_set_error("allocating stat_head for new RRD");
+ rrd_free(&rrdold);
+ rrd_close(rrd_file);
+ return (-1);
+ }
+ memcpy(rrdnew.stat_head,rrdold.stat_head,sizeof(stat_head_t));
+
+ if ((rrdnew.rra_def = (rra_def_t *)malloc(sizeof(rra_def_t) * rrdold.stat_head->rra_cnt)) == NULL) {
+ rrd_set_error("allocating rra_def for new RRD");
+ rrd_free(&rrdnew);
+ rrd_free(&rrdold);
+ rrd_close(rrd_file);
+ return (-1);
+ }
+ memcpy(rrdnew.rra_def,rrdold.rra_def,sizeof(rra_def_t) * rrdold.stat_head->rra_cnt);
+
+ /* Set this so that the file will be created with the correct size */
+ rrdnew.rra_def[target_rra].row_cnt += modify;
- if ((outfile=fopen(outfilename,"wb"))==NULL) {
- rrd_set_error("Can't create '%s'",outfilename);
- return(-1);
+ rrd_out_file = rrd_open(outfilename, &rrdnew, RRD_READWRITE | RRD_CREAT);
+ if (rrd_out_file == NULL) {
+ rrd_set_error("Can't create '%s': %s", outfilename,
+ rrd_strerror(errno));
+ rrd_free(&rrdnew);
+ rrd_free(&rrdold);
+ rrd_close(rrd_file);
+ rrd_close(rrd_out_file);
+ return (-1);
}
- if (LockRRD(outfile) != 0) {
+ if (rrd_lock(rrd_out_file) != 0) {
rrd_set_error("could not lock new RRD");
+ rrd_free(&rrdnew);
+ rrd_free(&rrdold);
+ rrd_close(rrd_file);
+ rrd_close(rrd_out_file);
+ return (-1);
+ }
+/*XXX: do one write for those parts of header that are unchanged */
+ if ((rrdnew.rra_ptr = (rra_ptr_t *)malloc(sizeof(rra_ptr_t) * rrdold.stat_head->rra_cnt)) == NULL) {
+ rrd_set_error("allocating rra_ptr for new RRD");
+ rrd_free(&rrdnew);
rrd_free(&rrdold);
- fclose(infile);
- fclose(outfile);
- return(-1);
- }
- fwrite(rrdnew.stat_head, sizeof(stat_head_t),1,outfile);
- fwrite(rrdnew.ds_def,sizeof(ds_def_t),rrdnew.stat_head->ds_cnt,outfile);
- fwrite(rrdnew.rra_def,sizeof(rra_def_t),rrdnew.stat_head->rra_cnt,outfile);
- fwrite(rrdnew.live_head,sizeof(live_head_t),1,outfile);
- fwrite(rrdnew.pdp_prep,sizeof(pdp_prep_t),rrdnew.stat_head->ds_cnt,outfile);
- fwrite(rrdnew.cdp_prep,sizeof(cdp_prep_t),rrdnew.stat_head->ds_cnt*rrdnew.stat_head->rra_cnt,outfile);
- fwrite(rrdnew.rra_ptr,sizeof(rra_ptr_t),rrdnew.stat_head->rra_cnt,outfile);
+ rrd_close(rrd_file);
+ rrd_close(rrd_out_file);
+ return (-1);
+ }
+
+ /* Put this back the way it was so that the rest of the algorithm
+ below remains unchanged, it will be corrected later */
+ rrdnew.rra_def[target_rra].row_cnt -= modify;
+
+ rrdnew.ds_def = rrdold.ds_def;
+ rrdnew.live_head = rrdold.live_head;
+ rrdnew.pdp_prep = rrdold.pdp_prep;
+ rrdnew.cdp_prep = rrdold.cdp_prep;
+ memcpy(rrdnew.rra_ptr,rrdold.rra_ptr,sizeof(rra_ptr_t) * rrdold.stat_head->rra_cnt);
+
+
+ version = atoi(rrdold.stat_head->version);
+ switch (version) {
+ case 4:
+ break;
+ case 3:
+ break;
+ case 1:
+ rrdnew.stat_head->version[3] = '3';
+ break;
+ default:
+ rrd_set_error("Do not know how to handle RRD version %s",
+ rrdold.stat_head->version);
+ rrd_free(&rrdnew);
+ rrd_free(&rrdold);
+ rrd_close(rrd_file);
+ rrd_close(rrd_out_file);
+ return (-1);
+ break;
+ }
+
+/* XXX: Error checking? */
+ rrd_write(rrd_out_file, rrdnew.stat_head, sizeof(stat_head_t) * 1);
+ rrd_write(rrd_out_file, rrdnew.ds_def,
+ sizeof(ds_def_t) * rrdnew.stat_head->ds_cnt);
+ rrd_write(rrd_out_file, rrdnew.rra_def,
+ sizeof(rra_def_t) * rrdnew.stat_head->rra_cnt);
+ rrd_write(rrd_out_file, rrdnew.live_head, sizeof(live_head_t) * 1);
+ rrd_write(rrd_out_file, rrdnew.pdp_prep,
+ sizeof(pdp_prep_t) * rrdnew.stat_head->ds_cnt);
+ rrd_write(rrd_out_file, rrdnew.cdp_prep,
+ sizeof(cdp_prep_t) * rrdnew.stat_head->ds_cnt *
+ rrdnew.stat_head->rra_cnt);
+ rrd_write(rrd_out_file, rrdnew.rra_ptr,
+ sizeof(rra_ptr_t) * rrdnew.stat_head->rra_cnt);
/* Move the CDPs from the old to the new database.
- ** This can be made (much) faster but isn't worth the effort. Clarity
- ** is much more important.
- */
+ ** This can be made (much) faster but isn't worth the effort. Clarity
+ ** is much more important.
+ */
/* Move data in unmodified RRAs
- */
- l=0;
- for (rra=0;rra<target_rra;rra++) {
- l+=rrdnew.stat_head->ds_cnt * rrdnew.rra_def[rra].row_cnt;
- }
- while (l>0) {
- fread(&buffer,sizeof(rrd_value_t),1,infile);
- fwrite(&buffer,sizeof(rrd_value_t),1,outfile);
+ */
+ l = 0;
+ for (rra = 0; rra < target_rra; rra++) {
+ l += rrdnew.stat_head->ds_cnt * rrdnew.rra_def[rra].row_cnt;
+ }
+ while (l > 0) {
+ rrd_read(rrd_file, &buffer, sizeof(rrd_value_t) * 1);
+ rrd_write(rrd_out_file, &buffer, sizeof(rrd_value_t) * 1);
l--;
}
/* Move data in this RRA, either removing or adding some rows
- */
- if (modify>0) {
+ */
+ if (modify > 0) {
/* Adding extra rows; insert unknown values just after the
- ** current row number.
- */
- l = rrdnew.stat_head->ds_cnt * (rrdnew.rra_ptr[target_rra].cur_row+1);
- while (l>0) {
- fread(&buffer,sizeof(rrd_value_t),1,infile);
- fwrite(&buffer,sizeof(rrd_value_t),1,outfile);
+ ** current row number.
+ */
+ l = rrdnew.stat_head->ds_cnt *
+ (rrdnew.rra_ptr[target_rra].cur_row + 1);
+ while (l > 0) {
+ rrd_read(rrd_file, &buffer, sizeof(rrd_value_t) * 1);
+ rrd_write(rrd_out_file, &buffer, sizeof(rrd_value_t) * 1);
l--;
}
- buffer=DNAN;
- l=rrdnew.stat_head->ds_cnt * modify;
- while (l>0) {
- fwrite(&buffer,sizeof(rrd_value_t),1,outfile);
+ buffer = DNAN;
+ l = rrdnew.stat_head->ds_cnt * modify;
+ while (l > 0) {
+ rrd_write(rrd_out_file, &buffer, sizeof(rrd_value_t) * 1);
l--;
}
} else {
/* Removing rows. Normally this would be just after the cursor
- ** however this may also mean that we wrap to the beginning of
- ** the array.
- */
- signed long int remove_end=0;
+ ** however this may also mean that we wrap to the beginning of
+ ** the array.
+ */
+ signed long int remove_end = 0;
- remove_end=(rrdnew.rra_ptr[target_rra].cur_row-modify)%rrdnew.rra_def[target_rra].row_cnt;
- if (remove_end <= (signed long int)rrdnew.rra_ptr[target_rra].cur_row) {
+ remove_end =
+ (rrdnew.rra_ptr[target_rra].cur_row -
+ modify) % rrdnew.rra_def[target_rra].row_cnt;
+ if (remove_end <=
+ (signed long int) rrdnew.rra_ptr[target_rra].cur_row) {
while (remove_end >= 0) {
- fseek(infile,sizeof(rrd_value_t)*rrdnew.stat_head->ds_cnt,SEEK_CUR);
+ rrd_seek(rrd_file,
+ sizeof(rrd_value_t) * rrdnew.stat_head->ds_cnt,
+ SEEK_CUR);
rrdnew.rra_ptr[target_rra].cur_row--;
rrdnew.rra_def[target_rra].row_cnt--;
remove_end--;
modify++;
}
- remove_end=rrdnew.rra_def[target_rra].row_cnt-1;
+ remove_end = rrdnew.rra_def[target_rra].row_cnt - 1;
}
- for (l=0;l<=rrdnew.rra_ptr[target_rra].cur_row;l++) {
+ for (l = 0; l <= rrdnew.rra_ptr[target_rra].cur_row; l++) {
unsigned int tmp;
- for (tmp=0;tmp<rrdnew.stat_head->ds_cnt;tmp++) {
- fread(&buffer,sizeof(rrd_value_t),1,infile);
- fwrite(&buffer,sizeof(rrd_value_t),1,outfile);
+
+ for (tmp = 0; tmp < rrdnew.stat_head->ds_cnt; tmp++) {
+ rrd_read(rrd_file, &buffer, sizeof(rrd_value_t) * 1);
+ rrd_write(rrd_out_file, &buffer, sizeof(rrd_value_t) * 1);
}
}
- while (modify<0) {
- fseek(infile,sizeof(rrd_value_t)*rrdnew.stat_head->ds_cnt,SEEK_CUR);
+ while (modify < 0) {
+ rrd_seek(rrd_file,
+ sizeof(rrd_value_t) * rrdnew.stat_head->ds_cnt,
+ SEEK_CUR);
rrdnew.rra_def[target_rra].row_cnt--;
modify++;
}
}
/* Move the rest of the CDPs
- */
+ */
while (1) {
- fread(&buffer,sizeof(rrd_value_t),1,infile);
- if (feof(infile))
- break;
- fwrite(&buffer,sizeof(rrd_value_t),1,outfile);
+ if (rrd_read(rrd_file, &buffer, sizeof(rrd_value_t) * 1) <= 0)
+ break;
+ rrd_write(rrd_out_file, &buffer, sizeof(rrd_value_t) * 1);
}
rrdnew.rra_def[target_rra].row_cnt += modify;
- fseek(outfile,sizeof(stat_head_t)+sizeof(ds_def_t)*rrdnew.stat_head->ds_cnt,SEEK_SET);
- fwrite(rrdnew.rra_def,sizeof(rra_def_t),rrdnew.stat_head->rra_cnt, outfile);
- fseek(outfile,sizeof(live_head_t),SEEK_CUR);
- fseek(outfile,sizeof(pdp_prep_t)*rrdnew.stat_head->ds_cnt,SEEK_CUR);
- fseek(outfile,sizeof(cdp_prep_t)*rrdnew.stat_head->ds_cnt*rrdnew.stat_head->rra_cnt,SEEK_CUR);
- fwrite(rrdnew.rra_ptr,sizeof(rra_ptr_t),rrdnew.stat_head->rra_cnt, outfile);
-
- fclose(outfile);
+ rrd_seek(rrd_out_file,
+ sizeof(stat_head_t) +
+ sizeof(ds_def_t) * rrdnew.stat_head->ds_cnt, SEEK_SET);
+ rrd_write(rrd_out_file, rrdnew.rra_def,
+ sizeof(rra_def_t) * rrdnew.stat_head->rra_cnt);
+ rrd_seek(rrd_out_file, sizeof(live_head_t), SEEK_CUR);
+ rrd_seek(rrd_out_file, sizeof(pdp_prep_t) * rrdnew.stat_head->ds_cnt,
+ SEEK_CUR);
+ rrd_seek(rrd_out_file,
+ sizeof(cdp_prep_t) * rrdnew.stat_head->ds_cnt *
+ rrdnew.stat_head->rra_cnt, SEEK_CUR);
+ rrd_write(rrd_out_file, rrdnew.rra_ptr,
+ sizeof(rra_ptr_t) * rrdnew.stat_head->rra_cnt);
+ rrd_close(rrd_file);
+ rrd_close(rrd_out_file);
rrd_free(&rrdold);
- fclose(infile);
- return(0);
+ rrd_free(&rrdnew);
+ return (0);
}