Tag Archive: perlmonks


I love perl, I really do. The problem is that I need to also work with XML as well. CPAN has numerous modules that work with XML to one degree or another.

Producing XML is simple and easy. Reading or manipulating it involves loading the XML through a parser. The parsers will create a myriad of hashes, arrays and the like but navigating them even with tools like XPath make you want to perform oral surgery on yourself using rusty tiddly winks.

So my question is this: Are there any XML parsers for Perl that are easy to use without having to deal with arbitrary hashes of hashes of hashes and …. (don’t forget the arrays)?

The examples in Linux::Inotify2 are for Event, Glib::IO and a manual loop. With the help of rcaputo, tye and Animator over on Perlmonks.org, I was able to get Linux::Inotify2 to work with POE. :)

#!/usr/bin/perl

use strict;
use warnings;

use Linux::Inotify2;
use POE;

$|++;

POE::Session->create
  ( inline_states =>
      { _start => sub {
            $_[KERNEL]->alias_set(‘notify’);
            $_[HEAP]{inotify} = new Linux::Inotify2
              or die "Unable to create new inotify object: $!";

            $_[HEAP]{inotify}->watch("/tmp/j", IN_CLOSE_WRITE, $_[SESSION]->postback("watch_hdlr"))
              or die "Unable to watch dir: $!";

            my $inotify_FH;
            open $inotify_FH, "< &=" . $_[HEAP]{inotify}->fileno or die "Can’t fdopen: $!\n";
            $_[KERNEL]->select_read( $inotify_FH, "inotify_poll" );
        },
        inotify_poll => sub {
          $_[HEAP]{inotify}->poll;
        },
        watch_hdlr => \&watch_hdlr,
      },
  );

sub watch_hdlr {
  my $event = $_[ARG1][0];

  my $name = $event->fullname;

  print "$name was accessed\n" if $event->IN_ACCESS;
  print "$name is no longer mounted\n" if $event->IN_UNMOUNT;
  print "$name is gone\n" if $event->IN_IGNORED;
  print "$name is new\n" if $event->IN_CLOSE_WRITE;
  print "events for $name have been lost\n" if $event->IN_Q_OVERFLOW;
}

POE::Kernel->run();

exit 0;

Create files for testing:

jason@jfroebe-laptop:~$ dd if=/dev/zero of=/tmp/j/p bs=1M count=2
2+0 records in
2+0 records out
2097152 bytes (2.1 MB) copied, 0.112971 s, 18.6 MB/s

Output

jason@jfroebe-laptop:~/bin$ ./test_poe_linux_inotify.pl
/tmp/j/p is new
/tmp/j/p is new

Hi all,

I’m trying to monitor a directory “/tmp/j” with Linux::Inotify2 to be notified when a file is accessed or when a (write) file descriptor is closed. So far, I haven’t been able to receive any notification events :( My guess is that I’m missing something simple.

#!/usr/bin/perl

use strict;
use warnings;

use Linux::Inotify2;

$|++;

my $inotify = new Linux::Inotify2
 or die "Unable to create new inotify object: $!";
 
1 while $inotify->poll;

$inotify->watch("/tmp/j", IN_ACCESS | IN_CLOSE_WRITE, sub {
 my $event = shift;
 
 my $name = $event->fullname;
 
 print "$name was accessed\n" if $event->IN_ACCESS;
 print "$name is no longer mounted\n" if $event->IN_UNMOUNT;
 print "$name is gone\n" if $event->IN_IGNORED;
 print "$name is new\n" if $event->IN_CLOSE_WRITE;
 print "events for $name have been lost\n" if $event->IN_Q_OVERFLOW;
 print "jjjj\n";
 
 $event->w->cancel;
}) or die "watch creation failed: $!";

$ dd if=/dev/zero of=/tmp/j/p bs=1M count=2
2+0 records in
2+0 records out
2097152 bytes (2.1 MB) copied, 0.101007 s, 20.8 MB/s

The script runs with no warnings.
linux kernel 2.6.24-19-generic

update:
To rule out an issue with the os, I tested with the inotifywatch of the inotify tools package. Running the dd command above several times.

$  inotifywatch -v -e access -e modify -t 20 -r /tmp/j
Establishing watches…
Setting up watch(es) on /tmp/j
OK, /tmp/j is now being watched.
Total of 1 watches.
Finished establishing watches, now collecting statistics.
Will listen for events for 20 seconds.
total  modify  filename
18     18      /tmp/j/

Update to the update:
Did more testing. Looks like the perldoc is wrong. The $inotify->poll needs to be called AFTER the $inotify->watch routines are set!
Thanks Animator for making me rethink how I was calling it. Working code:

#!/usr/bin/perl

use strict;
use warnings;

use Linux::Inotify2;

$|++;

my $inotify = new Linux::Inotify2
 or die "Unable to create new inotify object: $!";

$inotify->watch("/tmp/j", IN_ACCESS | IN_CLOSE_WRITE, sub {
 my $event = shift;
 
 my $name = $event->fullname;
 
 print "$name was accessed\n" if $event->IN_ACCESS;
 print "$name is no longer mounted\n" if $event->IN_UNMOUNT;
 print "$name is gone\n" if $event->IN_IGNORED;
 print "$name is new\n" if $event->IN_CLOSE_WRITE;
 print "events for $name have been lost\n" if $event->IN_Q_OVERFLOW;
 print "jjjj\n";

 # $event->w->cancel;
}) or die "watch creation failed: $!";

1 while $inotify->poll;