From 818549a636c390fb4a8390a7e2195a52293cd56b Mon Sep 17 00:00:00 2001 From: oetiker Date: Wed, 23 May 2007 20:42:13 +0000 Subject: [PATCH] * progress in moving all the fileaccess over to a wrapper system that can do fd based and mmap based fileaccess transparently ... * small fixes left and right to improve code quality and stability. -- Bernhard Fischer rep dot nop gmail com git-svn-id: svn://svn.oetiker.ch/rrdtool/trunk/program@1075 a5681a0c-68f1-0310-ab6d-d61299d08faa --- configure.ac | 235 ++++++++++++++++++++++++++----- src/Makefile.am | 12 +- src/rrd.h | 13 +- src/rrd_dump.c | 24 ++-- src/rrd_fetch.c | 52 +++---- src/rrd_first.c | 21 ++- src/rrd_hw.c | 64 ++++----- src/rrd_hw.h | 6 +- src/rrd_info.c | 8 +- src/rrd_last.c | 9 +- src/rrd_lastupdate.c | 8 +- src/rrd_open.c | 315 ++++++++++++++++++++++++++++++------------ src/rrd_resize.c | 96 +++++++------ src/rrd_restore.c | 6 +- src/rrd_stat.c | 17 ++- src/rrd_thread_safe.c | 2 +- src/rrd_tool.h | 95 ++----------- src/rrd_tune.c | 51 ++++--- src/rrd_update.c | 210 ++++++++++++++-------------- src/unused.h | 7 +- 20 files changed, 747 insertions(+), 504 deletions(-) diff --git a/configure.ac b/configure.ac index 09e0260..83bf7e6 100644 --- a/configure.ac +++ b/configure.ac @@ -52,12 +52,89 @@ AH_TOP([ ]) AH_BOTTOM([ +/* make sure that we pickup the correct stuff from all headers */ +#define _XOPEN_SOURCE 600 +#if HAVE_FEATURES_H +# include +#endif + +#if HAVE_SYS_TYPES_H +# include +#endif + +#if HAVE_SYS_PARAM_H +# include +#endif +#ifndef MAXPATH +# ifdef PATH_MAX +# define MAXPATH PATH_MAX +# endif +#endif +#ifndef MAXPATH +/* else try the BSD variant */ +# ifdef MAXPATHLEN +# define MAXPATH MAXPATHLEN +# endif +#endif + +#if HAVE_ERRNO_H +# include +#endif + +#if HAVE_SYS_MMAN_H +# include +#endif +#if !defined HAVE_MADVISE && defined HAVE_POSIX_MADVISE +/* use posix_madvise family */ +# define madvise posix_madvise +# define MADV_NORMAL POSIX_MADV_NORMAL +# define MADV_RANDOM POSIX_MADV_RANDOM +# define MADV_SEQUENTIAL POSIX_MADV_SEQUENTIAL +# define MADV_WILLNEED POSIX_MADV_WILLNEED +# define MADV_DONTNEED POSIX_MADV_DONTNEED +#endif +#if defined HAVE_MADVISE || defined HAVE_POSIX_MADVISE +# define USE_MADVISE 1 +#endif + +#if HAVE_SYS_STAT_H +# include +#endif + /* enable posix_fadvise on linux */ #if defined(HAVE_POSIX_FADVISE) && defined(HAVE_FCNTL_H) -#define _XOPEN_SOURCE 600 #include #endif +#if HAVE_UNISTD_H +# include +#endif + +#if TIME_WITH_SYS_TIME +# include +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif + +#if HAVE_SYS_TIMES_H +# include +#endif + +#if HAVE_SYS_RESOURCE_H +# include +#if (defined(__svr4__) && defined(__sun__)) +/* Solaris headers (pre 2.6) don't have a getrusage prototype. + Use this instead. */ +extern int getrusage(int, struct rusage *); +#endif /* __svr4__ && __sun__ */ +#endif + + /* define strrchr, strchr and memcpy, memmove in terms of bsd funcs make sure you are NOT using bcopy, index or rindex in the code */ @@ -85,20 +162,58 @@ char *strchr (), *strrchr (); # include #endif +#if HAVE_STDIO_H +# include +#endif + +#if HAVE_STDLIB_H +# include +#endif + +#if HAVE_CTYPE_H +# include +#endif + +#if HAVE_DIRENT_H +# include +# define NAMLEN(dirent) strlen((dirent)->d_name) +#else +# define dirent direct +# define NAMLEN(dirent) (dirent)->d_namlen +# if HAVE_SYS_NDIR_H +# include +# endif +# if HAVE_SYS_DIR_H +# include +# endif +# if HAVE_NDIR_H +# include +# endif +#endif + +#ifdef MUST_DISABLE_SIGFPE +# include +#endif + +#ifdef MUST_DISABLE_FPMASK +# include +#endif + + #ifdef HAVE_MATH_H -# include +# include #endif #ifdef HAVE_FLOAT_H -# include +# include #endif #ifdef HAVE_IEEEFP_H -# include +# include #endif #ifdef HAVE_FP_CLASS_H -# include +# include #endif /* for Solaris */ @@ -199,16 +314,16 @@ AC_PROG_CC AC_PROG_CPP AC_PROG_LIBTOOL -dnl which flags does the compile support? -if test "$GCC" = "yes"; then - for flag in -fno-strict-aliasing -Wall -std=gnu99 -pedantic -Wshadow -Wpointer-arith -Wcast-align -Wmissing-prototypes -Wmissing-declarations -Wnested-externs -Winline -W; do - oCFLAGS=$CFLAGS +dnl which flags does the compiler support? +if test "x$GCC" = "xyes"; then + for flag in -fno-strict-aliasing -Wall -std=c99 -pedantic -Wundef -Wshadow -Wpointer-arith -Wcast-align -Wmissing-prototypes -Wmissing-declarations -Wnested-externs -Winline -W; do + oCFLAGS="$CFLAGS" CFLAGS="$CFLAGS $flag" cachename=rd_cv_gcc_flag_`echo $flag|sed 's/[[^A-Za-z]]/_/g'` AC_CACHE_CHECK([if gcc likes the $flag flag], $cachename, [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[return 0 ]])],[eval $cachename=yes],[eval $cachename=no])]) if eval test \$$cachename = no; then - CFLAGS=$oCFLAGS + CFLAGS="$oCFLAGS" fi done fi @@ -222,7 +337,7 @@ CONFIGURE_PART(Checking for Header Files) dnl Checks for header files. AC_HEADER_STDC AC_HEADER_DIRENT -AC_CHECK_HEADERS(sys/stat.h sys/types.h fcntl.h locale.h fp_class.h malloc.h unistd.h ieeefp.h math.h sys/times.h sys/param.h sys/resource.h float.h) +AC_CHECK_HEADERS(features.h sys/stat.h sys/types.h fcntl.h locale.h fp_class.h malloc.h unistd.h ieeefp.h math.h sys/times.h sys/param.h sys/resource.h signal.h float.h stdio.h stdlib.h errno.h string.h ctype.h) dnl Checks for typedefs, structures, and compiler characteristics. AC_C_CONST @@ -247,50 +362,102 @@ 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 madvise) +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_DECLS(fdatasync, [], [], [#include ]) -AC_CHECK_DECLS(posix_fadvise, [], [], [#define _XOPEN_SOURCE 600 -#include ]) -AC_CHECK_DECLS(madvise, [], [], [#include ]) +dnl Could use these to know if we need to provide a prototype +dnl AC_CHECK_DECLS(fdatasync, [], [], [#include ]) +dnl AC_CHECK_DECLS(posix_fadvise, [], [], [#define _XOPEN_SOURCE 600 +dnl #include ]) -if test "x$enable_mmap" = xyes; then +dnl XXX: dunno about windows.. add AC_CHECK_FUNCS(munmap) there too? +if test "x$enable_mmap" = "xyes"; then case "$host" in - *cygwin*) - # the normal mmap test does not work in cygwin - AC_CHECK_FUNCS(mmap) - if [ "x${ac_cv_func_mmap}" = xyes ]; then - ac_cv_func_mmap_fixed_mapped=yes - fi - ;; - *) - AC_FUNC_MMAP - ;; + *cygwin*) + # the normal mmap test does not work in cygwin + AC_CHECK_FUNCS(mmap) + if test "x$ac_cv_func_mmap" = "xyes"; then + ac_cv_func_mmap_fixed_mapped=yes + fi + ;; + *) + AC_CHECK_HEADERS(sys/mman.h) + AC_FUNC_MMAP + AC_CHECK_FUNCS(mmap munmap) + AC_CHECK_DECLS(madvise, [], [], [#if HAVE_SYS_MMAN_H + # include + #endif]) + if test "x$ac_cv_have_decl_madvise" = "xyes"; + then + AC_CHECK_FUNCS(madvise) + else + AC_CHECK_FUNCS(posix_madvise) + if test "x$ac_cv_func_posix_madvise" != "xyes"; then + AC_MSG_WARN([madvise() nor posix_madvise() found.]) + fi + fi + ;; esac + if test "x$ac_cv_func_mmap" != "xyes"; + then + AC_MSG_ERROR([--enable-mmap requested but mmap() was not detected]) + fi fi CONFIGURE_PART(IEEE Math Checks) -dnl HP-UX 11.00 does not have finite but does have isfinite as a macro so we need + dnl actual code to check if this works AC_CHECK_FUNCS(fpclassify, , [AC_MSG_CHECKING(for fpclassify with ) AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include volatile int x;volatile float f; ]], [[x = fpclassify(f)]])],[AC_MSG_RESULT(yes) AC_DEFINE(HAVE_FPCLASSIFY)],[AC_MSG_RESULT(no)])]) -AC_CHECK_FUNCS(finite, , - [AC_CHECK_FUNCS(isfinite, , - [AC_MSG_CHECKING(for isfinite with ) - AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include -volatile int x;volatile float f; ]], [[x = isfinite(f)]])],[AC_MSG_RESULT(yes) - AC_DEFINE(HAVE_ISFINITE)],[AC_MSG_RESULT(no)])])]) + AC_CHECK_FUNCS(isinf, , [AC_MSG_CHECKING(for isinf with ) AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include volatile int x;volatile float f; ]], [[x = isinf(f)]])],[AC_MSG_RESULT(yes) AC_DEFINE(HAVE_ISINF)],[AC_MSG_RESULT(no)])]) +dnl finite is BSD, isfinite is C99, so prefer the latter +AC_CACHE_CHECK([whether isfinite is broken],[have_broken_isfinite],[ +AC_TRY_RUN([ +#ifdef HAVE_MATH_H +#include +#endif +#ifdef HAVE_FLOAT_H +#include +#endif +int main () +{ +#ifdef isfinite +#ifdef LDBL_MAX + if (!isfinite(LDBL_MAX)) return 1; +#endif +#ifdef DBL_MAX + if (!isfinite(DBL_MAX)) return 1; +#endif +#endif +return 0; +}],[ +have_broken_isfinite=no],have_broken_isfinite=yes,[ +case "${target}" in + hppa*-*-hpux*) have_broken_isfinite=yes ;; + *) have_broken_isfinite=no ;; +esac]) +]) +if test "x$have_broken_isfinite" = "xno"; then + AC_DEFINE(HAVE_ISFINITE) +else +AC_CHECK_FUNCS(finite,[], + [AC_CHECK_FUNCS(isfinite,[], + [AC_MSG_CHECKING(for isfinite with ) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include +volatile int x;volatile float f; ]],[[x = isfinite(f)]])],[AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_ISFINITE)],[AC_MSG_RESULT(no)])])]) +fi + AC_FULL_IEEE CONFIGURE_PART(Resolve Portability Issues) diff --git a/src/Makefile.am b/src/Makefile.am index 5ed0558..6fd4364 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 \ diff --git a/src/rrd.h b/src/rrd.h index 3873033..ce712d5 100644 --- a/src/rrd.h +++ b/src/rrd.h @@ -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; /* the data storage type is * 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_context *buf); /* 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 */ diff --git a/src/rrd_dump.c b/src/rrd_dump.c index c8cc7ee..5d76896 100644 --- a/src/rrd_dump.c +++ b/src/rrd_dump.c @@ -77,13 +77,14 @@ rrd_dump_r(const char *filename, char *outname) 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 *outname) 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 *outname) 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 *outname) 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 *outname) # 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 *outname) 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 *outname) return(0); } - - - diff --git a/src/rrd_fetch.c b/src/rrd_fetch.c index 1b85edb..4b0f2b5 100644 --- a/src/rrd_fetch.c +++ b/src/rrd_fetch.c @@ -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 end %10lu step %5lu\n", *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 end %10lu step %5lu\n", 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\n"); 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\n"); 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\n"); * 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,17 +439,17 @@ fprintf(stderr,"partial match, not best\n"); rrd_free(&rrd); free(*data); *data = NULL; - fclose(in_file); + close(rrd_file->fd); return(-1); } #ifdef DEBUG fprintf(stderr,"wrap seek ...\n"); -#endif +#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\n"); 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, 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 @@ -482,12 +486,12 @@ fprintf(stderr,"partial match, not best\n"); 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); } diff --git a/src/rrd_first.c b/src/rrd_first.c index f4e8d40..3782d4a 100644 --- a/src/rrd_first.c +++ b/src/rrd_first.c @@ -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 int rraindex) 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 int rraindex) 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 int rraindex) 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); } - - - diff --git a/src/rrd_hw.c b/src/rrd_hw.c index dccde50..9218f59 100644 --- a/src/rrd_hw.c +++ b/src/rrd_hw.c @@ -108,7 +108,7 @@ update_hwpredict(rrd_t *rrd, unsigned long cdp_idx, unsigned long rra_idx, 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 long rra_idx, unsigned long rra_start, 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 long cdp_idx, unsigned long rra_idx) * 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_idx, unsigned long rra_start, } /* 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 rra_idx, unsigned long rra_start, (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 rra_idx, unsigned long rra_start, 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 rra_idx, unsigned long rra_start, } /* 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 rra_idx, unsigned long rra_start, /* 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, FILE *rrd_file, unsigned long ds_idx) 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, FILE *rrd_file, unsigned long ds_idx) 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 */ } } diff --git a/src/rrd_hw.h b/src/rrd_hw.h index 89220b4..bd5502c 100644 --- a/src/rrd_hw.h +++ b/src/rrd_hw.h @@ -11,11 +11,11 @@ int update_aberrant_CF(rrd_t *rrd, rrd_value_t pdp_val, enum cf_en current_cf, 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 diff --git a/src/rrd_info.c b/src/rrd_info.c index d5ccbc5..2160962 100644 --- a/src/rrd_info.c +++ b/src/rrd_info.c @@ -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); } diff --git a/src/rrd_last.c b/src/rrd_last.c index c4b4b26..0f9ab9b 100644 --- a/src/rrd_last.c +++ b/src/rrd_last.c @@ -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); } diff --git a/src/rrd_lastupdate.c b/src/rrd_lastupdate.c index 169c49d..abba277 100644 --- a/src/rrd_lastupdate.c +++ b/src/rrd_lastupdate.c @@ -13,8 +13,8 @@ rrd_lastupdate(int argc, char **argv, time_t *last_update, 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, time_t *last_update, } 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, time_t *last_update, } rrd_free(&rrd); + rrd_close(rrd_file); return(0); } diff --git a/src/rrd_open.c b/src/rrd_open.c index 3740750..c29741c 100644 --- a/src/rrd_open.c +++ b/src/rrd_open.c @@ -63,118 +63,252 @@ *****************************************************************************/ #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)) { + Thanks to Dave Plonka for the Idea of using POSIX_FADV_RANDOM here. */ + 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); - return(-1); - } + goto out_close; + } #endif /* 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); - - - 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); - } + 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 USE_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 + +#ifdef USE_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);} - - version = atoi(rrd->stat_head->version); - - if (version > atoi(RRD_VERSION)){ + 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); + + 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 USE_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 USE_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 USE_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); - return(0); +// This could benefit from madvise()ing + rrd->rra_ptr = (rra_ptr_t*)(data + offset); + offset += sizeof(rra_ptr_t) * rrd->stat_head->rra_cnt; +#ifdef USE_MADVISE +out_done: +#endif + 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 +} + +/* Get current position in 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 +323,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 +387,3 @@ int readfile(const char *file_name, char **buffer, int skipfirst){ return writecnt; } - diff --git a/src/rrd_resize.c b/src/rrd_resize.c index c1bdda2..9fdd7c1 100644 --- a/src/rrd_resize.c +++ b/src/rrd_resize.c @@ -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); } diff --git a/src/rrd_restore.c b/src/rrd_restore.c index 1da3a59..b283f91 100644 --- a/src/rrd_restore.c +++ b/src/rrd_restore.c @@ -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 rc){ /* 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; }; diff --git a/src/rrd_stat.c b/src/rrd_stat.c index 74969bd..189b579 100644 --- a/src/rrd_stat.c +++ b/src/rrd_stat.c @@ -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); } diff --git a/src/rrd_thread_safe.c b/src/rrd_thread_safe.c index ca99202..4714327 100644 --- a/src/rrd_thread_safe.c +++ b/src/rrd_thread_safe.c @@ -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; } diff --git a/src/rrd_tool.h b/src/rrd_tool.h index 6663c56..f8ab9c4 100644 --- a/src/rrd_tool.h +++ b/src/rrd_tool.h @@ -7,7 +7,6 @@ extern "C" { #endif - #ifndef _RRD_TOOL_H #define _RRD_TOOL_H @@ -17,89 +16,6 @@ extern "C" { #include "../win32/config.h" #endif -#ifdef MUST_DISABLE_SIGFPE -#include -#endif - -#ifdef MUST_DISABLE_FPMASK -#include -#endif - -#include -#include -#include -#include -#include - -#if HAVE_SYS_PARAM_H -# include -#endif - -#ifndef MAXPATH -# define MAXPATH 1024 -#endif - -#if HAVE_MATH_H -# include -#endif -/* Sorry: don't know autoconf as well how to check the exist of - dirent.h ans sys/stat.h -*/ - -#if HAVE_DIRENT_H -# include -# define NAMLEN(dirent) strlen((dirent)->d_name) -#else -# define dirent direct -# define NAMLEN(dirent) (dirent)->d_namlen -# if HAVE_SYS_NDIR_H -# include -# endif -# if HAVE_SYS_DIR_H -# include -# endif -# if HAVE_NDIR_H -# include -# endif -#endif - -#if HAVE_SYS_TYPES_H -# include -#endif - -#if HAVE_SYS_STAT_H -# include -#endif - -#if HAVE_UNISTD_H -# include -#endif - -#if TIME_WITH_SYS_TIME -# include -# include -#else -# if HAVE_SYS_TIME_H -# include -# else -# include -# endif -#endif - -#if HAVE_SYS_TIMES_H -# include -#endif - - -#if HAVE_SYS_RESOURCE_H -# include -#if (defined(__svr4__) && defined(__sun__)) -/* Solaris headers (pre 2.6) don't have a getrusage prototype. - Use this instead. */ -extern int getrusage(int, struct rusage *); -#endif /* __svr4__ && __sun__ */ -#endif - #include "rrd.h" #if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__CYGWIN32__) @@ -133,7 +49,7 @@ int isnan(double value); #ifndef min #define min(a,b) ((a) < (b) ? (a) : (b)) -#endif +#endif #define DIM(x) (sizeof(x)/sizeof(x[0])) @@ -180,11 +96,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); diff --git a/src/rrd_tune.c b/src/rrd_tune.c index 8aa1630..61dc6ad 100644 --- a/src/rrd_tune.c +++ b/src/rrd_tune.c @@ -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; } diff --git a/src/rrd_update.c b/src/rrd_update.c index ed79a6a..f1242f3 100644 --- a/src/rrd_update.c +++ b/src/rrd_update.c @@ -70,21 +70,21 @@ static void normalize_time(struct timeval *t) } /* 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 char *tmplt, int argc, const char **argv 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 char *tmplt, int argc, const char **argv 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 char *tmplt, int argc, const char **argv 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 char *tmplt, int argc, const char **argv 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 char *tmplt, int argc, const char **argv 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 char *tmplt, int argc, const char **argv 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 char *tmplt, int argc, const char **argv 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 char *tmplt, int argc, const char **argv 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,10 +418,10 @@ _rrd_update(const char *filename, const char *tmplt, int argc, const char **argv free(pdp_temp); free(tmpl_idx); rrd_free(&rrd); - fclose(rrd_file); + close(rrd_file->fd); return(-1); } -#ifdef HAVE_MADVISE +#ifdef USE_MADVISE /* when we use mmaping we tell the kernel the mmap equivalent of POSIX_FADV_RANDOM */ madvise(rrd_mmaped_file,rrd_filesize,POSIX_MADV_RANDOM); @@ -449,9 +443,9 @@ _rrd_update(const char *filename, const char *tmplt, int argc, const char **argv 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 @@ -542,7 +536,7 @@ _rrd_update(const char *filename, const char *tmplt, int argc, const char **argv /* 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; @@ -939,7 +933,7 @@ _rrd_update(const char *filename, const char *tmplt, int argc, const char **argv } } - rra_current = ftell(rrd_file); + rra_current = rrd_tell(rrd_file); } /* if cf is DEVSEASONAL or SEASONAL */ if (rrd_test_error()) break; @@ -1174,7 +1168,7 @@ _rrd_update(const char *filename, const char *tmplt, int argc, const char **argv 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 */ @@ -1205,7 +1199,7 @@ _rrd_update(const char *filename, const char *tmplt, int argc, const char **argv /* 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) @@ -1215,7 +1209,7 @@ _rrd_update(const char *filename, const char *tmplt, int argc, const char **argv (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; } @@ -1224,7 +1218,7 @@ _rrd_update(const char *filename, const char *tmplt, int argc, const char **argv } #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) @@ -1234,10 +1228,10 @@ _rrd_update(const char *filename, const char *tmplt, int argc, const char **argv - ((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; @@ -1255,13 +1249,13 @@ _rrd_update(const char *filename, const char *tmplt, int argc, const char **argv /* 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; } @@ -1272,10 +1266,10 @@ _rrd_update(const char *filename, const char *tmplt, int argc, const char **argv - ((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 } @@ -1302,7 +1296,7 @@ _rrd_update(const char *filename, const char *tmplt, int argc, const char **argv 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 @@ -1314,14 +1308,14 @@ _rrd_update(const char *filename, const char *tmplt, int argc, const char **argv 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) { @@ -1331,76 +1325,75 @@ _rrd_update(const char *filename, const char *tmplt, int argc, const char **argv 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); } @@ -1411,23 +1404,13 @@ _rrd_update(const char *filename, const char *tmplt, int argc, const char **argv 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, @@ -1436,7 +1419,7 @@ _rrd_update(const char *filename, const char *tmplt, int argc, const char **argv * critical except during the burning cycles. */ if (schedule_smooth) { - rrd_file = fopen(filename,"rb+"); +// in_file = fopen(filename,"rb+"); rra_start = rra_begin; @@ -1457,14 +1440,26 @@ _rrd_update(const char *filename, const char *tmplt, int argc, const char **argv } #ifdef HAVE_POSIX_FADVISExxx /* 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); @@ -1480,19 +1475,16 @@ _rrd_update(const char *filename, const char *tmplt, int argc, const char **argv * 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; } @@ -1503,7 +1495,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 } @@ -1516,15 +1508,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 { @@ -1537,7 +1529,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) @@ -1555,8 +1547,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; diff --git a/src/unused.h b/src/unused.h index b5ac841..ecaa4de 100644 --- a/src/unused.h +++ b/src/unused.h @@ -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__) -- 2.30.2