X-Git-Url: http://www.git.stargrave.org/?a=blobdiff_plain;f=lib%2FPublicInbox%2FInbox.pm;h=0b118b28cea84418f18a73cd5f6a63cfbbe0dae9;hb=b6f480ed58abc5ae2a426ef4f792621b9d3cf283;hp=f71493a0e8eb487a2e5021e7de1b17548b896319;hpb=fad9acd35e56a289ade90a62d056b2a6663d448c;p=public-inbox.git diff --git a/lib/PublicInbox/Inbox.pm b/lib/PublicInbox/Inbox.pm index f71493a0..0b118b28 100644 --- a/lib/PublicInbox/Inbox.pm +++ b/lib/PublicInbox/Inbox.pm @@ -7,31 +7,64 @@ use strict; use warnings; use PublicInbox::Git; use PublicInbox::MID qw(mid2path); -use Devel::Peek qw(SvREFCNT); use PublicInbox::MIME; -use POSIX qw(strftime); +# Long-running "git-cat-file --batch" processes won't notice +# unlinked packs, so we need to restart those processes occasionally. +# Xapian and SQLite file handles are mostly stable, but sometimes an +# admin will attempt to replace them atomically after compact/vacuum +# and we need to be prepared for that. my $cleanup_timer; -eval { - $cleanup_timer = 'disabled'; - require PublicInbox::EvCleanup; - $cleanup_timer = undef; # OK if we get here -}; - +my $cleanup_avail = -1; # 0, or 1 +my $have_devel_peek; my $CLEANUP = {}; # string(inbox) -> inbox sub cleanup_task () { $cleanup_timer = undef; + my $next = {}; for my $ibx (values %$CLEANUP) { - foreach my $f (qw(git mm search)) { - delete $ibx->{$f} if SvREFCNT($ibx->{$f}) == 1; + my $again; + if ($have_devel_peek) { + foreach my $f (qw(mm search)) { + # we bump refcnt by assigning tmp, here: + my $tmp = $ibx->{$f} or next; + next if Devel::Peek::SvREFCNT($tmp) > 2; + delete $ibx->{$f}; + # refcnt is zero when tmp is out-of-scope + } + } + my $expire = time - 60; + if (my $git = $ibx->{git}) { + $again = $git->cleanup($expire); + } + if (my $gits = $ibx->{-repo_objs}) { + foreach my $git (@$gits) { + $again = 1 if $git->cleanup($expire); + } } + if ($have_devel_peek) { + $again ||= !!($ibx->{mm} || $ibx->{search}); + } + $next->{"$ibx"} = $ibx if $again; } - $CLEANUP = {}; + $CLEANUP = $next; +} + +sub cleanup_possible () { + # no need to require EvCleanup, here, if it were enabled another + # module would've require'd it, already + eval { PublicInbox::EvCleanup::enabled() } or return 0; + + eval { + require Devel::Peek; # needs separate package in Fedora + $have_devel_peek = 1; + }; + 1; } sub _cleanup_later ($) { my ($self) = @_; - return unless PublicInbox::EvCleanup::enabled(); + $cleanup_avail = cleanup_possible() if $cleanup_avail < 0; + return if $cleanup_avail != 1; $cleanup_timer ||= PublicInbox::EvCleanup::later(*cleanup_task); $CLEANUP->{"$self"} = $self; } @@ -80,6 +113,15 @@ sub new { if (defined $dir && -f "$dir/inbox.lock") { $opts->{version} = 2; } + + # allow any combination of multi-line or comma-delimited hide entries + my $hide = {}; + if (defined(my $h = $opts->{hide})) { + foreach my $v (@$h) { + $hide->{$_} = 1 foreach (split(/\s*,\s*/, $v)); + } + $opts->{-hide} = $hide; + } bless $opts, $class; } @@ -187,8 +229,8 @@ sub cloneurl { sub base_url { my ($self, $env) = @_; - if ($env) { # PSGI env - my $scheme = $env->{'psgi.url_scheme'}; + my $scheme; + if ($env && ($scheme = $env->{'psgi.url_scheme'})) { # PSGI env my $host_port = $env->{HTTP_HOST} || "$env->{SERVER_NAME}:$env->{SERVER_PORT}"; my $url = "$scheme://$host_port". ($env->{SCRIPT_NAME} || '/'); @@ -290,11 +332,6 @@ sub smsg_mime { } } -sub path_check { - my ($self, $path) = @_; - git($self)->check('HEAD:'.$path); -} - sub mid2num($$) { my ($self, $mid) = @_; my $mm = mm($self) or return; @@ -305,8 +342,9 @@ sub smsg_by_mid ($$) { my ($self, $mid) = @_; my $srch = search($self) or return; # favor the Message-ID we used for the NNTP article number: - my $num = mid2num($self, $mid); - defined $num ? $srch->lookup_article($num) : undef; + defined(my $num = mid2num($self, $mid)) or return; + my $smsg = $srch->lookup_article($num) or return; + PublicInbox::SearchMsg::psgi_cull($smsg); } sub msg_by_mid ($$;$) { @@ -322,4 +360,16 @@ sub recent { search($self)->{over_ro}->recent($opts, $after, $before); } +sub modified { + my ($self) = @_; + if (my $srch = search($self)) { + my $msgs = $srch->{over_ro}->recent({limit => 1}); + if (my $smsg = $msgs->[0]) { + return $smsg->{ts}; + } + return time; + } + git($self)->modified; # v1 +} + 1;