debug("wiki is locked by another process, not aggregating");
exit 1;
}
-
- # Fork a child process to handle the aggregation.
- # The parent process will then handle building the result.
- # This avoids messy code to clear state accumulated while
- # aggregating.
- defined(my $pid = fork) or error("Can't fork: $!");
- if (! $pid) {
- loadstate();
- IkiWiki::loadindex();
- aggregate();
- expire();
- savestate();
- exit 0;
- }
- waitpid($pid,0);
- if ($?) {
- error "aggregation failed with code $?";
- }
-
+
+ loadstate();
+ IkiWiki::loadindex();
+ aggregate();
+ expire();
+ savestate();
+ clearstate();
+
IkiWiki::unlockwiki();
}
} #}}}
return if $state_loaded;
$state_loaded=1;
if (-e "$config{wikistatedir}/aggregate") {
- open(IN, "$config{wikistatedir}/aggregate") ||
+ open(IN, "<", "$config{wikistatedir}/aggregate") ||
die "$config{wikistatedir}/aggregate: $!";
while (<IN>) {
$_=IkiWiki::possibly_foolish_untaint($_);
error($@) if $@;
my $newfile="$config{wikistatedir}/aggregate.new";
my $cleanup = sub { unlink($newfile) };
- open (OUT, ">$newfile") || error("open $newfile: $!", $cleanup);
+ open (OUT, ">", $newfile) || error("open $newfile: $!", $cleanup);
foreach my $data (values %feeds, values %guids) {
if ($data->{remove}) {
if ($data->{name}) {
error("rename $newfile: $!", $cleanup);
} #}}}
+sub clearstate () { #{{{
+ %feeds=();
+ %guids=();
+ $state_loaded=0;
+} #}}}
+
sub expire () { #{{{
foreach my $feed (values %feeds) {
next unless $feed->{expireage} || $feed->{expirecount};
return shift().".".$config{htmlext};
} #}}}
+my $aggregatelock;
+
+sub lockaggregate () { #{{{
+ # Take an exclusive lock to prevent multiple concurrent aggregators.
+ # Returns true if the lock was aquired.
+ if (! -d $config{wikistatedir}) {
+ mkdir($config{wikistatedir});
+ }
+ open($aggregatelock, '>', "$config{wikistatedir}/aggregatelock") ||
+ error ("cannot open to $config{wikistatedir}/aggregatelock: $!");
+ if (! flock($aggregatelock, 2 | 4)) { # LOCK_EX | LOCK_NB
+ close($aggregatelock) || error("failed closing aggregatelock: $!");
+ return 0;
+ }
+ return 1;
+} #}}}
+
+sub unlockaggregate () { #{{{
+ return close($aggregatelock) if $aggregatelock;
+ return;
+} #}}}
+
1