Updates from Bernhard Fischer rep dot nop gmail com
authoroetiker <oetiker@a5681a0c-68f1-0310-ab6d-d61299d08faa>
Fri, 25 May 2007 13:12:07 +0000 (13:12 +0000)
committeroetiker <oetiker@a5681a0c-68f1-0310-ab6d-d61299d08faa>
Fri, 25 May 2007 13:12:07 +0000 (13:12 +0000)
- fix typo in rrd_fetch where rrd_read result was checked against an
  incorrect size.
- in rrd_fetch, drop rrd_head_size in favour of rrd_file->header_len
- in rrd_fetch, make the message "post fetch" unambiguous (now past vs.
  post).
- change usage of param rdwr of rrd_open: allow for RRD_READONLY,
  RRD_READWRITE, RRD_CREAT, RRD_READAHEAD; adjust callers accordingly:
  + rrd_resize needs CREAT
  + rrd_dump may want READAHEAD
- implement FD based I/O in rrd_open, rrd_read, rrd_write, rrd_seek.
- in rrd_update, unify write_RRA_row().
- sort | uniq the -T in .indent.pro (info_t was duplicated)
- add stub of an option to use O_DIRECT to the configury
- in Makefile.am, simplify the "indent" invocation of find:
  My find may not support "-o" resp. "-or" nor braces.
  Using -name "*.[ch]" works everywhere, AFAIK.

git-svn-id: svn://svn.oetiker.ch/rrdtool/trunk/program@1084 a5681a0c-68f1-0310-ab6d-d61299d08faa

.indent.pro
Makefile.am
configure.ac
examples/perftest.pl.in
src/rrd_dump.c
src/rrd_fetch.c
src/rrd_open.c
src/rrd_resize.c
src/rrd_tool.h
src/rrd_update.c

index 262c7e0..73401ef 100644 (file)
 --case-brace-indentation0
 --leave-preprocessor-space
 --no-tabs
 --case-brace-indentation0
 --leave-preprocessor-space
 --no-tabs
--Trrd_t
--Tinfo_t
--Ttime_t
--Toff_t
+-TFIFOqueue
+-TFnv32_t
 -TTcl_Interp
 -TTcl_Interp
--Ttm
--Tstring_arr_t
 -T_ArtRgbaSVPAlphaData
 -T_ArtRgbaSVPAlphaData
--TFIFOqueue
+-Tafm_fontinfo
+-Tafm_sint16
+-Tafm_sint8
+-Tafm_uint16
+-Tafm_uint8
+-Tafm_unicode
+-Tcdp_prep_t
+-Tcgi_s
+-Tds_def_t
+-Teps_font
+-Teps_state
+-Tgfx_canvas_t
+-Tgfx_char_s
 -Tgfx_color_t
 -Tgfx_node_t
 -Tgfx_color_t
 -Tgfx_node_t
--Tgfx_canvas_t
--Tvar_s
--Tcgi_s
--Tinfoval
+-Tgfx_string_s
+-Tgraph_desc_t
+-Timage_desc_t
 -Tinfo_t
 -Tinfo_t
--TFnv32_t
--Trpnp_t
+-Tinfoval
+-Tlive_head_t
+-Toff_t
+-Told_afm_fontinfo
+-Tpdf_buffer
+-Tpdf_font
+-Tpdf_point
+-Tpdf_state
+-Tpdp_prep_t
 -Trpn_cdefds_t
 -Trpn_cdefds_t
+-Trpnp_t
 -Trpnstack_t
 -Trpnstack_t
--Tunival
--Tstat_head_t
--Tds_def_t
 -Trra_def_t
 -Trra_def_t
--Tlive_head_t
--Tpdp_prep_t
--Tcdp_prep_t
 -Trra_ptr_t
 -Trra_ptr_t
+-Trrd_file_t
 -Trrd_t
 -Trrd_t
+-Trrd_value_t
+-Tstat_head_t
+-Tstring_arr_t
+-Tsvg_dash
 -Ttext_prop_t
 -Ttext_prop_t
+-Ttime_t
+-Ttm
+-Tunival
+-Tva_list
+-Tvar_s
 -Tvdef_t
 -Txlab_t
 -Tygrid_scale_t
 -Tylab_t
 -Tvdef_t
 -Txlab_t
 -Tygrid_scale_t
 -Tylab_t
