our $debug = 0;
our $housekeepingeverydays = 1;
+our $gcintervaldays = 10;
our $treeexpiredays = 21;
our $fetchtimeout = 3600;
our $maxfetchtimeout = 7200;
| serve-timeout
| tree-expire-days
| housekeeping-interval-days
+ | gc-interval-days
)=(\d+)$//x) {
my $vn = $1;
$vn =~ y/-//d;
servinfo "locking";
}
+sub update_gcstamp ($) {
+ my ($gitdir) = (@_);
+ my $gcdone = "$gitdir/cache-proxy-gc.stamp";
+ open GCSTAMP, '>', $gcdone or fail "create $gcdone: $!";
+ close GCSTAMP;
+}
+
sub clonefetch () {
lockfile \*LOCK, $lock, LOCK_EX;
alarm 0;
if (!$exists) {
+ update_gcstamp($tmpd);
rename $tmpd, $gitd or fail "rename fresh $tmpd to $gitd: $!";
$exists = 1;
}
logm 'info', "housekeeping started";
foreach $lock (<[a-z]*\\.lock>) {
my $subdir = $lock; $subdir =~ s/\\.lock$//;
+ my $gcdone = "$subdir\\.git/cache-proxy-gc.stamp";
if (!lstat $lock) {
$! == ENOENT or hkfail "$lock: lstat: $!";
next;
}
my ($mode_what,$mode_locknb,$mode_action);
if (-M _ <= $treeexpiredays) {
- logm 'debug', "housekeeping: subdirs $subdir: touched recently";
- next;
+ if (!lstat "$gcdone") {
+ $! == ENOENT or hkfail "$gcdone: lstat: $!";
+ logm 'debug',
+ "housekeeping: subdirs $subdir: touched recently, never gc'd!";
+ } elsif (-M _ <= $gcintervaldays) {
+ logm 'debug',
+ "housekeeping: subdirs $subdir: touched recently, gc'd recently";
+ next;
+ } else {
+ logm 'debug',
+ "housekeeping: subdirs $subdir: touched recently, needs gc";
+ }
+ $mode_what = 'garbage collecting';
+ $mode_locknb = 0;
+ $mode_action = sub {
+ my $gclog = "$subdir/gc.log";
+ unlink $gclog or $!==ENOENT or hkfail "remove $gclog: $!";
+ my $r = system qw(sh -ec),
+ 'cd "$1"; shift; exec "$@"', 'x', "$subdir\\.git",
+ qw(git gc --quiet);
+ if ($r) {
+ logm 'err',
+ "housekeeping: subdirs $subdir: gc failed (status $r)";
+ } else {
+ update_gcstamp("$subdir\\.git");
+ logm 'debug',
+ "housekeeping: subdirs $subdir: gc done";
+ }
+ };
} else {
$mode_what = 'cleaning';
$mode_locknb = LOCK_NB;