Index: src/rrd_dump.c =================================================================== --- src/rrd_dump.c (revision 1064) +++ src/rrd_dump.c (working copy) @@ -77,13 +77,14 @@ rrd_dump_r(const char *filename, char *o time_t now; char somestring[255]; rrd_value_t my_cdp; - long rra_base, rra_start, rra_next; - FILE *in_file; + off_t rra_base, rra_start, rra_next; + rrd_file_t *rrd_file; FILE *out_file; rrd_t rrd; rrd_value_t value; struct tm tm; - if(rrd_open(filename, &in_file,&rrd, RRD_READONLY)==-1){ + rrd_file = rrd_open(filename, &rrd, RRD_READONLY); + if (rrd_file == NULL) { rrd_free(&rrd); return(-1); } @@ -151,7 +152,7 @@ rrd_dump_r(const char *filename, char *o fputs("", out_file); - rra_base=ftell(in_file); + rra_base = rrd_file->header_len; rra_next = rra_base; for(i=0;irra_cnt;i++){ @@ -314,7 +315,7 @@ rrd_dump_r(const char *filename, char *o fprintf(out_file, "\t\t\n"); fprintf(out_file, "\t\t\n"); - fseek(in_file,(rra_start + rrd_seek(rrd_file,(rra_start +(rrd.rra_ptr[i].cur_row+1) * rrd.stat_head->ds_cnt * sizeof(rrd_value_t)),SEEK_SET); @@ -323,7 +324,7 @@ rrd_dump_r(const char *filename, char *o for(ix=0;ix=rrd.rra_def[i].row_cnt) { - fseek(in_file,rra_start,SEEK_SET); + rrd_seek(rrd_file,rra_start,SEEK_SET); ii=0; /* wrap if max row cnt is reached */ } now = (rrd.live_head->last_up @@ -339,8 +340,8 @@ rrd_dump_r(const char *filename, char *o # error "Need strftime" #endif fprintf(out_file, "\t\t\t ",somestring,(int)now); - for(iii=0;iiids_cnt;iii++){ - fread(&my_cdp,sizeof(rrd_value_t),1,in_file); + for(iii=0;iiids_cnt;iii++){ + rrd_read(rrd_file, &my_cdp,sizeof(rrd_value_t)*1); if (isnan(my_cdp)){ fprintf(out_file, " NaN "); } else { @@ -350,11 +351,11 @@ rrd_dump_r(const char *filename, char *o fprintf(out_file, "\n"); } fprintf(out_file, "\t\t\n\t\n"); - + } fprintf(out_file, "\n"); rrd_free(&rrd); - fclose(in_file); + close(rrd_file->fd); if (out_file != stdout) { fclose(out_file); @@ -362,6 +363,3 @@ rrd_dump_r(const char *filename, char *o return(0); } - - - Index: src/rrd_fetch.c =================================================================== --- src/rrd_fetch.c (revision 1064) +++ src/rrd_fetch.c (working copy) @@ -194,7 +194,6 @@ rrd_fetch_fn( rrd_value_t **data) /* two dimensional array containing the data */ { long i,ii; - FILE *in_file; time_t cal_start,cal_end, rra_start_time,rra_end_time; long best_full_rra=0, best_part_rra=0, chosen_rra=0, rra_pointer=0; long best_full_step_diff=0, best_part_step_diff=0, tmp_step_diff=0, tmp_match=0, best_match=0; @@ -203,9 +202,12 @@ rrd_fetch_fn( int first_full = 1; int first_part = 1; rrd_t rrd; + rrd_file_t *rrd_file; rrd_value_t *data_ptr; unsigned long rows; +#ifdef HAVE_POSIX_FADVISE long rrd_head_size; +#endif #ifdef DEBUG fprintf(stderr,"Entered rrd_fetch_fn() searching for the best match\n"); @@ -213,17 +215,19 @@ fprintf(stderr,"Looking for: start %10lu *start,*end,*step); #endif - if(rrd_open(filename,&in_file,&rrd, RRD_READONLY)==-1) + rrd_file = rrd_open(filename,&rrd, RRD_READONLY); + if (rrd_file == NULL) return(-1); - rrd_head_size = ftell(in_file); - +#ifdef HAVE_POSIX_FADVISE + rrd_head_size = rrd_file->header_len; +#endif /* when was the really last update of this file ? */ if (((*ds_namv) = (char **) malloc(rrd.stat_head->ds_cnt * sizeof(char*)))==NULL){ rrd_set_error("malloc fetch ds_namv array"); rrd_free(&rrd); - fclose(in_file); + close(rrd_file->fd); return(-1); } @@ -232,7 +236,7 @@ fprintf(stderr,"Looking for: start %10lu rrd_set_error("malloc fetch ds_namv entry"); rrd_free(&rrd); free(*ds_namv); - fclose(in_file); + close(rrd_file->fd); return(-1); } strncpy((*ds_namv)[i],rrd.ds_def[i].ds_nam,DS_NAM_SIZE-1); @@ -312,7 +316,7 @@ fprintf(stderr,"partial match, not best\ else { rrd_set_error("the RRD does not contain an RRA matching the chosen CF"); rrd_free(&rrd); - fclose(in_file); + close(rrd_file->fd); return(-1); } @@ -340,14 +344,14 @@ fprintf(stderr,"partial match, not best\ free((*ds_namv)[i]); free(*ds_namv); rrd_free(&rrd); - fclose(in_file); + close(rrd_file->fd); return(-1); } data_ptr=(*data); /* find base address of rra */ - rra_base=ftell(in_file); + rra_base = rrd_file->header_len; for(i=0;ifd); return(-1); } @@ -425,7 +429,7 @@ fprintf(stderr,"partial match, not best\ * be wrapped*/ if (rra_pointer >= (signed)rrd.rra_def[chosen_rra].row_cnt) { rra_pointer -= rrd.rra_def[chosen_rra].row_cnt; - if(fseek(in_file,(rra_base+rra_pointer + if(rrd_seek(rrd_file,(rra_base+rra_pointer * *ds_cnt * sizeof(rrd_value_t)),SEEK_SET) != 0){ rrd_set_error("wrap seek in RRA did fail"); @@ -435,7 +439,7 @@ fprintf(stderr,"partial match, not best\ rrd_free(&rrd); free(*data); *data = NULL; - fclose(in_file); + close(rrd_file->fd); return(-1); } #ifdef DEBUG @@ -443,9 +447,9 @@ fprintf(stderr,"partial match, not best\ #endif } - if(fread(data_ptr, - sizeof(rrd_value_t), - *ds_cnt,in_file) != rrd.stat_head->ds_cnt){ + if(rrd_read(rrd_file,data_ptr, + sizeof(rrd_value_t)* (*ds_cnt)) + != (ssize_t)(sizeof(rrd_value_t)*(*ds_cnt)*rrd.stat_head->ds_cnt)){ rrd_set_error("fetching cdp from rra"); for (ii=0;(unsigned)ii<*ds_cnt;ii++) free((*ds_namv)[ii]); @@ -453,15 +457,15 @@ fprintf(stderr,"partial match, not best\ rrd_free(&rrd); free(*data); *data = NULL; - fclose(in_file); + close(rrd_file->fd); return(-1); } #ifdef HAVE_POSIX_FADVISE /* don't pollute the buffer cache with data read from the file. We do this while reading to keep damage minimal */ - if (0 != posix_fadvise(fileno(in_file), rrd_head_size, ftell(in_file), POSIX_FADV_DONTNEED)) { + if (0 != posix_fadvise(rrd_file->fd, rrd_head_size, rrd_file->pos, POSIX_FADV_DONTNEED)) { rrd_set_error("setting POSIX_FADV_DONTNEED on '%s': %s",filename, rrd_strerror(errno)); - fclose(in_file); + close(rrd_file->fd); return(-1); } #endif @@ -482,12 +486,12 @@ fprintf(stderr,"partial match, not best\ rrd_free(&rrd); #ifdef HAVE_POSIX_FADVISE /* and just to be sure we drop everything except the header at the end */ - if (0 != posix_fadvise(fileno(in_file), rrd_head_size, 0, POSIX_FADV_DONTNEED)) { + if (0 != posix_fadvise(rrd_file->fd, rrd_head_size, 0, POSIX_FADV_DONTNEED)) { rrd_set_error("setting POSIX_FADV_DONTNEED on '%s': %s",filename, rrd_strerror(errno)); - fclose(in_file); + close(rrd_file->fd); return(-1); } #endif - fclose(in_file); + close(rrd_file->fd); return(0); } Index: src/rrd_resize.c =================================================================== --- src/rrd_resize.c (revision 1064) +++ src/rrd_resize.c (working copy) @@ -12,7 +12,6 @@ int rrd_resize(int argc, char **argv) { char *infilename,outfilename[11]="resize.rrd"; - FILE *infile,*outfile; rrd_t rrdold,rrdnew; rrd_value_t buffer; int version; @@ -21,6 +20,7 @@ rrd_resize(int argc, char **argv) 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")) { @@ -51,21 +51,22 @@ rrd_resize(int argc, char **argv) if (shrink) modify = -modify; - if (rrd_open(infilename, &infile, &rrdold, RRD_READWRITE)==-1) { + rrd_file = rrd_open(infilename, &rrdold, RRD_READWRITE); + if (rrd_file == NULL) { rrd_set_error("could not open RRD"); return(-1); } - if (LockRRD(infile) != 0) { + if (LockRRD(rrd_file->fd) != 0) { rrd_set_error("could not lock original RRD"); rrd_free(&rrdold); - fclose(infile); + close(rrd_file->fd); return(-1); } if (target_rra >= rrdold.stat_head->rra_cnt) { rrd_set_error("no such RRA in this RRD"); rrd_free(&rrdold); - fclose(infile); + close(rrd_file->fd); return(-1); } @@ -73,10 +74,23 @@ rrd_resize(int argc, char **argv) if ((long)rrdold.rra_def[target_rra].row_cnt <= -modify) { rrd_set_error("This RRA is not that big"); rrd_free(&rrdold); - fclose(infile); + close(rrd_file->fd); return(-1); } + rrd_out_file = rrd_open(outfilename, &rrdnew, RRD_CREAT); + if (rrd_out_file == NULL) { + rrd_set_error("Can't create '%s': %s",outfilename, rrd_strerror(errno)); + return(-1); + } + if (LockRRD(rrd_out_file->fd) != 0) { + rrd_set_error("could not lock new RRD"); + rrd_free(&rrdold); + close(rrd_file->fd); + close(rrd_out_file->fd); + return(-1); + } +/*XXX: do one write for those parts of header that are unchanged */ rrdnew.stat_head = rrdold.stat_head; rrdnew.ds_def = rrdold.ds_def; rrdnew.rra_def = rrdold.rra_def; @@ -93,29 +107,20 @@ rrd_resize(int argc, char **argv) default: { rrd_set_error("Do not know how to handle RRD version %s",rrdold.stat_head->version); rrd_free(&rrdold); - fclose(infile); + close(rrd_file->fd); return(-1); } } - if ((outfile=fopen(outfilename,"wb"))==NULL) { - rrd_set_error("Can't create '%s'",outfilename); - return(-1); - } - if (LockRRD(outfile) != 0) { - rrd_set_error("could not lock new RRD"); - 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); + +/* 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 @@ -129,8 +134,8 @@ rrd_resize(int argc, char **argv) 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); + 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 @@ -141,14 +146,14 @@ rrd_resize(int argc, char **argv) */ 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); + 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); + rrd_write(rrd_out_file,&buffer,sizeof(rrd_value_t)*1); l--; } } else { @@ -161,7 +166,7 @@ rrd_resize(int argc, char **argv) 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--; @@ -172,12 +177,12 @@ rrd_resize(int argc, char **argv) for (l=0;l<=rrdnew.rra_ptr[target_rra].cur_row;l++) { unsigned int tmp; for (tmp=0;tmpds_cnt;tmp++) { - fread(&buffer,sizeof(rrd_value_t),1,infile); - fwrite(&buffer,sizeof(rrd_value_t),1,outfile); + 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); + rrd_seek(rrd_file,sizeof(rrd_value_t)*rrdnew.stat_head->ds_cnt,SEEK_CUR); rrdnew.rra_def[target_rra].row_cnt--; modify++; } @@ -185,21 +190,20 @@ rrd_resize(int argc, char **argv) /* Move the rest of the CDPs */ while (1) { - fread(&buffer,sizeof(rrd_value_t),1,infile); - if (feof(infile)) + if (rrd_read(rrd_file,&buffer,sizeof(rrd_value_t)*1) <= 0) break; - fwrite(&buffer,sizeof(rrd_value_t),1,outfile); + 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); + + close(rrd_out_file->fd); rrd_free(&rrdold); - fclose(infile); + close(rrd_file->fd); return(0); } Index: src/rrd_lastupdate.c =================================================================== --- src/rrd_lastupdate.c (revision 1064) +++ src/rrd_lastupdate.c (working copy) @@ -13,8 +13,8 @@ rrd_lastupdate(int argc, char **argv, ti unsigned long *ds_cnt, char ***ds_namv, char ***last_ds) { unsigned long i=0; char *filename; - FILE *in_file; rrd_t rrd; + rrd_file_t* rrd_file; if(argc < 2){ rrd_set_error("please specify an rrd"); @@ -22,10 +22,9 @@ rrd_lastupdate(int argc, char **argv, ti } filename = argv[1]; - if(rrd_open(filename,&in_file,&rrd, RRD_READONLY)==-1){ + rrd_file = rrd_open(filename, &rrd, RRD_READONLY); + if (rrd_file == NULL) return(-1); - } - fclose(in_file); *last_update=rrd.live_head->last_up; *ds_cnt = rrd.stat_head->ds_cnt; @@ -50,5 +49,6 @@ rrd_lastupdate(int argc, char **argv, ti } rrd_free(&rrd); + rrd_close(rrd_file); return(0); } Index: src/rrd_tune.c =================================================================== --- src/rrd_tune.c (revision 1064) +++ src/rrd_tune.c (working copy) @@ -51,7 +51,6 @@ int rrd_tune(int argc, char **argv) { rrd_t rrd; - FILE *rrd_file; int matches; int optcnt = 0; long ds; @@ -61,14 +60,15 @@ rrd_tune(int argc, char **argv) double min; double max; char dst[DST_SIZE]; + rrd_file_t *rrd_file; optind = 0; opterr = 0; /* initialize getopt */ - if(rrd_open(argv[1],&rrd_file,&rrd, RRD_READWRITE)==-1){ + rrd_file = rrd_open(argv[1],&rrd,RRD_READWRITE); + if (rrd_file == NULL) { return -1; } - while (1){ static struct option long_options[] = { @@ -102,12 +102,12 @@ rrd_tune(int argc, char **argv) if ((matches = sscanf(optarg, DS_NAM_FMT ":%ld",ds_nam,&heartbeat)) != 2){ rrd_set_error("invalid arguments for heartbeat"); rrd_free(&rrd); - fclose(rrd_file); + close(rrd_file->fd); return -1; } if ((ds=ds_match(&rrd,ds_nam))==-1){ rrd_free(&rrd); - fclose(rrd_file); + close(rrd_file->fd); return -1; } rrd.ds_def[ds].par[DS_mrhb_cnt].u_cnt = heartbeat; @@ -117,12 +117,12 @@ rrd_tune(int argc, char **argv) if ((matches = sscanf(optarg,DS_NAM_FMT ":%lf",ds_nam,&min)) <1){ rrd_set_error("invalid arguments for minimum ds value"); rrd_free(&rrd); - fclose(rrd_file); + close(rrd_file->fd); return -1; } if ((ds=ds_match(&rrd,ds_nam))==-1){ rrd_free(&rrd); - fclose(rrd_file); + close(rrd_file->fd); return -1; } @@ -135,12 +135,12 @@ rrd_tune(int argc, char **argv) if ((matches = sscanf(optarg, DS_NAM_FMT ":%lf",ds_nam,&max)) <1){ rrd_set_error("invalid arguments for maximum ds value"); rrd_free(&rrd); - fclose(rrd_file); + close(rrd_file->fd); return -1; } if ((ds=ds_match(&rrd,ds_nam))==-1){ rrd_free(&rrd); - fclose(rrd_file); + close(rrd_file->fd); return -1; } if(matches == 1) @@ -152,17 +152,17 @@ rrd_tune(int argc, char **argv) if ((matches = sscanf(optarg, DS_NAM_FMT ":" DST_FMT ,ds_nam,dst)) != 2){ rrd_set_error("invalid arguments for data source type"); rrd_free(&rrd); - fclose(rrd_file); + close(rrd_file->fd); return -1; } if ((ds=ds_match(&rrd,ds_nam))==-1){ rrd_free(&rrd); - fclose(rrd_file); + close(rrd_file->fd); return -1; } if ((int)dst_conv(dst) == -1){ rrd_free(&rrd); - fclose(rrd_file); + close(rrd_file->fd); return -1; } strncpy(rrd.ds_def[ds].dst,dst,DST_SIZE-1); @@ -180,12 +180,12 @@ rrd_tune(int argc, char **argv) sscanf(optarg,DS_NAM_FMT ":" DS_NAM_FMT , ds_nam,ds_new)) != 2){ rrd_set_error("invalid arguments for data source type"); rrd_free(&rrd); - fclose(rrd_file); + close(rrd_file->fd); return -1; } if ((ds=ds_match(&rrd,ds_nam))==-1){ rrd_free(&rrd); - fclose(rrd_file); + close(rrd_file->fd); return -1; } strncpy(rrd.ds_def[ds].ds_nam,ds_new,DS_NAM_SIZE-1); @@ -243,19 +243,19 @@ rrd_tune(int argc, char **argv) if (sscanf(optarg,DS_NAM_FMT,ds_nam) != 1){ rrd_set_error("invalid argument for aberrant-reset"); rrd_free(&rrd); - fclose(rrd_file); + close(rrd_file->fd); return -1; } if ((ds=ds_match(&rrd,ds_nam))==-1){ /* ds_match handles it own errors */ rrd_free(&rrd); - fclose(rrd_file); + close(rrd_file->fd); return -1; } reset_aberrant_coefficients(&rrd,rrd_file,(unsigned long) ds); if (rrd_test_error()) { rrd_free(&rrd); - fclose(rrd_file); + close(rrd_file->fd); return -1; } break; @@ -265,20 +265,19 @@ rrd_tune(int argc, char **argv) else rrd_set_error("unknown option '%s'",argv[optind-1]); rrd_free(&rrd); - fclose(rrd_file); + close(rrd_file->fd); return -1; } } if(optcnt>0){ - fseek(rrd_file,0,SEEK_SET); - 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); + rrd_seek(rrd_file,0,SEEK_SET); + rrd_write(rrd_file,rrd.stat_head, sizeof(stat_head_t)*1); + rrd_write(rrd_file,rrd.ds_def, + sizeof(ds_def_t)* rrd.stat_head->ds_cnt); /* need to write rra_defs for RRA parameter changes */ - fwrite(rrd.rra_def, sizeof(rra_def_t), rrd.stat_head->rra_cnt, - rrd_file); + rrd_write(rrd_file,rrd.rra_def, + sizeof(rra_def_t)*rrd.stat_head->rra_cnt); } else { int i; for(i=0;i< (int)rrd.stat_head->ds_cnt;i++) @@ -296,7 +295,7 @@ rrd_tune(int argc, char **argv) free(buffer); } } - fclose(rrd_file); + close(rrd_file->fd); rrd_free(&rrd); return 0; } Index: src/rrd_restore.c =================================================================== --- src/rrd_restore.c (revision 1064) +++ src/rrd_restore.c (working copy) @@ -22,7 +22,7 @@ int skipxml(char **); int eat_tag(char **, char *); int read_tag(char **, char *, char *, void *); int xml2rrd(char*, rrd_t*, char); -int rrd_write(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); @@ -461,7 +461,7 @@ int xml2rrd(char* buf, rrd_t* rrd, char /* create and empty rrd file according to the specs given */ int -rrd_write(char *file_name, rrd_t *rrd, char force_overwrite) +rrd_creat(char *file_name, rrd_t *rrd, char force_overwrite) { unsigned long i,ii,val_cnt; FILE *rrd_file=NULL; @@ -584,7 +584,7 @@ rrd_restore(int argc, char **argv) free(buf); - if(rrd_write(argv[optind+1],&rrd,force_overwrite)==-1){ + if(rrd_creat(argv[optind+1],&rrd,force_overwrite)==-1){ rrd_free(&rrd); return -1; }; Index: src/rrd_first.c =================================================================== --- src/rrd_first.c (revision 1064) +++ src/rrd_first.c (working copy) @@ -55,13 +55,14 @@ rrd_first(int argc, char **argv) time_t rrd_first_r(const char *filename, const int rraindex) { - long rra_start, + off_t rra_start, timer; time_t then; - FILE *in_file; rrd_t rrd; + rrd_file_t *rrd_file; - if(rrd_open(filename,&in_file,&rrd, RRD_READONLY)==-1){ + rrd_file = rrd_open(filename,&rrd, RRD_READONLY); + if (rrd_file == NULL) { rrd_set_error("could not open RRD"); return(-1); } @@ -69,12 +70,12 @@ rrd_first_r(const char *filename, const if((rraindex < 0) || (rraindex >= (int)rrd.stat_head->rra_cnt)) { rrd_set_error("invalid rraindex number"); rrd_free(&rrd); - fclose(in_file); + close(rrd_file->fd); return(-1); } - rra_start = ftell(in_file); - fseek(in_file, + rra_start = rrd_file->header_len; + rrd_seek(rrd_file, (rra_start + (rrd.rra_ptr[rraindex].cur_row+1) * rrd.stat_head->ds_cnt * @@ -82,7 +83,7 @@ rrd_first_r(const char *filename, const SEEK_SET); timer = - (rrd.rra_def[rraindex].row_cnt-1); if (rrd.rra_ptr[rraindex].cur_row + 1 > rrd.rra_def[rraindex].row_cnt) { - fseek(in_file,rra_start,SEEK_SET); + rrd_seek(rrd_file,rra_start,SEEK_SET); } then = (rrd.live_head->last_up - rrd.live_head->last_up % @@ -91,10 +92,8 @@ rrd_first_r(const char *filename, const rrd.rra_def[rraindex].pdp_cnt*rrd.stat_head->pdp_step); rrd_free(&rrd); - fclose(in_file); + close(rrd_file->fd); + rrd_close(rrd_file); return(then); } - - - Index: src/rrd_info.c =================================================================== --- src/rrd_info.c (revision 1064) +++ src/rrd_info.c (working copy) @@ -83,17 +83,18 @@ rrd_info(int argc, char **argv) { info_t * rrd_info_r(char *filename) { unsigned int i,ii=0; - FILE *in_file; rrd_t rrd; info_t *data,*cd; infoval info; + rrd_file_t* rrd_file; enum cf_en current_cf; enum dst_en current_ds; - if(rrd_open(filename,&in_file,&rrd, RRD_READONLY)==-1){ + rrd_file = rrd_open(filename,&rrd, RRD_READONLY); + if (rrd_file == NULL) { return(NULL); } - fclose(in_file); + close(rrd_file->fd); info.u_str=filename; cd=info_push(NULL,sprintf_alloc("filename"), RD_I_STR, info); @@ -233,6 +234,7 @@ rrd_info_r(char *filename) { } } rrd_free(&rrd); + rrd_close(rrd_file); return(data); } Index: src/unused.h =================================================================== --- src/unused.h (revision 1064) +++ src/unused.h (working copy) @@ -1,5 +1,8 @@ -/* define a macro to wrap variables in that would - otherwhise generate UNUSED variable warnings */ +/* define a macro to wrap variables that would + otherwise generate UNUSED variable warnings + Note that GCC's attribute unused only supresses the warning, so + it is perfectly safe to declare something unused although it is not. +*/ #ifdef UNUSED #elif defined(__GNUC__) Index: src/rrd_last.c =================================================================== --- src/rrd_last.c (revision 1064) +++ src/rrd_last.c (working copy) @@ -23,17 +23,18 @@ rrd_last(int argc, char **argv) time_t rrd_last_r(const char *filename) { - FILE *in_file; time_t lastup; + rrd_file_t* rrd_file; rrd_t rrd; - if(rrd_open(filename, &in_file, &rrd, RRD_READONLY)==-1){ + rrd_file = rrd_open(filename, &rrd, RRD_READONLY); + if (rrd_file == NULL) return(-1); - } + lastup = rrd.live_head->last_up; rrd_free(&rrd); - fclose(in_file); + rrd_close(rrd_file); return(lastup); } Index: src/rrd_thread_safe.c =================================================================== --- src/rrd_thread_safe.c (revision 1064) +++ src/rrd_thread_safe.c (working copy) @@ -52,7 +52,7 @@ struct rrd_context *rrd_get_context(void const char *rrd_strerror(int err) { struct rrd_context *ctx = rrd_get_context(); if (strerror_r(err, ctx->lib_errstr, ctx->errlen)) - return "strerror_r faild. sorry!"; + return "strerror_r failed. sorry!"; else return ctx->lib_errstr; } Index: src/rrd_hw.c =================================================================== --- src/rrd_hw.c (revision 1064) +++ src/rrd_hw.c (working copy) @@ -108,7 +108,7 @@ update_hwpredict(rrd_t *rrd, unsigned lo int lookup_seasonal(rrd_t *rrd, unsigned long rra_idx, unsigned long rra_start, - FILE *rrd_file, unsigned long offset, rrd_value_t **seasonal_coef) + rrd_file_t* rrd_file, unsigned long offset, rrd_value_t **seasonal_coef) { unsigned long pos_tmp; /* rra_ptr[].cur_row points to the rra row to be written; this function @@ -131,10 +131,10 @@ lookup_seasonal(rrd_t *rrd, unsigned lon return -1; } - if (!fseek(rrd_file,pos_tmp,SEEK_SET)) + if (!rrd_seek(rrd_file,pos_tmp,SEEK_SET)) { - if (fread(*seasonal_coef,sizeof(rrd_value_t),rrd->stat_head->ds_cnt,rrd_file) - == rrd -> stat_head -> ds_cnt) + if (rrd_read(rrd_file,*seasonal_coef,sizeof(rrd_value_t)*rrd->stat_head->ds_cnt) + == (ssize_t)(sizeof(rrd_value_t)*rrd->stat_head->ds_cnt)) { /* success! */ /* we can safely ignore the rule requiring a seek operation between read @@ -511,7 +511,7 @@ erase_violations(rrd_t *rrd, unsigned lo * length = 5% of the period. */ int apply_smoother(rrd_t *rrd, unsigned long rra_idx, unsigned long rra_start, - FILE *rrd_file) + rrd_file_t *rrd_file) { unsigned long i, j, k; unsigned long totalbytes; @@ -536,21 +536,23 @@ apply_smoother(rrd_t *rrd, unsigned long } /* rra_start is at the beginning of this rra */ - if (fseek(rrd_file,rra_start,SEEK_SET)) + if (rrd_seek(rrd_file,rra_start,SEEK_SET)) { rrd_set_error("seek to rra %d failed", rra_start); free(rrd_values); return -1; } - fflush(rrd_file); + rrd_flush(rrd_file); /* could read all data in a single block, but we need to * check for NA values */ for (i = 0; i < row_count; ++i) { for (j = 0; j < row_length; ++j) { - fread(&(rrd_values[i*row_length + j]),sizeof(rrd_value_t),1,rrd_file); - /* should check fread for errors... */ + if (rrd_read(rrd_file, &(rrd_values[i*row_length + j]),sizeof(rrd_value_t)*1) + != (ssize_t)(sizeof(rrd_value_t)*1)) { + rrd_set_error("reading value failed: %s", rrd_strerror(errno)); + } if (isnan(rrd_values[i*row_length + j])) { /* can't apply smoothing, still uninitialized values */ #ifdef DEBUG @@ -627,8 +629,8 @@ apply_smoother(rrd_t *rrd, unsigned long (rrd->cdp_prep[offset]).scratch[CDP_hw_intercept].u_val += baseline[j]; } /* flush cdp to disk */ - fflush(rrd_file); - if (fseek(rrd_file,sizeof(stat_head_t) + + rrd_flush(rrd_file); + if (rrd_seek(rrd_file,sizeof(stat_head_t) + rrd->stat_head->ds_cnt * sizeof(ds_def_t) + rrd->stat_head->rra_cnt * sizeof(rra_def_t) + sizeof(live_head_t) + @@ -638,11 +640,11 @@ apply_smoother(rrd_t *rrd, unsigned long free(rrd_values); return -1; } - if (fwrite( rrd -> cdp_prep, - sizeof(cdp_prep_t), - (rrd->stat_head->rra_cnt) * rrd->stat_head->ds_cnt, rrd_file) - != (rrd->stat_head->rra_cnt) * (rrd->stat_head->ds_cnt) ) - { + if (rrd_write(rrd_file, rrd -> cdp_prep, + sizeof(cdp_prep_t)* + (rrd->stat_head->rra_cnt) * rrd->stat_head->ds_cnt) + != (ssize_t)(sizeof(cdp_prep_t)*(rrd->stat_head->rra_cnt) * (rrd->stat_head->ds_cnt))) + { rrd_set_error("apply_smoother: cdp_prep write failed"); free(rrd_values); return -1; @@ -650,23 +652,23 @@ apply_smoother(rrd_t *rrd, unsigned long } /* endif CF_SEASONAL */ /* flush updated values to disk */ - fflush(rrd_file); - if (fseek(rrd_file,rra_start,SEEK_SET)) + rrd_flush(rrd_file); + if (rrd_seek(rrd_file,rra_start,SEEK_SET)) { rrd_set_error("apply_smoother: seek to pos %d failed", rra_start); free(rrd_values); return -1; } /* write as a single block */ - if (fwrite(rrd_values,sizeof(rrd_value_t),row_length*row_count,rrd_file) - != row_length*row_count) + if (rrd_write(rrd_file,rrd_values,sizeof(rrd_value_t)*row_length*row_count) + != (ssize_t)(sizeof(rrd_value_t)*row_length*row_count)) { rrd_set_error("apply_smoother: write failed to %lu",rra_start); free(rrd_values); return -1; } - fflush(rrd_file); + rrd_flush(rrd_file); free(rrd_values); free(baseline); return 0; @@ -675,7 +677,7 @@ apply_smoother(rrd_t *rrd, unsigned long /* Reset aberrant behavior model coefficients, including intercept, slope, * seasonal, and seasonal deviation for the specified data source. */ void -reset_aberrant_coefficients(rrd_t *rrd, FILE *rrd_file, unsigned long ds_idx) +reset_aberrant_coefficients(rrd_t *rrd, rrd_file_t *rrd_file, unsigned long ds_idx) { unsigned long cdp_idx, rra_idx, i; unsigned long cdp_start, rra_start; @@ -709,19 +711,19 @@ reset_aberrant_coefficients(rrd_t *rrd, rrd->cdp_prep[cdp_idx].scratch[CDP_hw_seasonal].u_val = DNAN; rrd->cdp_prep[cdp_idx].scratch[CDP_hw_last_seasonal].u_val = DNAN; /* move to first entry of data source for this rra */ - fseek(rrd_file,rra_start + ds_idx * sizeof(rrd_value_t),SEEK_SET); + rrd_seek(rrd_file,rra_start + ds_idx * sizeof(rrd_value_t),SEEK_SET); /* entries for the same data source are not contiguous, * temporal entries are contiguous */ for (i = 0; i < rrd->rra_def[rra_idx].row_cnt; ++i) { - if (fwrite(&nan_buffer,sizeof(rrd_value_t),1,rrd_file) != 1) + if (rrd_write(rrd_file,&nan_buffer,sizeof(rrd_value_t)*1) != sizeof(rrd_value_t)*1) { rrd_set_error( "reset_aberrant_coefficients: write failed data source %lu rra %s", ds_idx,rrd->rra_def[rra_idx].cf_nam); return; } - fseek(rrd_file,(rrd->stat_head->ds_cnt - 1) * + rrd_seek(rrd_file,(rrd->stat_head->ds_cnt - 1) * sizeof(rrd_value_t),SEEK_CUR); } break; @@ -735,14 +737,14 @@ reset_aberrant_coefficients(rrd_t *rrd, rra_start += rrd->rra_def[rra_idx].row_cnt * rrd->stat_head->ds_cnt * sizeof(rrd_value_t); } - fseek(rrd_file,cdp_start,SEEK_SET); - if (fwrite( rrd -> cdp_prep, - sizeof(cdp_prep_t), - (rrd->stat_head->rra_cnt) * rrd->stat_head->ds_cnt, rrd_file) - != (rrd->stat_head->rra_cnt) * (rrd->stat_head->ds_cnt) ) + rrd_seek(rrd_file,cdp_start,SEEK_SET); + if (rrd_write(rrd_file,rrd->cdp_prep, + sizeof(cdp_prep_t)* + (rrd->stat_head->rra_cnt) * rrd->stat_head->ds_cnt) + != (ssize_t)(sizeof(cdp_prep_t)*(rrd->stat_head->rra_cnt) * (rrd->stat_head->ds_cnt))) { rrd_set_error("reset_aberrant_coefficients: cdp_prep write failed"); - return; + return;/*XXX: delme */ } } Index: src/rrd_update.c =================================================================== --- src/rrd_update.c (revision 1064) +++ src/rrd_update.c (working copy) @@ -70,21 +70,21 @@ static void normalize_time(struct timeva } /* Local prototypes */ -int LockRRD(FILE *rrd_file); +int LockRRD(int in_file); #ifdef HAVE_MMAP info_t *write_RRA_row (rrd_t *rrd, unsigned long rra_idx, unsigned long *rra_current, unsigned short CDP_scratch_idx, #ifndef DEBUG -FILE UNUSED(*rrd_file), +int UNUSED(in_file), #else -FILE *rrd_file, +int in_file, #endif info_t *pcdp_summary, time_t *rra_time, void *rrd_mmaped_file); #else info_t *write_RRA_row (rrd_t *rrd, unsigned long rra_idx, unsigned long *rra_current, - unsigned short CDP_scratch_idx, FILE *rrd_file, + unsigned short CDP_scratch_idx, int in_file, info_t *pcdp_summary, time_t *rra_time); #endif int rrd_update_r(const char *filename, const char *tmplt, int argc, const char **argv); @@ -234,7 +234,6 @@ _rrd_update(const char *filename, const transported by the tmplt index */ unsigned long tmpl_cnt = 2; /* time and data */ - FILE *rrd_file; rrd_t rrd; time_t current_time = 0; time_t rra_time = 0; /* time of update for a RRA */ @@ -261,12 +260,7 @@ _rrd_update(const char *filename, const rpnstack_t rpnstack; /* used for COMPUTE DS */ int version; /* rrd version */ char *endptr; /* used in the conversion */ - -#ifdef HAVE_MMAP - void *rrd_mmaped_file; - unsigned long rrd_filesize; -#endif - + rrd_file_t* rrd_file; rpnstack_init(&rpnstack); @@ -275,10 +269,9 @@ _rrd_update(const char *filename, const rrd_set_error("Not enough arguments"); return -1; } - - - if(rrd_open(filename,&rrd_file,&rrd, RRD_READWRITE)==-1){ + rrd_file = rrd_open(filename,&rrd, RRD_READWRITE); + if (rrd_file == NULL) { return -1; } @@ -294,39 +287,40 @@ _rrd_update(const char *filename, const current_time_usec = 0; } - rra_current = rra_start = rra_begin = ftell(rrd_file); + rra_current = rra_start = rra_begin = rrd_file->header_len; /* This is defined in the ANSI C standard, section 7.9.5.3: When a file is opened with udpate mode ('+' as the second or third character in the ... list of mode argument - variables), both input and ouptut may be performed on the + variables), both input and output may be performed on the associated stream. However, ... input may not be directly followed by output without an intervening call to a file - positioning function, unless the input oepration encounters + positioning function, unless the input operation encounters end-of-file. */ -#ifdef HAVE_MMAP - fseek(rrd_file, 0, SEEK_END); - rrd_filesize = ftell(rrd_file); - fseek(rrd_file, rra_current, SEEK_SET); +#if 0//def HAVE_MMAP +rrd_filesize = rrd_file->file_size; + fseek(rrd_file->fd, 0, SEEK_END); + rrd_filesize = ftell(rrd_file->fd); + fseek(rrd_file->fd, rra_current, SEEK_SET); #else - fseek(rrd_file, 0, SEEK_CUR); +// fseek(rrd_file->fd, 0, SEEK_CUR); #endif /* get exclusive lock to whole file. * lock gets removed when we close the file. */ - if (LockRRD(rrd_file) != 0) { + if (LockRRD(rrd_file->fd) != 0) { rrd_set_error("could not lock RRD"); rrd_free(&rrd); - fclose(rrd_file); + close(rrd_file->fd); return(-1); } if((updvals = malloc( sizeof(char*) * (rrd.stat_head->ds_cnt+1)))==NULL){ rrd_set_error("allocating updvals pointer array"); rrd_free(&rrd); - fclose(rrd_file); + close(rrd_file->fd); return(-1); } @@ -335,7 +329,7 @@ _rrd_update(const char *filename, const rrd_set_error("allocating pdp_temp ..."); free(updvals); rrd_free(&rrd); - fclose(rrd_file); + close(rrd_file->fd); return(-1); } @@ -345,7 +339,7 @@ _rrd_update(const char *filename, const free(pdp_temp); free(updvals); rrd_free(&rrd); - fclose(rrd_file); + close(rrd_file->fd); return(-1); } /* initialize tmplt redirector */ @@ -377,14 +371,14 @@ _rrd_update(const char *filename, const rrd_set_error("tmplt contains more DS definitions than RRD"); free(updvals); free(pdp_temp); free(tmpl_idx); rrd_free(&rrd); - fclose(rrd_file); return(-1); + close(rrd_file->fd); return(-1); } if ((tmpl_idx[tmpl_cnt++] = ds_match(&rrd,dsname)) == -1){ rrd_set_error("unknown DS name '%s'",dsname); free(updvals); free(pdp_temp); free(tmplt_copy); free(tmpl_idx); rrd_free(&rrd); - fclose(rrd_file); return(-1); + close(rrd_file->fd); return(-1); } else { /* the first element is always the time */ tmpl_idx[tmpl_cnt-1]++; @@ -407,16 +401,16 @@ _rrd_update(const char *filename, const free(pdp_temp); free(tmpl_idx); rrd_free(&rrd); - fclose(rrd_file); + close(rrd_file->fd); return(-1); } -#ifdef HAVE_MMAP +#if 0//def HAVE_MMAP rrd_mmaped_file = mmap(0, - rrd_filesize, + rrd_file->file_len, PROT_READ | PROT_WRITE, MAP_SHARED, - fileno(rrd_file), + fileno(in_file), 0); if (rrd_mmaped_file == MAP_FAILED) { rrd_set_error("error mmapping file %s", filename); @@ -424,7 +418,7 @@ _rrd_update(const char *filename, const free(pdp_temp); free(tmpl_idx); rrd_free(&rrd); - fclose(rrd_file); + close(rrd_file->fd); return(-1); } #endif @@ -444,9 +438,9 @@ _rrd_update(const char *filename, const free(tmpl_idx); rrd_free(&rrd); #ifdef HAVE_MMAP - munmap(rrd_mmaped_file, rrd_filesize); + rrd_close(rrd_file); #endif - fclose(rrd_file); + close(rrd_file->fd); return(-1); } /* initialize all ds input to unknown except the first one @@ -537,7 +531,7 @@ _rrd_update(const char *filename, const /* seek to the beginning of the rra's */ if (rra_current != rra_begin) { #ifndef HAVE_MMAP - if(fseek(rrd_file, rra_begin, SEEK_SET) != 0) { + if(rrd_seek(rrd_file, rra_begin, SEEK_SET) != 0) { rrd_set_error("seek error in rrd"); free(step_start); break; @@ -934,7 +928,7 @@ _rrd_update(const char *filename, const } } - rra_current = ftell(rrd_file); + rra_current = rrd_tell(rrd_file); } /* if cf is DEVSEASONAL or SEASONAL */ if (rrd_test_error()) break; @@ -1169,7 +1163,7 @@ _rrd_update(const char *filename, const lookup_seasonal(&rrd,i,rra_start,rrd_file, elapsed_pdp_st + (scratch_idx == CDP_primary_val ? 1 : 2), &seasonal_coef); - rra_current = ftell(rrd_file); + rra_current = rrd_tell(rrd_file); } if (rrd_test_error()) break; /* loop over data soures within each RRA */ @@ -1200,7 +1194,7 @@ _rrd_update(const char *filename, const /* write the first row */ #ifdef DEBUG - fprintf(stderr," -- RRA Preseek %ld\n",ftell(rrd_file)); + fprintf(stderr," -- RRA Preseek %ld\n",rrd_file->pos); #endif rrd.rra_ptr[i].cur_row++; if (rrd.rra_ptr[i].cur_row >= rrd.rra_def[i].row_cnt) @@ -1210,7 +1204,7 @@ _rrd_update(const char *filename, const (rrd.stat_head->ds_cnt)*(rrd.rra_ptr[i].cur_row)*sizeof(rrd_value_t); if(rra_pos_tmp != rra_current) { #ifndef HAVE_MMAP - if(fseek(rrd_file, rra_pos_tmp, SEEK_SET) != 0){ + if(rrd_seek(rrd_file, rra_pos_tmp, SEEK_SET) != 0){ rrd_set_error("seek error in rrd"); break; } @@ -1219,7 +1213,7 @@ _rrd_update(const char *filename, const } #ifdef DEBUG - fprintf(stderr," -- RRA Postseek %ld\n",ftell(rrd_file)); + fprintf(stderr," -- RRA Postseek %ld\n",rrd_file->pos); #endif scratch_idx = CDP_primary_val; if (pcdp_summary != NULL) @@ -1229,10 +1223,10 @@ _rrd_update(const char *filename, const - ((rra_step_cnt[i]-1)*rrd.rra_def[i].pdp_cnt*rrd.stat_head->pdp_step); } #ifdef HAVE_MMAP - pcdp_summary = write_RRA_row(&rrd, i, &rra_current, scratch_idx, rrd_file, - pcdp_summary, &rra_time, rrd_mmaped_file); + pcdp_summary = write_RRA_row(&rrd, i, &rra_current, scratch_idx, rrd_file->fd, + pcdp_summary, &rra_time, rrd_file->file_start); #else - pcdp_summary = write_RRA_row(&rrd, i, &rra_current, scratch_idx, rrd_file, + pcdp_summary = write_RRA_row(&rrd, i, &rra_current, scratch_idx, rrd_file->fd, pcdp_summary, &rra_time); #endif if (rrd_test_error()) break; @@ -1250,13 +1244,13 @@ _rrd_update(const char *filename, const /* wrap */ rrd.rra_ptr[i].cur_row = 0; /* seek back to beginning of current rra */ - if (fseek(rrd_file, rra_start, SEEK_SET) != 0) + if (rrd_seek(rrd_file, rra_start, SEEK_SET) != 0) { rrd_set_error("seek error in rrd"); break; } #ifdef DEBUG - fprintf(stderr," -- Wraparound Postseek %ld\n",ftell(rrd_file)); + fprintf(stderr," -- Wraparound Postseek %ld\n",rrd_file->pos); #endif rra_current = rra_start; } @@ -1267,10 +1261,10 @@ _rrd_update(const char *filename, const - ((rra_step_cnt[i]-2)*rrd.rra_def[i].pdp_cnt*rrd.stat_head->pdp_step); } #ifdef HAVE_MMAP - pcdp_summary = write_RRA_row(&rrd, i, &rra_current, scratch_idx, rrd_file, - pcdp_summary, &rra_time, rrd_mmaped_file); + pcdp_summary = write_RRA_row(&rrd, i, &rra_current, scratch_idx, rrd_file->fd, + pcdp_summary, &rra_time, rrd_file->file_start); #else - pcdp_summary = write_RRA_row(&rrd, i, &rra_current, scratch_idx, rrd_file, + pcdp_summary = write_RRA_row(&rrd, i, &rra_current, scratch_idx, rrd_file->fd, pcdp_summary, &rra_time); #endif } @@ -1297,7 +1291,7 @@ _rrd_update(const char *filename, const rpnstack_free(&rpnstack); #ifdef HAVE_MMAP - if (munmap(rrd_mmaped_file, rrd_filesize) == -1) { + if (munmap(rrd_file->file_start, rrd_file->file_len) == -1) { rrd_set_error("error writing(unmapping) file: %s", filename); } #endif @@ -1309,14 +1303,14 @@ _rrd_update(const char *filename, const rrd_free(&rrd); free(pdp_temp); free(pdp_new); - fclose(rrd_file); + close(rrd_file->fd); return(-1); } /* aargh ... that was tough ... so many loops ... anyway, its done. * we just need to write back the live header portion now*/ - if (fseek(rrd_file, (sizeof(stat_head_t) + if (rrd_seek(rrd_file, (sizeof(stat_head_t) + sizeof(ds_def_t)*rrd.stat_head->ds_cnt + sizeof(rra_def_t)*rrd.stat_head->rra_cnt), SEEK_SET) != 0) { @@ -1326,76 +1320,75 @@ _rrd_update(const char *filename, const rrd_free(&rrd); free(pdp_temp); free(pdp_new); - fclose(rrd_file); + close(rrd_file->fd); return(-1); } if(version >= 3) { - if(fwrite( rrd.live_head, - sizeof(live_head_t), 1, rrd_file) != 1){ - rrd_set_error("fwrite live_head to rrd"); + if(rrd_write(rrd_file, rrd.live_head, + sizeof(live_head_t)*1) != sizeof(live_head_t)*1){ + rrd_set_error("rrd_write live_head to rrd"); free(updvals); rrd_free(&rrd); free(tmpl_idx); free(pdp_temp); free(pdp_new); - fclose(rrd_file); + close(rrd_file->fd); return(-1); } } else { - if(fwrite( &rrd.live_head->last_up, - sizeof(time_t), 1, rrd_file) != 1){ - rrd_set_error("fwrite live_head to rrd"); + if(rrd_write(rrd_file, &rrd.live_head->last_up, + sizeof(time_t)*1) != sizeof(time_t)*1){ + rrd_set_error("rrd_write live_head to rrd"); free(updvals); rrd_free(&rrd); free(tmpl_idx); free(pdp_temp); free(pdp_new); - fclose(rrd_file); + close(rrd_file->fd); return(-1); } } - if(fwrite( rrd.pdp_prep, - sizeof(pdp_prep_t), - rrd.stat_head->ds_cnt, rrd_file) != rrd.stat_head->ds_cnt){ - rrd_set_error("ftwrite pdp_prep to rrd"); + if(rrd_write(rrd_file, rrd.pdp_prep, + sizeof(pdp_prep_t)*rrd.stat_head->ds_cnt) + != (ssize_t)(sizeof(pdp_prep_t)*rrd.stat_head->ds_cnt)){ + rrd_set_error("rrd_write pdp_prep to rrd"); free(updvals); rrd_free(&rrd); free(tmpl_idx); free(pdp_temp); free(pdp_new); - fclose(rrd_file); + close(rrd_file->fd); return(-1); } - if(fwrite( rrd.cdp_prep, - sizeof(cdp_prep_t), - rrd.stat_head->rra_cnt *rrd.stat_head->ds_cnt, rrd_file) - != rrd.stat_head->rra_cnt *rrd.stat_head->ds_cnt){ + if(rrd_write(rrd_file, rrd.cdp_prep, + sizeof(cdp_prep_t)*rrd.stat_head->rra_cnt *rrd.stat_head->ds_cnt) + != (ssize_t)(sizeof(cdp_prep_t)*rrd.stat_head->rra_cnt *rrd.stat_head->ds_cnt)){ - rrd_set_error("ftwrite cdp_prep to rrd"); + rrd_set_error("rrd_write cdp_prep to rrd"); free(updvals); free(tmpl_idx); rrd_free(&rrd); free(pdp_temp); free(pdp_new); - fclose(rrd_file); + close(rrd_file->fd); return(-1); } - if(fwrite( rrd.rra_ptr, - sizeof(rra_ptr_t), - rrd.stat_head->rra_cnt,rrd_file) != rrd.stat_head->rra_cnt){ - rrd_set_error("fwrite rra_ptr to rrd"); + if(rrd_write(rrd_file, rrd.rra_ptr, + sizeof(rra_ptr_t)* rrd.stat_head->rra_cnt) + != (ssize_t)(sizeof(rra_ptr_t)*rrd.stat_head->rra_cnt)){ + rrd_set_error("rrd_write rra_ptr to rrd"); free(updvals); free(tmpl_idx); rrd_free(&rrd); free(pdp_temp); free(pdp_new); - fclose(rrd_file); + close(rrd_file->fd); return(-1); } #ifdef HAVE_POSIX_FADVISE @@ -1405,23 +1398,13 @@ _rrd_update(const char *filename, const will let the data off the hook as soon as it is written when if it is from a previous update cycle. Calling fdsync to force things is much too hard here. */ - if (0 != posix_fadvise(fileno(rrd_file), rra_begin, 0, POSIX_FADV_DONTNEED)) { + if (0 != posix_fadvise(rrd_file->fd, rra_begin, 0, POSIX_FADV_DONTNEED)) { rrd_set_error("setting POSIX_FADV_DONTNEED on '%s': %s",filename, rrd_strerror(errno)); - fclose(rrd_file); + close(rrd_file->fd); return(-1); } #endif - - /* OK now close the files and free the memory */ - if(fclose(rrd_file) != 0){ - rrd_set_error("closing rrd"); - free(updvals); - free(tmpl_idx); - rrd_free(&rrd); - free(pdp_temp); - free(pdp_new); - return(-1); - } + /*XXX: ? */rrd_flush(rrd_file); /* calling the smoothing code here guarantees at most * one smoothing operation per rrd_update call. Unfortunately, @@ -1430,7 +1413,7 @@ _rrd_update(const char *filename, const * critical except during the burning cycles. */ if (schedule_smooth) { - rrd_file = fopen(filename,"rb+"); +// in_file = fopen(filename,"rb+"); rra_start = rra_begin; @@ -1451,14 +1434,26 @@ _rrd_update(const char *filename, const } #ifdef HAVE_POSIX_FADVISE /* same procedure as above ... */ - if (0 != posix_fadvise(fileno(rrd_file), rra_begin, 0, POSIX_FADV_DONTNEED)) { + if (0 != posix_fadvise(rrd_file->fd, rra_begin, 0, POSIX_FADV_DONTNEED)) { rrd_set_error("setting POSIX_FADV_DONTNEED on '%s': %s",filename, rrd_strerror(errno)); - fclose(rrd_file); + close(rrd_file->fd); return(-1); } #endif - fclose(rrd_file); + close(rrd_file->fd); } + + /* OK now close the files and free the memory */ + if(close(rrd_file->fd) != 0){ + rrd_set_error("closing rrd"); + free(updvals); + free(tmpl_idx); + rrd_free(&rrd); + free(pdp_temp); + free(pdp_new); + return(-1); + } + rrd_free(&rrd); free(updvals); free(tmpl_idx); @@ -1474,19 +1469,16 @@ _rrd_update(const char *filename, const * returns 0 on success */ int -LockRRD(FILE *rrdfile) +LockRRD(int in_file) { - int rrd_fd; /* File descriptor for RRD */ int rcstat; - rrd_fd = fileno(rrdfile); - { #if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__CYGWIN32__) struct _stat st; - if ( _fstat( rrd_fd, &st ) == 0 ) { - rcstat = _locking ( rrd_fd, _LK_NBLCK, st.st_size ); + if ( _fstat( in_file, &st ) == 0 ) { + rcstat = _locking ( in_file, _LK_NBLCK, st.st_size ); } else { rcstat = -1; } @@ -1497,7 +1489,7 @@ LockRRD(FILE *rrdfile) lock.l_start = 0; /* start of file */ lock.l_whence = SEEK_SET; /* end of file */ - rcstat = fcntl(rrd_fd, F_SETLK, &lock); + rcstat = fcntl(in_file, F_SETLK, &lock); #endif } @@ -1510,15 +1502,15 @@ info_t *write_RRA_row (rrd_t *rrd, unsigned long rra_idx, unsigned long *rra_current, unsigned short CDP_scratch_idx, #ifndef DEBUG -FILE UNUSED(*rrd_file), +int UNUSED(in_file), #else -FILE *rrd_file, +int in_file, #endif info_t *pcdp_summary, time_t *rra_time, void *rrd_mmaped_file) #else info_t *write_RRA_row (rrd_t *rrd, unsigned long rra_idx, unsigned long *rra_current, - unsigned short CDP_scratch_idx, FILE *rrd_file, + unsigned short CDP_scratch_idx, int in_file, info_t *pcdp_summary, time_t *rra_time) #endif { @@ -1531,7 +1523,7 @@ info_t cdp_idx =rra_idx * (rrd -> stat_head->ds_cnt) + ds_idx; #ifdef DEBUG fprintf(stderr," -- RRA WRITE VALUE %e, at %ld CF:%s\n", - rrd -> cdp_prep[cdp_idx].scratch[CDP_scratch_idx].u_val,ftell(rrd_file), + rrd -> cdp_prep[cdp_idx].scratch[CDP_scratch_idx].u_val,rrd_file->pos, rrd -> rra_def[rra_idx].cf_nam); #endif if (pcdp_summary != NULL) @@ -1549,8 +1541,8 @@ info_t &(rrd -> cdp_prep[cdp_idx].scratch[CDP_scratch_idx].u_val), sizeof(rrd_value_t)); #else - if(fwrite(&(rrd -> cdp_prep[cdp_idx].scratch[CDP_scratch_idx].u_val), - sizeof(rrd_value_t),1,rrd_file) != 1) + if(rrd_write(rrd_file,&(rrd -> cdp_prep[cdp_idx].scratch[CDP_scratch_idx].u_val), + sizeof(rrd_value_t)*1) != sizeof(rrd_value_t)*1) { rrd_set_error("writing rrd"); return 0; Index: src/rrd_tool.h =================================================================== --- src/rrd_tool.h (revision 1064) +++ src/rrd_tool.h (working copy) @@ -171,11 +171,18 @@ void rrd_free(rrd_t *rrd); void rrd_freemem(void *mem); void rrd_init(rrd_t *rrd); -int rrd_open(const char *file_name, FILE **in_file, rrd_t *rrd, int rdwr); +rrd_file_t* rrd_open(const char * const file_name, rrd_t *rrd, unsigned rdwr); +int rrd_close(rrd_file_t* rrd_file); +ssize_t rrd_read(rrd_file_t* rrd_file, void*buf, size_t count); +ssize_t rrd_write(rrd_file_t* rrd_file, const void*buf, size_t count); +void rrd_flush(rrd_file_t* rrd_file); +off_t rrd_seek(rrd_file_t* rrd_file, off_t off, int whence); +off_t rrd_tell(rrd_file_t* rrd_file); int readfile(const char *file, char **buffer, int skipfirst); #define RRD_READONLY 0 #define RRD_READWRITE 1 +#define RRD_CREAT 2 enum cf_en cf_conv(const char *string); enum dst_en dst_conv(char *string); Index: src/rrd_hw.h =================================================================== --- src/rrd_hw.h (revision 1064) +++ src/rrd_hw.h (working copy) @@ -11,11 +11,11 @@ int update_aberrant_CF(rrd_t *rrd, rrd_v int create_hw_contingent_rras(rrd_t *rrd, unsigned short period, unsigned long hashed_name); int lookup_seasonal(rrd_t *rrd, unsigned long rra_idx, unsigned long rra_start, - FILE *rrd_file, unsigned long offset, rrd_value_t **seasonal_coef); + rrd_file_t* rrd_file, unsigned long offset, rrd_value_t **seasonal_coef); void erase_violations(rrd_t *rrd, unsigned long cdp_idx, unsigned long rra_idx); int apply_smoother(rrd_t *rrd, unsigned long rra_idx, unsigned long rra_start, - FILE *rrd_file); -void reset_aberrant_coefficients(rrd_t *rrd, FILE *rrd_file, unsigned long ds_idx); + rrd_file_t *rrd_file); +void reset_aberrant_coefficients(rrd_t *rrd, rrd_file_t *rrd_file, unsigned long ds_idx); void init_hwpredict_cdp(cdp_prep_t *); void init_seasonal_cdp(cdp_prep_t *); #define BURNIN_CYCLES 3 Index: src/rrd.h =================================================================== --- src/rrd.h (revision 1064) +++ src/rrd.h (working copy) @@ -52,6 +52,8 @@ extern "C" { #ifndef _RRDLIB_H #define _RRDLIB_H +#include /* for off_t */ +#include /* for off_t */ #include #include /* for FILE */ @@ -60,6 +62,15 @@ typedef double rrd_value_t; * double */ /* END rrd_format.h */ +/* information about an rrd file */ +typedef struct rrd_file_t { + int fd; /* file descriptor if this rrd file */ + char* file_start; /* start address of an open rrd file */ + off_t header_len; /* length of the header of this rrd file */ + off_t file_len; /* total size of the rrd file */ + off_t pos; /* current pos in file */ +} rrd_file_t; + /* main function blocks */ int rrd_create(int, char **); int rrd_update(int, char **); @@ -143,7 +154,7 @@ void rrd_free_context (struct rrd_cont /* int rrd_test_error_r (struct rrd_context *); */ /* char *rrd_get_error_r (struct rrd_context *); */ -int LockRRD(FILE *); +int LockRRD(int in_file); #endif /* _RRDLIB_H */ Index: src/rrd_open.c =================================================================== --- src/rrd_open.c (revision 1064) +++ src/rrd_open.c (working copy) @@ -63,39 +63,62 @@ *****************************************************************************/ #include "rrd_tool.h" +#include "unused.h" #define MEMBLK 8192 /* open a database file, return its header and a open filehandle */ /* positioned to the first cdp in the first rra */ -int -rrd_open(const char *file_name, FILE **in_file, rrd_t *rrd, int rdwr) +rrd_file_t* +rrd_open(const char * const file_name, rrd_t *rrd, unsigned rdwr) { + int flags = 0; + mode_t mode = S_IRUSR; + int version, prot = PROT_READ; + off_t offset = 0; + char *data; + struct stat statb; + rrd_file_t *rrd_file = malloc(sizeof(rrd_file_t)); + if (rrd_file == NULL) { + rrd_set_error("allocating rrd_file descriptor for '%s'", + file_name); + return NULL; + } + memset(rrd_file, 0, sizeof(rrd_file_t)); + rrd_init(rrd); + if (rdwr == RRD_READWRITE) { + mode |= S_IWUSR; + prot |= PROT_WRITE; + } else if (rdwr == RRD_CREAT) { + mode |= S_IWUSR; + prot |= PROT_WRITE; + flags |= (O_CREAT|O_TRUNC); + } +#ifdef O_NONBLOCK + flags |= O_NONBLOCK; +#endif - - char *mode = NULL; - int version; - - rrd_init(rrd); - if (rdwr == RRD_READONLY) { - mode = "rb"; - } else { - mode = "rb+"; - } - - if (((*in_file) = fopen(file_name,mode)) == NULL ){ - rrd_set_error("opening '%s': %s",file_name, rrd_strerror(errno)); - return (-1); - } + if ((rrd_file->fd = open(file_name, flags, mode)) < 0 ){ + rrd_set_error("opening '%s': %s",file_name, rrd_strerror(errno)); + return NULL; + } + + /* ???: length = lseek(rrd_file->fd, 0, SEEK_END); */ + /* ??? locking the whole area of the file may overdo it a bit, does it? */ + if ((fstat(rrd_file->fd, &statb)) < 0) { + rrd_set_error("fstat '%s': %s",file_name, rrd_strerror(errno)); + goto out_close; + } + rrd_file->file_len = statb.st_size; #ifdef HAVE_POSIX_FADVISE /* In general we need no read-ahead when dealing with rrd_files. When we stop reading, it is highly unlikely that we start up again. In this manner we actually save time and diskaccess (and buffer cache). Thanks to Dave Plonka for the Idea of using POSIX_FADV_RANDOM here. */ - if (0 != posix_fadvise(fileno(*in_file), 0, 0, POSIX_FADV_RANDOM)) { + if (0 != posix_fadvise(rrd_file->fd, 0, 0, POSIX_FADV_RANDOM)) { rrd_set_error("setting POSIX_FADV_RANDOM on '%s': %s",file_name, rrd_strerror(errno)); - fclose(*in_file); + close(fd); return(-1); } #endif @@ -103,78 +126,188 @@ rrd_open(const char *file_name, FILE **i /* if (rdwr == RRD_READWRITE) { - if (setvbuf((*in_file),NULL,_IONBF,2)) { + if (setvbuf((rrd_file->fd),NULL,_IONBF,2)) { rrd_set_error("failed to disable the stream buffer\n"); return (-1); } } */ - -#define MYFREAD(MYVAR,MYVART,MYCNT) \ - if ((MYVAR = malloc(sizeof(MYVART) * MYCNT)) == NULL) {\ - rrd_set_error("" #MYVAR " malloc"); \ - fclose(*in_file); \ - return (-1); } \ - fread(MYVAR,sizeof(MYVART),MYCNT, *in_file); + data = mmap(0, rrd_file->file_len, prot, MAP_SHARED, + rrd_file->fd, offset); + /* lets see if the first read worked */ + if (data == MAP_FAILED) { + rrd_set_error("error mmaping file '%s'",file_name); + goto out_close; + } + rrd_file->file_start = data; +#ifdef HAVE_MADVISE + if (rrd == NULL) { /*XXX: currently not used! */ + /* We will read everything in a moment (copying) */ + madvise(data, rrd_file->file_len, MADV_WILLNEED|MADV_SEQUENTIAL); + goto out_done; + } + /* We do not need to read anything in for the moment */ + madvise(data, rrd_file->file_len, MADV_DONTNEED); +#endif - MYFREAD(rrd->stat_head, stat_head_t, 1) - /* lets see if the first read worked */ - if (ferror( *in_file ) || feof(*in_file)) { - rrd_set_error("reading the cookie off %s faild",file_name); - fclose(*in_file); - return(-1); - } +#ifdef HAVE_MADVISE + /* the stat_head will be needed soonish, so hint accordingly */ + madvise(data+offset, sizeof(stat_head_t), MADV_WILLNEED); +#endif + + rrd->stat_head = (stat_head_t*)(data + offset); + offset += sizeof(stat_head_t); /* lets do some test if we are on track ... */ - if (strncmp(rrd->stat_head->cookie,RRD_COOKIE,4) != 0){ - rrd_set_error("'%s' is not an RRD file",file_name); - free(rrd->stat_head); - rrd->stat_head = NULL; - fclose(*in_file); - return(-1);} - - if (rrd->stat_head->float_cookie != FLOAT_COOKIE){ - rrd_set_error("This RRD was created on other architecture"); - free(rrd->stat_head); - rrd->stat_head = NULL; - fclose(*in_file); - return(-1);} + if (memcmp(rrd->stat_head->cookie,RRD_COOKIE,sizeof(RRD_COOKIE)) != 0) { + rrd_set_error("'%s' is not an RRD file",file_name); + goto out_nullify_head; + } + + if (rrd->stat_head->float_cookie != FLOAT_COOKIE){ + rrd_set_error("This RRD was created on other architecture"); + goto out_nullify_head; + } - version = atoi(rrd->stat_head->version); + version = atoi(rrd->stat_head->version); - if (version > atoi(RRD_VERSION)){ + if (version > atoi(RRD_VERSION)) { rrd_set_error("can't handle RRD file version %s", rrd->stat_head->version); - free(rrd->stat_head); - rrd->stat_head = NULL; - fclose(*in_file); - return(-1);} + goto out_nullify_head; + } +#ifdef HAVE_MADVISE + /* the ds_def will be needed soonish, so hint accordingly */ + madvise(data+offset, sizeof(ds_def_t)*rrd->stat_head->ds_cnt, MADV_WILLNEED); +#endif + rrd->ds_def = (ds_def_t*)(data + offset); + offset += sizeof(ds_def_t) * rrd->stat_head->ds_cnt; + +#ifdef HAVE_MADVISE + /* the rra_def will be needed soonish, so hint accordingly */ + madvise(data+offset, sizeof(rra_def_t)*rrd->stat_head->rra_cnt, MADV_WILLNEED); +#endif + rrd->rra_def = (rra_def_t*)(data + offset); + offset += sizeof(rra_def_t) * rrd->stat_head->rra_cnt; - MYFREAD(rrd->ds_def, ds_def_t, rrd->stat_head->ds_cnt) - MYFREAD(rrd->rra_def, rra_def_t, rrd->stat_head->rra_cnt) /* handle different format for the live_head */ - if(version < 3) { + if (version < 3) { rrd->live_head = (live_head_t *)malloc(sizeof(live_head_t)); - if(rrd->live_head == NULL) { + if (rrd->live_head == NULL) { rrd_set_error("live_head_t malloc"); - fclose(*in_file); - return (-1); + goto out_close; } - fread(&rrd->live_head->last_up, sizeof(long), 1, *in_file); - rrd->live_head->last_up_usec = 0; - } - else { - MYFREAD(rrd->live_head, live_head_t, 1) - } - MYFREAD(rrd->pdp_prep, pdp_prep_t, rrd->stat_head->ds_cnt) - MYFREAD(rrd->cdp_prep, cdp_prep_t, (rrd->stat_head->rra_cnt - * rrd->stat_head->ds_cnt)) - MYFREAD(rrd->rra_ptr, rra_ptr_t, rrd->stat_head->rra_cnt) -#undef MYFREAD + memmove(&rrd->live_head->last_up, data+offset, sizeof(long)); + rrd->live_head->last_up_usec = 0; + } else { +#ifdef HAVE_MADVISE + /* the live_head will be needed soonish, so hint accordingly */ + madvise(data+offset, sizeof(live_head_t), MADV_WILLNEED); +#endif + rrd->live_head = (live_head_t*)(data + offset); + offset += sizeof(live_head_t); + } +// This doesn't look like it needs madvise + rrd->pdp_prep = (pdp_prep_t*)(data + offset); + offset += sizeof(pdp_prep_t) * rrd->stat_head->ds_cnt; + +// This could benefit from madvise()ing + rrd->cdp_prep = (cdp_prep_t*)(data + offset); + offset += sizeof(cdp_prep_t) * + (rrd->stat_head->rra_cnt * rrd->stat_head->ds_cnt); + +// This could benefit from madvise()ing + rrd->rra_ptr = (rra_ptr_t*)(data + offset); + offset += sizeof(rra_ptr_t) * rrd->stat_head->rra_cnt; +out_done: + rrd_file->header_len = offset; + rrd_file->pos = offset; +/* we could close(rrd_file->fd); here, the mapping is still valid anyway */ + return (rrd_file); +out_nullify_head: + rrd->stat_head = NULL; +out_close: + close(rrd_file->fd); + return NULL; +} + +/* Close a reference to an rrd_file. */ +int rrd_close(rrd_file_t* rrd_file) { + int ret = 0; +#ifdef HAVE_MMAP + ret = munmap(rrd_file->file_start, rrd_file->file_len); +// if (ret != 0) +// rrd_set_error("munmap rrd_file"); +#endif + free(rrd_file); + rrd_file = NULL; + return ret; +} + +/* Set position of rrd_file. */ +off_t rrd_seek(rrd_file_t* rrd_file, off_t off, int whence) { + off_t ret = 0; +#ifdef HAVE_MMAP + if (whence == SEEK_SET) + rrd_file->pos = off; + else if (whence == SEEK_CUR) + rrd_file->pos += off; + else if (whence == SEEK_END) + rrd_file->pos = rrd_file->file_len + off; +#else + ret = lseek(rrd_file->fd, off, whence); + if (ret < 0) + rrd_set_error("lseek: %s", rrd_strerror(errno)); + rrd_file->pos = ret; +#endif +//XXX: mimic fseek, which returns 0 upon success + return ret == -1; //XXX: or just ret to mimic lseek +} - return(0); +/* Get position of rrd_file. */ +off_t rrd_tell(rrd_file_t* rrd_file) { + return rrd_file->pos; +} + +/* read count bytes into buffer buf, starting at rrd_file->pos. + * Returns the number of bytes read. */ +ssize_t rrd_read(rrd_file_t* rrd_file, void*buf, size_t count) { +#ifdef HAVE_MMAP + char* pos = rrd_file->file_start + rrd_file->pos; + buf = memmove(buf, pos, count); + return count; +#else + ssize_t ret; + ret = read(rrd_file->fd, buf, count); + //XXX: eventually add generic rrd_set_error(""); here + return ret; +#endif +} + +/* write count bytes from buffer buf to the current position + * rrd_file->pos of rrd_file->fd. */ +ssize_t rrd_write(rrd_file_t * rrd_file, const void*buf, size_t count) { + ssize_t ret = count; +#ifdef HAVE_MMAP + char *off, *new_pos; + off = rrd_file->file_start + rrd_file->pos; + new_pos = memmove(rrd_file->file_start + rrd_file->pos, buf, count); + ret = new_pos - off; +#else + ret = write(rrd_file->fd, buf, count) +#endif + return ret; +} + +/* flush all data pending to be written to FD. */ +void rrd_flush(rrd_file_t* rrd_file) +{ + if (fdatasync(rrd_file->fd) != 0) { + rrd_set_error("flushing fd %d: %s", rrd_file->fd, + rrd_strerror(errno)); + } } void rrd_init(rrd_t *rrd) @@ -189,24 +322,26 @@ void rrd_init(rrd_t *rrd) rrd->rrd_value = NULL; } -void rrd_free(rrd_t *rrd) +void rrd_free(rrd_t UNUSED(*rrd)) { - if (rrd->stat_head) free(rrd->stat_head); - if (rrd->ds_def) free(rrd->ds_def); - if (rrd->rra_def) free(rrd->rra_def); - if (rrd->live_head) free(rrd->live_head); - if (rrd->rra_ptr) free(rrd->rra_ptr); - if (rrd->pdp_prep) free(rrd->pdp_prep); - if (rrd->cdp_prep) free(rrd->cdp_prep); - if (rrd->rrd_value) free(rrd->rrd_value); +#ifndef HAVE_MMAP + if (atoi(rrd->stat_head->version) < 3) + free(rrd->live_head); + free(rrd->stat_head); + free(rrd->ds_def); + free(rrd->rra_def); + free(rrd->rra_ptr); + free(rrd->pdp_prep); + free(rrd->cdp_prep); + free(rrd->rrd_value); +#endif } /* routine used by external libraries to free memory allocated by * rrd library */ void rrd_freemem(void *mem) { - - if (mem) free(mem); + free(mem); } int readfile(const char *file_name, char **buffer, int skipfirst){ @@ -251,4 +386,3 @@ int readfile(const char *file_name, char return writecnt; } - Index: src/rrd_stat.c =================================================================== --- src/rrd_stat.c (revision 1064) +++ src/rrd_stat.c (working copy) @@ -6,6 +6,8 @@ #include "rrd_tool.h" +XXX: This file is not compiled. Is this on purpose? + extern char *tzname[2]; stat_node @@ -16,11 +18,12 @@ rrd_stat(int argc, char **argv) char somestring[255]; rrd_value_t my_cdp; long rra_base, rra_start, rra_next; - FILE *in_file; rrd_t rrd; + rrd_file_t *rrd_file; - if(rrd_open(argv[1],&in_file,&rrd, RRD_READONLY)==-1){ + rrd_file = rrd_open(argv[1],&rrd, RRD_READONLY); + if (rrd_file == NULL) { return(-1); } puts(""); @@ -66,7 +69,7 @@ rrd_stat(int argc, char **argv) puts(""); - rra_base=ftell(in_file); + rra_base = rrd_file->header_len; rra_next = rra_base; for(i=0;irra_cnt;i++){ @@ -97,7 +100,7 @@ rrd_stat(int argc, char **argv) printf("\t\t\n"); printf("\t\t\n"); - fseek(in_file,(rra_start + rrd_seek(rrd_file,(rra_start +(rrd.rra_ptr[i].cur_row+1) * rrd.stat_head->ds_cnt * sizeof(rrd_value_t)),SEEK_SET); @@ -106,7 +109,7 @@ rrd_stat(int argc, char **argv) for(ix=0;ix=rrd.rra_def[i].row_cnt) { - fseek(in_file,rra_start,SEEK_SET); + rrd_seek(rrd_file,rra_start,SEEK_SET); ii=0; /* wrap if max row cnt is reached */ } now = (rrd.live_head->last_up @@ -122,7 +125,7 @@ rrd_stat(int argc, char **argv) #endif printf("\t\t\t ",somestring); for(iii=0;iiids_cnt;iii++){ - fread(&my_cdp,sizeof(rrd_value_t),1,in_file); + rrd_read(rrd_file,&my_cdp,sizeof(rrd_value_t)*1); if (isnan(my_cdp)){ printf(" NaN "); } else { @@ -136,7 +139,7 @@ rrd_stat(int argc, char **argv) } printf("\n"); rrd_free(&rrd); - fclose(in_file); + close(rrd_file->fd); return(0); } Index: src/Makefile.am =================================================================== --- src/Makefile.am (revision 1064) +++ src/Makefile.am (working copy) @@ -30,22 +30,22 @@ RRD_C_FILES = \ hash_32.c \ pngsize.c \ rrd_create.c \ - rrd_dump.c \ - rrd_fetch.c \ rrd_graph.c \ rrd_graph_helper.c \ + rrd_version.c \ rrd_last.c \ rrd_lastupdate.c \ rrd_first.c \ - rrd_resize.c \ rrd_restore.c \ - rrd_tune.c \ - rrd_version.c \ rrd_xport.c \ art_rgba_svp.c \ rrd_gfx.c \ rrd_afm.c rrd_afm_data.c \ - rrd_tool.c + rrd_dump.c \ + rrd_fetch.c \ + rrd_tool.c \ + rrd_resize.c \ + rrd_tune.c noinst_HEADERS = \ art_rgba_svp.h \ Index: configure.ac =================================================================== --- configure.ac (revision 1064) +++ configure.ac (working copy) @@ -70,10 +70,21 @@ char *strchr (), *strrchr (); # endif #endif +#if defined(HAVE_OPEN) +#include +#include +#include +#endif + +#if defined(HAVE_MADVISE) +#include +#endif + /* enable posix_fadvise on linux */ #if defined(HAVE_POSIX_FADVISE) && defined(HAVE_FCNTL_H) -#include +#error no need for fadvise here.. #define __USE_XOPEN2K 1 +#include #endif #ifdef NO_NULL_REALLOC @@ -248,7 +259,7 @@ AC_C_BIGENDIAN dnl for each function found we get a definition in config.h dnl of the form HAVE_FUNCTION -AC_CHECK_FUNCS(tzset mbstowcs opendir readdir chdir chroot getuid setlocale strerror strerror_r snprintf vsnprintf fpclass class fp_class isnan memmove strchr mktime getrusage gettimeofday posix_fadvise) +AC_CHECK_FUNCS(tzset mbstowcs opendir readdir chdir chroot getuid setlocale strerror strerror_r snprintf vsnprintf fpclass class fp_class isnan memmove strchr mktime getrusage gettimeofday open close madvise) if test "x$enable_mmap" = xyes; then