時計を壊せ

駆け出してからそこそこ経ったWebプログラマーの雑記

IO::KQueueでディレクトリとファイルを監視する

経緯とかなんか

Filesys::Notify::SimpleとかAnyEvent::Filesys::NotifyとかがKQueueに対応していないので自分で書くことにしました。
そのうちこれらのライブラリをKQueueに対応させてpull req送ろうと思います。


AnyEvent::Filesys::NotifyはMoose使ってるっぽいのでRoleだけ書いてそのうちCPANに上げられたら良いなぁ。
と思ってリポジトリだけ作っておきました。
https://github.com/karupanerura/p5-AnyEvent-Filesys-Notify-Role-KQueue


やっつけで書いたコードは以下。


これ何やってるの?

ファイルやディレクトリを「ファイルとして開いて」(これが気持ち悪い)そのファイルディスクリプタをKQueueに渡してあげて監視してます。

sub add_dir {
    my($self, $dir) = @_;

    $self->{_files}{$dir} = do {
        my $fh = IO::File->new($dir, 'r') or die("Can't open '$dir': $!");
        die "Can't get fileno '$dir'" unless defined $fh->fileno;

        # add to watch
        $self->kqueue->EV_SET(
            $fh->fileno,
            EVFILT_VNODE,
            EV_ADD | EV_CLEAR,
            NOTE_DELETE | NOTE_WRITE | NOTE_RENAME | NOTE_REVOKE,
            0,
            $dir,
        );

        $fh;
    };

    find(+{
        wanted => sub { $self->add($File::Find::name) },
        no_chdir => 1,
    }, $dir);
}

ディレクトリをファイルとして開いています。気持ち悪いですね。
ディレクトリ開いたらファイルディスクリプタとかねーじゃん!とか思ってハマりました。