/* define strrchr, strchr and memcpy, memmove in terms of bsd funcs
make sure you are NOT using bcopy, index or rindex in the code */
-#if STDC_HEADERS
+#ifdef STDC_HEADERS
# include <string.h>
#else
# ifndef HAVE_STRCHR
# endif
#endif
+/* enable posix_fadvise on linux */
+#ifdef HAVE_POSIX_FADVISE
+#define __USE_XOPEN2K 1
+#endif
-#if NO_NULL_REALLOC
+#ifdef NO_NULL_REALLOC
# define rrd_realloc(a,b) ( (a) == NULL ? malloc( (b) ) : realloc( (a) , (b) ))
#else
# define rrd_realloc(a,b) realloc((a), (b))
#endif
-#if NEED_MALLOC_MALLOC_H
+#ifdef NEED_MALLOC_MALLOC_H
# include <malloc/malloc.h>
#endif
-#if HAVE_MATH_H
+#ifdef HAVE_MATH_H
# include <math.h>
#endif
-#if HAVE_FLOAT_H
+#ifdef HAVE_FLOAT_H
# include <float.h>
#endif
-#if HAVE_IEEEFP_H
+#ifdef HAVE_IEEEFP_H
# include <ieeefp.h>
#endif
-#if HAVE_FP_CLASS_H
+#ifdef HAVE_FP_CLASS_H
# include <fp_class.h>
#endif
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)
+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)
if test "x$enable_mmap" = xyes; then
# your package will not be binary compatible with any other release.
#
# see http://www.gnu.org/software/libtool/manual.html#SEC32 for explanation
-librrd_la_LDFLAGS = -version-info 2:10:0
+librrd_la_LDFLAGS = -version-info 2:11:0
librrd_th_la_SOURCES = $(UPD_C_FILES) $(RRD_C_FILES) rrd_thread_safe.c
librrd_th_la_CFLAGS = $(MULTITHREAD_CFLAGS)
-librrd_th_la_LDFLAGS = $(MULTITHREAD_LDFLAGS) -version-info 2:8:0
+librrd_th_la_LDFLAGS = $(MULTITHREAD_LDFLAGS) -version-info 2:11:0
librrd_th_la_LIBADD = $(ALL_LIBS)
include_HEADERS = rrd.h
FILE *rrd_file;
rrd_value_t *unknown;
int unkn_cnt;
-
+
+ long rrd_head_size;
+
if ((rrd_file = fopen(file_name,"wb")) == NULL ) {
rrd_set_error("creating '%s': %s",file_name, rrd_strerror(errno));
free(rrd->stat_head);
rrd->rra_ptr->cur_row = rrd->rra_def[i].row_cnt - 1;
fwrite( rrd->rra_ptr, sizeof(rra_ptr_t),1,rrd_file);
}
-
+ rrd_head_size = ftell(rrd_file);
+
/* write the empty data area */
if ((unknown = (rrd_value_t *)malloc(512 * sizeof(rrd_value_t))) == NULL) {
rrd_set_error("allocating unknown");
return(-1);
}
+#ifdef POSIX_FADVISE
+ /* this file is not going to be read again any time
+ soon, so we drop everything except the header portion from
+ the buffer cache. for this to work, we have to fdsync the file
+ first though. This will not be all that fast, but 'good' data
+ like other rrdfiles headers will stay in cache. Now this only works if creating
+ a single rrd file is not too large, but I assume this should not be the case
+ in general. Otherwhise we would have to sync and release while writing all
+ the unknown data. */
+ fdatasync(fileno(rrd_file));
+ if (0 != posix_fadvise(fileno(rrd_file), rrd_head_size, 0, POSIX_FADV_DONTNEED)) {
+ rrd_set_error("setting POSIX_FADV_DONTNEED on '%s': %s",file_name, rrd_strerror(errno));
+ fclose(rrd_file);
+ return(-1);
+ }
+#endif
+
fclose(rrd_file);
rrd_free(rrd);
return (0);
rrd_t rrd;
rrd_value_t *data_ptr;
unsigned long rows;
+ long rrd_head_size;
#ifdef DEBUG
fprintf(stderr,"Entered rrd_fetch_fn() searching for the best match\n");
if(rrd_open(filename,&in_file,&rrd, RRD_READONLY)==-1)
return(-1);
+
+ rrd_head_size = ftell(in_file);
/* when was the really last update of this file ? */
fclose(in_file);
return(-1);
}
+#ifdef POSIX_FADVISE
+ /* don't pollute the buffer cache with data read from the file. We do this while reading to
+ keep damage minimal */
+ if (0 != posix_fadvise(fileno(in_file), rrd_head_size, ftell(in_file), POSIX_FADV_DONTNEED)) {
+ rrd_set_error("setting POSIX_FADV_DONTNEED on '%s': %s",file_name, rrd_strerror(errno));
+ fclose(in_file);
+ return(-1);
+ }
+#endif
+
#ifdef DEBUG
fprintf(stderr,"post fetch %li -- ",i);
for(ii=0;ii<*ds_cnt;ii++)
}
rrd_free(&rrd);
+#ifdef 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)) {
+ rrd_set_error("setting POSIX_FADV_DONTNEED on '%s': %s",file_name, rrd_strerror(errno));
+ fclose(in_file);
+ return(-1);
+ }
+#endif
fclose(in_file);
return(0);
}
rrd_set_error("opening '%s': %s",file_name, rrd_strerror(errno));
return (-1);
}
+
+#ifdef 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)) {
+ rrd_set_error("setting POSIX_FADV_RANDOM on '%s': %s",file_name, rrd_strerror(errno));
+ fclose(*in_file);
+ return(-1);
+ }
+#endif
+
/*
if (rdwr == RRD_READWRITE)
{
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;
if(rrd_open(filename,&rrd_file,&rrd, RRD_READWRITE)==-1){
return -1;
}
+
/* initialize time */
version = atoi(rrd.stat_head->version);
gettimeofday(&tmp_time, 0);
fclose(rrd_file);
return(-1);
}
+#ifdef POSIX_FADVISE
+
+ /* with update we have write ops, so they will probably not be done by now, this means
+ the buffers will not get freed. But calling this for the whole file - header
+ 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(in_file), rra_begin, 0, POSIX_FADV_DONTNEED)) {
+ rrd_set_error("setting POSIX_FADV_DONTNEED on '%s': %s",file_name, rrd_strerror(errno));
+ fclose(in_file);
+ return(-1);
+ }
+#endif
/* OK now close the files and free the memory */
if(fclose(rrd_file) != 0){
if (schedule_smooth)
{
rrd_file = fopen(filename,"rb+");
+
+
rra_start = rra_begin;
for (i = 0; i < rrd.stat_head -> rra_cnt; ++i)
{
rra_start += rrd.rra_def[i].row_cnt
*rrd.stat_head->ds_cnt*sizeof(rrd_value_t);
}
+#ifdef POSIX_FADVISE
+ /* same procedure as above ... */
+ if (0 != posix_fadvise(fileno(in_file), rrd_head_size, 0, POSIX_FADV_DONTNEED)) {
+ rrd_set_error("setting POSIX_FADV_DONTNEED on '%s': %s",file_name, rrd_strerror(errno));
+ fclose(in_file);
+ return(-1);
+ }
+#endif
fclose(rrd_file);
}
rrd_free(&rrd);