X-Git-Url: http://www.git.stargrave.org/?a=blobdiff_plain;f=lib%2FPublicInbox%2FWatch.pm;h=3f6fe21b726f30d3d185032e45ca7e20d358a561;hb=950485f0da0b79832e7ef100ac419f40c8bd30e0;hp=0b72bd160330a1474b0c9387eda79106cc934767;hpb=48bae7dc634583b58fd747bd557392cac60123b3;p=public-inbox.git diff --git a/lib/PublicInbox/Watch.pm b/lib/PublicInbox/Watch.pm index 0b72bd16..3f6fe21b 100644 --- a/lib/PublicInbox/Watch.pm +++ b/lib/PublicInbox/Watch.pm @@ -2,7 +2,7 @@ # License: AGPL-3.0+ # # ref: https://cr.yp.to/proto/maildir.html -# httsp://wiki2.dovecot.org/MailboxFormat/Maildir +# https://wiki2.dovecot.org/MailboxFormat/Maildir package PublicInbox::Watch; use strict; use v5.10.1; @@ -12,7 +12,6 @@ use PublicInbox::MdirReader; use PublicInbox::NetReader; use PublicInbox::Filter::Base qw(REJECT); use PublicInbox::Spamcheck; -use PublicInbox::Sigfd; use PublicInbox::DS qw(now add_timer); use PublicInbox::MID qw(mids); use PublicInbox::ContentHash qw(content_hash); @@ -53,8 +52,7 @@ sub new { # indefinitely... foreach my $pfx (qw(publicinboxwatch publicinboxlearn)) { my $k = "$pfx.watchspam"; - defined(my $dirs = $cfg->{$k}) or next; - $dirs = PublicInbox::Config::_array($dirs); + my $dirs = $cfg->get_all($k) // next; for my $dir (@$dirs) { my $uri; if (is_maildir($dir)) { @@ -284,33 +282,13 @@ sub watch_fs_init ($) { }; require PublicInbox::DirIdle; # inotify_create + EPOLL_CTL_ADD - PublicInbox::DirIdle->new([keys %{$self->{mdmap}}], $cb); -} - -sub imap_import_msg ($$$$$) { - my ($self, $uri, $uid, $raw, $flags) = @_; - # our target audience expects LF-only, save storage - $$raw =~ s/\r\n/\n/sg; - - my $inboxes = $self->{imap}->{$$uri}; - if (ref($inboxes)) { - for my $ibx (@$inboxes) { - my $eml = PublicInbox::Eml->new($$raw); - import_eml($self, $ibx, $eml); - } - } elsif ($inboxes eq 'watchspam') { - return if $flags !~ /\\Seen\b/; # don't remove unseen messages - local $SIG{__WARN__} = PublicInbox::Eml::warn_ignore_cb(); - my $eml = PublicInbox::Eml->new($raw); - $self->{pi_cfg}->each_inbox(\&remove_eml_i, - $self, $eml, "$uri UID:$uid"); - } else { - die "BUG: destination unknown $inboxes"; - } + my $dir_idle = PublicInbox::DirIdle->new($cb); + $dir_idle->add_watches([keys %{$self->{mdmap}}]); } sub net_cb { # NetReader::(nntp|imap)_each callback my ($uri, $art, $kw, $eml, $self, $inboxes) = @_; + return if grep(/\Adraft\z/, @$kw); local $self->{cur_uid} = $art; # IMAP UID or NNTP article if (ref($inboxes)) { my @ibx = @$inboxes; @@ -321,6 +299,9 @@ sub net_cb { # NetReader::(nntp|imap)_each callback } import_eml($self, $last, $eml); } elsif ($inboxes eq 'watchspam') { + if ($uri->scheme =~ /\Aimaps?\z/ && !grep(/\Aseen\z/, @$kw)) { + return; + } $self->{pi_cfg}->each_inbox(\&remove_eml_i, $self, $eml, "$uri #$art"); } else { @@ -349,6 +330,7 @@ sub imap_idle_once ($$$$) { my $end = now() + $intvl; warn "I: $uri idling for ${intvl}s\n"; local $0 = "IDLE $0"; + return if $self->{quit}; unless ($mic->idle) { return if $self->{quit}; return "E: IDLE failed on $uri: $!"; @@ -372,12 +354,13 @@ sub imap_idle_once ($$$$) { sub watch_imap_idle_1 ($$$) { my ($self, $uri, $intvl) = @_; my $sec = uri_section($uri); - my $mic_arg = $self->{mic_arg}->{$sec} or + my $mic_arg = $self->{net_arg}->{$sec} or die "BUG: no Mail::IMAPClient->new arg for $sec"; my $mic; local $0 = $uri->mailbox." $sec"; until ($self->{quit}) { - $mic //= PublicInbox::IMAPClient->new(%$mic_arg); + $mic //= PublicInbox::NetReader::mic_new( + $self, $mic_arg, $sec, $uri); my $err; if ($mic && $mic->IsConnected) { local $self->{mics_cached}->{$sec} = $mic; @@ -402,15 +385,13 @@ sub watch_atfork_child ($) { delete $self->{poll_pids}; delete $self->{opendirs}; PublicInbox::DS->Reset; - %SIG = (%SIG, %{$self->{sig}}, CHLD => 'DEFAULT'); + my $sig = delete $self->{sig}; + $sig->{CHLD} = 'DEFAULT'; + @SIG{keys %$sig} = values %$sig; PublicInbox::DS::sig_setmask($self->{oldset}); } -sub watch_atfork_parent ($) { - my ($self) = @_; - _done_for_now($self); - PublicInbox::DS::block_signals(); -} +sub watch_atfork_parent ($) { _done_for_now($_[0]) } sub imap_idle_requeue { # DS::add_timer callback my ($self, $uri_intvl) = @_; @@ -464,13 +445,12 @@ sub event_step { return if $self->{quit}; my $idle_todo = $self->{idle_todo}; if ($idle_todo && @$idle_todo) { - my $oldset = watch_atfork_parent($self); + watch_atfork_parent($self); eval { while (my $uri_intvl = shift(@$idle_todo)) { imap_idle_fork($self, $uri_intvl); } }; - PublicInbox::DS::sig_setmask($oldset); die $@ if $@; } fs_scan_step($self) if $self->{mdre}; @@ -507,7 +487,7 @@ sub poll_fetch_fork { # DS::add_timer callback my ($self, $intvl, $uris) = @_; return if $self->{quit}; pipe(my ($r, $w)) or die "pipe: $!"; - my $oldset = watch_atfork_parent($self); + watch_atfork_parent($self); my $seed = rand(0xffffffff); my $pid = fork; if (defined($pid) && $pid == 0) { @@ -523,7 +503,6 @@ sub poll_fetch_fork { # DS::add_timer callback close $w; _exit(0); } - PublicInbox::DS::sig_setmask($oldset); die "fork: $!" unless defined $pid; $self->{poll_pids}->{$pid} = [ $intvl, $uris ]; PublicInbox::EOFpipe->new($r, \&reap, [$pid, \&poll_fetch_reap, $self]); @@ -544,14 +523,14 @@ sub poll_fetch_reap { sub watch_imap_init ($$) { my ($self, $poll) = @_; - my $mics = imap_common_init($self); # read args from config + my $mics = PublicInbox::NetReader::imap_common_init($self); my $idle = []; # [ [ uri1, intvl1 ], [uri2, intvl2] ] for my $uri (@{$self->{imap_order}}) { my $sec = uri_section($uri); my $mic = $mics->{$sec}; - my $intvl = $self->{imap_opt}->{$sec}->{pollInterval}; + my $intvl = $self->{cfg_opt}->{$sec}->{pollInterval}; if ($mic->has_capability('IDLE') && !$intvl) { - $intvl = $self->{imap_opt}->{$sec}->{idleInterval}; + $intvl = $self->{cfg_opt}->{$sec}->{idleInterval}; push @$idle, [ $uri, $intvl // () ]; } else { push @{$poll->{$intvl || 120}}, $uri; @@ -565,10 +544,10 @@ sub watch_imap_init ($$) { sub watch_nntp_init ($$) { my ($self, $poll) = @_; - nntp_common_init($self); # read args from config + PublicInbox::NetReader::nntp_common_init($self); for my $uri (@{$self->{nntp_order}}) { my $sec = uri_section($uri); - my $intvl = $self->{nntp_opt}->{$sec}->{pollInterval}; + my $intvl = $self->{cfg_opt}->{$sec}->{pollInterval}; push @{$poll->{$intvl || 120}}, $uri; } } @@ -586,7 +565,7 @@ sub watch { # main entry point } watch_fs_init($self) if $self->{mdre}; PublicInbox::DS->SetPostLoopCallback(sub { !$self->quit_done }); - PublicInbox::DS->EventLoop; # calls ->event_step + PublicInbox::DS::event_loop($sig, $oldset); # calls ->event_step _done_for_now($self); } @@ -701,4 +680,6 @@ EOF undef; } +sub folder_select { 'select' } # for PublicInbox::NetReader + 1;