]> sipb.mit.edu Git - ikiwiki.git/blobdiff - IkiWiki/Plugin/aggregate.pm
add aggregate locking functions
[ikiwiki.git] / IkiWiki / Plugin / aggregate.pm
index 2a4d10411dab8ac87655e6101f20f7dff1c8bd3f..cfc4ec955328e2dfa812b04b4cacd683ba336884 100644 (file)
@@ -37,25 +37,14 @@ sub checkconfig () { #{{{
                        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();
        }
 } #}}}
@@ -143,7 +132,7 @@ sub loadstate () { #{{{
        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($_);
@@ -181,7 +170,7 @@ sub savestate () { #{{{
        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}) {
@@ -223,6 +212,12 @@ sub savestate () { #{{{
                error("rename $newfile: $!", $cleanup);
 } #}}}
 
+sub clearstate () { #{{{
+       %feeds=();
+       %guids=();
+       $state_loaded=0;
+} #}}}
+
 sub expire () { #{{{
        foreach my $feed (values %feeds) {
                next unless $feed->{expireage} || $feed->{expirecount};
@@ -500,4 +495,26 @@ sub htmlfn ($) { #{{{
        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