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;
}
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;
}
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} || '/');
my ($self, $smsg, $ref) = @_;
# ghosts may have undef smsg (from SearchThread.node) or
- # no {blob} field (from each_smsg_by_mid)
+ # no {blob} field
return unless defined $smsg;
defined(my $blob = $smsg->{blob}) or return;
}
}
-sub path_check {
- my ($self, $path) = @_;
- git($self)->check('HEAD:'.$path);
-}
-
sub mid2num($$) {
my ($self, $mid) = @_;
my $mm = mm($self) or return;
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 ($$;$) {
}
sub recent {
- my ($self, $opts) = @_;
- my $qs = '';
- my $srch = search($self);
- if (!$opts->{offset}) {
- # this complicated bit cuts /$INBOX/ loading time by
- # over 400ms on my system:
- my ($min, $max) = mm($self)->minmax;
- my $n = $max - $opts->{limit};
- $n = $min if $n < $min;
- for (; $qs eq '' && $n >= $min; --$n) {
- my $smsg = $srch->lookup_article($n) or next;
- $qs = strftime('d:%Y%m%d..', gmtime($smsg->ts));
+ my ($self, $opts, $after, $before) = @_;
+ 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;
}
- $srch->query($qs, $opts);
+ git($self)->modified; # v1
}
1;