IO-AIO
view release on metacpan or search on metacpan
During their existance, aio requests travel through the following states,
in order:
=over 4
=item ready
Immediately after a request is created it is put into the ready state,
waiting for a thread to execute it.
=item execute
A thread has accepted the request for processing and is currently
executing it (e.g. blocking in read).
=item pending
The request has been executed and is waiting for result processing.
While request submission and execution is fully asynchronous, result
processing is not and relies on the perl interpreter calling C<poll_cb>
(or another function with the same effect).
=item result
The request results are processed synchronously by C<poll_cb>.
The C<poll_cb> function will process all outstanding aio requests by
calling their callbacks, freeing memory associated with them and managing
any groups they are contained in.
=item done
Request has reached the end of its lifetime and holds no resources anymore
(except possibly for the Perl object, but its connection to the actual
aio request is severed and calling its methods will either do nothing or
result in a runtime error).
=back
=cut
package IO::AIO;
use Carp ();
use common::sense;
use base 'Exporter';
BEGIN {
our $VERSION = 4.81;
our @AIO_REQ = qw(aio_sendfile aio_seek aio_read aio_write aio_open aio_close
aio_stat aio_lstat aio_unlink aio_rmdir aio_readdir aio_readdirx
aio_scandir aio_symlink aio_readlink aio_realpath aio_fcntl aio_ioctl
aio_sync aio_fsync aio_syncfs aio_fdatasync aio_sync_file_range
aio_pathsync aio_readahead aio_fiemap aio_allocate
aio_rename aio_rename2 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
aio_msync aio_mtouch aio_mlock aio_mlockall
aio_statvfs
aio_slurp
aio_wd);
our @EXPORT = (@AIO_REQ, qw(aioreq_pri aioreq_nice));
our @EXPORT_OK = qw(poll_fileno poll_cb poll_wait flush
min_parallel max_parallel max_idle idle_timeout
nreqs nready npending nthreads
max_poll_time max_poll_reqs
sendfile fadvise madvise
mmap munmap mremap munlock munlockall
accept4 tee splice pipe2 pipesize
fexecve mount umount memfd_create eventfd
timerfd_create timerfd_settime timerfd_gettime
pidfd_open pidfd_send_signal pidfd_getfd);
push @AIO_REQ, qw(aio_busy); # not exported
@IO::AIO::GRP::ISA = 'IO::AIO::REQ';
require XSLoader;
XSLoader::load ("IO::AIO", $VERSION);
}
=head1 FUNCTIONS
=head2 QUICK OVERVIEW
This section simply lists the prototypes most of the functions for
quick reference. See the following sections for function-by-function
documentation.
aio_wd $pathname, $callback->($wd)
aio_open $pathname, $flags, $mode, $callback->($fh)
aio_close $fh, $callback->($status)
aio_seek $fh,$offset,$whence, $callback->($offs)
aio_read $fh,$offset,$length, $data,$dataoffset, $callback->($retval)
aio_write $fh,$offset,$length, $data,$dataoffset, $callback->($retval)
aio_sendfile $out_fh, $in_fh, $in_offset, $length, $callback->($retval)
aio_readahead $fh,$offset,$length, $callback->($retval)
aio_stat $fh_or_path, $callback->($status)
aio_lstat $fh, $callback->($status)
aio_statvfs $fh_or_path, $callback->($statvfs)
aio_utime $fh_or_path, $atime, $mtime, $callback->($status)
aio_chown $fh_or_path, $uid, $gid, $callback->($status)
aio_chmod $fh_or_path, $mode, $callback->($status)
aio_truncate $fh_or_path, $offset, $callback->($status)
aio_allocate $fh, $mode, $offset, $len, $callback->($status)
aio_fiemap $fh, $start, $length, $flags, $count, $cb->(\@extents)
aio_unlink $pathname, $callback->($status)
aio_mknod $pathname, $mode, $dev, $callback->($status)
aio_link $srcpath, $dstpath, $callback->($status)
aio_symlink $srcpath, $dstpath, $callback->($status)
aio_readlink $pathname, $callback->($link)
aio_realpath $pathname, $callback->($path)
aio_rename $srcpath, $dstpath, $callback->($status)
aio_rename2 $srcpath, $dstpath, $flags, $callback->($status)
aio_mkdir $pathname, $mode, $callback->($status)
aio_rmdir $pathname, $callback->($status)
aio_readdir $pathname, $callback->($entries)
aio_readdirx $pathname, $flags, $callback->($entries, $flags)
IO::AIO::READDIR_DENTS IO::AIO::READDIR_DIRS_FIRST
IO::AIO::READDIR_STAT_ORDER IO::AIO::READDIR_FOUND_UNKNOWN
aio_scandir $pathname, $maxreq, $callback->($dirs, $nondirs)
aio_load $pathname, $data, $callback->($status)
aio_copy $srcpath, $dstpath, $callback->($status)
aio_move $srcpath, $dstpath, $callback->($status)
aio_rmtree $pathname, $callback->($status)
aio_fcntl $fh, $cmd, $arg, $callback->($status)
aio_ioctl $fh, $request, $buf, $callback->($status)
aio_sync $callback->($status)
aio_syncfs $fh, $callback->($status)
aio_fsync $fh, $callback->($status)
aio_fdatasync $fh, $callback->($status)
aio_sync_file_range $fh, $offset, $nbytes, $flags, $callback->($status)
aio_pathsync $pathname, $callback->($status)
aio_msync $scalar, $offset = 0, $length = undef, flags = MS_SYNC, $callback->($status)
aio_mtouch $scalar, $offset = 0, $length = undef, flags = 0, $callback->($status)
aio_mlock $scalar, $offset = 0, $length = undef, $callback->($status)
aio_mlockall $flags, $callback->($status)
aio_group $callback->(...)
aio_nop $callback->()
$prev_pri = aioreq_pri [$pri]
aioreq_nice $pri_adjust
IO::AIO::poll_wait
IO::AIO::poll_cb
IO::AIO::poll
IO::AIO::flush
IO::AIO::max_poll_reqs $nreqs
IO::AIO::max_poll_time $seconds
IO::AIO::min_parallel $nthreads
IO::AIO::max_parallel $nthreads
IO::AIO::max_idle $nthreads
IO::AIO::idle_timeout $seconds
IO::AIO::max_outstanding $maxreqs
IO::AIO::nreqs
IO::AIO::nready
IO::AIO::npending
IO::AIO::reinit
$nfd = IO::AIO::get_fdlimit
IO::AIO::min_fdlimit $nfd
whether a file handle or path was passed.
On success, the callback is passed a hash reference with the following
members: C<bsize>, C<frsize>, C<blocks>, C<bfree>, C<bavail>, C<files>,
C<ffree>, C<favail>, C<fsid>, C<flag> and C<namemax>. On failure, C<undef>
is passed.
The following POSIX IO::AIO::ST_* constants are defined: C<ST_RDONLY> and
C<ST_NOSUID>.
The following non-POSIX IO::AIO::ST_* flag masks are defined to
their correct value when available, or to C<0> on systems that do
not support them: C<ST_NODEV>, C<ST_NOEXEC>, C<ST_SYNCHRONOUS>,
C<ST_MANDLOCK>, C<ST_WRITE>, C<ST_APPEND>, C<ST_IMMUTABLE>, C<ST_NOATIME>,
C<ST_NODIRATIME> and C<ST_RELATIME>.
Example: stat C</wd> and dump out the data if successful.
aio_statvfs "/wd", sub {
my $f = $_[0]
or die "statvfs: $!";
use Data::Dumper;
say Dumper $f;
};
# result:
{
bsize => 1024,
bfree => 4333064312,
blocks => 10253828096,
files => 2050765568,
flag => 4096,
favail => 2042092649,
bavail => 4333064312,
ffree => 2042092649,
namemax => 255,
frsize => 1024,
fsid => 1810
}
=item aio_utime $fh_or_path, $atime, $mtime, $callback->($status)
Works like perl's C<utime> function (including the special case of $atime
and $mtime being undef). Fractional times are supported if the underlying
syscalls support them.
When called with a pathname, uses utimensat(2) or utimes(2) if available,
otherwise utime(2). If called on a file descriptor, uses futimens(2)
or futimes(2) if available, otherwise returns ENOSYS, so this is not
portable.
Examples:
# set atime and mtime to current time (basically touch(1)):
aio_utime "path", undef, undef;
# set atime to current time and mtime to beginning of the epoch:
aio_utime "path", time, undef; # undef==0
=item aio_chown $fh_or_path, $uid, $gid, $callback->($status)
Works like perl's C<chown> function, except that C<undef> for either $uid
or $gid is being interpreted as "do not change" (but -1 can also be used).
Examples:
# same as "chown root path" in the shell:
aio_chown "path", 0, -1;
# same as above:
aio_chown "path", 0, undef;
=item aio_truncate $fh_or_path, $offset, $callback->($status)
Works like truncate(2) or ftruncate(2).
=item aio_allocate $fh, $mode, $offset, $len, $callback->($status)
Allocates or frees disk space according to the C<$mode> argument. See the
linux C<fallocate> documentation for details.
C<$mode> is usually C<0> or C<IO::AIO::FALLOC_FL_KEEP_SIZE> to allocate
space, or C<IO::AIO::FALLOC_FL_PUNCH_HOLE | IO::AIO::FALLOC_FL_KEEP_SIZE>,
to deallocate a file range.
IO::AIO also supports C<FALLOC_FL_COLLAPSE_RANGE>, to remove a range
(without leaving a hole), C<FALLOC_FL_ZERO_RANGE>, to zero a range,
C<FALLOC_FL_INSERT_RANGE> to insert a range and C<FALLOC_FL_UNSHARE_RANGE>
to unshare shared blocks (see your L<fallocate(2)> manpage).
The file system block size used by C<fallocate> is presumably the
C<f_bsize> returned by C<statvfs>, but different filesystems and filetypes
can dictate other limitations.
If C<fallocate> isn't available or cannot be emulated (currently no
emulation will be attempted), passes C<-1> and sets C<$!> to C<ENOSYS>.
=item aio_chmod $fh_or_path, $mode, $callback->($status)
Works like perl's C<chmod> function.
=item aio_unlink $pathname, $callback->($status)
Asynchronously unlink (delete) a file and call the callback with the
result code.
=item aio_mknod $pathname, $mode, $dev, $callback->($status)
[EXPERIMENTAL]
Asynchronously create a device node (or fifo). See mknod(2).
The only (POSIX-) portable way of calling this function is:
aio_mknod $pathname, IO::AIO::S_IFIFO | $mode, 0, sub { ...
See C<aio_stat> for info about some potentially helpful extra constants
and functions.
=item aio_link $srcpath, $dstpath, $callback->($status)
Asynchronously create a new link to the existing object at C<$srcpath> at
the path C<$dstpath> and call the callback with the result code.
=item aio_symlink $srcpath, $dstpath, $callback->($status)
my $fh = shift
or return $grp->result (-1);
aioreq_pri $pri;
add $grp aio_read $fh, 0, (-s $fh), $$data, 0, sub {
$grp->result ($_[0]);
};
};
$grp
}
=item aio_copy $srcpath, $dstpath, $callback->($status)
Try to copy the I<file> (directories not supported as either source or
destination) from C<$srcpath> to C<$dstpath> and call the callback with
a status of C<0> (ok) or C<-1> (error, see C<$!>).
Existing destination files will be truncated.
This is a composite request that creates the destination file with
mode 0200 and copies the contents of the source file into it using
C<aio_sendfile>, followed by restoring atime, mtime, access mode and
uid/gid, in that order.
If an error occurs, the partial destination file will be unlinked, if
possible, except when setting atime, mtime, access mode and uid/gid, where
errors are being ignored.
=cut
sub aio_copy($$;$) {
my ($src, $dst, $cb) = @_;
my $pri = aioreq_pri;
my $grp = aio_group $cb;
aioreq_pri $pri;
add $grp aio_open $src, O_RDONLY, 0, sub {
if (my $src_fh = $_[0]) {
my @stat = stat $src_fh; # hmm, might block over nfs?
aioreq_pri $pri;
add $grp aio_open $dst, O_CREAT | O_WRONLY | O_TRUNC, 0200, sub {
if (my $dst_fh = $_[0]) {
# best-effort preallocate
aioreq_pri $pri;
add $grp aio_allocate $dst_fh, IO::AIO::FALLOC_FL_KEEP_SIZE, 0, $stat[7], sub { };
aioreq_pri $pri;
add $grp aio_sendfile $dst_fh, $src_fh, 0, $stat[7], sub {
if ($_[0] == $stat[7]) {
$grp->result (0);
close $src_fh;
my $ch = sub {
aioreq_pri $pri;
add $grp aio_chmod $dst_fh, $stat[2] & 07777, sub {
aioreq_pri $pri;
add $grp aio_chown $dst_fh, $stat[4], $stat[5], sub {
aioreq_pri $pri;
add $grp aio_close $dst_fh;
}
};
};
aioreq_pri $pri;
add $grp aio_utime $dst_fh, $stat[8], $stat[9], sub {
if ($_[0] < 0 && $! == ENOSYS) {
aioreq_pri $pri;
add $grp aio_utime $dst, $stat[8], $stat[9], $ch;
} else {
$ch->();
}
};
} else {
$grp->result (-1);
close $src_fh;
close $dst_fh;
aioreq $pri;
add $grp aio_unlink $dst;
}
};
} else {
$grp->result (-1);
}
},
} else {
$grp->result (-1);
}
};
$grp
}
=item aio_move $srcpath, $dstpath, $callback->($status)
Try to move the I<file> (directories not supported as either source or
destination) from C<$srcpath> to C<$dstpath> and call the callback with
a status of C<0> (ok) or C<-1> (error, see C<$!>).
This is a composite request that tries to rename(2) the file first; if
rename fails with C<EXDEV>, it copies the file with C<aio_copy> and, if
that is successful, unlinks the C<$srcpath>.
=cut
sub aio_move($$;$) {
my ($src, $dst, $cb) = @_;
my $pri = aioreq_pri;
my $grp = aio_group $cb;
aioreq_pri $pri;
add $grp aio_rename $src, $dst, sub {
if ($_[0] && $! == EXDEV) {
aioreq_pri $pri;
add $grp aio_copy $src, $dst, sub {
( run in 2.194 seconds using v1.01-cache-2.11-cpan-71847e10f99 )