Feature #4038 » io-advise.patch
| configure.in | ||
|---|---|---|
| 
     fi 
   | 
||
| 
     AC_CHECK_FUNCS(fmod killpg wait4 waitpid fork spawnv syscall chroot getcwd eaccess\ 
   | 
||
| 
     	      truncate ftruncate chsize times utimes utimensat fcntl lockf lstat\ 
   | 
||
| 
     	      link symlink readlink readdir_r fsync fdatasync fchown\ 
   | 
||
| 
     	      link symlink readlink readdir_r fsync fdatasync fchown posix_fadvise\ 
   | 
||
| 
     	      setitimer setruid seteuid setreuid setresuid setproctitle socketpair\ 
   | 
||
| 
     	      setrgid setegid setregid setresgid issetugid pause lchown lchmod\ 
   | 
||
| 
     	      getpgrp setpgrp getpgid setpgid initgroups getgroups setgroups\ 
   | 
||
| io.c | ||
|---|---|---|
| 
     /********************************************************************** 
   | 
||
| 
       io.c - 
   | 
||
| ... | ... | |
| 
     #define rb_io_fdatasync rb_f_notimplement 
   | 
||
| 
     #endif 
   | 
||
| 
     static VALUE sym_normal,   sym_sequential, sym_random, 
   | 
||
| 
                  sym_willneed, sym_dontneed, sym_noreuse; 
   | 
||
| 
     /* 
   | 
||
| 
      *  call-seq: 
   | 
||
| 
      *     ios.advise(advice, offset=0, len=0) -> nil 
   | 
||
| 
      * 
   | 
||
| 
      *  Announce an intention to access data from the current file in a 
   | 
||
| 
      *  specific pattern. On platforms that do not support the 
   | 
||
| 
      *  <em>posix_fadvise(2)</em> system call, this method is a no-op. 
   | 
||
| 
      * 
   | 
||
| 
      * _advice_ is one of the following symbols: 
   | 
||
| 
      * 
   | 
||
| 
      *  * :normal - No advice to give; the default assumption for an open file. 
   | 
||
| 
      *  * :sequential - The data will be accessed sequentially: 
   | 
||
| 
      *     with lower offsets read before higher ones. 
   | 
||
| 
      *  * :random - The data will be accessed in random order. 
   | 
||
| 
      *  * :willneed - The data will be accessed in the near future. 
   | 
||
| 
      *  * :dontneed - The data will not be accessed in the near future. 
   | 
||
| 
      *  * :noreuse - The data will only be accessed once. 
   | 
||
| 
      * 
   | 
||
| 
      *  "data" means the region of the current file that begins 
   | 
||
| 
      *  at _offset_ and extends for _len_ bytes. By default, both _offset_ 
   | 
||
| 
      *  and _len_ are 0, meaning that the advice applies to the entire 
   | 
||
| 
      *  file. 
   | 
||
| 
      * 
   | 
||
| 
      *  If an error occurs, one of the following exceptions will be raised: 
   | 
||
| 
      * 
   | 
||
| 
      *  * <code>IOError</code> - The <code>IO</code> stream is closed. 
   | 
||
| 
      *  * <code>Errno::EBADF</code> - The file descriptor of the current file is 
   | 
||
| 
           invalid. 
   | 
||
| 
      *  * <code>Errno::EINVAL</code> - An invalid value for _advice_ was given. 
   | 
||
| 
      *  * <code>Errno::ESPIPE</code> - The file descriptor of the current 
   | 
||
| 
      *  * file refers to a FIFO or pipe. (Linux raises <code>Errno::EINVAL</code> 
   | 
||
| 
      *  * in this case). 
   | 
||
| 
      *  * <code>TypeError</code> - Either _advice_ was not a Symbol, or one of the 
   | 
||
| 
           other arguments was not an <code>Integer</code>. 
   | 
||
| 
      *  * <code>RangeError</code> - One of the arguments given was too big/small. 
   | 
||
| 
      */ 
   | 
||
| 
     static VALUE 
   | 
||
| 
     rb_io_advise(int argc, VALUE *argv, VALUE io) 
   | 
||
| 
     { 
   | 
||
| 
       off_t offset, len; 
   | 
||
| 
       int advice, rv; 
   | 
||
| 
       VALUE initadvice, initoffset, initlen; 
   | 
||
| 
       rb_io_t *fptr; 
   | 
||
| 
       rb_scan_args(argc, argv, "12", &initadvice, &initoffset, &initlen); 
   | 
||
| 
       if (TYPE(initadvice) != T_SYMBOL) 
   | 
||
| 
           rb_raise(rb_eTypeError, "advice must be a Symbol"); 
   | 
||
| 
       offset = NIL_P(initoffset) ? 0 : NUM2OFFT(initoffset); 
   | 
||
| 
       len    = NIL_P(initlen)    ? 0 : NUM2OFFT(initlen); 
   | 
||
| 
       advice = 0; 
   | 
||
| 
       if      (initadvice == sym_normal)     { 
   | 
||
| 
     #ifdef POSIX_FADV_NORMAL 
   | 
||
| 
           advice = POSIX_FADV_NORMAL; 
   | 
||
| 
     #endif 
   | 
||
| 
       } 
   | 
||
| 
       else if (initadvice == sym_random)     { 
   | 
||
| 
     #ifdef POSIX_FADV_RANDOM 
   | 
||
| 
           advice = POSIX_FADV_RANDOM; 
   | 
||
| 
     #endif 
   | 
||
| 
       } 
   | 
||
| 
       else if (initadvice == sym_sequential) { 
   | 
||
| 
     #ifdef POSIX_FADV_SEQUENTIAL 
   | 
||
| 
           advice = POSIX_FADV_SEQUENTIAL; 
   | 
||
| 
     #endif 
   | 
||
| 
       } 
   | 
||
| 
       else if (initadvice == sym_willneed)   { 
   | 
||
| 
     #ifdef POSIX_FADV_WILLNEED 
   | 
||
| 
           advice = POSIX_FADV_WILLNEED; 
   | 
||
| 
     #endif 
   | 
||
| 
       } 
   | 
||
| 
       else if (initadvice == sym_dontneed)   { 
   | 
||
| 
     #ifdef POSIX_FADV_DONTNEED 
   | 
||
| 
           advice = POSIX_FADV_DONTNEED; 
   | 
||
| 
     #endif 
   | 
||
| 
       } 
   | 
||
| 
       else if (initadvice == sym_noreuse)    { 
   | 
||
| 
     #ifdef POSIX_FADV_NOREUSE 
   | 
||
| 
           advice = POSIX_FADV_NOREUSE; 
   | 
||
| 
     #endif 
   | 
||
| 
       } 
   | 
||
| 
       else 
   | 
||
| 
           rb_raise(rb_eArgError, "Invalid advice: :%s", 
   | 
||
| 
     	       RSTRING_PTR(rb_id2str(SYM2ID(initadvice)))); 
   | 
||
| 
     #ifdef HAVE_POSIX_FADVISE 
   | 
||
| 
       io = GetWriteIO(io); 
   | 
||
| 
       GetOpenFile(io, fptr); 
   | 
||
| 
       if (rv = posix_fadvise(fptr->fd, offset, len, advice)) { 
   | 
||
| 
         /* posix_fadvise(2) doesn't set errno. On success it returns 0; otherwise 
   | 
||
| 
            it returns the error code. */ 
   | 
||
| 
         errno = rv; 
   | 
||
| 
         rb_sys_fail_path(fptr->pathv); 
   | 
||
| 
       } 
   | 
||
| 
     #endif 
   | 
||
| 
       return Qnil; 
   | 
||
| 
     } 
   | 
||
| 
     /* 
   | 
||
| 
      *  call-seq: 
   | 
||
| 
      *     ios.fileno    -> fixnum 
   | 
||
| ... | ... | |
| 
         rb_define_method(rb_cIO, "binmode",  rb_io_binmode_m, 0); 
   | 
||
| 
         rb_define_method(rb_cIO, "binmode?", rb_io_binmode_p, 0); 
   | 
||
| 
         rb_define_method(rb_cIO, "sysseek", rb_io_sysseek, -1); 
   | 
||
| 
         rb_define_method(rb_cIO, "advise", rb_io_advise, -1); 
   | 
||
| 
         rb_define_method(rb_cIO, "ioctl", rb_io_ioctl, -1); 
   | 
||
| 
         rb_define_method(rb_cIO, "fcntl", rb_io_fcntl, -1); 
   | 
||
| ... | ... | |
| 
         sym_textmode = ID2SYM(rb_intern("textmode")); 
   | 
||
| 
         sym_binmode = ID2SYM(rb_intern("binmode")); 
   | 
||
| 
         sym_autoclose = ID2SYM(rb_intern("autoclose")); 
   | 
||
| 
         sym_normal = ID2SYM(rb_intern("normal")); 
   | 
||
| 
         sym_sequential = ID2SYM(rb_intern("sequential")); 
   | 
||
| 
         sym_random = ID2SYM(rb_intern("random")); 
   | 
||
| 
         sym_willneed = ID2SYM(rb_intern("willneed")); 
   | 
||
| 
         sym_dontneed = ID2SYM(rb_intern("dontneed")); 
   | 
||
| 
         sym_noreuse = ID2SYM(rb_intern("noreuse")); 
   | 
||
| 
     } 
   | 
||