--- IO-AIO/AIO.pm 2006/06/24 19:14:04 1.51 +++ IO-AIO/AIO.pm 2006/10/21 23:06:04 1.52 @@ -17,6 +17,11 @@ $_[0] > 0 or die "read error: $!"; }; + use IO::AIO 2; # version has aio objects + + my $req = aio_unlink "/tmp/file", sub { }; + $req->cancel; # cancel request if still in queue + # AnyEvent open my $fh, "<&=" . IO::AIO::poll_fileno or die "$!"; my $w = AnyEvent->io (fh => $fh, poll => 'r', cb => sub { IO::AIO::poll_cb }); @@ -94,6 +99,10 @@ All functions expecting a filehandle keep a copy of the filehandle internally until the request has finished. +All non-composite requests (requests that are not broken down into +multiple requests) return objects of type L that allow +further manipulation of running requests. + The pathnames you pass to these routines I be absolute and encoded in byte form. The reason for the former is that at the time the request is being executed, the current working directory could have @@ -170,10 +179,9 @@ =item aio_move $srcpath, $dstpath, $callback->($status) -[EXPERIMENTAL] - -Try to move the I (directories not supported as either source or destination) -from C<$srcpath> to C<$dstpath> and call the callback with the C<0> (error) or C<-1> ok. +Try to move the I (directories not supported as either source or +destination) from C<$srcpath> to C<$dstpath> and call the callback with +the C<0> (error) or C<-1> ok. This is a composite request that tries to rename(2) the file first. If rename files with C, it creates the destination file with mode 0200 @@ -328,13 +336,14 @@ =item aio_scandir $path, $maxreq, $callback->($dirs, $nondirs) -Scans a directory (similar to C) and tries to separate the -entries of directory C<$path> into two sets of names, ones you can recurse -into (directories), and ones you cannot recurse into (everything else). - -C is a composite request that consists of many -aio-primitives. C<$maxreq> specifies the maximum number of outstanding -aio requests that this function generates. If it is C<< <= 0 >>, then a +Scans a directory (similar to C) but additionally tries to +separate the entries of directory C<$path> into two sets of names, ones +you can recurse into (directories or links to them), and ones you cannot +recurse into (everything else). + +C is a composite request that consists of many sub +requests. C<$maxreq> specifies the maximum number of outstanding aio +requests that this function generates. If it is C<< <= 0 >>, then a suitable default will be chosen (currently 8). On error, the callback is called without arguments, otherwise it receives @@ -353,21 +362,29 @@ The C cannot be avoided, but C'ing every entry can. After reading the directory, the modification time, size etc. of the -directory before and after the readdir is checked, and if they match, the -link count will be used to decide how many entries are directories (if ->= 2). Otherwise, no knowledge of the number of subdirectories will be -assumed. - -Then entires will be sorted into likely directories (everything without a -non-initial dot) and likely non-directories (everything else). Then every -entry + C will be C'ed, likely directories first. This is often -faster because filesystems might detect the type of the entry without -reading the inode data (e.g. ext2fs filetype feature). If that succeeds, -it assumes that the entry is a directory or a symlink to directory (which -will be checked seperately). - -If the known number of directories has been reached, the rest of the -entries is assumed to be non-directories. +directory before and after the readdir is checked, and if they match (and +isn't the current time), the link count will be used to decide how many +entries are directories (if >= 2). Otherwise, no knowledge of the number +of subdirectories will be assumed. + +Then entries will be sorted into likely directories (everything without +a non-initial dot currently) and likely non-directories (everything +else). Then every entry plus an appended C will be C'ed, +likely directories first. If that succeeds, it assumes that the entry +is a directory or a symlink to directory (which will be checked +seperately). This is often faster than stat'ing the entry itself because +filesystems might detect the type of the entry without reading the inode +data (e.g. ext2fs filetype feature). + +If the known number of directories (link count - 2) has been reached, the +rest of the entries is assumed to be non-directories. + +This only works with certainty on POSIX (= UNIX) filesystems, which +fortunately are the vast majority of filesystems around. + +It will also likely work on non-POSIX filesystems with reduced efficiency +as those tend to return 0 or 1 as link counts, which disables the +directory counting heuristic. =cut @@ -379,6 +396,7 @@ # stat once aio_stat $path, sub { return $cb->() if $_[0]; + my $now = time; my $hash1 = join ":", (stat _)[0,1,3,7,9]; # read the directory entries @@ -393,7 +411,7 @@ my $ndirs; # take the slow route if anything looks fishy - if ($hash1 ne $hash2) { + if ($hash1 ne $hash2 or (stat _)[9] == $now) { $ndirs = -1; } else { # if nlink == 2, we are finished @@ -478,6 +496,31 @@ =back +=head2 IO::AIO::CB CLASS + +All non-aggregate C functions return an object of this class when +called in non-void context. + +A request always moves through the following five states in its lifetime, +in order: B (request has been created, but has not been executed +yet), B (request is currently being executed), B +(request has been executed but callback has not been called yet), +B (results are being processed synchronously, includes calling the +callback) and B (request has reached the end of its lifetime and +holds no resources anymore). + +=over 4 + +=item $req->cancel + +Cancels the request, if possible. Has the effect of skipping execution +when entering the B state and skipping calling the callback when +entering the the B state, but will leave the request otherwise +untouched. That means that requests that currently execute will not be +stopped and resources held by the request will not be freed prematurely. + +=back + =head2 SUPPORT FUNCTIONS =over 4 @@ -613,17 +656,23 @@ =head2 FORK BEHAVIOUR +This module should do "the right thing" when the process using it forks: + Before the fork, IO::AIO enters a quiescent state where no requests can be added in other threads and no results will be processed. After the fork the parent simply leaves the quiescent state and continues request/result processing, while the child clears the request/result queue (so the requests started before the fork will only be handled in -the parent). Threats will be started on demand until the limit ste in the +the parent). Threads will be started on demand until the limit ste in the parent process has been reached again. +In short: the parent will, after a short pause, continue as if fork had +not been called, while the child will act as if IO::AIO has not been used +yet. + =head1 SEE ALSO -L, L. +L, L (obsolete). =head1 AUTHOR