--Tgraph_desc_t
--Timage_desc_t
--Tafm_uint8
--Tafm_sint8
--Tafm_uint16
--Tafm_sint16
--Tafm_unicode
--Tafm_uint8
--Tafm_sint8
--Tafm_uint16
--Tafm_sint16
--Tafm_unicode
--Tafm_fontinfo
--Told_afm_fontinfo
--Tgfx_char_s
--Tgfx_string_s
--Tpdf_point
--Tsvg_dash
--Teps_font
--Teps_state
--Tpdf_buffer
--Tpdf_font
--Tpdf_state
--Trrd_value_t
--Trrd_file_t
--Tva_list
index 4689aac..1c87994 100644 (file)
@@ -49,6 +49,6 @@ site-python-install: all
 
 # find . -name "*.c" -or -name "*.h" | xargs perl -0777 -n -e 'while (s/typedef\s+(?:unsigned\s+|signed\s+|unival\s+)?\S+\s+\*?([^{}\s;(]+)//){print "-T$1\n"}'
 indent:
 
 # find . -name "*.c" -or -name "*.h" | xargs perl -0777 -n -e 'while (s/typedef\s+(?:unsigned\s+|signed\s+|unival\s+)?\S+\s+\*?([^{}\s;(]+)//){print "-T$1\n"}'
 indent:
-       find . -name "*.c" -or -name "*.h" | xargs indent
+       find ./ -name "*.[ch]" | xargs indent
 
 ##END##
 
 ##END##
index e508eb3..8fa3c00 100644 (file)
@@ -299,7 +299,10 @@ AC_ARG_ENABLE([mmap],
 [  --disable-mmap          disable mmap in rrd_update, use seek+write instead],
 [],
 [enable_mmap=yes])
 [  --disable-mmap          disable mmap in rrd_update, use seek+write instead],
 [],
 [enable_mmap=yes])
-
+AC_ARG_ENABLE([direct-io],
+[  --enable-direct-io      enable O_DIRECT],
+[],
+[enable_direct_io=yes])
 
  AC_ARG_ENABLE(pthread,[  --disable-pthread       disable multithread support],
 [],[enable_pthread=yes])
 
  AC_ARG_ENABLE(pthread,[  --disable-pthread       disable multithread support],
 [],[enable_pthread=yes])
@@ -404,6 +407,11 @@ if test "x$enable_mmap" = "xyes"; then
 fi
 
 
 fi
 
 
+dnl if test "x$enable_direct_io" = "xyes"; then
+dnl check for working O_DIRECT
+dnl fi
+AC_SUBST([USE_DIRECT_IO])
+
 CONFIGURE_PART(IEEE Math Checks)
  
 
 CONFIGURE_PART(IEEE Math Checks)
  
 
index b10f59f..312ca57 100755 (executable)
@@ -21,14 +21,12 @@ is highly dependent on the cache situation in your machine.
 
 This test tries to cater for this. It works like this:
 
 
 This test tries to cater for this. It works like this:
 
-1) Create 100 RRD files (and sync them to disk)
+1) Create 20k RRD files (and sync them to disk)
 
 
-2) Update the 100 RRD file three times in a row.
+2) Update the RRD files several times in a row.
    We run the Update several times to see the difference
    it makes in the cache.
 
    We run the Update several times to see the difference
    it makes in the cache.
 
-3) Go back to 1)
-
 NOTE
 
 use strict;
 NOTE
 
 use strict;
@@ -191,3 +189,163 @@ sub main (){
 }
 
 main;
 }
 
 main;
