IO-AIO
view release on metacpan or search on metacpan
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
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)
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
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;
{
dREQ;
req->int2 = mode;
req_set_fh_or_path (req, EIO_CHMOD, EIO_FCHMOD, fh_or_path);
REQ_SEND;
}
void
aio_chown (SV8 *fh_or_path, SV *uid, SV *gid, SV *callback = &PL_sv_undef)
PPCODE:
{
dREQ;
req->int2 = SvOK (uid) ? SvIV (uid) : -1;
req->int3 = SvOK (gid) ? SvIV (gid) : -1;
req_set_fh_or_path (req, EIO_CHOWN, EIO_FCHOWN, fh_or_path);
REQ_SEND;
}
http://stackoverflow.com/questions/65170/how-to-get-name-associated-with-open-handle/5286888#5286888
http://blogs.msdn.com/b/adioltean/archive/2005/04/16/408947.aspx
http://msdn.microsoft.com/en-us/library/aa366789%28v=vs.85%29.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/aa366789%28v=vs.85%29.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/aa364425%28v=vs.85%29.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/aa364963%28v=vs.85%29.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/aa364996%28v=vs.85%29.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/aa364994%28v=vs.85%29.aspx
TODO: extra socket/tcp constants &c?
TODO: name_to_handle_At + open_by_handle_at = clone fds
TODO: lchown
TODO: ioprio_get/set
TODO: rewrite rmtree et al. to support working directories (also speed them up)
TODO: maybe IO::AIO leaks fds when requests are cancelled? maybe initialise result to -1?
TODO: aio_wd should use O_PATH on linux, due to lacking O_SEARCH (http://comments.gmane.org/gmane.linux.file-systems/33611)
http://www.openwall.com/lists/musl/2013/02/23/4
TODO: FIDEDUPERANGE, file_ioctl.c
TODO: mincore
TODO: SOCK_CLOEXEc etc.
TODO: unlinkat flags, linkat flags, statat, renameat2 flags
- do not use qsort() but our own algorithm: glibc initialises
the whole locale and I/O subsystem inside qsort, causing
a stack overflow on 32 bit machines. The new sort uses much less
stack and is more than twice as fast in typical situations.
3.2 Sun Jun 7 20:30:05 CEST 2009
- (libeio) pwrite emulation was even more flawed than intended and did
not restore the file offset.
- add aio_readdirx, which can return inode and filetype and sort
the names in various ways.
- unfortunately, utime, chmod, chown on an open file that has just
been written can easily block, which caused aio_copy to block the
process. no more!
- no longer rely on dst path in aio_copy when futime is available.
3.19 Tue Apr 21 22:05:21 CEST 2009
- more perl 5.10 workarounds for aio_read and write.
- aio_write no longer modifies the sv (if possible).
- aio_read now works correctly with magic values.
3.18 Sun Apr 19 21:17:32 CEST 2009
- aio_close will now try to do "the right thing" and thus might
work sensibly for the very first time.
2.41 Mon Sep 24 21:28:21 CEST 2007
- after fork, invest some work to make sure that the poll_fileno
stays stable (by dup2'ing the new fd over the old one), to make
it easier for programs/libs that don't control their forking
behaviour and cannot recreate their watchers.
2.4 Sun Aug 5 18:44:22 CEST 2007
- add aio_truncate, aio_chmod, aio_chown, aio_utime (linux
successfully demonstrated that you can block on futimes...).
- allow undef as fileoffset for aio_read/write and use read/write(2)
internally (useful for sockets or O_APPEND handles).
- allow undef for length in aio_write.
- negative dataoffsets work as expected now in aio_read/aio_write.
- use NV instead of UV for 32 bit perls and file offsets, as NVs
have a larger range then.
- shared code between BDB and IO::AIO.
- aio_busy was completely broken. now fixed.
- readahead emulation now returns something.
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)
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
aio_chown $fh_or_path, $uid, $gid, $callback->($status)
Works like perl's "chown" function, except that "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;
aio_truncate $fh_or_path, $offset, $callback->($status)
Works like truncate(2) or ftruncate(2).
aio_allocate $fh, $mode, $offset, $len, $callback->($status)
Allocates or frees disk space according to the $mode argument. See
the linux "fallocate" documentation for details.
$mode is usually 0 or "IO::AIO::FALLOC_FL_KEEP_SIZE" to allocate
space, or "IO::AIO::FALLOC_FL_PUNCH_HOLE |
libeio/eio.c view on Meta::CPAN
#define link(old,neu) (CreateHardLink (neu, old, 0) ? 0 : EIO_ERRNO (ENOENT, -1))
#define chmod(path,mode) _chmod (path, mode)
#define dup(fd) _dup (fd)
#define dup2(fd1,fd2) _dup2 (fd1, fd2)
#define pipe(fds) _pipe (fds, 4096, O_BINARY)
#define fcntl(fd,cmd,arg) EIO_ENOSYS ()
#define ioctl(fd,cmd,arg) EIO_ENOSYS ()
#define fchmod(fd,mode) EIO_ENOSYS ()
#define chown(path,uid,gid) EIO_ENOSYS ()
#define fchown(fd,uid,gid) EIO_ENOSYS ()
#define truncate(path,offs) EIO_ENOSYS () /* far-miss: SetEndOfFile */
#define ftruncate(fd,offs) EIO_ENOSYS () /* near-miss: SetEndOfFile */
#define mknod(path,mode,dev) EIO_ENOSYS ()
#define sync() EIO_ENOSYS ()
#define readlink(path,buf,s) EIO_ENOSYS ()
#define statvfs(path,buf) EIO_ENOSYS ()
#define fstatvfs(fd,buf) EIO_ENOSYS ()
#define pread(fd,buf,count,offset) eio__pread (fd, buf, count, offset)
#define pwrite(fd,buf,count,offset) eio__pwrite (fd, buf, count, offset)
libeio/eio.c view on Meta::CPAN
case EIO_READAHEAD: req->result = readahead (req->int1, req->offs, req->size); break;
case EIO_SENDFILE: req->result = eio__sendfile (req->int1, req->int2, req->offs, req->size); break;
#if HAVE_AT
case EIO_STAT: ALLOC (sizeof (EIO_STRUCT_STAT));
req->result = fstatat (dirfd, req->ptr1, (EIO_STRUCT_STAT *)req->ptr2, 0); break;
case EIO_LSTAT: ALLOC (sizeof (EIO_STRUCT_STAT));
req->result = fstatat (dirfd, req->ptr1, (EIO_STRUCT_STAT *)req->ptr2, AT_SYMLINK_NOFOLLOW); break;
case EIO_CHOWN: req->result = fchownat (dirfd, req->ptr1, req->int2, req->int3, 0); break;
case EIO_CHMOD: req->result = fchmodat (dirfd, req->ptr1, (mode_t)req->int2, 0); break;
case EIO_TRUNCATE: req->result = eio__truncateat (dirfd, req->ptr1, req->offs); break;
case EIO_OPEN: req->result = openat (dirfd, req->ptr1, req->int1, (mode_t)req->int2); break;
case EIO_SLURP: eio__slurp ( openat (dirfd, req->ptr1, O_RDONLY | O_CLOEXEC), req); break;
case EIO_UNLINK: req->result = unlinkat (dirfd, req->ptr1, 0); break;
case EIO_RMDIR: /* complications arise because "." cannot be removed, so we might have to expand */
req->result = req->wd && SINGLEDOT (req->ptr1)
? rmdir (req->wd->str)
: unlinkat (dirfd, req->ptr1, AT_REMOVEDIR); break;
libeio/eio.c view on Meta::CPAN
: utimensat (dirfd, req->ptr1, times, 0);
}
break;
#else
case EIO_STAT: ALLOC (sizeof (EIO_STRUCT_STAT));
req->result = stat (path , (EIO_STRUCT_STAT *)req->ptr2); break;
case EIO_LSTAT: ALLOC (sizeof (EIO_STRUCT_STAT));
req->result = lstat (path , (EIO_STRUCT_STAT *)req->ptr2); break;
case EIO_CHOWN: req->result = chown (path , req->int2, req->int3); break;
case EIO_CHMOD: req->result = chmod (path , (mode_t)req->int2); break;
case EIO_TRUNCATE: req->result = truncate (path , req->offs); break;
case EIO_OPEN: req->result = open (path , req->int1, (mode_t)req->int2); break;
case EIO_SLURP: eio__slurp ( open (path , O_RDONLY | O_CLOEXEC), req); break;
case EIO_UNLINK: req->result = unlink (path ); break;
case EIO_RMDIR: req->result = rmdir (path ); break;
case EIO_MKDIR: req->result = mkdir (path , (mode_t)req->int2); break;
case EIO_RENAME: req->result = req->int2 ? EIO_ENOSYS () : rename (path, req->ptr2); break;
case EIO_LINK: req->result = link (path , req->ptr2); break;
libeio/eio.c view on Meta::CPAN
memcpy (req->ptr2, self->tmpbuf.ptr, req->result);
}
break;
case EIO_FSTAT: ALLOC (sizeof (EIO_STRUCT_STAT));
req->result = fstat (req->int1, (EIO_STRUCT_STAT *)req->ptr2); break;
case EIO_FSTATVFS: ALLOC (sizeof (EIO_STRUCT_STATVFS));
req->result = fstatvfs (req->int1, (EIO_STRUCT_STATVFS *)req->ptr2); break;
case EIO_FCHOWN: req->result = fchown (req->int1, req->int2, req->int3); break;
case EIO_FCHMOD: req->result = fchmod (req->int1, (mode_t)req->int2); break;
case EIO_FTRUNCATE: req->result = ftruncate (req->int1, req->offs); break;
case EIO_CLOSE: req->result = eio__close (req->int1); break;
case EIO_DUP2: req->result = dup2 (req->int1, req->int2); break;
case EIO_SYNC: req->result = 0; sync (); break;
case EIO_FSYNC: req->result = fsync (req->int1); break;
case EIO_FDATASYNC: req->result = fdatasync (req->int1); break;
case EIO_SYNCFS: req->result = eio__syncfs (req->int1); break;
case EIO_SYNC_FILE_RANGE: req->result = eio__sync_file_range (req->int1, req->offs, req->size, req->int2); break;
libeio/eio.c view on Meta::CPAN
eio_req *eio_ftruncate (int fd, off_t offset, int pri, eio_cb cb, void *data)
{
REQ (EIO_FTRUNCATE); req->int1 = fd; req->offs = offset; SEND;
}
eio_req *eio_fchmod (int fd, mode_t mode, int pri, eio_cb cb, void *data)
{
REQ (EIO_FCHMOD); req->int1 = fd; req->int2 = (long)mode; SEND;
}
eio_req *eio_fchown (int fd, eio_uid_t uid, eio_gid_t gid, int pri, eio_cb cb, void *data)
{
REQ (EIO_FCHOWN); req->int1 = fd; req->int2 = (long)uid; req->int3 = (long)gid; SEND;
}
eio_req *eio_dup2 (int fd, int fd2, int pri, eio_cb cb, void *data)
{
REQ (EIO_DUP2); req->int1 = fd; req->int2 = fd2; SEND;
}
eio_req *eio_sendfile (int out_fd, int in_fd, off_t in_offset, size_t length, int pri, eio_cb cb, void *data)
libeio/eio.c view on Meta::CPAN
eio_req *eio_utime (const char *path, double atime, double mtime, int pri, eio_cb cb, void *data)
{
REQ (EIO_UTIME); PATH; req->nv1 = atime; req->nv2 = mtime; SEND;
}
eio_req *eio_truncate (const char *path, off_t offset, int pri, eio_cb cb, void *data)
{
REQ (EIO_TRUNCATE); PATH; req->offs = offset; SEND;
}
eio_req *eio_chown (const char *path, eio_uid_t uid, eio_gid_t gid, int pri, eio_cb cb, void *data)
{
REQ (EIO_CHOWN); PATH; req->int2 = (long)uid; req->int3 = (long)gid; SEND;
}
eio_req *eio_chmod (const char *path, mode_t mode, int pri, eio_cb cb, void *data)
{
REQ (EIO_CHMOD); PATH; req->int2 = (long)mode; SEND;
}
eio_req *eio_mkdir (const char *path, mode_t mode, int pri, eio_cb cb, void *data)
libeio/eio.h view on Meta::CPAN
eio_ssize_t result; /* result of syscall, e.g. result = read (... */
off_t offs; /* read, write, truncate, readahead, sync_file_range, fallocate, slurp: file offset, mknod: dev_t */
size_t size; /* read, write, readahead, sendfile, msync, mlock, sync_file_range, fallocate, slurp: length */
void *ptr1; /* all applicable requests: pathname, old name, readdir: optional eio_dirents */
void *ptr2; /* all applicable requests: new name or memory buffer; readdir: name strings */
eio_tstamp nv1; /* utime, futime: atime; busy: sleep time */
eio_tstamp nv2; /* utime, futime: mtime */
int int1; /* all applicable requests: file descriptor; sendfile: output fd; open, msync, mlockall, readdir: flags */
long int2; /* chown, fchown: uid; sendfile: input fd; open, chmod, mkdir, mknod: file mode, seek: whence, fcntl, ioctl: request, sync_file_range, fallocate, rename: flags */
long int3; /* chown, fchown: gid; rename, link: working directory of new name */
int errorno; /* errno value on syscall return */
unsigned char flags; /* private */
signed char type;/* EIO_xxx constant ETP */
signed char pri; /* the priority ETP */
#if __i386 || __amd64
unsigned char cancelled; /* ETP */
#else
sig_atomic_t cancelled; /* ETP */
libeio/eio.h view on Meta::CPAN
eio_req *eio_seek (int fd, off_t offset, int whence, int pri, eio_cb cb, void *data);
eio_req *eio_read (int fd, void *buf, size_t length, off_t offset, int pri, eio_cb cb, void *data);
eio_req *eio_write (int fd, void *buf, size_t length, off_t offset, int pri, eio_cb cb, void *data);
eio_req *eio_fcntl (int fd, int cmd, void *arg, int pri, eio_cb cb, void *data);
eio_req *eio_ioctl (int fd, unsigned long request, void *buf, int pri, eio_cb cb, void *data);
eio_req *eio_fstat (int fd, int pri, eio_cb cb, void *data); /* stat buffer=ptr2 allocated dynamically */
eio_req *eio_fstatvfs (int fd, int pri, eio_cb cb, void *data); /* stat buffer=ptr2 allocated dynamically */
eio_req *eio_futime (int fd, eio_tstamp atime, eio_tstamp mtime, int pri, eio_cb cb, void *data);
eio_req *eio_ftruncate (int fd, off_t offset, int pri, eio_cb cb, void *data);
eio_req *eio_fchmod (int fd, mode_t mode, int pri, eio_cb cb, void *data);
eio_req *eio_fchown (int fd, eio_uid_t uid, eio_gid_t gid, int pri, eio_cb cb, void *data);
eio_req *eio_dup2 (int fd, int fd2, int pri, eio_cb cb, void *data);
eio_req *eio_sendfile (int out_fd, int in_fd, off_t in_offset, size_t length, int pri, eio_cb cb, void *data);
eio_req *eio_open (const char *path, int flags, mode_t mode, int pri, eio_cb cb, void *data);
eio_req *eio_utime (const char *path, eio_tstamp atime, eio_tstamp mtime, int pri, eio_cb cb, void *data);
eio_req *eio_truncate (const char *path, off_t offset, int pri, eio_cb cb, void *data);
eio_req *eio_chown (const char *path, eio_uid_t uid, eio_gid_t gid, int pri, eio_cb cb, void *data);
eio_req *eio_chmod (const char *path, mode_t mode, int pri, eio_cb cb, void *data);
eio_req *eio_mkdir (const char *path, mode_t mode, int pri, eio_cb cb, void *data);
eio_req *eio_readdir (const char *path, int flags, int pri, eio_cb cb, void *data); /* result=ptr2 allocated dynamically */
eio_req *eio_rmdir (const char *path, int pri, eio_cb cb, void *data);
eio_req *eio_unlink (const char *path, int pri, eio_cb cb, void *data);
eio_req *eio_readlink (const char *path, int pri, eio_cb cb, void *data); /* result=ptr2 allocated dynamically */
eio_req *eio_realpath (const char *path, int pri, eio_cb cb, void *data); /* result=ptr2 allocated dynamically */
eio_req *eio_stat (const char *path, int pri, eio_cb cb, void *data); /* stat buffer=ptr2 allocated dynamically */
eio_req *eio_lstat (const char *path, int pri, eio_cb cb, void *data); /* stat buffer=ptr2 allocated dynamically */
eio_req *eio_statvfs (const char *path, int pri, eio_cb cb, void *data); /* stat buffer=ptr2 allocated dynamically */
( run in 1.490 second using v1.01-cache-2.11-cpan-71847e10f99 )