The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

POEx::Inotify - inotify interface for POE

SYNOPSIS

    use strict;

    use POE;
    use POEx::Inotify;

    POEx::Inotify->new( alias=>'notify' );

    POE::Session->create(
        package_states => [ 
                'main' => [ qw(_start notification) ],
        ],
    );

    $poe_kernel->run();
    exit 0;

    sub _start {
        my( $kernel, $heap ) = @_[ KERNEL, HEAP ];

        $kernel->post( 'notify' => monitor => {
                path => '.',
                mask  => IN_CLOSE_WRITE,
                event => 'notification',
                args => [ $args ]
             } );
        return;  
    }

    sub notification {
        my( $kernel, $e, $args ) = @_[ KERNEL, ARG0, ARG1];
        print "File ready: ", $e->fullname, "\n";
        $kernel->post( notify => 'shutdown' );
        return;
    }

DESCRIPTION

POEx::Inotify is a simple interface to the Linux file and directory change notification interface, also called inotify.

It can monitor an existing directory for new files, deleted files, new directories and more. It can monitor an existing file to see if it changes, is deleted or moved.

METHODS

spawn

    POEx::Inotify->spawn( %options );

Creates the POEx::Inotify session. It takes a number of arguments, all of which are optional.

alias

The session alias to register with the kernel. Defaults to inotify.

options

A hashref of POE::Session options that are passed to the component's session creator.

EVENTS

monitor

    $poe_kernel->call( inotify => 'monitor', $arg );

Starts monitoring the specified path for the specified types of changes.

Accepts one argument, a hashref containing the following keys:

path

The filesystem path to the directory to be monitored. Mandatory.

mask

A mask of events that you wish to monitor. May be any of the following constants (exported by Linux::Inotify2) ORed together. Defaults to IN_ALL_EVENTS.

IN_ACCESS

object was accessed

IN_MODIFY

object was modified

IN_ATTRIB

object metadata changed

IN_CLOSE_WRITE

writable fd to file / to object was closed

IN_CLOSE_NOWRITE

readonly fd to file / to object closed

IN_OPEN

object was opened

IN_MOVED_FROM

file was moved from this object (directory)

IN_MOVED_TO

file was moved to this object (directory)

IN_CREATE

file was created in this object (directory always, file in cooked mode)

IN_DELETE

file was deleted from this object (directory)

IN_DELETE_SELF

object itself was deleted

IN_MOVE_SELF

object itself was moved

IN_ALL_EVENTS

all of the above events

IN_ONESHOT

only send event once

IN_ONLYDIR

only watch the path if it is a directory

IN_DONT_FOLLOW

don't follow a sym link

IN_MASK_ADD

not supported with the current version of this module

IN_CLOSE

same as IN_CLOSE_WRITE | IN_CLOSE_NOWRITE

IN_MOVE

same as IN_MOVED_FROM | IN_MOVED_TO

event

The name of the event handler in the current session to post changes back to. Mandatory.

The event handler will receive an Linux::Inotify2::Event as its first argument. Other arguments are those specified by "args".

args

An arrayref of arguments that will be passed to the event handler.

events

A hashref of mask=>event tupples. You may use events to register multiple callbacks at once. The keys are masks, the values are either a scalar (event in current session), arrayref (first element is an event, next elements are arguments) or hashref (with the keys event and args.

And remember, => will turn a bare word into a string. So use , or () to force the use of a constant.

    { IN_CLOSE_WRITE => 'file_changed' }    # WRONG!
    { IN_CLOSE_WRITE, 'file_changed' }      # OK
    { IN_CLOSE_WRITE() => 'file_changed' }  # OK
mode

One of 2 strings: raw or cooked. Raw mode requires that the monitored path exist prior to calling "monitor"; if the path doesn't exist, an exception is thrown.

Cooked mode, however, will wait for the path to be created and then start monitoring it. It does this by checking the parent directories and monitoring the deepest one that exists. And if the path is deleted then parent directories are monitored until the path is created again.

Finaly, in cooked mode, IN_CREATE events are generated for the path. These are normaly never generated for files. For directories, which normaly generate IN_CREATE when a file is created, you may check name; it will be '' for the directory creation event.

The default is cooked.

Example

    use Linux::Inotify2;

    my $dir = '/var/ftp/incoming';

    # Monitor a single event
    my $M = {
            path => $dir,
            mask => IN_DELETE|IN_CLOSE,
            event => 'uploaded',
            args  => [ $dir ]
        };
    $poe_kernel->call( inotify => 'monitor', $M );

    sub uploaded 
    {
        my( $e, $dir ) = @_[ARG0, ARG1];
        warn $e->fullname, " was uploaded to $dir";
        .....
    }

    # monitor multiple events
    $M = {
            path => $path
            events => {
                    (IN_MOVE_TO|IN_CLOSE_WRITE) => 'file_created',
                    (IN_MOVE_FROM|IN_DELETE) => { event => 'file_deleted',
                                                    args  => [ $one, $two ] },
                    IN_CLOSE_NOWRITE, [ 'file_accessed', $path ]
                }
        };
    $poe_kernel->call( inotify => 'monitor', $M );

    sub file_created
    {
        my( $e ) = $_[ARG0];
        .....
    }

    sub file_deleted
    {
        my( $e, $one, $two ) = $_[ARG0, ARG1, ARG2];
        .....
    }

    sub file_accessed
    {
        my( $e, $path ) = $_[ARG0, ARG1];
        .....
    }

unmonitor

    $poe_kernel->call( inotify => 'unmonitor', $arg );

Ends monitoring of the specified path for the current session.

Accepts one argument, a hashref containing the following keys:

path

The filesystem path to the directory to to stop monitoring. Mandatory.

event

Name of the monitor event that was used in the original "monitor" call. You may use * to unmonitor all events for the current session.

events

Use this to unregister multiple events at once. This argument may be an arrayref of event names, or a hashref of mask=>event name tupples.

    events => \@names,
    events => { IN_CLOSE_WRITE() => 'event' }

Note that the mask doesn't have to be an exact match to remove an event. For example, if you monitored IN_CLOSE, which is IN_CLOSE_WRITE|IN_CLOSE_NOWRITE, but only use IN_CLOSE_NOWRITE in your unmonitor call, it will still match and unmonitor IN_CLOSE.

Note

Multiple sessions may monitor the same path at the same time. A single session may monitor multiple paths. However, if a single session is monitoring the same path multiple times it must use different events to distinguish them.

shutdown

    $poe_kernel->call( inotify => 'shutdown' );
    # OR
    $poe_kernel->signal( $poe_kernel => 'shutdown' );
 

Shuts down the component gracefully. All monitored paths will be closed. Has no arguments.

BUGS

The fake IN_CREATE events for cooked mode should be called IN_CREATE_SELF.

TODO

Add a recursive mode. It would create monitors for all subdirectories of a path.

SEE ALSO

Inotify, POE, Linux::Inotify2.

This module's API was heavily inspired by POE::Component::Win32::ChangeNotify.

AUTHOR

Philip Gwyn, <gwyn -at- cpan.org>

COPYRIGHT AND LICENSE

Copyright (C) 2012 by Philip Gwyn. All rights reserved.

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.8 or, at your option, any later version of Perl 5 you may have available.