+use strict;
+use Time::HiRes qw(time);
+use RRDs;
+use IO::File;
+use Time::HiRes qw( usleep );
+
+sub create($$){
+  my $file = shift;
+  my $time = shift;
+  my $start = time; #since we loaded HiRes
+  RRDs::create  ( $file.".rrd", "-b$time", qw(
+                       -s300                        
+                       DS:in:GAUGE:400:U:U
+                       DS:out:GAUGE:400:U:U
+                       RRA:AVERAGE:0.5:1:600
+                       RRA:AVERAGE:0.5:6:600
+                       RRA:MAX:0.5:6:600
+                       RRA:AVERAGE:0.5:24:600
+                       RRA:MAX:0.5:24:600
+                       RRA:AVERAGE:0.5:144:600
+                       RRA:MAX:0.5:144:600
+               ));
+   my $total = time - $start;
+   my $error =  RRDs::error;
+   die $error if $error;
+   return $total;
+}
+
+sub update($$){
+  my $file = shift;
+  my $time = shift;
+  my $in = rand(1000);
+  my $out = rand(1000);
+  my $start = time;
+  my $ret = RRDs::updatev($file.".rrd", $time.":$in:$out");
+#  print join("",map {"  $_ " . $ret->{$_}."\n" } grep /AVERAGE.\[1\]/, sort keys %$ret)."\n** $time\n\n";
+  # sync updates to disk immediately  
+#  usleep(1) if (rand(3) <1 );
+  my $total = time - $start;
+  my $error =  RRDs::error;
+  die $error if $error;
+  return $total;
+}
+
+sub tune($){
+  my $file = shift;
+  my $start = time;
+  RRDs::tune ($file.".rrd", "-a","in:U","-a","out:U","-d","in:GAUGE","-d","out:GAUGE");
+  my $total = time - $start;
+  my $error =  RRDs::error;
+  die $error if $error;
+  return $total;
+}
+
+sub infofetch($){
+  my $file = shift;
+  my $start = time;
+  my $info = RRDs::info ($file.".rrd");
+  my $error =  RRDs::error;
+  die $error if $error;
+  my $lasttime =  $info->{last_update} - $info->{last_update} % $info->{step};           
+  my $fetch = RRDs::fetch ($file.".rrd",'AVERAGE','-s',$lasttime-1,'-e',$lasttime);
+  my $total = time - $start;
+  my $error =  RRDs::error;
+  die $error if $error;
+  return $total;
+}
+
+sub stddev ($$$){ #http://en.wikipedia.org/wiki/Standard_deviation
+  my $sum = shift;
+  my $squaresum = shift;
+  my $count = shift;
+  return sqrt( 1 / $count * ( $squaresum - $sum*$sum / $count ))
+}
+
+sub makerrds($$$$){
+    my $count = shift;
+    my $total = shift;
+    my $list = shift;
+    my $time = shift;
+    my @files;
+    for (1..$count){
+        my $id = sprintf ("%07d",$total);
+        $id =~ s/^(.)(.)(.)(.)(.)//;
+        push @$list, "$1/$2/$3/$4/$5/$id";    
+        -d "$1" or mkdir "$1";
+        -d "$1/$2" or mkdir "$1/$2";
+        -d "$1/$2/$3" or mkdir "$1/$2/$3";
+        -d "$1/$2/$3/$4" or mkdir "$1/$2/$3/$4";
+        -d "$1/$2/$3/$4/$5" or mkdir "$1/$2/$3/$4/$5";
+       push @files, $list->[$total];
+        create $list->[$total++],$time-2;
+       print STDERR ".";
+    }
+   for (@files){ 
+       my $fd = new IO::File("$_.rrd","r");
+       if (defined $fd) {
+           $fd->sync;
+           $fd->close;
+        } else {
+            warn "failed to sync $_\n";
+        }        
+    }
+    return $count;
+}
+    
+    
+sub main (){
+    mkdir "db-$$" or die $!;
+    chdir "db-$$";
+
+    my $step = 200000; # number of rrds to creat for every round
+    
+    my @path;
+    my $time=int(time);
+
+    my $tracksize = 0;
+    my $uppntr = 0;
+
+    
+    my %squaresum = ( cr => 0, up => 0 );
+    my %sum = ( cr => 0, up => 0 );
+    my %count =( cr => 0, up => 0 );
+
+    my $printtime = time;
+    while (1) {
+        # enhance the track
+           $time += 300;
+        $tracksize += makerrds $step,$tracksize,\@path,$time;            
+        # run benchmark
+        for (0..10){
+           $time += 300;
+            my $count = 0;
+            my $sum = 0;
+            my $squaresum = 0;
+            for (my $i = 0; $i<$tracksize;$i ++){
+               my $elapsed = update($path[$i],$time); 
+               $sum += $elapsed;
+               $squaresum += $elapsed**2;
+               $count++;
+            };
+#            for (my $i = 0; $i<$tracksize;$i ++){
+#             my $fh = new IO::File "$path[$i].rrd","r";
+#             if (defined $fh) {
+#                 $fh->sync;
+#                 $fh->close;
+#                } else {
+#                 warn "failed to sync $path[$i]\n";
+#              }       
+#            }
+            my $ups = $count/$sum;
+            my $sdv = stddev($sum,$squaresum,$count);
+            printf STDERR "%4d %6.0f Up/s (%6.5f sdv)\n",$count,$ups,$sdv;
+        }
+       print STDERR "\n";
+       exit ;
+    }
+}
+
+main;
index 56ebda7..3b2a025 100644 (file)
@@ -83,7 +83,7 @@ int rrd_dump_r(
     rrd_value_t value;
     struct tm tm;
 
     rrd_value_t value;
     struct tm tm;
 
-    rrd_file = rrd_open(filename, &rrd, RRD_READONLY);
+    rrd_file = rrd_open(filename, &rrd, RRD_READONLY|RRD_READAHEAD);
     if (rrd_file == NULL) {
         rrd_free(&rrd);
         return (-1);
     if (rrd_file == NULL) {
         rrd_free(&rrd);
         return (-1);
index a995fec..866bf97 100644 (file)
@@ -210,10 +210,6 @@ int rrd_fetch_fn(
     rrd_value_t *data_ptr;
     unsigned long rows;
 
     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");
     fprintf(stderr, "Looking for: start %10lu end %10lu step %5lu\n",
 #ifdef DEBUG
     fprintf(stderr, "Entered rrd_fetch_fn() searching for the best match\n");
     fprintf(stderr, "Looking for: start %10lu end %10lu step %5lu\n",
@@ -224,9 +220,6 @@ int rrd_fetch_fn(
     if (rrd_file == NULL)
         return (-1);
 
     if (rrd_file == NULL)
         return (-1);
 
-#ifdef HAVE_POSIX_FADVISE
-    rrd_head_size = rrd_file->header_len;
-#endif
     /* when was the really last update of this file ? */
 
     if (((*ds_namv) =
     /* when was the really last update of this file ? */
 
     if (((*ds_namv) =
@@ -387,7 +380,7 @@ int rrd_fetch_fn(
 
     if (rrd_seek(rrd_file, (rra_base
                             + (rra_pointer
 
     if (rrd_seek(rrd_file, (rra_base
                             + (rra_pointer
-                               * *ds_cnt
+                               * (*ds_cnt)
                                * sizeof(rrd_value_t))), SEEK_SET) != 0) {
         rrd_set_error("seek error in RRA");
         for (i = 0; (unsigned) i < *ds_cnt; i++)
                                * sizeof(rrd_value_t))), SEEK_SET) != 0) {
         rrd_set_error("seek error in RRA");
         for (i = 0; (unsigned) i < *ds_cnt; i++)
@@ -423,7 +416,7 @@ int rrd_fetch_fn(
         /* past the valid data area */
         else if (i >= (signed) rrd.rra_def[chosen_rra].row_cnt) {
 #ifdef DEBUG
         /* past the valid data area */
         else if (i >= (signed) rrd.rra_def[chosen_rra].row_cnt) {
 #ifdef DEBUG
-            fprintf(stderr, "post fetch %li -- ", i);
+            fprintf(stderr, "past fetch %li -- ", i);
 #endif
             for (ii = 0; (unsigned) ii < *ds_cnt; ii++) {
                 *(data_ptr++) = DNAN;
 #endif
             for (ii = 0; (unsigned) ii < *ds_cnt; ii++) {
                 *(data_ptr++) = DNAN;
@@ -437,7 +430,7 @@ int rrd_fetch_fn(
             if (rra_pointer >= (signed) rrd.rra_def[chosen_rra].row_cnt) {
                 rra_pointer -= rrd.rra_def[chosen_rra].row_cnt;
                 if (rrd_seek(rrd_file, (rra_base + rra_pointer
             if (rra_pointer >= (signed) rrd.rra_def[chosen_rra].row_cnt) {
                 rra_pointer -= rrd.rra_def[chosen_rra].row_cnt;
                 if (rrd_seek(rrd_file, (rra_base + rra_pointer
-                                        * *ds_cnt
+                                        * (*ds_cnt)
                                         * sizeof(rrd_value_t)),
                              SEEK_SET) != 0) {
                     rrd_set_error("wrap seek in RRA did fail");
                                         * sizeof(rrd_value_t)),
                              SEEK_SET) != 0) {
                     rrd_set_error("wrap seek in RRA did fail");
@@ -456,8 +449,7 @@ int rrd_fetch_fn(
             }
 
             if (rrd_read(rrd_file, data_ptr, sizeof(rrd_value_t) * (*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)) {
+                != (ssize_t) (sizeof(rrd_value_t) * (*ds_cnt))) {
                 rrd_set_error("fetching cdp from rra");
                 for (ii = 0; (unsigned) ii < *ds_cnt; ii++)
                     free((*ds_namv)[ii]);
                 rrd_set_error("fetching cdp from rra");
                 for (ii = 0; (unsigned) ii < *ds_cnt; ii++)
                     free((*ds_namv)[ii]);
@@ -472,7 +464,7 @@ int rrd_fetch_fn(
             /* don't pollute the buffer cache with data read from the file. We do this while reading to 
                keep damage minimal */
             if (0 !=
             /* 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(rrd_file->fd, rrd_head_size, 0,
+                posix_fadvise(rrd_file->fd, rrd_file->header_len, 0,
                               POSIX_FADV_DONTNEED)) {
                 rrd_set_error("setting POSIX_FADV_DONTNEED on '%s': %s",
                               filename, rrd_strerror(errno));
                               POSIX_FADV_DONTNEED)) {
                 rrd_set_error("setting POSIX_FADV_DONTNEED on '%s': %s",
                               filename, rrd_strerror(errno));
@@ -498,7 +490,8 @@ int rrd_fetch_fn(
 #ifdef HAVE_POSIX_FADVISE
     /* and just to be sure we drop everything except the header at the end */
     if (0 !=
 #ifdef HAVE_POSIX_FADVISE
     /* and just to be sure we drop everything except the header at the end */
     if (0 !=
-        posix_fadvise(rrd_file->fd, rrd_head_size, 0, POSIX_FADV_DONTNEED)) {
+        posix_fadvise(rrd_file->fd, rrd_file->header_len, 0,
+                      POSIX_FADV_DONTNEED)) {
         rrd_set_error("setting POSIX_FADV_DONTNEED on '%s': %s", filename,
                       rrd_strerror(errno));
         close(rrd_file->fd);
         rrd_set_error("setting POSIX_FADV_DONTNEED on '%s': %s", filename,
                       rrd_strerror(errno));
         close(rrd_file->fd);
index db4715b..07ee109 100644 (file)
 #include "unused.h"
 #define MEMBLK 8192
 
 #include "unused.h"
 #define MEMBLK 8192
 
-/* open a database file, return its header and a open filehandle */
+#ifdef HAVE_MMAP
+#define __rrd_read(dst, dst_t, cnt) \
+       (dst) = (dst_t*) (data + offset); \
+       offset += sizeof(dst_t) * (cnt)
+#else
+#define __rrd_read(dst, dst_t, cnt) \
+       if ((dst = malloc(sizeof(dst_t)*(cnt))) == NULL) { \
+               rrd_set_error(#dst " malloc"); \
+               goto out_nullify_head; \
+       } \
+       offset += read (rrd_file->fd, dst, sizeof(dst_t)*(cnt))
+#endif
+
+/* open a database file, return its header and an open filehandle */
 /* positioned to the first cdp in the first rra */
 
 rrd_file_t *rrd_open(
 /* positioned to the first cdp in the first rra */
 
 rrd_file_t *rrd_open(
@@ -76,9 +89,13 @@ rrd_file_t *rrd_open(
 {
     int       flags = 0;
     mode_t    mode = S_IRUSR;
 {
     int       flags = 0;
     mode_t    mode = S_IRUSR;
-    int       version, prot = PROT_READ;
-    off_t     offset = 0;
+    int       version;
+
+#ifdef HAVE_MMAP
+    int       mm_prot = PROT_READ, mm_flags = 0;
     char     *data;
     char     *data;
+#endif
+    off_t     offset = 0;
     struct stat statb;
     rrd_file_t *rrd_file = malloc(sizeof(rrd_file_t));
 
     struct stat statb;
     rrd_file_t *rrd_file = malloc(sizeof(rrd_file_t));
 
@@ -88,25 +105,59 @@ rrd_file_t *rrd_open(
     }
     memset(rrd_file, 0, sizeof(rrd_file_t));
     rrd_init(rrd);
     }
     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 DEBUG
+    if ((rdwr & (RRD_READONLY | RRD_READWRITE)) ==
+        (RRD_READONLY | RRD_READWRITE)) {
+        /* Both READONLY and READWRITE were given, which is invalid.  */
+        rrd_set_error("in read/write request mask");
+        exit(-1);
+    }
+#endif
+    if (rdwr & RRD_READONLY) {
+        flags |= O_RDONLY;
+#ifdef HAVE_MMAP
+        mm_flags = MAP_PRIVATE;
+# ifdef MAP_NORESERVE
+        mm_flags |= MAP_NORESERVE;
+# endif
+        mm_flags |= MAP_PRIVATE;
+#endif
+    } else {
+        if (rdwr & RRD_READWRITE) {
+            mode |= S_IWUSR;
+            flags |= O_RDWR;
+#ifdef HAVE_MMAP
+            mm_flags = MAP_SHARED;
+            mm_prot |= PROT_WRITE;
+#endif
+        }
+        if (rdwr & RRD_CREAT) {
+            flags |= (O_CREAT | O_TRUNC);
+        }
     }
     }
-#ifdef O_NONBLOCK
-    flags |= O_NONBLOCK;
+    if (rdwr & RRD_READAHEAD) {
+#ifdef MAP_POPULATE
+        mm_flags |= MAP_POPULATE;
+#endif
+#if defined MAP_NONBLOCK && !defined USE_DIRECT_IO
+        mm_flags |= MAP_NONBLOCK;   /* just populage ptes */
+#endif
+    } else {
+#ifdef USE_DIRECT_IO
+        flags |= O_DIRECT;
+#endif
+#if 0                   //def O_NONBLOCK
+        flags |= O_NONBLOCK;
 #endif
 #endif
+    }
 
     if ((rrd_file->fd = open(file_name, flags, mode)) < 0) {
         rrd_set_error("opening '%s': %s", file_name, rrd_strerror(errno));
         return NULL;
     }
 
 
     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? */
+    /* Better try to avoid seeks as much as possible. stat may be heavy but
+     * many concurrent seeks are even worse.  */
     if ((fstat(rrd_file->fd, &statb)) < 0) {
         rrd_set_error("fstat '%s': %s", file_name, rrd_strerror(errno));
         goto out_close;
     if ((fstat(rrd_file->fd, &statb)) < 0) {
         rrd_set_error("fstat '%s': %s", file_name, rrd_strerror(errno));
         goto out_close;
@@ -126,7 +177,7 @@ rrd_file_t *rrd_open(
 #endif
 
 /*
 #endif
 
 /*
-        if (rdwr == RRD_READWRITE)
+        if (rdwr & RRD_READWRITE)
         {
            if (setvbuf((rrd_file->fd),NULL,_IONBF,2)) {
                   rrd_set_error("failed to disable the stream buffer\n");
         {
            if (setvbuf((rrd_file->fd),NULL,_IONBF,2)) {
                   rrd_set_error("failed to disable the stream buffer\n");
@@ -134,17 +185,21 @@ rrd_file_t *rrd_open(
            }
         }
 */
            }
         }
 */
-    data = mmap(0, rrd_file->file_len, prot, MAP_SHARED,
+#ifdef HAVE_MMAP
+    data = mmap(0, rrd_file->file_len, mm_prot, mm_flags,
                 rrd_file->fd, offset);
 
     /* lets see if the first read worked */
     if (data == MAP_FAILED) {
                 rrd_file->fd, offset);
 
     /* lets see if the first read worked */
     if (data == MAP_FAILED) {
-        rrd_set_error("error mmaping file '%s'", file_name);
+        rrd_set_error("error mmaping file '%s': %s", file_name,
+                      rrd_strerror(errno));
         goto out_close;
     }
     rrd_file->file_start = data;
         goto out_close;
     }
     rrd_file->file_start = data;
+#else
+#endif
 #ifdef USE_MADVISE
 #ifdef USE_MADVISE
-    if (rrd == NULL) {  /*XXX: currently not used! */
+    if (rdwr & RRD_COPY) {  /*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 will read everything in a moment (copying) */
         madvise(data, rrd_file->file_len, MADV_WILLNEED | MADV_SEQUENTIAL);
         goto out_done;
@@ -158,8 +213,8 @@ rrd_file_t *rrd_open(
     madvise(data + offset, sizeof(stat_head_t), MADV_WILLNEED);
 #endif
 
     madvise(data + offset, sizeof(stat_head_t), MADV_WILLNEED);
 #endif
 
-    rrd->stat_head = (stat_head_t *) (data + offset);
-    offset += sizeof(stat_head_t);
+    __rrd_read(rrd->stat_head, stat_head_t,
+               1);
 
     /* lets do some test if we are on track ... */
     if (memcmp(rrd->stat_head->cookie, RRD_COOKIE, sizeof(RRD_COOKIE)) != 0) {
 
     /* lets do some test if we are on track ... */
     if (memcmp(rrd->stat_head->cookie, RRD_COOKIE, sizeof(RRD_COOKIE)) != 0) {
@@ -184,16 +239,16 @@ rrd_file_t *rrd_open(
     madvise(data + offset, sizeof(ds_def_t) * rrd->stat_head->ds_cnt,
             MADV_WILLNEED);
 #endif
     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;
+    __rrd_read(rrd->ds_def, 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
 
 #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;
+    __rrd_read(rrd->rra_def, rra_def_t,
+               rrd->stat_head->rra_cnt);
 
     /* handle different format for the live_head */
     if (version < 3) {
 
     /* handle different format for the live_head */
     if (version < 3) {
@@ -202,28 +257,33 @@ rrd_file_t *rrd_open(
             rrd_set_error("live_head_t malloc");
             goto out_close;
         }
             rrd_set_error("live_head_t malloc");
             goto out_close;
         }
+#ifdef HAVE_MMAP
         memmove(&rrd->live_head->last_up, data + offset, sizeof(long));
         memmove(&rrd->live_head->last_up, data + offset, sizeof(long));
+        offset += sizeof(long);
+#else
+        offset += read(rrd_file->fd, &rrd->live_head->last_up, sizeof(long));
+#endif
         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->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);
+        __rrd_read(rrd->live_head, live_head_t,
+                   1);
     }
     }
-// This doesn't look like it needs madvise
-    rrd->pdp_prep = (pdp_prep_t *) (data + offset);
-    offset += sizeof(pdp_prep_t) * rrd->stat_head->ds_cnt;
-
-// This could benefit from madvise()ing
-    rrd->cdp_prep = (cdp_prep_t *) (data + offset);
-    offset += sizeof(cdp_prep_t) *
-        (rrd->stat_head->rra_cnt * rrd->stat_head->ds_cnt);
-
-// This could benefit from madvise()ing
-    rrd->rra_ptr = (rra_ptr_t *) (data + offset);
-    offset += sizeof(rra_ptr_t) * rrd->stat_head->rra_cnt;
+//XXX: This doesn't look like it needs madvise
+    __rrd_read(rrd->pdp_prep, pdp_prep_t,
+               rrd->stat_head->ds_cnt);
+
+//XXX: This could benefit from madvise()ing
+    __rrd_read(rrd->cdp_prep, cdp_prep_t,
+               rrd->stat_head->rra_cnt * rrd->stat_head->ds_cnt);
+
+//XXX: This could benefit from madvise()ing
+    __rrd_read(rrd->rra_ptr, rra_ptr_t,
+               rrd->stat_head->rra_cnt);
+
 #ifdef USE_MADVISE
   out_done:
 #endif
 #ifdef USE_MADVISE
   out_done:
 #endif
@@ -280,7 +340,7 @@ off_t rrd_seek(
 }
 
 /* Get current position in rrd_file.  */
 }
 
 /* Get current position in rrd_file.  */
-off_t rrd_tell(
+inline off_t rrd_tell(
     rrd_file_t *rrd_file)
 {
     return rrd_file->pos;
     rrd_file_t *rrd_file)
 {
     return rrd_file->pos;
@@ -297,18 +357,21 @@ ssize_t rrd_read(
     char     *pos = rrd_file->file_start + rrd_file->pos;
 
     buf = memmove(buf, pos, count);
     char     *pos = rrd_file->file_start + rrd_file->pos;
 
     buf = memmove(buf, pos, count);
+    rrd_file->pos += count; /* mimmic read() semantics */
     return count;
 #else
     ssize_t   ret;
 
     ret = read(rrd_file->fd, buf, count);
     //XXX: eventually add generic rrd_set_error(""); here
     return count;
 #else
     ssize_t   ret;
 
     ret = read(rrd_file->fd, buf, count);
     //XXX: eventually add generic rrd_set_error(""); here
+    rrd_file->pos += count; /* mimmic read() semantics */
     return ret;
 #endif
 }
 
 /* write count bytes from buffer buf to the current position
     return ret;
 #endif
 }
 
 /* write count bytes from buffer buf to the current position
- * rrd_file->pos of rrd_file->fd.  */
+ * rrd_file->pos of rrd_file->fd.
+ * Returns the number of bytes written.  */
 ssize_t rrd_write(
     rrd_file_t *rrd_file,
     const void *buf,
 ssize_t rrd_write(
     rrd_file_t *rrd_file,
     const void *buf,
@@ -323,13 +386,13 @@ ssize_t rrd_write(
     new_pos = memmove(rrd_file->file_start + rrd_file->pos, buf, count);
     ret = new_pos - off;
 #else
     new_pos = memmove(rrd_file->file_start + rrd_file->pos, buf, count);
     ret = new_pos - off;
 #else
-    ret = write(rrd_file->fd, buf, count)
+    ret = write(rrd_file->fd, buf, count);
 #endif
 #endif
-        return ret;
+    return ret;
 }
 
 /* flush all data pending to be written to FD.  */
 }
 
 /* flush all data pending to be written to FD.  */
-void rrd_flush(
+inline void rrd_flush(
     rrd_file_t *rrd_file)
 {
     if (fdatasync(rrd_file->fd) != 0) {
     rrd_file_t *rrd_file)
 {
     if (fdatasync(rrd_file->fd) != 0) {
index 1778f42..e29f2dd 100644 (file)
@@ -82,7 +82,7 @@ int rrd_resize(
             return (-1);
         }
 
             return (-1);
         }
 
-    rrd_out_file = rrd_open(outfilename, &rrdnew, RRD_CREAT);
+    rrd_out_file = rrd_open(outfilename, &rrdnew, RRD_READWRITE|RRD_CREAT);
     if (rrd_out_file == NULL) {
         rrd_set_error("Can't create '%s': %s", outfilename,
                       rrd_strerror(errno));
     if (rrd_out_file == NULL) {
         rrd_set_error("Can't create '%s': %s", outfilename,
                       rrd_strerror(errno));
index e888c1f..4f43dbf 100644 (file)
@@ -160,9 +160,11 @@ extern    "C" {
     char **buffer,
     int skipfirst);
 
     char **buffer,
     int skipfirst);
 
-#define RRD_READONLY    0
-#define RRD_READWRITE   1
-#define RRD_CREAT       2
+#define RRD_READONLY    (1<<0)
+#define RRD_READWRITE   (1<<1)
+#define RRD_CREAT       (1<<2)
+#define RRD_READAHEAD   (1<<3)
+#define RRD_COPY        (1<<4)
 
     enum cf_en cf_conv(
     const char *string);
 
     enum cf_en cf_conv(
     const char *string);
index a34da71..7890f28 100644 (file)
@@ -7,11 +7,6 @@
  *****************************************************************************/
 
 #include "rrd_tool.h"
  *****************************************************************************/
 
 #include "rrd_tool.h"
-#include <sys/types.h>
-#include <fcntl.h>
-#ifdef HAVE_MMAP
-# include <sys/mman.h>
-#endif
 
 #if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__CYGWIN32__)
 #include <sys/locking.h>
 
 #if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__CYGWIN32__)
 #include <sys/locking.h>
@@ -73,34 +68,51 @@ static void normalize_time(
     }
 }
 
     }
 }
 
-/* Local prototypes */
-int       LockRRD(
-    int in_file);
-
-#ifdef HAVE_MMAP
-info_t   *write_RRA_row(
+static info_t *write_RRA_row(
+    rrd_file_t *rrd_file,
     rrd_t *rrd,
     unsigned long rra_idx,
     unsigned long *rra_current,
     unsigned short CDP_scratch_idx,
     rrd_t *rrd,
     unsigned long rra_idx,
     unsigned long *rra_current,
     unsigned short CDP_scratch_idx,
-#ifndef DEBUG
-    int UNUSED(in_file),
-#else
-    int in_file,
-#endif
     info_t *pcdp_summary,
     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,
-    int in_file,
-    info_t *pcdp_summary,
-    time_t *rra_time);
+    time_t *rra_time)
+{
+    unsigned long ds_idx, cdp_idx;
+    infoval   iv;
+
+    for (ds_idx = 0; ds_idx < rrd->stat_head->ds_cnt; ds_idx++) {
+        /* compute the cdp index */
+        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,
+                rrd_file->pos, rrd->rra_def[rra_idx].cf_nam);
 #endif
 #endif
+        if (pcdp_summary != NULL) {
+            iv.u_val = rrd->cdp_prep[cdp_idx].scratch[CDP_scratch_idx].u_val;
+            /* append info to the return hash */
+            pcdp_summary = info_push(pcdp_summary,
+                                     sprintf_alloc("[%d]RRA[%s][%lu]DS[%s]",
+                                                   *rra_time,
+                                                   rrd->rra_def[rra_idx].
+                                                   cf_nam,
+                                                   rrd->rra_def[rra_idx].
+                                                   pdp_cnt,
+                                                   rrd->ds_def[ds_idx].
+                                                   ds_nam), RD_I_VAL, iv);
+        }
+        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;
+        }
+        *rra_current += sizeof(rrd_value_t);
+    }
+    return (pcdp_summary);
+}
+
 int       rrd_update_r(
     const char *filename,
     const char *tmplt,
 int       rrd_update_r(
     const char *filename,
     const char *tmplt,
@@ -1380,16 +1392,9 @@ int _rrd_update(
                           1) * rrd.rra_def[i].pdp_cnt *
                          rrd.stat_head->pdp_step);
                 }
                           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->fd, pcdp_summary, &rra_time,
-                                  rrd_file->file_start);
-#else
                 pcdp_summary =
                 pcdp_summary =
-                    write_RRA_row(&rrd, i, &rra_current, scratch_idx,
-                                  rrd_file->fd, pcdp_summary, &rra_time);
-#endif
+                    write_RRA_row(rrd_file, &rrd, i, &rra_current,
+                                  scratch_idx, pcdp_summary, &rra_time);
                 if (rrd_test_error())
                     break;
 
                 if (rrd_test_error())
                     break;
 
@@ -1424,16 +1429,9 @@ int _rrd_update(
                               2) * rrd.rra_def[i].pdp_cnt *
                              rrd.stat_head->pdp_step);
                     }
                               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->fd, pcdp_summary, &rra_time,
-                                      rrd_file->file_start);
-#else
                     pcdp_summary =
                     pcdp_summary =
-                        write_RRA_row(&rrd, i, &rra_current, scratch_idx,
-                                      rrd_file->fd, pcdp_summary, &rra_time);
-#endif
+                        write_RRA_row(rrd_file, &rrd, i, &rra_current,
+                                      scratch_idx, pcdp_summary, &rra_time);
                 }
 
                 if (rrd_test_error())
                 }
 
                 if (rrd_test_error())
@@ -1667,89 +1665,3 @@ int LockRRD(
 
     return (rcstat);
 }
 
     return (rcstat);
 }
-
-
-#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
-    int UNUSED(in_file),
-#else
-    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,
-    int in_file,
-    info_t *pcdp_summary,
-    time_t *rra_time)
-#endif
-{
-    unsigned long ds_idx, cdp_idx;
-    infoval   iv;
-
-    for (ds_idx = 0; ds_idx < rrd->stat_head->ds_cnt; ds_idx++) {
-        /* compute the cdp index */
-        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,
-                rrd_file->pos, rrd->rra_def[rra_idx].cf_nam);
-#endif
-        if (pcdp_summary != NULL) {
-            iv.u_val = rrd->cdp_prep[cdp_idx].scratch[CDP_scratch_idx].u_val;
-            /* append info to the return hash */
-            pcdp_summary = info_push(pcdp_summary,
-                                     sprintf_alloc("[%d]RRA[%s][%lu]DS[%s]",
-                                                   *rra_time,
-                                                   rrd->rra_def[rra_idx].
-                                                   cf_nam,
-                                                   rrd->rra_def[rra_idx].
-                                                   pdp_cnt,
-                                                   rrd->ds_def[ds_idx].
-                                                   ds_nam), RD_I_VAL, iv);
-        }
-#ifdef HAVE_MMAP
-        memcpy((char *) rrd_mmaped_file + *rra_current,
-               &(rrd->cdp_prep[cdp_idx].scratch[CDP_scratch_idx].u_val),
-               sizeof(rrd_value_t));
-#else
-        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;
-        }
-#endif
-        *rra_current += sizeof(rrd_value_t);
-    }
-    return (pcdp_summary);
-}