X-Git-Url: http://www.git.stargrave.org/?a=blobdiff_plain;f=lib%2FPublicInbox%2FKQNotify.pm;h=7efb8b604c99e326d02c38c3876355aa23018a35;hb=23af251dd607c4e75ab1e68063f2c885c48cc035;hp=fc321a1674992558904e85c33251e6c3e15721ae;hpb=671e7f4c9d82b053fba475aaeaa16a94dc3adad2;p=public-inbox.git diff --git a/lib/PublicInbox/KQNotify.pm b/lib/PublicInbox/KQNotify.pm index fc321a16..7efb8b60 100644 --- a/lib/PublicInbox/KQNotify.pm +++ b/lib/PublicInbox/KQNotify.pm @@ -33,14 +33,16 @@ sub watch { 'PublicInbox::KQNotify::Watch'; } my $ident = fileno($fh); - $self->{dskq}->{kq}->EV_SET($ident, # ident + $self->{dskq}->{kq}->EV_SET($ident, # ident (fd) EVFILT_VNODE, # filter EV_ADD | EV_CLEAR, # flags $mask, # fflags 0, 0); # data, udata - if ($mask & (MOVED_TO_OR_CREATE | NOTE_DELETE)) { + if ($mask & (MOVED_TO_OR_CREATE|NOTE_DELETE|NOTE_LINK|NOTE_REVOKE)) { $self->{watch}->{$ident} = $watch; - fill_dirlist($self, $path, $fh) if $mask & NOTE_DELETE; + if ($mask & (NOTE_DELETE|NOTE_LINK|NOTE_REVOKE)) { + fill_dirlist($self, $path, $fh) + } } else { die "TODO Not implemented: $mask"; } @@ -63,21 +65,37 @@ sub read { my ($self) = @_; my @kevents = $self->{dskq}->{kq}->kevent(0); my $events = []; + my @gone; + my $watch = $self->{watch}; for my $kev (@kevents) { my $ident = $kev->[KQ_IDENT]; my $mask = $kev->[KQ_FFLAGS]; - my ($dh, $path, $old_ctime) = @{$self->{watch}->{$ident}}; + my ($dh, $path, $old_ctime) = @{$watch->{$ident}}; if (!defined($old_ctime)) { push @$events, bless(\$path, 'PublicInbox::FakeInotify::Event') - } elsif ($mask & (MOVED_TO_OR_CREATE | NOTE_DELETE)) { - my @new_st = stat($path) or next; - $self->{watch}->{$ident}->[3] = $new_st[10]; # ctime + } elsif ($mask & (MOVED_TO_OR_CREATE|NOTE_DELETE|NOTE_LINK| + NOTE_REVOKE|NOTE_RENAME)) { + my @new_st = stat($path); + if (!@new_st && $!{ENOENT}) { + push @$events, bless(\$path, + 'PublicInbox::FakeInotify::'. + 'SelfGoneEvent'); + push @gone, $ident; + delete $self->{dirlist}->{$path}; + next; + } + if (!@new_st) { + warn "unhandled stat($path) error: $!\n"; + next; + } + $watch->{$ident}->[3] = $new_st[10]; # ctime rewinddir($dh); on_dir_change($events, $dh, $path, $old_ctime, $self->{dirlist}); } } + delete @$watch{@gone}; @$events; }