]> git.openstreetmap.org Git - nominatim.git/blob - lib-php/admin/update.php
Merge pull request #2186 from lonvia/port-import-to-python
[nominatim.git] / lib-php / admin / update.php
1 <?php
2 @define('CONST_LibDir', dirname(dirname(__FILE__)));
3
4 require_once(CONST_LibDir.'/init-cmd.php');
5 require_once(CONST_LibDir.'/setup_functions.php');
6 require_once(CONST_LibDir.'/setup/SetupClass.php');
7
8 ini_set('memory_limit', '800M');
9
10 use Nominatim\Setup\SetupFunctions as SetupFunctions;
11
12 // (long-opt, short-opt, min-occurs, max-occurs, num-arguments, num-arguments, type, help)
13 $aCMDOptions
14 = array(
15    'Import / update / index osm data',
16    array('help', 'h', 0, 1, 0, 0, false, 'Show Help'),
17    array('quiet', 'q', 0, 1, 0, 0, 'bool', 'Quiet output'),
18    array('verbose', 'v', 0, 1, 0, 0, 'bool', 'Verbose output'),
19
20    array('init-updates', '', 0, 1, 0, 0, 'bool', 'Set up database for updating'),
21    array('check-for-updates', '', 0, 1, 0, 0, 'bool', 'Check if new updates are available'),
22    array('no-update-functions', '', 0, 1, 0, 0, 'bool', 'Do not update trigger functions to support differential updates (assuming the diff update logic is already present)'),
23    array('import-osmosis', '', 0, 1, 0, 0, 'bool', 'Import updates once'),
24    array('import-osmosis-all', '', 0, 1, 0, 0, 'bool', 'Import updates forever'),
25    array('no-index', '', 0, 1, 0, 0, 'bool', 'Do not index the new data'),
26
27    array('calculate-postcodes', '', 0, 1, 0, 0, 'bool', 'Update postcode centroid table'),
28
29    array('import-file', '', 0, 1, 1, 1, 'realpath', 'Re-import data from an OSM file'),
30    array('import-diff', '', 0, 1, 1, 1, 'realpath', 'Import a diff (osc) file from local file system'),
31    array('osm2pgsql-cache', '', 0, 1, 1, 1, 'int', 'Cache size used by osm2pgsql'),
32
33    array('import-node', '', 0, 1, 1, 1, 'int', 'Re-import node'),
34    array('import-way', '', 0, 1, 1, 1, 'int', 'Re-import way'),
35    array('import-relation', '', 0, 1, 1, 1, 'int', 'Re-import relation'),
36    array('import-from-main-api', '', 0, 1, 0, 0, 'bool', 'Use OSM API instead of Overpass to download objects'),
37
38    array('index', '', 0, 1, 0, 0, 'bool', 'Index'),
39    array('index-rank', '', 0, 1, 1, 1, 'int', 'Rank to start indexing from'),
40    array('index-instances', '', 0, 1, 1, 1, 'int', 'Number of indexing instances (threads)'),
41
42    array('recompute-word-counts', '', 0, 1, 0, 0, 'bool', 'Compute frequency of full-word search terms'),
43    array('update-address-levels', '', 0, 1, 0, 0, 'bool', 'Reimport address level configuration (EXPERT)'),
44    array('recompute-importance', '', 0, 1, 0, 0, 'bool', 'Recompute place importances'),
45
46    array('project-dir', '', 0, 1, 1, 1, 'realpath', 'Base directory of the Nominatim installation (default: .)'),
47   );
48
49 getCmdOpt($_SERVER['argv'], $aCMDOptions, $aResult, true, true);
50
51 loadSettings($aCMDResult['project-dir'] ?? getcwd());
52 setupHTTPProxy();
53
54 if (!isset($aResult['index-instances'])) $aResult['index-instances'] = 1;
55 if (!isset($aResult['index-rank'])) $aResult['index-rank'] = 0;
56
57 date_default_timezone_set('Etc/UTC');
58
59 $oDB = new Nominatim\DB();
60 $oDB->connect();
61 $fPostgresVersion = $oDB->getPostgresVersion();
62
63 $aDSNInfo = Nominatim\DB::parseDSN(getSetting('DATABASE_DSN'));
64 if (!isset($aDSNInfo['port']) || !$aDSNInfo['port']) $aDSNInfo['port'] = 5432;
65
66 // cache memory to be used by osm2pgsql, should not be more than the available memory
67 $iCacheMemory = (isset($aResult['osm2pgsql-cache'])?$aResult['osm2pgsql-cache']:2000);
68 if ($iCacheMemory + 500 > getTotalMemoryMB()) {
69     $iCacheMemory = getCacheMemoryMB();
70     echo "WARNING: resetting cache memory to $iCacheMemory\n";
71 }
72
73 $oOsm2pgsqlCmd = (new \Nominatim\Shell(getOsm2pgsqlBinary()))
74                  ->addParams('--hstore')
75                  ->addParams('--latlong')
76                  ->addParams('--append')
77                  ->addParams('--slim')
78                  ->addParams('--with-forward-dependencies', 'false')
79                  ->addParams('--log-progress', 'true')
80                  ->addParams('--number-processes', 1)
81                  ->addParams('--cache', $iCacheMemory)
82                  ->addParams('--output', 'gazetteer')
83                  ->addParams('--style', getImportStyle())
84                  ->addParams('--database', $aDSNInfo['database'])
85                  ->addParams('--port', $aDSNInfo['port']);
86
87 if (isset($aDSNInfo['hostspec']) && $aDSNInfo['hostspec']) {
88     $oOsm2pgsqlCmd->addParams('--host', $aDSNInfo['hostspec']);
89 }
90 if (isset($aDSNInfo['username']) && $aDSNInfo['username']) {
91     $oOsm2pgsqlCmd->addParams('--user', $aDSNInfo['username']);
92 }
93 if (isset($aDSNInfo['password']) && $aDSNInfo['password']) {
94     $oOsm2pgsqlCmd->addEnvPair('PGPASSWORD', $aDSNInfo['password']);
95 }
96 if (getSetting('FLATNODE_FILE')) {
97     $oOsm2pgsqlCmd->addParams('--flat-nodes', getSetting('FLATNODE_FILE'));
98 }
99 if ($fPostgresVersion >= 11.0) {
100     $oOsm2pgsqlCmd->addEnvPair(
101         'PGOPTIONS',
102         '-c jit=off -c max_parallel_workers_per_gather=0'
103     );
104 }
105
106 $oNominatimCmd = new \Nominatim\Shell(getSetting('NOMINATIM_TOOL'));
107
108 function run($oCmd)
109 {
110     global $aCMDResult;
111     if ($aCMDResult['quiet'] ?? false) {
112         $oCmd->addParams('--quiet');
113     }
114     if ($aCMDResult['verbose'] ?? false) {
115         $oCmd->addParams('--verbose');
116     }
117     $oCmd->run(true);
118 }
119
120
121 if ($aResult['init-updates']) {
122     $oCmd = (clone($oNominatimCmd))->addParams('replication', '--init');
123
124     if ($aResult['no-update-functions']) {
125         $oCmd->addParams('--no-update-functions');
126     }
127
128     run($oCmd);
129 }
130
131 if ($aResult['check-for-updates']) {
132     exit((clone($oNominatimCmd))->addParams('replication', '--check-for-updates')->run());
133 }
134
135 if (isset($aResult['import-diff']) || isset($aResult['import-file'])) {
136     // import diffs and files directly (e.g. from osmosis --rri)
137     $sNextFile = isset($aResult['import-diff']) ? $aResult['import-diff'] : $aResult['import-file'];
138
139     if (!file_exists($sNextFile)) {
140         fail("Cannot open $sNextFile\n");
141     }
142
143     // Import the file
144     $oCMD = (clone $oOsm2pgsqlCmd)->addParams($sNextFile);
145     echo $oCMD->escapedCmd()."\n";
146     $iRet = $oCMD->run();
147
148     if ($iRet) {
149         fail("Error from osm2pgsql, $iRet\n");
150     }
151
152     // Don't update the import status - we don't know what this file contains
153 }
154
155 if ($aResult['calculate-postcodes']) {
156     run((clone($oNominatimCmd))->addParams('refresh', '--postcodes'));
157 }
158
159 $sTemporaryFile = CONST_InstallDir.'/osmosischange.osc';
160 $bHaveDiff = false;
161 $bUseOSMApi = isset($aResult['import-from-main-api']) && $aResult['import-from-main-api'];
162 $sContentURL = '';
163 if (isset($aResult['import-node']) && $aResult['import-node']) {
164     if ($bUseOSMApi) {
165         $sContentURL = 'https://www.openstreetmap.org/api/0.6/node/'.$aResult['import-node'];
166     } else {
167         $sContentURL = 'https://overpass-api.de/api/interpreter?data=node('.$aResult['import-node'].');out%20meta;';
168     }
169 }
170
171 if (isset($aResult['import-way']) && $aResult['import-way']) {
172     if ($bUseOSMApi) {
173         $sContentURL = 'https://www.openstreetmap.org/api/0.6/way/'.$aResult['import-way'].'/full';
174     } else {
175         $sContentURL = 'https://overpass-api.de/api/interpreter?data=(way('.$aResult['import-way'].');%3E;);out%20meta;';
176     }
177 }
178
179 if (isset($aResult['import-relation']) && $aResult['import-relation']) {
180     if ($bUseOSMApi) {
181         $sContentURL = 'https://www.openstreetmap.org/api/0.6/relation/'.$aResult['import-relation'].'/full';
182     } else {
183         $sContentURL = 'https://overpass-api.de/api/interpreter?data=(rel(id:'.$aResult['import-relation'].');%3E;);out%20meta;';
184     }
185 }
186
187 if ($sContentURL) {
188     file_put_contents($sTemporaryFile, file_get_contents($sContentURL));
189     $bHaveDiff = true;
190 }
191
192 if ($bHaveDiff) {
193     // import generated change file
194
195     $oCMD = (clone $oOsm2pgsqlCmd)->addParams($sTemporaryFile);
196     echo $oCMD->escapedCmd()."\n";
197
198     $iRet = $oCMD->run();
199     if ($iRet) {
200         fail("osm2pgsql exited with error level $iRet\n");
201     }
202 }
203
204 if ($aResult['recompute-word-counts']) {
205     run((clone($oNominatimCmd))->addParams('refresh', '--word-counts'));
206 }
207
208 if ($aResult['index']) {
209     run((clone $oNominatimCmd)
210         ->addParams('index', '--minrank', $aResult['index-rank'])
211         ->addParams('--threads', $aResult['index-instances']));
212 }
213
214 if ($aResult['update-address-levels']) {
215     run((clone($oNominatimCmd))->addParams('refresh', '--address-levels'));
216 }
217
218 if ($aResult['recompute-importance']) {
219     run((clone($oNominatimCmd))->addParams('refresh', '--importance'));
220 }
221
222 if ($aResult['import-osmosis'] || $aResult['import-osmosis-all']) {
223     $oCmd = (clone($oNominatimCmd))
224               ->addParams('replication')
225               ->addParams('--threads', $aResult['index-instances']);
226
227     if (!$aResult['import-osmosis-all']) {
228         $oCmd->addParams('--once');
229     }
230
231     if ($aResult['no-index']) {
232         $oCmd->addParams('--no-index');
233     }
234
235     run($oCmd);
236 }