… | |
… | |
131 | our $VERSION = '2.0'; |
131 | our $VERSION = '2.0'; |
132 | |
132 | |
133 | our @AIO_REQ = qw(aio_sendfile aio_read aio_write aio_open aio_close aio_stat |
133 | our @AIO_REQ = qw(aio_sendfile aio_read aio_write aio_open aio_close aio_stat |
134 | aio_lstat aio_unlink aio_rmdir aio_readdir aio_scandir aio_symlink |
134 | aio_lstat aio_unlink aio_rmdir aio_readdir aio_scandir aio_symlink |
135 | aio_fsync aio_fdatasync aio_readahead aio_rename aio_link aio_move |
135 | aio_fsync aio_fdatasync aio_readahead aio_rename aio_link aio_move |
136 | aio_group aio_nop); |
136 | aio_copy aio_group aio_nop aio_mknod); |
137 | our @EXPORT = (@AIO_REQ, qw(aioreq_pri aioreq_nice)); |
137 | our @EXPORT = (@AIO_REQ, qw(aioreq_pri aioreq_nice)); |
138 | our @EXPORT_OK = qw(poll_fileno poll_cb poll_wait flush |
138 | our @EXPORT_OK = qw(poll_fileno poll_cb poll_wait flush |
139 | min_parallel max_parallel nreqs nready npending); |
139 | min_parallel max_parallel nreqs nready npending); |
140 | |
140 | |
141 | @IO::AIO::GRP::ISA = 'IO::AIO::REQ'; |
141 | @IO::AIO::GRP::ISA = 'IO::AIO::REQ'; |
… | |
… | |
264 | |
264 | |
265 | aio_read $fh, 7, 15, $buffer, 0, sub { |
265 | aio_read $fh, 7, 15, $buffer, 0, sub { |
266 | $_[0] > 0 or die "read error: $!"; |
266 | $_[0] > 0 or die "read error: $!"; |
267 | print "read $_[0] bytes: <$buffer>\n"; |
267 | print "read $_[0] bytes: <$buffer>\n"; |
268 | }; |
268 | }; |
269 | |
|
|
270 | =item aio_move $srcpath, $dstpath, $callback->($status) |
|
|
271 | |
|
|
272 | Try to move the I<file> (directories not supported as either source or |
|
|
273 | destination) from C<$srcpath> to C<$dstpath> and call the callback with |
|
|
274 | the C<0> (error) or C<-1> ok. |
|
|
275 | |
|
|
276 | This is a composite request that tries to rename(2) the file first. If |
|
|
277 | rename files with C<EXDEV>, it creates the destination file with mode 0200 |
|
|
278 | and copies the contents of the source file into it using C<aio_sendfile>, |
|
|
279 | followed by restoring atime, mtime, access mode and uid/gid, in that |
|
|
280 | order, and unlinking the C<$srcpath>. |
|
|
281 | |
|
|
282 | If an error occurs, the partial destination file will be unlinked, if |
|
|
283 | possible, except when setting atime, mtime, access mode and uid/gid, where |
|
|
284 | errors are being ignored. |
|
|
285 | |
|
|
286 | =cut |
|
|
287 | |
|
|
288 | sub aio_move($$$) { |
|
|
289 | my ($src, $dst, $cb) = @_; |
|
|
290 | |
|
|
291 | my $pri = aioreq_pri; |
|
|
292 | my $grp = aio_group $cb; |
|
|
293 | |
|
|
294 | aioreq_pri $pri; |
|
|
295 | add $grp aio_rename $src, $dst, sub { |
|
|
296 | if ($_[0] && $! == EXDEV) { |
|
|
297 | aioreq_pri $pri; |
|
|
298 | add $grp aio_open $src, O_RDONLY, 0, sub { |
|
|
299 | if (my $src_fh = $_[0]) { |
|
|
300 | my @stat = stat $src_fh; |
|
|
301 | |
|
|
302 | aioreq_pri $pri; |
|
|
303 | add $grp aio_open $dst, O_WRONLY, 0200, sub { |
|
|
304 | if (my $dst_fh = $_[0]) { |
|
|
305 | aioreq_pri $pri; |
|
|
306 | add $grp aio_sendfile $dst_fh, $src_fh, 0, $stat[7], sub { |
|
|
307 | close $src_fh; |
|
|
308 | |
|
|
309 | if ($_[0] == $stat[7]) { |
|
|
310 | utime $stat[8], $stat[9], $dst; |
|
|
311 | chmod $stat[2] & 07777, $dst_fh; |
|
|
312 | chown $stat[4], $stat[5], $dst_fh; |
|
|
313 | close $dst_fh; |
|
|
314 | |
|
|
315 | aioreq_pri $pri; |
|
|
316 | add $grp aio_unlink $src, sub { |
|
|
317 | $grp->result ($_[0]); |
|
|
318 | }; |
|
|
319 | } else { |
|
|
320 | my $errno = $!; |
|
|
321 | aioreq_pri $pri; |
|
|
322 | add $grp aio_unlink $dst, sub { |
|
|
323 | $! = $errno; |
|
|
324 | $grp->result (-1); |
|
|
325 | }; |
|
|
326 | } |
|
|
327 | }; |
|
|
328 | } else { |
|
|
329 | $grp->result (-1); |
|
|
330 | } |
|
|
331 | }, |
|
|
332 | |
|
|
333 | } else { |
|
|
334 | $grp->result (-1); |
|
|
335 | } |
|
|
336 | }; |
|
|
337 | } else { |
|
|
338 | $grp->result ($_[0]); |
|
|
339 | } |
|
|
340 | }; |
|
|
341 | |
|
|
342 | $grp |
|
|
343 | } |
|
|
344 | |
269 | |
345 | =item aio_sendfile $out_fh, $in_fh, $in_offset, $length, $callback->($retval) |
270 | =item aio_sendfile $out_fh, $in_fh, $in_offset, $length, $callback->($retval) |
346 | |
271 | |
347 | Tries to copy C<$length> bytes from C<$in_fh> to C<$out_fh>. It starts |
272 | Tries to copy C<$length> bytes from C<$in_fh> to C<$out_fh>. It starts |
348 | reading at byte offset C<$in_offset>, and starts writing at the current |
273 | reading at byte offset C<$in_offset>, and starts writing at the current |
… | |
… | |
404 | =item aio_unlink $pathname, $callback->($status) |
329 | =item aio_unlink $pathname, $callback->($status) |
405 | |
330 | |
406 | Asynchronously unlink (delete) a file and call the callback with the |
331 | Asynchronously unlink (delete) a file and call the callback with the |
407 | result code. |
332 | result code. |
408 | |
333 | |
|
|
334 | =item aio_mknod $path, $mode, $dev, $callback->($status) |
|
|
335 | |
|
|
336 | Asynchronously create a device node (or fifo). See mknod(2): the only |
|
|
337 | portable value for C<$mode> is C<S_IFIFO> ored with permissions, and C<0> |
|
|
338 | for C<$dev>. |
|
|
339 | |
409 | =item aio_link $srcpath, $dstpath, $callback->($status) |
340 | =item aio_link $srcpath, $dstpath, $callback->($status) |
410 | |
341 | |
411 | Asynchronously create a new link to the existing object at C<$srcpath> at |
342 | Asynchronously create a new link to the existing object at C<$srcpath> at |
412 | the path C<$dstpath> and call the callback with the result code. |
343 | the path C<$dstpath> and call the callback with the result code. |
413 | |
344 | |
… | |
… | |
432 | directory (i.e. opendir + readdir + closedir). The entries will not be |
363 | directory (i.e. opendir + readdir + closedir). The entries will not be |
433 | sorted, and will B<NOT> include the C<.> and C<..> entries. |
364 | sorted, and will B<NOT> include the C<.> and C<..> entries. |
434 | |
365 | |
435 | The callback a single argument which is either C<undef> or an array-ref |
366 | The callback a single argument which is either C<undef> or an array-ref |
436 | with the filenames. |
367 | with the filenames. |
|
|
368 | |
|
|
369 | =item aio_copy $srcpath, $dstpath, $callback->($status) |
|
|
370 | |
|
|
371 | Try to copy the I<file> (directories not supported as either source or |
|
|
372 | destination) from C<$srcpath> to C<$dstpath> and call the callback with |
|
|
373 | the C<0> (error) or C<-1> ok. |
|
|
374 | |
|
|
375 | This is a composite request that it creates the destination file with |
|
|
376 | mode 0200 and copies the contents of the source file into it using |
|
|
377 | C<aio_sendfile>, followed by restoring atime, mtime, access mode and |
|
|
378 | uid/gid, in that order. |
|
|
379 | |
|
|
380 | If an error occurs, the partial destination file will be unlinked, if |
|
|
381 | possible, except when setting atime, mtime, access mode and uid/gid, where |
|
|
382 | errors are being ignored. |
|
|
383 | |
|
|
384 | =cut |
|
|
385 | |
|
|
386 | sub aio_copy($$;$) { |
|
|
387 | my ($src, $dst, $cb) = @_; |
|
|
388 | |
|
|
389 | my $pri = aioreq_pri; |
|
|
390 | my $grp = aio_group $cb; |
|
|
391 | |
|
|
392 | aioreq_pri $pri; |
|
|
393 | add $grp aio_open $src, O_RDONLY, 0, sub { |
|
|
394 | if (my $src_fh = $_[0]) { |
|
|
395 | my @stat = stat $src_fh; |
|
|
396 | |
|
|
397 | aioreq_pri $pri; |
|
|
398 | add $grp aio_open $dst, O_CREAT | O_WRONLY | O_TRUNC, 0200, sub { |
|
|
399 | if (my $dst_fh = $_[0]) { |
|
|
400 | aioreq_pri $pri; |
|
|
401 | add $grp aio_sendfile $dst_fh, $src_fh, 0, $stat[7], sub { |
|
|
402 | if ($_[0] == $stat[7]) { |
|
|
403 | $grp->result (0); |
|
|
404 | close $src_fh; |
|
|
405 | |
|
|
406 | # those should not normally block. should. should. |
|
|
407 | utime $stat[8], $stat[9], $dst; |
|
|
408 | chmod $stat[2] & 07777, $dst_fh; |
|
|
409 | chown $stat[4], $stat[5], $dst_fh; |
|
|
410 | close $dst_fh; |
|
|
411 | } else { |
|
|
412 | $grp->result (-1); |
|
|
413 | close $src_fh; |
|
|
414 | close $dst_fh; |
|
|
415 | |
|
|
416 | aioreq $pri; |
|
|
417 | add $grp aio_unlink $dst; |
|
|
418 | } |
|
|
419 | }; |
|
|
420 | } else { |
|
|
421 | $grp->result (-1); |
|
|
422 | } |
|
|
423 | }, |
|
|
424 | |
|
|
425 | } else { |
|
|
426 | $grp->result (-1); |
|
|
427 | } |
|
|
428 | }; |
|
|
429 | |
|
|
430 | $grp |
|
|
431 | } |
|
|
432 | |
|
|
433 | =item aio_move $srcpath, $dstpath, $callback->($status) |
|
|
434 | |
|
|
435 | Try to move the I<file> (directories not supported as either source or |
|
|
436 | destination) from C<$srcpath> to C<$dstpath> and call the callback with |
|
|
437 | the C<0> (error) or C<-1> ok. |
|
|
438 | |
|
|
439 | This is a composite request that tries to rename(2) the file first. If |
|
|
440 | rename files with C<EXDEV>, it copies the file with C<aio_copy> and, if |
|
|
441 | that is successful, unlinking the C<$srcpath>. |
|
|
442 | |
|
|
443 | =cut |
|
|
444 | |
|
|
445 | sub aio_move($$;$) { |
|
|
446 | my ($src, $dst, $cb) = @_; |
|
|
447 | |
|
|
448 | my $pri = aioreq_pri; |
|
|
449 | my $grp = aio_group $cb; |
|
|
450 | |
|
|
451 | aioreq_pri $pri; |
|
|
452 | add $grp aio_rename $src, $dst, sub { |
|
|
453 | if ($_[0] && $! == EXDEV) { |
|
|
454 | aioreq_pri $pri; |
|
|
455 | add $grp aio_copy $src, $dst, sub { |
|
|
456 | $grp->result ($_[0]); |
|
|
457 | |
|
|
458 | if (!$_[0]) { |
|
|
459 | aioreq_pri $pri; |
|
|
460 | add $grp aio_unlink $src; |
|
|
461 | } |
|
|
462 | }; |
|
|
463 | } else { |
|
|
464 | $grp->result ($_[0]); |
|
|
465 | } |
|
|
466 | }; |
|
|
467 | |
|
|
468 | $grp |
|
|
469 | } |
437 | |
470 | |
438 | =item aio_scandir $path, $maxreq, $callback->($dirs, $nondirs) |
471 | =item aio_scandir $path, $maxreq, $callback->($dirs, $nondirs) |
439 | |
472 | |
440 | Scans a directory (similar to C<aio_readdir>) but additionally tries to |
473 | Scans a directory (similar to C<aio_readdir>) but additionally tries to |
441 | efficiently separate the entries of directory C<$path> into two sets of |
474 | efficiently separate the entries of directory C<$path> into two sets of |
… | |
… | |
955 | *$sym |
988 | *$sym |
956 | } |
989 | } |
957 | |
990 | |
958 | min_parallel 8; |
991 | min_parallel 8; |
959 | |
992 | |
|
|
993 | END { |
|
|
994 | flush; |
|
|
995 | }; |
|
|
996 | |
960 | 1; |
997 | 1; |
961 | |
998 | |
962 | =head2 FORK BEHAVIOUR |
999 | =head2 FORK BEHAVIOUR |
963 | |
1000 | |
964 | This module should do "the right thing" when the process using it forks: |
1001 | This module should do "the right thing" when the process using it forks: |