--- IO-AIO/AIO.pm 2007/06/03 09:44:17 1.109 +++ IO-AIO/AIO.pm 2008/04/16 16:45:18 1.121 @@ -28,10 +28,13 @@ my $grp = aio_group sub { print "all stats done\n" }; add $grp aio_stat "..." for ...; - # AnyEvent integration + # AnyEvent integration (EV, Event, Glib, Tk, urxvt, pureperl...) open my $fh, "<&=" . IO::AIO::poll_fileno or die "$!"; my $w = AnyEvent->io (fh => $fh, poll => 'r', cb => sub { IO::AIO::poll_cb }); + # EV integration + my $w = EV::io IO::AIO::poll_fileno, EV::READ, \&IO::AIO::poll_cb; + # Event integration Event->io (fd => IO::AIO::poll_fileno, poll => 'r', @@ -185,19 +188,24 @@ package IO::AIO; +use Carp (); + no warnings; use strict 'vars'; use base 'Exporter'; BEGIN { - our $VERSION = '2.4'; + our $VERSION = '2.61'; + + our @AIO_REQ = qw(aio_sendfile aio_read aio_write aio_open aio_close + aio_stat aio_lstat aio_unlink aio_rmdir aio_readdir + aio_scandir aio_symlink aio_readlink aio_sync aio_fsync + aio_fdatasync aio_pathsync aio_readahead + aio_rename aio_link aio_move aio_copy aio_group + aio_nop aio_mknod aio_load aio_rmtree aio_mkdir aio_chown + aio_chmod aio_utime aio_truncate); - our @AIO_REQ = qw(aio_sendfile aio_read aio_write aio_open aio_close aio_stat - aio_lstat aio_unlink aio_rmdir aio_readdir aio_scandir aio_symlink - aio_readlink aio_fsync aio_fdatasync aio_readahead aio_rename aio_link - aio_move aio_copy aio_group aio_nop aio_mknod aio_load aio_rmtree aio_mkdir - aio_chown aio_chmod aio_utime); our @EXPORT = (@AIO_REQ, qw(aioreq_pri aioreq_nice aio_block)); our @EXPORT_OK = qw(poll_fileno poll_cb poll_wait flush min_parallel max_parallel max_idle @@ -313,14 +321,19 @@ =item aio_close $fh, $callback->($status) Asynchronously close a file and call the callback with the result -code. I although accepted, you should not pass in a perl -filehandle here, as perl will likely close the file descriptor another -time when the filehandle is destroyed. Normally, you can safely call perls -C or just let filehandles go out of scope. +code. + +Unfortunately, you can't do this to perl. Perl I very strongly on +closing the file descriptor associated with the filehandle itself. -This is supposed to be a bug in the API, so that might change. It's -therefore best to avoid this function. +Therefore, C will not close the filehandle - instead it will +use dup2 to overwrite the file descriptor with the write-end of a pipe +(the pipe fd will be created on demand and will be cached). +Or in other words: the file descriptor will be closed, but it will not be +free for reuse until the perl filehandle is closed. + +=cut =item aio_read $fh,$offset,$length, $data,$dataoffset, $callback->($retval) @@ -331,10 +344,11 @@ callback without the actual number of bytes read (or -1 on error, just like the syscall). -If C<$offset> is undefined, then the current file offset will be used (and -updated), otherwise the file offset will not be changed by these calls. +If C<$offset> is undefined, then the current file descriptor offset will +be used (and updated), otherwise the file descriptor offset will not be +changed by these calls. -If C<$length> is undefined in C, use the remaining length of C<$data>. +If C<$length> is undefined in C, use the remaining length of C<$data>. If C<$dataoffset> is less than zero, it will be counted from the end of C<$data>. @@ -445,6 +459,11 @@ aio_chown "path", 0, undef; +=item aio_truncate $fh_or_path, $offset, $callback->($status) + +Works like truncate(2) or ftruncate(2). + + =item aio_chmod $fh_or_path, $mode, $callback->($status) Works like perl's C function. @@ -587,7 +606,9 @@ utime $stat[8], $stat[9], $dst; chmod $stat[2] & 07777, $dst_fh; chown $stat[4], $stat[5], $dst_fh; - close $dst_fh; + + aioreq_pri $pri; + add $grp aio_close $dst_fh; } else { $grp->result (-1); close $src_fh; @@ -830,6 +851,10 @@ } } +=item aio_sync $callback->($status) + +Asynchronously call sync and call the callback when finished. + =item aio_fsync $fh, $callback->($status) Asynchronously call fsync on the given filehandle and call the callback @@ -843,6 +868,46 @@ If this call isn't available because your OS lacks it or it couldn't be detected, it will be emulated by calling C instead. +=item aio_pathsync $path, $callback->($status) + +This request tries to open, fsync and close the given path. This is a +composite request intended tosync directories after directory operations +(E.g. rename). This might not work on all operating systems or have any +specific effect, but usually it makes sure that directory changes get +written to disc. It works for anything that can be opened for read-only, +not just directories. + +Passes C<0> when everything went ok, and C<-1> on error. + +=cut + +sub aio_pathsync($;$) { + aio_block { + my ($path, $cb) = @_; + + my $pri = aioreq_pri; + my $grp = aio_group $cb; + + aioreq_pri $pri; + add $grp aio_open $path, O_RDONLY, 0, sub { + my ($fh) = @_; + if ($fh) { + aioreq_pri $pri; + add $grp aio_fsync $fh, sub { + $grp->result ($_[0]); + + aioreq_pri $pri; + add $grp aio_close $fh; + }; + } else { + $grp->result (-1); + } + }; + + $grp + } +} + =item aio_group $callback->(...) This is a very special aio request: Instead of doing something, it is a @@ -988,7 +1053,7 @@ =item $grp->result (...) Set the result value(s) that will be passed to the group callback when all -subrequests have finished and set thre groups errno to the current value +subrequests have finished and set the groups errno to the current value of errno (just like calling C without an error number). By default, no argument will be passed and errno is zero. @@ -1203,7 +1268,7 @@ use an C together with a feed callback. Sets the maximum number of outstanding requests to C<$nreqs>. If you -to queue up more than this number of requests, the next call to the +do queue up more than this number of requests, the next call to the C (and C and other functions calling C) function will block until the limit is no longer exceeded. @@ -1244,22 +1309,6 @@ =cut -# support function to convert a fd into a perl filehandle -sub _fd2fh { - return undef if $_[0] < 0; - - # try to generate nice filehandles - my $sym = "IO::AIO::fd#$_[0]"; - local *$sym; - - open *$sym, "+<&=$_[0]" # usually works under any unix - or open *$sym, "<&=$_[0]" # cygwin needs this - or open *$sym, ">&=$_[0]" # or this - or return undef; - - *$sym -} - min_parallel 8; END { flush } @@ -1292,7 +1341,7 @@ scalars and other data passed into aio requests will also be locked and will consume memory till the request has entered the done state. -This is now awfully much, so queuing lots of requests is not usually a +This is not awfully much, so queuing lots of requests is not usually a problem. Per-thread usage: