docker-renderd-osm/osm-loader.pl

170 lines
5.5 KiB
Perl
Raw Normal View History

2018-04-05 23:33:53 +03:00
#!/usr/bin/perl
2018-09-26 09:22:09 +03:00
# Configuration in env: OSM_CACHE_DIR, OSM_CARTO_DIR, URL_LATEST, URL_UPDATES,
# plus PG_ENV_OSM_{DB,HOST,PORT,USER,PASSWORD} like in README for the render server itself
2018-04-05 23:33:53 +03:00
use strict;
use DBI;
use POSIX;
my $dir = $ENV{OSM_CACHE_DIR} || '/var/lib/mod_tile/downloads';
my $carto_dir = '/usr/share/mapnik/openstreetmap-carto-'.$ENV{OSM_CARTO_VERSION};
2018-09-26 09:22:09 +03:00
my $url_latest = $ENV{URL_LATEST} || 'http://download.geofabrik.de/russia-latest.osm.pbf';
my $url_updates = $ENV{URL_UPDATES} || 'http://download.geofabrik.de/russia-updates';
2018-04-05 23:33:53 +03:00
-e $dir || mkdir($dir);
chdir $dir or die "Failed to chdir $dir";
2018-08-02 02:33:27 +03:00
my $state = parse_geofabrik_state($url_updates, $dir);
2018-04-05 23:33:53 +03:00
my $dbh = DBI->connect(
2018-11-27 19:00:45 +03:00
'dbi:Pg:dbname='.$ENV{PG_ENV_OSM_DB}.';host='.$ENV{PG_ENV_OSM_HOST}.';port='.($ENV{PG_ENV_OSM_PORT}||5432),
2018-04-05 23:33:53 +03:00
$ENV{PG_ENV_OSM_USER}, $ENV{PG_ENV_OSM_PASSWORD}, {AutoCommit => 0, RaiseError => 1}
);
my ($version) = eval { $dbh->selectrow_array(
'SELECT value FROM replication_state WHERE name=? FOR UPDATE', {}, 'osm_version'
) };
if (!$version)
{
2018-08-02 02:33:27 +03:00
if (!$ENV{OSM_INIT})
2018-04-05 23:33:53 +03:00
{
2018-08-02 02:33:27 +03:00
die "Current OSM version missing, run with OSM_INIT=1 environment variable to initialize\n";
2018-04-05 23:33:53 +03:00
}
2018-08-02 02:33:27 +03:00
$dbh->rollback;
2018-11-27 19:00:45 +03:00
my ($fn) = $url_latest =~ /([^\/]+)$/so;
2018-08-02 02:33:27 +03:00
$fn =~ s/^([^\.]+)/$1-$state->{timestamp}/;
system("curl -s -C - -f '$url_latest' -o $dir/$fn");
if (!-e "$dir/$fn")
2018-04-05 23:33:53 +03:00
{
2018-08-02 02:33:27 +03:00
die "Failed to download $url_latest or $url_updates/state.txt\n";
2018-04-05 23:33:53 +03:00
}
2018-08-02 02:33:27 +03:00
load_and_init($dbh, $state->{timestamp} . ' ' . $state->{sequenceNumber}, "$dir/$fn", $carto_dir);
}
else
{
my $apply = load_geofabrik_deltas($version, $state, $url_updates, $dir);
apply_deltas($apply, $state->{timestamp} . ' ' . $state->{sequenceNumber}, $dir, $carto_dir);
2018-04-05 23:33:53 +03:00
}
2018-08-02 02:33:27 +03:00
exit;
2018-04-05 23:33:53 +03:00
2018-08-02 02:33:27 +03:00
sub parse_geofabrik_state
2018-04-05 23:33:53 +03:00
{
2018-08-02 02:33:27 +03:00
my ($url_updates, $dir) = @_;
2018-11-27 19:00:45 +03:00
system("curl -s -f '$url_updates/state.txt' -o $dir/state.txt");
2018-08-02 02:33:27 +03:00
if (!-r "$dir/state.txt")
2018-04-05 23:33:53 +03:00
{
2018-08-02 02:33:27 +03:00
die "Error downloading $url_updates/state.txt";
2018-04-05 23:33:53 +03:00
}
else
{
2018-08-02 02:33:27 +03:00
my $state;
if (open FD, "<$dir/state.txt")
{
local $/ = undef;
$state = <FD>;
close FD;
2018-11-27 19:00:45 +03:00
$state = { map { (split /\s*=\s*/, $_, 2) } grep { !/^\s*(#.*)?$/so && /=/so } split /\n/, $state };
2018-08-02 02:33:27 +03:00
if (!$state->{timestamp} || !$state->{sequenceNumber})
{
print "State file incorrect, should have timestamp=<ISO8601 date> and sequenceNumber=<integer>\n";
exit;
}
$state->{timestamp} =~ s/\\//g;
2018-11-27 19:00:45 +03:00
return $state;
2018-08-02 02:33:27 +03:00
}
2018-04-05 23:33:53 +03:00
}
2018-11-27 19:00:45 +03:00
die "Error downloading $url_updates/state.txt";
2018-04-05 23:33:53 +03:00
}
2018-08-02 02:33:27 +03:00
sub load_and_init
2018-04-05 23:33:53 +03:00
{
2018-08-02 02:33:27 +03:00
my ($dbh, $state_text, $path, $carto_dir) = @_;
$dbh->do('CREATE EXTENSION IF NOT EXISTS postgis');
$dbh->do('CREATE EXTENSION IF NOT EXISTS hstore');
$dbh->commit;
$dbh->do('CREATE TABLE IF NOT EXISTS replication_state (name varchar(1024) not null primary key, value text not null)');
$dbh->do(
'INSERT INTO replication_state (name, value) VALUES (?, ?)',
{}, 'osm_version', $state_text
);
2018-04-05 23:33:53 +03:00
my $cmd =
2018-08-02 02:33:27 +03:00
"PGPASSWORD='".$ENV{PG_ENV_OSM_PASSWORD}."' osm2pgsql -I -s -c --hstore".
2018-04-05 23:33:53 +03:00
" --style $carto_dir/openstreetmap-carto.style".
" --tag-transform-script $carto_dir/openstreetmap-carto.lua".
" -C 4000 -G -H '".$ENV{PG_ENV_OSM_HOST}."' -U '".$ENV{PG_ENV_OSM_USER}."' -d '".$ENV{PG_ENV_OSM_DB}."'".
2018-08-02 02:33:27 +03:00
" -P ".($ENV{PG_ENV_OSM_PORT} || 5432)." '$path'";
2018-04-05 23:33:53 +03:00
system($cmd);
if ($?)
{
print "$cmd failed\n";
$dbh->rollback;
exit;
}
$dbh->commit;
{
2018-08-02 02:33:27 +03:00
local $/ = undef;
my $fd;
open $fd, "$carto_dir/indexes.sql";
for my $index (split /;\s*/, <$fd>)
{
$dbh->do($index);
}
close $fd;
2018-04-05 23:33:53 +03:00
}
2018-08-02 02:33:27 +03:00
$dbh->commit;
}
sub load_geofabrik_deltas
{
my ($version, $state, $url_updates, $dir) = @_;
my ($timestamp, $i) = split /\s+/, $version;
my $apply = [];
while ($i <= $state->{sequenceNumber})
{
my $subdir = sprintf("%03d/%03d", $i / 1000000, ($i / 1000) % 1000);
my $fn = sprintf("%03d.osc.gz", $i % 1000);
system("mkdir -p $dir/$subdir && curl -C - -s -f '$url_updates/$subdir/$fn' -o $dir/$subdir/$fn");
if (-e "$dir/$subdir/$fn")
{
push @$apply, "$subdir/$fn";
}
else
{
die "Delta not available: $url_updates/$subdir/$fn\n";
}
$i++;
}
return $apply;
}
sub apply_deltas
{
my ($apply, $state_text, $dir, $carto_dir) = @_;
if (@$apply)
{
chdir($dir);
my $cmd =
"PGPASSWORD='".$ENV{PG_ENV_OSM_PASSWORD}."' osm2pgsql --append -e15 -o $dir/expire.list -I -s --hstore".
" --style $carto_dir/openstreetmap-carto.style".
" --tag-transform-script $carto_dir/openstreetmap-carto.lua".
" -C 4000 -G -H '".$ENV{PG_ENV_OSM_HOST}."' -U '".$ENV{PG_ENV_OSM_USER}."' -d '".$ENV{PG_ENV_OSM_DB}."'".
" -P ".($ENV{PG_ENV_OSM_PORT} || 5432)." '".join("' '", @$apply)."'";
system($cmd);
if ($?)
{
print "$cmd failed\n";
$dbh->rollback;
exit;
}
$dbh->do(
'UPDATE replication_state SET value=? WHERE name=?',
{}, $state_text, 'osm_version'
);
$dbh->commit;
if ($ENV{OSM_EXPIRE})
{
system("cat $dir/expire.list | render_expired --map=osm_carto --touch-from=11");
system("cat $dir/expire.list | render_expired --map=osm_bright --touch-from=11");
}
}
$dbh->commit;
2018-04-05 23:33:53 +03:00
}