Skip Menu |

Preferred bug tracker

Please visit the preferred bug tracker to report your issue.

This queue is for tickets about the Filesys-Notify-Simple CPAN distribution.

Report information
The Basics
Id: 70351
Status: resolved
Priority: 0/
Queue: Filesys-Notify-Simple

People
Owner: Nobody in particular
Requestors: sgifford [...] suspectclass.com
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in: (no value)
Fixed in: (no value)



Subject: Improvements to Filesys::Notify::Simple (with patch)
Hello, Here is a patch with some improvements I made to Filesys::Notify::Simple. These are the changes: * Adds options to the constructor, including: * Details: Set to 0 to get a single notification of some change, instead of one notification for each change * Latency: Set the time to wait for notification. Sets the FSEvents latency, or the sleep time for the timer method * Method: Choose a method, instead of auto-detecting. * Adds documentation of these options * Pass object to the various wait_* handlers, so they can see the object's properties Thanks!
Subject: filesys-notify-simple-sg.patch
--- Simple.pm 2011-01-13 14:32:18.000000000 -0500 +++ /Users/sgifford/perl/lib/perl5/site_perl/5.8.9/Filesys/Notify/Simple.pm 2011-08-18 16:54:13.000000000 -0400 @@ -9,13 +9,29 @@ use constant NO_OPT => $ENV{PERL_FNS_NO_OPT}; sub new { - my($class, $path) = @_; + my($class, $path, %opt) = @_; unless (ref $path eq 'ARRAY') { Carp::croak('Usage: Filesys::Notify::Simple->new([ $path1, $path2 ])'); } my $self = bless { paths => $path }, $class; + if (defined($opt{Detail})) { + $self->{detail} = $opt{Detail}; + } else { + $self->{detail} = 1; + } + + if (defined($opt{Latency})) { + $self->{latency} = $opt{Latency}; + } else { + $self->{latency} = 2; + } + + if (defined($opt{Method})) { + $self->{method} = $opt{Method}; + } + $self->init; $self; @@ -24,7 +40,7 @@ sub wait { my($self, $cb) = @_; - $self->{watcher} ||= $self->{watcher_cb}->(@{$self->{paths}}); + $self->{watcher} ||= $self->{watcher_cb}->($self, @{$self->{paths}}); $self->{watcher}->($cb); } @@ -32,16 +48,31 @@ my $self = shift; local $@; - if ($^O eq 'linux' && !NO_OPT && eval { require Linux::Inotify2; 1 }) { + if (!$self->{method}) { + if ($^O eq 'linux' && !NO_OPT && eval { require Linux::Inotify2; 1 }) { + $self->{method} = 'inotify2'; + } elsif ($^O eq 'darwin' && !NO_OPT && eval { require Mac::FSEvents; 1 }) { + $self->{method} = 'fsevents'; + } else { + $self->{method} = 'timer'; + } + } + + if ($self->{method} eq 'inotify2') { + require Linux::Inotify2; $self->{watcher_cb} = \&wait_inotify2; - } elsif ($^O eq 'darwin' && !NO_OPT && eval { require Mac::FSEvents; 1 }) { - $self->{watcher_cb} = \&wait_fsevents; - } else { + } elsif ($self->{method} eq 'fsevents') { + require Mac::FSEvents; + $self->{watcher_cb} = \&wait_fsevents; + } elsif ($self->{method} eq 'timer') { $self->{watcher_cb} = \&wait_timer; + } else { + die "Invalid method requested\n"; } } sub wait_inotify2 { + my $obj = shift; my @path = @_; Linux::Inotify2->import; @@ -62,14 +93,18 @@ sub wait_fsevents { require IO::Select; + my $obj = shift; my @path = @_; - my $fs = _full_scan(@path); + my $fs; + if ($obj->{detail} > 0) { + $fs = _full_scan(@path); + } my $sel = IO::Select->new; my %events; for my $path (@path) { - my $fsevents = Mac::FSEvents->new({ path => $path, latency => 1 }); + my $fsevents = Mac::FSEvents->new({ path => $path, latency => $obj->{latency} }); my $fh = $fsevents->watch; $sel->add($fh); $events{fileno $fh} = $fsevents; @@ -84,11 +119,14 @@ my $fsevents = $events{fileno $fh}; my %uniq; my @path = grep !$uniq{$_}++, map { $_->path } $fsevents->read_events; - - my $new_fs = _full_scan(@path); - my $old_fs = +{ map { ($_ => $fs->{$_}) } keys %$new_fs }; - _compare_fs($old_fs, $new_fs, sub { push @events, { path => $_[0] } }); - $fs->{$_} = $new_fs->{$_} for keys %$new_fs; + if ($obj->{details} > 0) { + my $new_fs = _full_scan(@path); + my $old_fs = +{ map { ($_ => $fs->{$_}) } keys %$new_fs }; + _compare_fs($old_fs, $new_fs, sub { push @events, { path => $_[0] } }); + $fs->{$_} = $new_fs->{$_} for keys %$new_fs; + } else { + push(@events,map { { path => $_ } } @path); + } last if @events; } @@ -97,6 +135,7 @@ } sub wait_timer { + my $obj = shift; my @path = @_; my $fs = _full_scan(@path); @@ -105,7 +144,7 @@ my $cb = shift; my @events; while (1) { - sleep 2; + sleep $obj->{latency}; my $new_fs = _full_scan(@path); _compare_fs($fs, $new_fs, sub { push @events, { path => $_[0] } }); $fs = $new_fs; @@ -220,6 +259,81 @@ modules. Platform specific optimizations with L<Linux::Inotify2> and L<Mac::FSEvents> are truely optional. +=head1 CONSTRUCTOR + +=over 4 + +=item new ( [ @dirs ], opt1 => val1, ... ) + +Creates a new filesystem monitor. C<@dirs> is a list of directories +to monitor, given as an array reference. Additional named parameters +can be passed after that, including: + +=over 4 + +=item Detail + +Set to 1 (the default) or higher to get a notification for each change +to the filesystem with the full path to each changed file. Set to 0 +to get just a notification of some change to the monitored +directories, without information about individual changes. Note that +if the individual changes have been detected already, they may be sent. + +=item Latency + +Requested time to wait between notifications, in seconds. The default +is 2 seconds. This is advisory, and you may get notifications more or +less frequently than this. + +=item Method + +Method to use to monitor for changes. The default is to auto-detect +the most efficient method based on your OS and installed modules. +Values are: + +=over 4 + +=item timer + +Periodically scan the entire filesystem for changes. See the +C<Latency> option to control how often files are checked. + +=item inotify2 + +Use Linux inotify, version 2. Requires L<Linux::Inotify2>. + +=item fsevent + +Use MacOS X FS Events. Requires L<Mac::FSEvents>. + +=back + +=back + +=back + +=head1 METHODS + +=over 4 + +=item wait ( &notify_sub ) + +Callback sub which should be called whenever a modified file is +changed. It will be passed a single parameter containing an array +reference; each item in the array is a hash reference with the +following values: + +=over 4 + +=item path + +The path of the file that changed, or the monitored directory if +C<Detail> was set to 0 in the constructor. + +=back + +=back + =head1 AUTHOR Tatsuhiko Miyagawa E<lt>miyagawa@bulknews.netE<gt>
Subject: Re: [rt.cpan.org #70351] Improvements to Filesys::Notify::Simple (with patch)
Date: Sun, 18 Sep 2011 13:03:16 -0700
To: bug-Filesys-Notify-Simple [...] rt.cpan.org
From: Tatsuhiko Miyagawa <miyagawa [...] gmail.com>
the repository is on github - could you open a pull request there? On Thu, Aug 18, 2011 at 1:59 PM, sgifford@suspectclass.com via RT <bug-Filesys-Notify-Simple@rt.cpan.org> wrote: Show quoted text
> Thu Aug 18 16:59:55 2011: Request 70351 was acted upon. > Transaction: Ticket created by sgifford@suspectclass.com >       Queue: Filesys-Notify-Simple >     Subject: Improvements to Filesys::Notify::Simple (with patch) >   Broken in: (no value) >    Severity: Normal >       Owner: Nobody >  Requestors: sgifford@suspectclass.com >      Status: new >  Ticket <URL: https://rt.cpan.org/Ticket/Display.html?id=70351 > > > > Hello, > > Here is a patch with some improvements I made to Filesys::Notify::Simple.  These are the > changes: > >  * Adds options to the constructor, including: >    * Details: Set to 0 to get a single notification of some change, instead of one notification > for each change >    * Latency: Set the time to wait for notification.  Sets the FSEvents latency, or the sleep time > for the timer method >    * Method: Choose a method, instead of auto-detecting. >  * Adds documentation of these options >  * Pass object to the various wait_* handlers, so they can see the object's properties > > Thanks! > >
-- Tatsuhiko Miyagawa
Please open a bug report and pull request on github instead.