])
AH_BOTTOM([
+/* make sure that we pickup the correct stuff from all headers */
+#define _XOPEN_SOURCE 600
+#if HAVE_FEATURES_H
+# include <features.h>
+#endif
+
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#if HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#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 <errno.h>
+#endif
+
+#if HAVE_SYS_MMAN_H
+# include <sys/mman.h>
+#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 <sys/stat.h>
+#endif
+
/* enable posix_fadvise on linux */
#if defined(HAVE_POSIX_FADVISE) && defined(HAVE_FCNTL_H)
-#define _XOPEN_SOURCE 600
#include <fcntl.h>
#endif
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+#endif
+
+#if HAVE_SYS_TIMES_H
+# include <sys/times.h>
+#endif
+
+#if HAVE_SYS_RESOURCE_H
+# include <sys/resource.h>
+#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 */
# include <malloc/malloc.h>
#endif
+#if HAVE_STDIO_H
+# include <stdio.h>
+#endif
+
+#if HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+
+#if HAVE_CTYPE_H
+# include <ctype.h>
+#endif
+
+#if HAVE_DIRENT_H
+# include <dirent.h>
+# define NAMLEN(dirent) strlen((dirent)->d_name)
+#else
+# define dirent direct
+# define NAMLEN(dirent) (dirent)->d_namlen
+# if HAVE_SYS_NDIR_H
+# include <sys/ndir.h>
+# endif
+# if HAVE_SYS_DIR_H
+# include <sys/dir.h>
+# endif
+# if HAVE_NDIR_H
+# include <ndir.h>
+# endif
+#endif
+
+#ifdef MUST_DISABLE_SIGFPE
+# include <signal.h>
+#endif
+
+#ifdef MUST_DISABLE_FPMASK
+# include <floatingpoint.h>
+#endif
+
+
#ifdef HAVE_MATH_H
-# include <math.h>
+# include <math.h>
#endif
#ifdef HAVE_FLOAT_H
-# include <float.h>
+# include <float.h>
#endif
#ifdef HAVE_IEEEFP_H
-# include <ieeefp.h>
+# include <ieeefp.h>
#endif
#ifdef HAVE_FP_CLASS_H
-# include <fp_class.h>
+# include <fp_class.h>
#endif
/* for Solaris */
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
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
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 <unistd.h>])
-AC_CHECK_DECLS(posix_fadvise, [], [], [#define _XOPEN_SOURCE 600
-#include <fcntl.h>])
-AC_CHECK_DECLS(madvise, [], [], [#include <sys/mman.h>])
+dnl Could use these to know if we need to provide a prototype
+dnl AC_CHECK_DECLS(fdatasync, [], [], [#include <unistd.h>])
+dnl AC_CHECK_DECLS(posix_fadvise, [], [], [#define _XOPEN_SOURCE 600
+dnl #include <fcntl.h>])
-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 <sys/mman.h>
+ #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 <math.h>)
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <math.h>
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 <math.h>)
- AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <math.h>
-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 <math.h>)
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <math.h>
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 <math.h>
+#endif
+#ifdef HAVE_FLOAT_H
+#include <float.h>
+#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 <math.h>)
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <math.h>
+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)
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 \
#ifndef _RRDLIB_H
#define _RRDLIB_H
+#include <sys/types.h> /* for off_t */
+#include <unistd.h> /* for off_t */
#include <time.h>
#include <stdio.h> /* for FILE */
* 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 **);
/* 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 */
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);
}
fputs("<!-- Round Robin Archives -->", out_file);
- rra_base=ftell(in_file);
+ rra_base = rrd_file->header_len;
rra_next = rra_base;
for(i=0;i<rrd.stat_head->rra_cnt;i++){
fprintf(out_file, "\t\t</cdp_prep>\n");
fprintf(out_file, "\t\t<database>\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);
for(ix=0;ix<rrd.rra_def[i].row_cnt;ix++){
ii++;
if (ii>=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
# error "Need strftime"
#endif
fprintf(out_file, "\t\t\t<!-- %s / %d --> <row>",somestring,(int)now);
- for(iii=0;iii<rrd.stat_head->ds_cnt;iii++){
- fread(&my_cdp,sizeof(rrd_value_t),1,in_file);
+ for(iii=0;iii<rrd.stat_head->ds_cnt;iii++){
+ rrd_read(rrd_file, &my_cdp,sizeof(rrd_value_t)*1);
if (isnan(my_cdp)){
fprintf(out_file, "<v> NaN </v>");
} else {
fprintf(out_file, "</row>\n");
}
fprintf(out_file, "\t\t</database>\n\t</rra>\n");
-
+
}
fprintf(out_file, "</rrd>\n");
rrd_free(&rrd);
- fclose(in_file);
+ close(rrd_file->fd);
if (out_file != stdout)
{
fclose(out_file);
return(0);
}
-
-
-
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;
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");
*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);
}
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);
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);
}
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;i<chosen_rra;i++)
rra_base += ( *ds_cnt
* rrd.rra_def[i].row_cnt
else
rra_pointer = rrd.rra_ptr[chosen_rra].cur_row+1+start_offset;
- if(fseek(in_file,(rra_base
+ if(rrd_seek(rrd_file,(rra_base
+ (rra_pointer
* *ds_cnt
* sizeof(rrd_value_t))),SEEK_SET) != 0){
rrd_free(&rrd);
free(*data);
*data = NULL;
- fclose(in_file);
+ close(rrd_file->fd);
return(-1);
}
* 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");
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]);
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
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);
}
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);
}
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 *
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 %
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);
}
-
-
-
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
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
* 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;
}
/* 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
(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) +
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;
} /* 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;
/* 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;
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;
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 */
}
}
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
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);
}
}
rrd_free(&rrd);
+ rrd_close(rrd_file);
return(data);
}
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);
}
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");
}
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;
}
rrd_free(&rrd);
+ rrd_close(rrd_file);
return(0);
}
*****************************************************************************/
#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)
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){
return writecnt;
}
-
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;
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")) {
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);
}
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;
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
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
*/
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 {
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--;
for (l=0;l<=rrdnew.rra_ptr[target_rra].cur_row;l++) {
unsigned int tmp;
for (tmp=0;tmp<rrdnew.stat_head->ds_cnt;tmp++) {
- fread(&buffer,sizeof(rrd_value_t),1,infile);
- fwrite(&buffer,sizeof(rrd_value_t),1,outfile);
+ 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++;
}
/* 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);
}
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);
/* 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;
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;
};
#include "rrd_tool.h"
+XXX: This file is not compiled. Is this on purpose?
+
extern char *tzname[2];
stat_node
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("<!-- Round Robin Database Dump -->");
puts("<!-- Round Robin Archives -->");
- rra_base=ftell(in_file);
+ rra_base = rrd_file->header_len;
rra_next = rra_base;
for(i=0;i<rrd.stat_head->rra_cnt;i++){
printf("\t\t</cdp_prep>\n");
printf("\t\t<database>\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);
for(ix=0;ix<rrd.rra_def[i].row_cnt;ix++){
ii++;
if (ii>=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
#endif
printf("\t\t\t<!-- %s --> <row>",somestring);
for(iii=0;iii<rrd.stat_head->ds_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("<v> NaN </v>");
} else {
}
printf("</rrd>\n");
rrd_free(&rrd);
- fclose(in_file);
+ close(rrd_file->fd);
return(0);
}
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;
}
extern "C" {
#endif
-
#ifndef _RRD_TOOL_H
#define _RRD_TOOL_H
#include "../win32/config.h"
#endif
-#ifdef MUST_DISABLE_SIGFPE
-#include <signal.h>
-#endif
-
-#ifdef MUST_DISABLE_FPMASK
-#include <floatingpoint.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <ctype.h>
-
-#if HAVE_SYS_PARAM_H
-# include <sys/param.h>
-#endif
-
-#ifndef MAXPATH
-# define MAXPATH 1024
-#endif
-
-#if HAVE_MATH_H
-# include <math.h>
-#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 <dirent.h>
-# define NAMLEN(dirent) strlen((dirent)->d_name)
-#else
-# define dirent direct
-# define NAMLEN(dirent) (dirent)->d_namlen
-# if HAVE_SYS_NDIR_H
-# include <sys/ndir.h>
-# endif
-# if HAVE_SYS_DIR_H
-# include <sys/dir.h>
-# endif
-# if HAVE_NDIR_H
-# include <ndir.h>
-# endif
-#endif
-
-#if HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-
-#if HAVE_SYS_STAT_H
-# include <sys/stat.h>
-#endif
-
-#if HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
-#if HAVE_SYS_TIMES_H
-# include <sys/times.h>
-#endif
-
-
-#if HAVE_SYS_RESOURCE_H
-# include <sys/resource.h>
-#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__)
#ifndef min
#define min(a,b) ((a) < (b) ? (a) : (b))
-#endif
+#endif
#define DIM(x) (sizeof(x)/sizeof(x[0]))
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);
rrd_tune(int argc, char **argv)
{
rrd_t rrd;
- FILE *rrd_file;
int matches;
int optcnt = 0;
long ds;
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[] =
{
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;
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;
}
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)
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);
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);
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;
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++)
free(buffer);
}
}
- fclose(rrd_file);
+ close(rrd_file->fd);
rrd_free(&rrd);
return 0;
}
}
/* 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);
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 */
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);
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;
}
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);
}
rrd_set_error("allocating pdp_temp ...");
free(updvals);
rrd_free(&rrd);
- fclose(rrd_file);
+ close(rrd_file->fd);
return(-1);
}
free(pdp_temp);
free(updvals);
rrd_free(&rrd);
- fclose(rrd_file);
+ close(rrd_file->fd);
return(-1);
}
/* initialize tmplt redirector */
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]++;
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);
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);
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
/* 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;
}
}
- rra_current = ftell(rrd_file);
+ rra_current = rrd_tell(rrd_file);
} /* if cf is DEVSEASONAL or SEASONAL */
if (rrd_test_error()) break;
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 */
/* 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)
(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;
}
}
#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)
- ((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;
/* 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;
}
- ((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
}
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
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) {
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);
}
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,
* critical except during the burning cycles. */
if (schedule_smooth)
{
- rrd_file = fopen(filename,"rb+");
+// in_file = fopen(filename,"rb+");
rra_start = rra_begin;
}
#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);
* 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;
}
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
}
*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
{
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)
&(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;
-/* 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__)