]> Sergey Matveev's repositories - public-inbox.git/blob - lib/PublicInbox/FakeInotify.pm
inboxidle: new class to detect inbox changes
[public-inbox.git] / lib / PublicInbox / FakeInotify.pm
1 # Copyright (C) 2020 all contributors <meta@public-inbox.org>
2 # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
3
4 # for systems lacking Linux::Inotify2 or IO::KQueue, just emulates
5 # enough of Linux::Inotify2
6 package PublicInbox::FakeInotify;
7 use strict;
8 use Time::HiRes qw(stat);
9 my $IN_CLOSE = 0x08 | 0x10; # match Linux inotify
10
11 sub new { bless { watch => {} }, __PACKAGE__ }
12
13 # behaves like Linux::Inotify2->watch
14 sub watch {
15         my ($self, $path, $mask, $cb) = @_;
16         my @st = stat($path) or return;
17         $self->{watch}->{"$path\0$mask"} = [ @st, $cb ];
18 }
19
20 # behaves like non-blocking Linux::Inotify2->poll
21 sub poll {
22         my ($self) = @_;
23         my $watch = $self->{watch} or return;
24         for my $x (keys %$watch) {
25                 my ($path, $mask) = split(/\0/, $x, 2);
26                 my @now = stat($path) or next;
27                 my $prv = $watch->{$x};
28                 my $cb = $prv->[-1];
29                 # 10: ctime, 7: size
30                 if ($prv->[10] != $now[10]) {
31                         if (($mask & $IN_CLOSE) == $IN_CLOSE) {
32                                 eval { $cb->() };
33                         }
34                 }
35                 @$prv = (@now, $cb);
36         }
37 }
38
39 1;