]> Sergey Matveev's repositories - public-inbox.git/commitdiff
inbox: perform cleanup of Git objects for coderepos
authorEric Wong <e@80x24.org>
Thu, 31 Jan 2019 00:32:42 +0000 (00:32 +0000)
committerEric Wong <e@80x24.org>
Thu, 31 Jan 2019 00:32:42 +0000 (00:32 +0000)
Otherwise, long-running but idle git processes may keep unlinked
packs around indefinitely and waste disk space.

lib/PublicInbox/Git.pm
lib/PublicInbox/Inbox.pm
t/git.t

index e844884a2acf8f5d94469c65ee37d4550d455627..a756684a70355b6435b26b753f1dc6593e5481fa 100644 (file)
@@ -206,7 +206,15 @@ sub check {
 }
 
 sub _destroy {
-       my ($self, $in, $out, $pid) = @_;
+       my ($self, $in, $out, $pid, $expire) = @_;
+       my $rfh = $self->{$in} or return;
+       if (defined $expire) {
+               # at least FreeBSD 11.2 and Linux 4.20 update mtime of the
+               # read end of a pipe when the pipe is written to; dunno
+               # about other OSes.
+               my $mtime = (stat($rfh))[9];
+               return if $mtime > $expire;
+       }
        my $p = delete $self->{$pid} or return;
        foreach my $f ($in, $out) {
                delete $self->{$f};
@@ -236,10 +244,12 @@ sub qx {
        <$fh>
 }
 
+# returns true if there are pending "git cat-file" processes
 sub cleanup {
-       my ($self) = @_;
-       _destroy($self, qw(in out pid));
-       _destroy($self, qw(in_c out_c pid_c));
+       my ($self, $expire) = @_;
+       _destroy($self, qw(in out pid), $expire);
+       _destroy($self, qw(in_c out_c pid_c), $expire);
+       !!($self->{pid} || $self->{pid_c});
 }
 
 # assuming a well-maintained repo, this should be a somewhat
index d57e46d29b2785f5b358f125cdb8beda00e332ae..6fe896f49efeb64a6a9fe364763aca2cbaa54c54 100644 (file)
@@ -22,12 +22,25 @@ my $cleanup_broken = $@;
 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)) {
+               my $again;
+               foreach my $f (qw(mm search)) {
                        delete $ibx->{$f} if SvREFCNT($ibx->{$f}) == 1;
                }
+               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);
+                       }
+               }
+               $again ||= !!($ibx->{mm} || $ibx->{search});
+               $next->{"$ibx"} = $ibx if $again;
        }
-       $CLEANUP = {};
+       $CLEANUP = $next;
 }
 
 sub _cleanup_later ($) {
diff --git a/t/git.t b/t/git.t
index 9c80fbb422172cd9e9f0136fe7af7bd52d6e0db1..d637e63ba8d49381941431e4966d3abd5d125823 100644 (file)
--- a/t/git.t
+++ b/t/git.t
@@ -142,6 +142,10 @@ if ('alternates reloaded') {
        open $fh, '<', "$alt/config" or die "open failed: $!\n";
        my $config = eval { local $/; <$fh> };
        is($$found, $config, 'alternates reloaded');
+
+       ok($gcf->cleanup(time - 30), 'cleanup did not expire');
+       ok(!$gcf->cleanup(time + 30), 'cleanup can expire');
+       ok(!$gcf->cleanup, 'cleanup idempotent');
 }
 
 use_ok 'PublicInbox::Git', qw(git_unquote git_quote);