Добавил возможность обновления локального файла .osm.pbf
parent
2ecaeee50a
commit
5729dc92eb
18
Dockerfile
18
Dockerfile
|
@ -1,10 +1,14 @@
|
||||||
FROM debian:sid AS build
|
FROM debian:sid AS build
|
||||||
MAINTAINER Vitaliy Filippov <vitalif@mail.ru>
|
MAINTAINER Vitaliy Filippov <vitalif@mail.ru>
|
||||||
|
|
||||||
ADD etc /etc
|
# Используем одинаковое начало для ускорения сборки
|
||||||
|
ADD [ "etc/apt/apt.conf", "/etc/apt/" ]
|
||||||
|
ADD etc/locale.gen /etc/locale.gen
|
||||||
|
RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y -q \
|
||||||
|
less wget sudo curl unzip git mc ca-certificates gnupg2 && \
|
||||||
|
apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y -q \
|
RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y -q \
|
||||||
less wget sudo curl unzip git mc ca-certificates \
|
|
||||||
build-essential golang-go libleveldb-dev libgeos-dev && \
|
build-essential golang-go libleveldb-dev libgeos-dev && \
|
||||||
apt-get clean && rm -rf /var/lib/apt/lists/*
|
apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
@ -20,13 +24,17 @@ RUN dpkg -l | grep libgeos | awk '{print $2}' >> /root/pkg.lst
|
||||||
FROM debian:sid AS run
|
FROM debian:sid AS run
|
||||||
MAINTAINER Vitaliy Filippov <vitalif@mail.ru>
|
MAINTAINER Vitaliy Filippov <vitalif@mail.ru>
|
||||||
|
|
||||||
ADD etc /etc
|
# Используем одинаковое начало для ускорения сборки
|
||||||
|
ADD [ "etc/apt/apt.conf", "/etc/apt/" ]
|
||||||
|
ADD etc/locale.gen /etc/locale.gen
|
||||||
|
RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y -q \
|
||||||
|
less wget sudo curl unzip git mc ca-certificates gnupg2 && \
|
||||||
|
apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
COPY --from=build /root/pkg.lst /root/
|
COPY --from=build /root/pkg.lst /root/
|
||||||
|
|
||||||
RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y -q \
|
RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y -q \
|
||||||
less wget sudo curl unzip git mc \
|
osmctools `cat /root/pkg.lst` libleveldb1v5 libdbd-pg-perl && \
|
||||||
`cat /root/pkg.lst` libleveldb1v5 libdbd-pg-perl && \
|
|
||||||
apt-get clean && rm -rf /var/lib/apt/lists/*
|
apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
COPY --from=build /root/go/src/github.com/omniscale/imposm3/imposm /usr/bin/imposm3
|
COPY --from=build /root/go/src/github.com/omniscale/imposm3/imposm /usr/bin/imposm3
|
||||||
|
|
|
@ -7,7 +7,8 @@ docker build -t imposm3 .
|
||||||
## Running
|
## Running
|
||||||
|
|
||||||
```
|
```
|
||||||
docker run -it -d --restart always \
|
docker run -t --rm=true \
|
||||||
-v /home/test/russia-latest.osm.pbf:/home/valhalla/data.osm.pbf \
|
-e OSM_CACHE_DIR=/home/data \
|
||||||
--name valhalla -p 8002:8002 valhalla
|
-v /home/data/osm:/home/data \
|
||||||
|
--name imposm3 imposm3
|
||||||
```
|
```
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
en_US.UTF-8 UTF-8
|
||||||
|
ru_RU.UTF-8 UTF-8
|
|
@ -1,6 +1,19 @@
|
||||||
#!/usr/bin/perl
|
#!/usr/bin/perl
|
||||||
# Configuration in env: OSM_CACHE_DIR, OSM_CARTO_VERSION, URL_LATEST, URL_UPDATES,
|
# Конфигурация в переменных окружения:
|
||||||
# plus PG_ENV_OSM_{DB,HOST,PORT,USER,PASSWORD} like in README for the render server itself
|
#
|
||||||
|
# OSM_CACHE_DIR - путь к директории с временными и загружаемыми файлами
|
||||||
|
# OSM_INIT - если 1, то при пустой базе инициализировать базу
|
||||||
|
# OSM_UPDATE_FILE - если 1, то обновлять локальный файл osm.pbf до актуального состояния путём наката дельт
|
||||||
|
# OSM_EXPIRE - если 1, то вызывать утилиту render_expired
|
||||||
|
# OSM_METHOD - режим загрузки: osm2pgsql-carto или imposm3-all
|
||||||
|
# OSM_CARTO_VERSION - для режима osm2pgsql-carto - версия osm-carto. Файлы должны быть в /usr/share/mapnik/openstreetmap-carto-ВЕРСИЯ
|
||||||
|
# URL_LATEST - URL последней версии .osm.pbf экспортного файла
|
||||||
|
# URL_UPDATES - URL директории с обновлениями (должна содержать state.txt и дельты)
|
||||||
|
# PG_ENV_OSM_DB - БД PostGIS
|
||||||
|
# PG_ENV_OSM_HOST - хост/сокет БД
|
||||||
|
# PG_ENV_OSM_PORT - порт БД (по умолчанию 5432)
|
||||||
|
# PG_ENV_OSM_USER - пользователь БД
|
||||||
|
# PG_ENV_OSM_PASSWORD - пароль пользователя БД
|
||||||
|
|
||||||
use strict;
|
use strict;
|
||||||
use DBI;
|
use DBI;
|
||||||
|
@ -14,22 +27,19 @@ my $url_updates = $ENV{URL_UPDATES} || 'http://download.geofabrik.de/russia-upda
|
||||||
|
|
||||||
if (!$ENV{PG_ENV_OSM_DB})
|
if (!$ENV{PG_ENV_OSM_DB})
|
||||||
{
|
{
|
||||||
fatal("OSM database not specified");
|
fatal("Не задана БД OSM");
|
||||||
}
|
}
|
||||||
|
info("Начато обновлением OSM базы данных: $ENV{PG_ENV_OSM_DB}");
|
||||||
info("Started OSM update for database: $ENV{PG_ENV_OSM_DB}");
|
|
||||||
|
|
||||||
if ($method ne 'osm2pgsql-carto' && $method ne 'imposm3-all')
|
if ($method ne 'osm2pgsql-carto' && $method ne 'imposm3-all')
|
||||||
{
|
{
|
||||||
fatal("Incorrect OSM update mode: $method");
|
fatal("Некорректный режим обновления: $method (поддерживаются только osm2pgsql-carto и imposm3-all)");
|
||||||
}
|
}
|
||||||
|
|
||||||
-e $dir || mkdir($dir);
|
-e $dir || mkdir($dir);
|
||||||
chdir $dir or fatal("Failed to chdir $dir");
|
chdir $dir or fatal("Директория $dir не существует");
|
||||||
eval { run_update() };
|
eval { run_update() };
|
||||||
if ($@)
|
if ($@)
|
||||||
{
|
{
|
||||||
fatal("$@");
|
fatal("Ошибка кода: $@");
|
||||||
}
|
}
|
||||||
exit(0);
|
exit(0);
|
||||||
|
|
||||||
|
@ -47,7 +57,7 @@ sub run_update
|
||||||
{
|
{
|
||||||
if (!$ENV{OSM_INIT})
|
if (!$ENV{OSM_INIT})
|
||||||
{
|
{
|
||||||
fatal("Current OSM version missing, run with OSM_INIT=1 environment variable to initialize");
|
fatal("БД OSM не инициализирована, запустите скрипт с переменной окружения OSM_INIT=1 для инициализации");
|
||||||
}
|
}
|
||||||
$dbh->rollback; # иначе postgresql пишет "statements until the end ignored"
|
$dbh->rollback; # иначе postgresql пишет "statements until the end ignored"
|
||||||
# создаём таблицу и оставляем её заблокированной
|
# создаём таблицу и оставляем её заблокированной
|
||||||
|
@ -56,13 +66,13 @@ sub run_update
|
||||||
$dbh->do('CREATE EXTENSION IF NOT EXISTS hstore');
|
$dbh->do('CREATE EXTENSION IF NOT EXISTS hstore');
|
||||||
# качаем дамп
|
# качаем дамп
|
||||||
my ($fn) = $url_latest =~ /([^\/]+)$/so;
|
my ($fn) = $url_latest =~ /([^\/]+)$/so;
|
||||||
$fn =~ s/^([^\.]+)/$1-$state->{timestamp}/;
|
info("Скачивается файл $url_latest");
|
||||||
info("Downloading $url_latest");
|
|
||||||
system("curl -s -C - -f '$url_latest' -o $dir/$fn");
|
system("curl -s -C - -f '$url_latest' -o $dir/$fn");
|
||||||
if ($? || !-e "$dir/$fn")
|
if ($? || !-e "$dir/$fn")
|
||||||
{
|
{
|
||||||
fatal("Failed to download $url_latest");
|
fatal("Не удалось скачать файл $url_latest");
|
||||||
}
|
}
|
||||||
|
system("cp $dir/state.txt $dir/$fn.state.txt");
|
||||||
if ($method eq 'osm2pgsql-carto')
|
if ($method eq 'osm2pgsql-carto')
|
||||||
{
|
{
|
||||||
init_osm2pgsql($dbh, $state->{timestamp} . ' ' . $state->{sequenceNumber}, "$dir/$fn");
|
init_osm2pgsql($dbh, $state->{timestamp} . ' ' . $state->{sequenceNumber}, "$dir/$fn");
|
||||||
|
@ -72,10 +82,12 @@ sub run_update
|
||||||
init_imposm3($dbh, $state->{timestamp} . ' ' . $state->{sequenceNumber}, "$dir/$fn");
|
init_imposm3($dbh, $state->{timestamp} . ' ' . $state->{sequenceNumber}, "$dir/$fn");
|
||||||
}
|
}
|
||||||
$dbh->commit;
|
$dbh->commit;
|
||||||
info("OSM database initialized with version: ".$state->{timestamp});
|
info("База данных OSM $ENV{PG_ENV_OSM_DB} инициализирована версией: ".$state->{timestamp});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
$version = [ split /\s+/, $version ];
|
||||||
|
$version = { timestamp => $version->[0], sequenceNumber => $version->[1] };
|
||||||
my $apply = load_geofabrik_deltas($version, $state, $url_updates, $dir);
|
my $apply = load_geofabrik_deltas($version, $state, $url_updates, $dir);
|
||||||
chdir($dir);
|
chdir($dir);
|
||||||
if ($method eq 'osm2pgsql-carto')
|
if ($method eq 'osm2pgsql-carto')
|
||||||
|
@ -88,53 +100,63 @@ sub run_update
|
||||||
}
|
}
|
||||||
update_state($dbh, $state);
|
update_state($dbh, $state);
|
||||||
$dbh->commit;
|
$dbh->commit;
|
||||||
info("OSM database updated to version: ".$state->{timestamp});
|
info("База данных OSM $ENV{PG_ENV_OSM_DB} обновлена до версии: ".$state->{timestamp});
|
||||||
if ($ENV{OSM_EXPIRE})
|
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_carto --touch-from=11");
|
||||||
system("cat $dir/expire.list | render_expired --map=osm_bright --touch-from=11");
|
system("cat $dir/expire.list | render_expired --map=osm_bright --touch-from=11");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ($ENV{OSM_UPDATE_FILE})
|
||||||
|
{
|
||||||
|
apply_deltas_file($url_latest, $url_updates, $dir);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub parse_geofabrik_state
|
sub parse_geofabrik_state
|
||||||
{
|
{
|
||||||
my ($url_updates, $dir) = @_;
|
my ($url_updates, $dir) = @_;
|
||||||
system("curl -s -f '$url_updates/state.txt' -o $dir/state.txt");
|
system("curl -s -f '$url_updates/state.txt' -o $dir/state.txt");
|
||||||
if (!-r "$dir/state.txt")
|
if (-r "$dir/state.txt")
|
||||||
{
|
{
|
||||||
fatal("Error downloading $url_updates/state.txt");
|
return parse_geofabrik_state_file("$dir/state.txt");
|
||||||
}
|
}
|
||||||
else
|
fatal("Не удалось скачать файл $url_updates/state.txt");
|
||||||
|
}
|
||||||
|
|
||||||
|
sub parse_geofabrik_state_file
|
||||||
|
{
|
||||||
|
my ($file) = @_;
|
||||||
|
my $state;
|
||||||
|
if (open FD, "<$file")
|
||||||
{
|
{
|
||||||
my $state;
|
local $/ = undef;
|
||||||
if (open FD, "<$dir/state.txt")
|
$state = <FD>;
|
||||||
|
close FD;
|
||||||
|
$state = { map { (split /\s*=\s*/, $_, 2) } grep { !/^\s*(#.*)?$/so && /=/so } split /\n/, $state };
|
||||||
|
if (!$state->{timestamp} || !$state->{sequenceNumber})
|
||||||
{
|
{
|
||||||
local $/ = undef;
|
fatal("Файл состояния репликации OSM некорректный, должен содержать строки timestamp=<дата_ISO8601> и sequenceNumber=<число>");
|
||||||
$state = <FD>;
|
|
||||||
close FD;
|
|
||||||
$state = { map { (split /\s*=\s*/, $_, 2) } grep { !/^\s*(#.*)?$/so && /=/so } split /\n/, $state };
|
|
||||||
if (!$state->{timestamp} || !$state->{sequenceNumber})
|
|
||||||
{
|
|
||||||
fatal("State file incorrect, should have timestamp=<ISO8601 date> and sequenceNumber=<integer>");
|
|
||||||
}
|
|
||||||
$state->{timestamp} =~ s/\\//g;
|
|
||||||
return $state;
|
|
||||||
}
|
}
|
||||||
|
$state->{timestamp} =~ s/\\//g;
|
||||||
|
return $state;
|
||||||
}
|
}
|
||||||
fatal("Error downloading $url_updates/state.txt");
|
return undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub load_geofabrik_deltas
|
sub load_geofabrik_deltas
|
||||||
{
|
{
|
||||||
my ($version, $state, $url_updates, $dir) = @_;
|
my ($old_state, $state, $url_updates, $dir) = @_;
|
||||||
my ($timestamp, $i) = split /\s+/, $version;
|
my $i = $old_state->{sequenceNumber};
|
||||||
my $apply = [];
|
my $apply = [];
|
||||||
while ($i <= $state->{sequenceNumber})
|
while ($i < $state->{sequenceNumber})
|
||||||
{
|
{
|
||||||
my $subdir = sprintf("%03d/%03d", $i / 1000000, ($i / 1000) % 1000);
|
my $subdir = sprintf("%03d/%03d", $i / 1000000, ($i / 1000) % 1000);
|
||||||
my $fn = sprintf("%03d.osc.gz", $i % 1000);
|
my $fn = sprintf("%03d.osc.gz", $i % 1000);
|
||||||
info("Downloading $url_updates/$subdir/$fn");
|
if (!-e "$dir/$subdir/$fn")
|
||||||
|
{
|
||||||
|
info("Скачивается файл дельты $url_updates/$subdir/$fn");
|
||||||
|
}
|
||||||
system("mkdir -p $dir/$subdir && curl -C - -s -f '$url_updates/$subdir/$fn' -o $dir/$subdir/$fn");
|
system("mkdir -p $dir/$subdir && curl -C - -s -f '$url_updates/$subdir/$fn' -o $dir/$subdir/$fn");
|
||||||
if (-e "$dir/$subdir/$fn")
|
if (-e "$dir/$subdir/$fn")
|
||||||
{
|
{
|
||||||
|
@ -142,7 +164,8 @@ sub load_geofabrik_deltas
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fatal("Delta not available: $url_updates/$subdir/$fn\n");
|
unlink("$dir/$subdir/$fn") if -e "$dir/$subdir/$fn";
|
||||||
|
fatal("Не удалось скачать файл дельты $url_updates/$subdir/$fn\n");
|
||||||
}
|
}
|
||||||
$i++;
|
$i++;
|
||||||
}
|
}
|
||||||
|
@ -174,7 +197,7 @@ sub init_osm2pgsql
|
||||||
my $carto_dir = '/usr/share/mapnik/openstreetmap-carto-'.$ENV{OSM_CARTO_VERSION};
|
my $carto_dir = '/usr/share/mapnik/openstreetmap-carto-'.$ENV{OSM_CARTO_VERSION};
|
||||||
if (!$ENV{OSM_CARTO_VERSION})
|
if (!$ENV{OSM_CARTO_VERSION})
|
||||||
{
|
{
|
||||||
fatal("osm-carto path not specified");
|
fatal("Не задан путь к osm-carto");
|
||||||
}
|
}
|
||||||
my $cmd =
|
my $cmd =
|
||||||
"PGPASSWORD='".$ENV{PG_ENV_OSM_PASSWORD}."' osm2pgsql -I -s -c --hstore".
|
"PGPASSWORD='".$ENV{PG_ENV_OSM_PASSWORD}."' osm2pgsql -I -s -c --hstore".
|
||||||
|
@ -185,7 +208,7 @@ sub init_osm2pgsql
|
||||||
system($cmd);
|
system($cmd);
|
||||||
if ($?)
|
if ($?)
|
||||||
{
|
{
|
||||||
fatal("$cmd failed");
|
fatal("Загрузка полного дампа с помощью osm2pgsql не удалась");
|
||||||
}
|
}
|
||||||
local $/ = undef;
|
local $/ = undef;
|
||||||
my $fd;
|
my $fd;
|
||||||
|
@ -208,7 +231,7 @@ sub init_imposm3
|
||||||
system($cmd);
|
system($cmd);
|
||||||
if ($?)
|
if ($?)
|
||||||
{
|
{
|
||||||
fatal("$cmd failed");
|
fatal("Загрузка полного дампа с помощью imposm3 не удалась");
|
||||||
}
|
}
|
||||||
my $indexes = "SET SEARCH_PATH TO import, public;
|
my $indexes = "SET SEARCH_PATH TO import, public;
|
||||||
CREATE INDEX IF NOT EXISTS osm_polygon_area ON osm_polygon (st_area(geometry));
|
CREATE INDEX IF NOT EXISTS osm_polygon_area ON osm_polygon (st_area(geometry));
|
||||||
|
@ -240,7 +263,7 @@ sub apply_deltas_osm2pgsql
|
||||||
system($cmd);
|
system($cmd);
|
||||||
if ($?)
|
if ($?)
|
||||||
{
|
{
|
||||||
fatal("$cmd failed");
|
fatal("Загрузка дельт osm2pgsql не удалась");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -251,7 +274,7 @@ sub apply_deltas_imposm3
|
||||||
my $carto_dir = '/usr/share/mapnik/openstreetmap-carto-'.$ENV{OSM_CARTO_VERSION};
|
my $carto_dir = '/usr/share/mapnik/openstreetmap-carto-'.$ENV{OSM_CARTO_VERSION};
|
||||||
if (!$ENV{OSM_CARTO_VERSION})
|
if (!$ENV{OSM_CARTO_VERSION})
|
||||||
{
|
{
|
||||||
fatal("osm-carto path not specified");
|
fatal("Не задан путь к osm-carto");
|
||||||
}
|
}
|
||||||
if (@$apply)
|
if (@$apply)
|
||||||
{
|
{
|
||||||
|
@ -263,11 +286,31 @@ sub apply_deltas_imposm3
|
||||||
system($cmd);
|
system($cmd);
|
||||||
if ($?)
|
if ($?)
|
||||||
{
|
{
|
||||||
fatal("$cmd failed");
|
fatal("Загрузка дельт imposm3 не удалась");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub apply_deltas_file
|
||||||
|
{
|
||||||
|
my ($url_latest, $url_updates, $dir) = @_;
|
||||||
|
my ($full_fn) = $url_latest =~ /([^\/]+)$/so;
|
||||||
|
my $old_state = parse_geofabrik_state_file("$dir/$full_fn.state.txt");
|
||||||
|
my $state = parse_geofabrik_state($url_updates, $dir);
|
||||||
|
my $apply = load_geofabrik_deltas($old_state, $state, $url_updates, $dir);
|
||||||
|
if (@$apply)
|
||||||
|
{
|
||||||
|
my $cmd = "osmconvert $dir/$full_fn '".join("' '", @$apply)."' -o $dir/new-$full_fn";
|
||||||
|
system($cmd);
|
||||||
|
if ($?)
|
||||||
|
{
|
||||||
|
fatal("Обновление локального файла .osm.pbf не удалось");
|
||||||
|
}
|
||||||
|
system("mv $dir/new-$full_fn $dir/$full_fn");
|
||||||
|
system("cp $dir/state.txt $full_fn.state.txt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sub info
|
sub info
|
||||||
{
|
{
|
||||||
my ($msg) = @_;
|
my ($msg) = @_;
|
||||||
|
|
Loading…
Reference in New Issue