Add a mechanism for invalidating the front-end cache, if any. Currently it spits...
authorSteinar H. Gunderson <sesse@debian.org>
Sun, 3 May 2009 17:35:22 +0000 (19:35 +0200)
committerSteinar H. Gunderson <sesse@debian.org>
Sun, 3 May 2009 17:35:22 +0000 (19:35 +0200)
perl/Sesse/pr0n/Common.pm
perl/Sesse/pr0n/NewEvent.pm
perl/Sesse/pr0n/Rotate.pm
perl/Sesse/pr0n/WebDAV.pm

index 00fa9e9b0c42213676fc70707955ba8a9a696988..57d0a6ba26b66514ab9d1b3f9abc5d675efa8d40 100644 (file)
@@ -26,6 +26,7 @@ use LWP::Simple;
 use Image::ExifTool;
 use HTML::Entities;
 use URI::Escape;
 use Image::ExifTool;
 use HTML::Entities;
 use URI::Escape;
+use File::Basename;
 
 BEGIN {
        use Exporter ();
 
 BEGIN {
        use Exporter ();
@@ -879,7 +880,7 @@ sub gcd {
 }
 
 sub add_new_event {
 }
 
 sub add_new_event {
-       my ($dbh, $id, $date, $desc, $vhost) = @_;
+       my ($r, $dbh, $id, $date, $desc) = @_;
        my @errors = ();
 
        if (!defined($id) || $id =~ /^\s*$/ || $id !~ /^([a-zA-Z0-9-]+)$/) {
        my @errors = ();
 
        if (!defined($id) || $id =~ /^\s*$/ || $id !~ /^([a-zA-Z0-9-]+)$/) {
@@ -896,12 +897,14 @@ sub add_new_event {
                return @errors;
        }
                
                return @errors;
        }
                
+       my $vhost = $r->get_server_name;
        $dbh->do("INSERT INTO events (event,date,name,vhost) VALUES (?,?,?,?)",
                undef, $id, $date, $desc, $vhost)
                or return ("Kunne ikke sette inn ny hendelse" . $dbh->errstr);
        $dbh->do("INSERT INTO last_picture_cache (vhost,event,last_picture) VALUES (?,?,NULL)",
                undef, $vhost, $id)
                or return ("Kunne ikke sette inn ny cache-rad" . $dbh->errstr);
        $dbh->do("INSERT INTO events (event,date,name,vhost) VALUES (?,?,?,?)",
                undef, $id, $date, $desc, $vhost)
                or return ("Kunne ikke sette inn ny hendelse" . $dbh->errstr);
        $dbh->do("INSERT INTO last_picture_cache (vhost,event,last_picture) VALUES (?,?,NULL)",
                undef, $vhost, $id)
                or return ("Kunne ikke sette inn ny cache-rad" . $dbh->errstr);
+       purge_cache($r, "/");
 
        return ();
 }
 
        return ();
 }
@@ -920,6 +923,69 @@ sub guess_charset {
        return $decoded;
 }
 
        return $decoded;
 }
 
+# Depending on your front-end cache, you might want to get creative somehow here.
+# This example assumes you have a front-end cache and it can translate an X-Pr0n-Purge
+# regex tacked onto a request into something useful. The elements given in
+# should not be regexes, though, as e.g. Squid will not be able to handle that.
+sub purge_cache {
+       my ($r, @elements) = @_;
+       return if (scalar @elements == 0);
+
+       my @pe = ();
+       for my $elem (@elements) {
+               $r->log->info("Purging $elem");
+               (my $e = $elem) =~ s/[.+*|()]/\\$&/g;
+               push @pe, $e;
+       }
+
+       my $regex = "^";
+       if (scalar @pe == 1) {
+               $regex .= $pe[0];
+       } else {
+               $regex .= "(" . join('|', @pe) . ")";
+       }
+       $regex .= "(\\?.*)?\$";
+       $r->headers_out->{'X-Pr0n-Purge'} = $regex;
+
+       $r->log->info($r->headers_out->{'X-Pr0n-Purge'});
+}
+                               
+# Find a list of all cache URLs for a given image, given what we have on disk.
+sub get_all_cache_urls {
+       my ($r, $dbh, $id) = @_;
+        my $dir = POSIX::floor($id / 256);
+       my @ret = ();
+
+       my $q = $dbh->prepare('SELECT event, filename FROM images WHERE id=?')
+               or die "Couldn't prepare: " . $dbh->errstr;
+       $q->execute($id)
+               or die "Couldn't find event and filename: " . $dbh->errstr;
+       my $ref = $q->fetchrow_hashref; 
+       my $event = $ref->{'event'};
+       my $filename = $ref->{'filename'};
+       $q->finish;
+
+       my $base = get_base($r) . "cache/$dir";
+       for my $file (<$base/$id-*>) {
+               my $fname = File::Basename::basename($file);
+               if ($fname =~ /^$id-mipmap-.*\.jpg$/) {
+                       # Mipmaps don't have an URL, ignore
+               } elsif ($fname =~ /^$id--1--1\.jpg$/) {
+                       push @ret, "/$event/$filename";
+               } elsif ($fname =~ /^$id-(\d+)-(\d+)\.jpg$/) {
+                       push @ret, "/$event/$1x$2/$filename";
+               } elsif ($fname =~ /^$id-(\d+)-(\d+)-nobox\.jpg$/) {
+                       push @ret, "/$event/$1x$2/nobox/$filename";
+               } elsif ($fname =~ /^$id-(\d+)-(\d+)-box\.png$/) {
+                       push @ret, "/$event/$1x$2/box/$filename";
+               } else {
+                       $r->log->warning("Couldn't find a purging URL for $fname");
+               }
+       }
+
+       return @ret;
+}
+
 1;
 
 
 1;
 
 
index 61124536ef2b1c0ddd0f5672f3542c9929551394..2aac990d02fc7dee685249f17c8a3a9b0096b367 100644 (file)
@@ -20,7 +20,7 @@ sub handler {
        my $date = $apr->param('date');
        my $desc = $apr->param('desc');
 
        my $date = $apr->param('date');
        my $desc = $apr->param('desc');
 
-       my @errors = Sesse::pr0n::Common::add_new_event($dbh, $id, $date, $desc, $r->get_server_name);
+       my @errors = Sesse::pr0n::Common::add_new_event($r, $dbh, $id, $date, $desc);
        
        if (scalar @errors > 0) {
                for my $err (@errors) {
        
        if (scalar @errors > 0) {
                for my $err (@errors) {
index be562255da39bb134ac488c9b7c1d2894d3a7290..eb8d17ebc8c386ea7f1cc746e9d410a0355dc4e6 100644 (file)
@@ -14,6 +14,11 @@ sub handler {
                return Apache2::Const::OK;
        }
 
                return Apache2::Const::OK;
        }
 
+       # FIXME: People can rotate and delete across vhosts using this interface.
+       # We should add some sanity checks.
+
+       my @to_purge = ();
+
        Sesse::pr0n::Common::header($r, "Rotation/deletion results");
 
        {
        Sesse::pr0n::Common::header($r, "Rotation/deletion results");
 
        {
@@ -28,6 +33,7 @@ sub handler {
                        if ($key =~ /^rot-(\d+)-(90|180|270)$/ && $apr->param($key) eq 'on') {
                                my ($id, $rotval) = ($1,$2);
                                my $fname = Sesse::pr0n::Common::get_disk_location($r, $id);
                        if ($key =~ /^rot-(\d+)-(90|180|270)$/ && $apr->param($key) eq 'on') {
                                my ($id, $rotval) = ($1,$2);
                                my $fname = Sesse::pr0n::Common::get_disk_location($r, $id);
+                               push @to_purge, Sesse::pr0n::Common::get_all_cache_urls($r, $dbh, $id);
                                (my $tmpfname = $fname) =~ s/\.jpg$/-tmp.jpg/;
 
                                system("/usr/bin/jpegtran -rotate $rotval -copy all < '$fname' > '$tmpfname' && mv '$tmpfname' '$fname'") == 0
                                (my $tmpfname = $fname) =~ s/\.jpg$/-tmp.jpg/;
 
                                system("/usr/bin/jpegtran -rotate $rotval -copy all < '$fname' > '$tmpfname' && mv '$tmpfname' '$fname'") == 0
@@ -43,6 +49,7 @@ sub handler {
                                }
                        } elsif ($key =~ /^del-(\d+)$/ && $apr->param($key) eq 'on') {
                                my $id = $1;
                                }
                        } elsif ($key =~ /^del-(\d+)$/ && $apr->param($key) eq 'on') {
                                my $id = $1;
+                               push @to_purge, Sesse::pr0n::Common::get_all_cache_urls($r, $dbh, $id);
                                {
 
                                        eval {
                                {
 
                                        eval {
@@ -70,6 +77,10 @@ sub handler {
        $dbh->do('UPDATE last_picture_cache SET last_update=CURRENT_TIMESTAMP WHERE vhost=? AND event=?', undef, $r->get_server_name, $event)
                or dberror($r, "Cache invalidation failed");
 
        $dbh->do('UPDATE last_picture_cache SET last_update=CURRENT_TIMESTAMP WHERE vhost=? AND event=?', undef, $r->get_server_name, $event)
                or dberror($r, "Cache invalidation failed");
 
+       push @to_purge, "/$event/";
+       push @to_purge, "/+all/";
+       Sesse::pr0n::Common::purge_cache($r, @to_purge);
+
        Sesse::pr0n::Common::footer($r);
 
        return Apache2::Const::OK;
        Sesse::pr0n::Common::footer($r);
 
        return Apache2::Const::OK;
index c38e7b2f159a1888822dc3d3d230b5011bdf7056..09f10e519cd1ebd312be7e6a51d84f0a58b6a008 100644 (file)
@@ -470,6 +470,7 @@ EOF
                                        undef, $newid, $r->get_server_name, $event, $user, $takenby, $filename);
                                $dbh->do('UPDATE last_picture_cache SET last_update=CURRENT_TIMESTAMP WHERE vhost=? AND event=?',
                                        undef, $r->get_server_name, $event);
                                        undef, $newid, $r->get_server_name, $event, $user, $takenby, $filename);
                                $dbh->do('UPDATE last_picture_cache SET last_update=CURRENT_TIMESTAMP WHERE vhost=? AND event=?',
                                        undef, $r->get_server_name, $event);
+                               Sesse::pr0n::Common::purge_cache($r, "/$event/");
 
                                # Now save the file to disk
                                $fname = Sesse::pr0n::Common::get_disk_location($r, $newid);
 
                                # Now save the file to disk
                                $fname = Sesse::pr0n::Common::get_disk_location($r, $newid);