| 1 | #!/usr/bin/perl -w |
| 2 | |
| 3 | # This script is used to delete tiles that are extremely cheap to rerender. |
| 4 | # If a tile can be regenerated in one second, we really don't need to keep it |
| 5 | # on disk and regularily update it. This can happen on the fly when it is |
| 6 | # requested instead. |
| 7 | |
| 8 | # Where are the tile directories? |
| 9 | $tiledirprefix = '/mnt/tiles/tiles/'; |
| 10 | # Map for map-ID in DB to tile subdir. |
| 11 | %tiledirmap = ( 1 => 'osm', |
| 12 | 2 => 'osmde', |
| 13 | 4 => 'osmhd', |
| 14 | 5 => 'osmdehd' |
| 15 | ); |
| 16 | # What is the maximum rendertime to consider a tile useless? |
| 17 | $maxuselesstime = 0.5; |
| 18 | |
| 19 | # How old do files need to be before we delete them? in seconds |
| 20 | $minuselessage = 48 * 60 * 60; |
| 21 | |
| 22 | # Where is the osm stats database? |
| 23 | $statsdb = 'osmstats'; |
| 24 | |
| 25 | # ----------------------------------------------------------------------------- |
| 26 | |
| 27 | use DBI; |
| 28 | use POSIX qw(strftime mktime); |
| 29 | use Fcntl ':mode'; |
| 30 | |
| 31 | # Par. 0: x |
| 32 | # Par. 1: y |
| 33 | sub calcpathfromcomponents($$) { |
| 34 | my @res = (); |
| 35 | my $i; my $x = $_[0]; my $y = $_[1]; |
| 36 | for ($i = 4; $i >= 0; $i--) { |
| 37 | $res[$i] = sprintf("%d", (($x & 0x0f) << 4) + ($y & 0x0f)); |
| 38 | $x = $x >> 4; |
| 39 | $y = $y >> 4; |
| 40 | } |
| 41 | return $res[0] . "/" . $res[1] . "/" . $res[2] . "/" . $res[3] . "/" . $res[4]; |
| 42 | } |
| 43 | |
| 44 | unless ($dbh = DBI->connect("dbi:Pg:dbname=$statsdb","","")) { |
| 45 | print(STDERR "Failed to open database. Please try again later.\n"); exit(1); |
| 46 | } |
| 47 | # select x, y, z, avg(rendertime) as avgrt, max(rendertime) as maxrt from renderrequests where mapid=1 group by x, y, z |
| 48 | # select distinct on (x, y, z) x, y, z, rendertime from renderrequests where mapid=1 order by x,y,z,ts desc; |
| 49 | foreach $mapid (sort(keys(%tiledirmap))) { |
| 50 | my $ndeleted = 0; |
| 51 | my $sth = $dbh->prepare("select distinct on (x, y, z) x, y, z, rendertime" |
| 52 | . " from renderrequests where mapid=? order by x, y, z, ts desc"); |
| 53 | unless ($sth->execute($mapid)) { |
| 54 | print(STDERR "Sorry, database query blew up.!\n"); |
| 55 | exit(1); |
| 56 | } |
| 57 | while (($x, $y, $z, $rendertime) = $sth->fetchrow_array()) { |
| 58 | if ($z < 5) { next; } |
| 59 | if ($rendertime > $maxuselesstime) { |
| 60 | #print("$tiledirmap{$mapid} $z/$x/$y rendered in $rendertime seconds, leaving it alone\n"); |
| 61 | next; |
| 62 | } |
| 63 | my $tilepath = $tiledirprefix . $tiledirmap{$mapid} . '/'; |
| 64 | $tilepath .= $z . '/' . calcpathfromcomponents($x, $y) . '.meta'; |
| 65 | unless (-e $tilepath) { |
| 66 | #print("...file does not exist, nothing to delete.\n"); |
| 67 | next; |
| 68 | } |
| 69 | @statres = lstat($tilepath); |
| 70 | unless (@statres > 12) { |
| 71 | # This usually happens if we have a symlink to a file for which we have |
| 72 | # no permission to read. |
| 73 | #print("...stat failed\n"); |
| 74 | next; |
| 75 | } |
| 76 | if (S_ISLNK($statres[2])) { next; } # A symlink? We no like. |
| 77 | if (($statres[9] + $minuselessage) >= time()) { |
| 78 | #print("...not old enough, skipped\n"); |
| 79 | next; |
| 80 | } |
| 81 | print("$tiledirmap{$mapid} $z/$x/$y rendered in $rendertime seconds, deleting $tilepath\n"); |
| 82 | unlink($tilepath); |
| 83 | $ndeleted++; |
| 84 | } |
| 85 | $sth->finish(); |
| 86 | print("Deleted $ndeleted tiles in $tiledirmap{$mapid}\n"); |
| 87 | } |