package Win32::FileSystem::Watcher;
use version; our $VERSION = qv('0.1.0');
require Exporter;
our @ISA = qw(Exporter Win32::FileSystem::Watcher::SimpleAccessors);
use Win32::MMF::Shareable;
use Win32::FileSystem::Watcher::Constants;
use Win32::FileSystem::Watcher::Synchronous;
use POSIX ":sys_wait_h";
use Win32::FileSystem::Watcher::SimpleAccessors;
use Carp;
use strict;
use warnings;
our @EXPORT = ( keys %{&FILE_NOTIFICATION_CONSTANTS}, keys %{&FILE_ACTION_CONSTANTS} );
__PACKAGE__->accessor('path');
__PACKAGE__->accessor('notify_filter');
__PACKAGE__->accessor('watch_sub_tree');
__PACKAGE__->accessor('watcher');
__PACKAGE__->accessor('child_pid');
__PACKAGE__->accessor('monitoring');
__PACKAGE__->accessor('results');
__PACKAGE__->accessor('mmf_options');
sub new {
my $pkg = shift;
croak 'Need a path' unless @_ >= 1;
my ( $path, ) = shift;
my $self = {
watch_sub_tree => 1,
notify_filter => FILE_NOTIFY_ALL,
mmf_options => { size => 2 * 1024 * 1024 },
@_,
};
bless $self, $pkg;
$self->path($path);
$self->monitoring(0);
return $self;
}
sub start {
my $self = shift;
carp 'Monitoring already started' if $self->monitoring;
$self->child_pid( fork() );
die 'cannot fork.' unless defined( $self->child_pid );
if ( !$self->child_pid ) {
# Child
$self->_init_watcher();
$self->watcher(
Win32::FileSystem::Watcher::Synchronous->new(
$self->path,
notify_filter => $self->notify_filter,
watch_sub_tree => $self->watch_sub_tree,
)
);
while ( $self->monitoring ) {
my @results = $self->watcher->get_results();
if ( @results > 0 ) {
my $r = $self->results || [];
push @$r, $_ foreach @results;
$self->results($r);
}
}
exit;
}
$self->_init_watcher();
}
sub stop {
my $self = shift;
carp 'Not monitoring.' unless $self->monitoring;
$self->monitoring(0);
kill 9, $self->child_pid;
}
sub get_results {
my $self = shift;
my @results = ();
my $results = $self->results;
if ($results) {
push @results, $_ foreach @$results;
$self->results(0);
}
return @results;
}
sub _init_watcher {
my $self = shift;
tie $self->{results}, "Win32::MMF::Shareable", 'results', $self->mmf_options
or carp 'Cannot create memory mapped namespace';
$self->results(0);
tie $self->{monitoring}, "Win32::MMF::Shareable", 'monitoring', $self->mmf_options
or carp 'Cannot create memory mapped namespace';
$self->monitoring(1);
}
sub DESTROY {
my $self = shift;
if ( $self->monitoring ) {
$self->stop();
}
}
1;
__END__
=head1 NAME
Win32::FileSystem::Watcher - Watch a Win32 file system for changes (asynchronously).
=head1 SYNOPSIS
use Win32::FileSystem::Watcher;
my $watcher = Win32::FileSystem::Watcher->new( "c:\\" );
# or
my $watcher = Win32::FileSystem::Watcher->new(
"c:\\",
notify_filter => FILE_NOTIFY_ALL,
watch_sub_tree => 1,
);
$watcher->start();
print "Monitoring started.";
sleep(5);
# Get a list of changes since start().
my @entries = $watcher->get_results();
# Get a list of changes since the last get_results()
@entries = $watcher->get_results();
# ... repeat as needed ...
$watcher->stop(); # or undef $watcher
foreach my $entry (@entries) {
print $entry->action_name . " " . $entry->file_name . "\n";
}
# Restart monitoring
# $watcher->start();
# ...
# $watcher->stop();
=head1 DESCRIPTION
TODO
=head1 SUBROUTINES/METHODS
TODO
=head1 DIAGNOSTICS
TODO
=head1 DEPENDENCIES
Win32::API
Win32::MMF
=head1 BUGS AND LIMITATIONS
There are no known bugs in this module.
Please report problems to Andres N. Kievsky (ank@ank.com.ar)
Patches are welcome.
=head1 AUTHOR
Andres N. Kievsky (ank@ank.com.ar)
=head1 LICENCE AND COPYRIGHT
Copyright (c) 2008 Andres N. Kievsky (ank@ank.com.ar). All rights reserved.
This module is free software; you can redistribute it and/or
modify it under the same terms as Perl itself. See L<perlartistic>.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.