X-Git-Url: http://www.git.stargrave.org/?a=blobdiff_plain;f=lib%2FPublicInbox%2FInbox.pm;h=0d86771fbd33677f08e652bcbbe9cfa87852d144;hb=e220b8b2ee5cfd458167dc2c6c92726352c4c80e;hp=286555f65cb3b4c8f4a7820b0489e4f6f6005e72;hpb=7a3946ef122e8218c6ce3355d7f968562212d53b;p=public-inbox.git diff --git a/lib/PublicInbox/Inbox.pm b/lib/PublicInbox/Inbox.pm index 286555f6..0d86771f 100644 --- a/lib/PublicInbox/Inbox.pm +++ b/lib/PublicInbox/Inbox.pm @@ -7,26 +7,30 @@ 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_broken = $@; - +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) { my $again; - foreach my $f (qw(mm search)) { - delete $ibx->{$f} if SvREFCNT($ibx->{$f}) == 1; + if ($have_devel_peek) { + foreach my $f (qw(mm search over)) { + # 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}) { @@ -37,16 +41,31 @@ sub cleanup_task () { $again = 1 if $git->cleanup($expire); } } - $again ||= !!($ibx->{mm} || $ibx->{search}); + if ($have_devel_peek) { + $again ||= !!($ibx->{over} || $ibx->{mm} || + $ibx->{search}); + } $next->{"$ibx"} = $ibx if $again; } $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 if $cleanup_broken; - 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; } @@ -168,12 +187,24 @@ sub mm { }; } -sub search { - my ($self) = @_; - $self->{search} ||= eval { +sub search ($;$) { + my ($self, $over_only) = @_; + my $srch = $self->{search} ||= eval { _cleanup_later($self); + require PublicInbox::Search; PublicInbox::Search->new($self, $self->{altid}); }; + ($over_only || eval { $srch->xdb }) ? $srch : undef; +} + +sub over ($) { + my ($self) = @_; + my $srch = search($self, 1) or return; + $self->{over} ||= eval { + my $over = $srch->{over_ro}; + $over->dbh_new; # may fail + $over; + } } sub try_cat { @@ -280,8 +311,8 @@ sub nntp_url { sub nntp_usable { my ($self) = @_; - my $ret = $self->mm && $self->search; - $self->{mm} = $self->{search} = undef; + my $ret = mm($self) && over($self); + $self->{mm} = $self->{over} = $self->{search} = undef; $ret; } @@ -322,30 +353,32 @@ sub mid2num($$) { sub smsg_by_mid ($$) { my ($self, $mid) = @_; - my $srch = search($self) or return; + my $over = over($self) or return; # favor the Message-ID we used for the NNTP article number: defined(my $num = mid2num($self, $mid)) or return; - my $smsg = $srch->lookup_article($num) or return; + my $smsg = $over->get_art($num) or return; PublicInbox::SearchMsg::psgi_cull($smsg); } sub msg_by_mid ($$;$) { my ($self, $mid, $ref) = @_; - my $srch = search($self) or + + over($self) or return msg_by_path($self, mid2path($mid), $ref); + my $smsg = smsg_by_mid($self, $mid); $smsg ? msg_by_smsg($self, $smsg, $ref) : undef; } sub recent { my ($self, $opts, $after, $before) = @_; - search($self)->{over_ro}->recent($opts, $after, $before); + over($self)->recent($opts, $after, $before); } sub modified { my ($self) = @_; - if (my $srch = search($self)) { - my $msgs = $srch->{over_ro}->recent({limit => 1}); + if (my $over = over($self)) { + my $msgs = $over->recent({limit => 1}); if (my $smsg = $msgs->[0]) { return $smsg->{ts}; }