Hue-Bond has asked for the wisdom of the Perl Monks concerning the following question:

Today I spent some minutes in seeing what could be done with Linux::Inotify. Actually not much because all you can do with events is print them or know the name of the file affected. I googled a bit and learnt that with C, one can do a switch and test for every possible event in order to do this or that. AFAICT, with Linux::Inotify there's no way of knowing which event occurred, what makes the module pretty useless. Except that I'm missing something, of course. The doc says "An Linux::Inotify::Event object has some interesting data members: mask, cookie and name" but I shouldn't be accessing them directly but through method calls, should I? (I'm pretty newbie to this OO thingy, precisely these days I'm reading on the subject).

So I decided to add this lines to the Event.pm module, where I think they belong:

sub type(%) { my $self = shift; return $reverse{$self->{mask}}; }

Now, one can do something more useful than just printing what happened:

## This code has no checking at all. use strict; use warnings; use Linux::Inotify; my $notifier = Linux::Inotify->new(); my $watch = $notifier->add_watch('.', Linux::Inotify::CREATE); sub do_create { print "File $_[0] created\n"; unlink $_[0]; ## Just for fun } my %dt = ( create => \&do_create, ); for (;;) { my @events = $notifier->read(); for (@events) { $dt{$_->type()}->($_->fullname()); } }

Now, is there a way of knowing what happened without my sub type?

--
David Serrano

Replies are listed 'Best First'.
Re: Linux::Inotify usage.
by Tanktalus (Canon) on Dec 19, 2005 at 02:33 UTC

    First off, your sub type method. That prototype is, as I recall, useless. Which, in my opinion, is worse than normal prototypes in that it's promising a certain behaviour which it can't fulfill (thus it's misleading). Due to the way that prototypes (compile-time checking) and object methods (run-time lookup and resolution) work together, that prototype will get ignored. This is evidenced by the fact that you're actually passing in a scalar (the $_ in $_->type()) rather than calling it as type(%$_). You're best off using prototypes much like goto - avoid it unless you know why you need it.

    The next item I'll address is the fact you're modifying Event.pm, which I presume is part of the Linux::Inotify distribution. This is great if your intention is to submit it as a patch to the author. Otherwise, next time you upgrade your Linux::Inotify installation, or next time you go to a new box, you'll end up without your patch. This will lead to annoying bugs - in this case, they probably won't be hard to find, but they probably will be hard to figure out why it worked before and suddenly stopped when you upgraded or moved to a new machine unless you happen to remember every single patch you've made.

    Better would be to put it in your code like this:

    { package Linux::Inotify::Event; sub type { shift->{map} } }
    That is, it's better only if either you aren't going to submit a patch to the author or if the author isn't being responsive.

    As for your core questions, you're right that there probably should be accessor methods (but not attribute-setting methods - this seems to be a read-only object here). The author in this case has elected not to provide them and implicitly says that you should access them directly when he says "An Linux::Inotify::Event object has some interesting data members: mask, cookie and name." Thus Torsten seems to be saying that you should just use "$_->{mask}" - no need for a function.

    As there are no access restrictions in perl (except via closures), whatever you can do in sub type, you can do outside of that sub.

    Good luck!

      that prototype will get ignored

      Actually, from what I've recently read in the Camel, I supposed that. But the other methods have a prototype too and I only wanted a dirty solution to test my little OO skills.

      modifying Event.pm, which I presume is part of the Linux::Inotify distribution

      Yes, it is. I was thinking in submitting the change but before that I wanted to ask here just in case I was overlooking something.

      I tried using $_->{mask} before asking but I got a "256". That's why there is a $reverse{$self->{mask}} in my sub (copied and pasted from another one). That turns the "256" into the more intelligible "create".

      --
      David Serrano