From af1a8bbe9c2906c4834fb35a93e94a16289cbf50 Mon Sep 17 00:00:00 2001 From: "Kyle J. McKay" Date: Tue, 12 Dec 2017 17:43:11 -0800 Subject: [PATCH] gc: no waiting to play it again Although extremely unlikely, when a "mini" garbage collection gets performed, the end result could be to trigger a normal full garbage collection. This can only happen if the "mini" garbage collection was unable to sufficiently reduce the total number of pack files. Up until now, what this meant was that the newly triggered full garbage collection would not run until the next time garbage collection was performed by running the gc.sh script again on that same project. For users of the jobd.pl "--all-once" option this could potentially be a bad thing, perhaps even a very bad thing. For users of the projtool.pl "gc" command it's more of an annoyance when it happens requiring the command to be run again. If the gitweb.lastgc value was set before running gc.sh then gc.sh completes successfully and now gitweb.lastgc is unset we need to run gc.sh one more time. Address this by making jobd.pl and projtool.pl run gc.sh one more time for the same project under these circumstances. For jobd.pl it will just be added to the end of the job queue whereas projtool.pl will do it immediately since it has no queue. Signed-off-by: Kyle J. McKay --- jobd/jobd.pl | 23 +++++++++++++++++++++++ toolbox/projtool.pl | 11 ++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/jobd/jobd.pl b/jobd/jobd.pl index cf208ef..ac411b2 100755 --- a/jobd/jobd.pl +++ b/jobd/jobd.pl @@ -88,6 +88,7 @@ sub gc_project { return; } # allow garbage collection to run for longer than an update + $job->{'lastgc'} = get_git_config($projpath, "gitweb.lastgc"); $job->{'timeout_factor'} = 2; exec_job_command($job, ["$Girocco::Config::basedir/jobd/gc.sh", $p], $quiet); } @@ -99,9 +100,31 @@ sub setup_gc { type => 'gc', command => \&gc_project, intensive => 1, + on_success => \&maybe_setup_gc_again, ); } +sub maybe_setup_gc_again { + my $job = shift; + # If lastgc was set then gc.sh ran successfully and now it's not set + # then queue up another run of gc.sh for the project. + # However, just in case, no matter what happens with the extra + # gc.sh run no more "bonus" runs are possible to avoid any loops. + # This allows a "mini" gc that triggers a full gc to have the + # full gc run as part of the same --all-once run through instead + # of waiting. A very good thing for users of the --all-once option. + if ($job->{'lastgc'}) { + my $projpath = get_project_path($job->{'project'}); + get_git_config($projpath, "gitweb.lastgc") or + queue_job( + project => $job->{'project'}, + type => 'gc', + command => \&gc_project, + intensive => 1, + ); + } +} + sub check_project_exists { my $job = shift; my $p = $job->{'project'}; diff --git a/toolbox/projtool.pl b/toolbox/projtool.pl index 5811adb..8ea151e 100755 --- a/toolbox/projtool.pl +++ b/toolbox/projtool.pl @@ -1195,7 +1195,16 @@ sub cmd_gc { } my @args = ($Girocco::Config::basedir . "/jobd/gc.sh", $project->{name}); $redelta and push(@args, "-f"); - return system({$args[0]} @args) ? 1 : 0; + my $lastgc = $project->{lastgc}; + system({$args[0]} @args) != 0 and return 1; + # Do it again Sam, but only if lastgc was set, gc.sh succeeded and now it's not set + if ($lastgc) { + my $newlastgc = get_git("--git-dir=$project->{path}", 'config', '--get', 'gitweb.lastgc'); + if (!$newlastgc) { + system({$args[0]} @args) != 0 and return 1; + } + } + return 0; } sub cmd_remirror { -- 2.11.4.GIT