]> git.openstreetmap.org Git - nominatim.git/blob - lib/admin/update.php
Merge remote-tracking branch 'upstream/master'
[nominatim.git] / lib / 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
56 if (!isset($aResult['index-rank'])) $aResult['index-rank'] = 0;
57
58 date_default_timezone_set('Etc/UTC');
59
60 $oDB = new Nominatim\DB();
61 $oDB->connect();
62 $fPostgresVersion = $oDB->getPostgresVersion();
63
64 $aDSNInfo = Nominatim\DB::parseDSN(getSetting('DATABASE_DSN'));
65 if (!isset($aDSNInfo['port']) || !$aDSNInfo['port']) $aDSNInfo['port'] = 5432;
66
67 // cache memory to be used by osm2pgsql, should not be more than the available memory
68 $iCacheMemory = (isset($aResult['osm2pgsql-cache'])?$aResult['osm2pgsql-cache']:2000);
69 if ($iCacheMemory + 500 > getTotalMemoryMB()) {
70     $iCacheMemory = getCacheMemoryMB();
71     echo "WARNING: resetting cache memory to $iCacheMemory\n";
72 }
73
74 $oOsm2pgsqlCmd = (new \Nominatim\Shell(getOsm2pgsqlBinary()))
75                  ->addParams('--hstore')
76                  ->addParams('--latlong')
77                  ->addParams('--append')
78                  ->addParams('--slim')
79                  ->addParams('--with-forward-dependencies', 'false')
80                  ->addParams('--log-progress', 'true')
81                  ->addParams('--number-processes', 1)
82                  ->addParams('--cache', $iCacheMemory)
83                  ->addParams('--output', 'gazetteer')
84                  ->addParams('--style', getImportStyle())
85                  ->addParams('--database', $aDSNInfo['database'])
86                  ->addParams('--port', $aDSNInfo['port']);
87
88 if (isset($aDSNInfo['hostspec']) && $aDSNInfo['hostspec']) {
89     $oOsm2pgsqlCmd->addParams('--host', $aDSNInfo['hostspec']);
90 }
91 if (isset($aDSNInfo['username']) && $aDSNInfo['username']) {
92     $oOsm2pgsqlCmd->addParams('--user', $aDSNInfo['username']);
93 }
94 if (isset($aDSNInfo['password']) && $aDSNInfo['password']) {
95     $oOsm2pgsqlCmd->addEnvPair('PGPASSWORD', $aDSNInfo['password']);
96 }
97 if (getSetting('FLATNODE_FILE')) {
98     $oOsm2pgsqlCmd->addParams('--flat-nodes', getSetting('FLATNODE_FILE'));
99 }
100 if ($fPostgresVersion >= 11.0) {
101     $oOsm2pgsqlCmd->addEnvPair(
102         'PGOPTIONS',
103         '-c jit=off -c max_parallel_workers_per_gather=0'
104     );
105 }
106
107 $oNominatimCmd = new \Nominatim\Shell(getSetting('NOMINATIM_TOOL'));
108 if ($aResult['quiet']) {
109     $oNominatimCmd->addParams('--quiet');
110 }
111 if ($aResult['verbose']) {
112     $oNominatimCmd->addParams('--verbose');
113 }
114
115
116 if ($aResult['init-updates']) {
117     $oCmd = (clone($oNominatimCmd))->addParams('replication', '--init');
118
119     if ($aResult['no-update-functions']) {
120         $oCmd->addParams('--no-update-functions');
121     }
122
123     $oCmd->run();
124 }
125
126 if ($aResult['check-for-updates']) {
127     exit((clone($oNominatimCmd))->addParams('replication', '--check-for-updates')->run());
128 }
129
130 if (isset($aResult['import-diff']) || isset($aResult['import-file'])) {
131     // import diffs and files directly (e.g. from osmosis --rri)
132     $sNextFile = isset($aResult['import-diff']) ? $aResult['import-diff'] : $aResult['import-file'];
133
134     if (!file_exists($sNextFile)) {
135         fail("Cannot open $sNextFile\n");
136     }
137
138     // Import the file
139     $oCMD = (clone $oOsm2pgsqlCmd)->addParams($sNextFile);
140     echo $oCMD->escapedCmd()."\n";
141     $iRet = $oCMD->run();
142
143     if ($iRet) {
144         fail("Error from osm2pgsql, $iRet\n");
145     }
146
147     // Don't update the import status - we don't know what this file contains
148 }
149
150 if ($aResult['calculate-postcodes']) {
151     (clone($oNominatimCmd))->addParams('refresh', '--postcodes')->run();
152 }
153
154 $sTemporaryFile = CONST_InstallDir.'/osmosischange.osc';
155 $bHaveDiff = false;
156 $bUseOSMApi = isset($aResult['import-from-main-api']) && $aResult['import-from-main-api'];
157 $sContentURL = '';
158 if (isset($aResult['import-node']) && $aResult['import-node']) {
159     if ($bUseOSMApi) {
160         $sContentURL = 'https://www.openstreetmap.org/api/0.6/node/'.$aResult['import-node'];
161     } else {
162         $sContentURL = 'https://overpass-api.de/api/interpreter?data=node('.$aResult['import-node'].');out%20meta;';
163     }
164 }
165
166 if (isset($aResult['import-way']) && $aResult['import-way']) {
167     if ($bUseOSMApi) {
168         $sContentURL = 'https://www.openstreetmap.org/api/0.6/way/'.$aResult['import-way'].'/full';
169     } else {
170         $sContentURL = 'https://overpass-api.de/api/interpreter?data=(way('.$aResult['import-way'].');%3E;);out%20meta;';
171     }
172 }
173
174 if (isset($aResult['import-relation']) && $aResult['import-relation']) {
175     if ($bUseOSMApi) {
176         $sContentURL = 'https://www.openstreetmap.org/api/0.6/relation/'.$aResult['import-relation'].'/full';
177     } else {
178         $sContentURL = 'https://overpass-api.de/api/interpreter?data=(rel(id:'.$aResult['import-relation'].');%3E;);out%20meta;';
179     }
180 }
181
182 if ($sContentURL) {
183     file_put_contents($sTemporaryFile, file_get_contents($sContentURL));
184     $bHaveDiff = true;
185 }
186
187 if ($bHaveDiff) {
188     // import generated change file
189
190     $oCMD = (clone $oOsm2pgsqlCmd)->addParams($sTemporaryFile);
191     echo $oCMD->escapedCmd()."\n";
192
193     $iRet = $oCMD->run();
194     if ($iRet) {
195         fail("osm2pgsql exited with error level $iRet\n");
196     }
197 }
198
199 if ($aResult['recompute-word-counts']) {
200     (clone($oNominatimCmd))->addParams('refresh', '--word-counts')->run();
201 }
202
203 if ($aResult['index']) {
204     (clone $oNominatimCmd)
205         ->addParams('index', '--minrank', $aResult['index-rank'])
206         ->addParams('--threads', $aResult['index-instances'])
207         ->run();
208 }
209
210 if ($aResult['update-address-levels']) {
211     (clone($oNominatimCmd))->addParams('refresh', '--address-levels')->run();
212 }
213
214 if ($aResult['recompute-importance']) {
215     echo "Updating importance values for database.\n";
216     $oDB = new Nominatim\DB();
217     $oDB->connect();
218
219     $sSQL = 'ALTER TABLE placex DISABLE TRIGGER ALL;';
220     $sSQL .= 'UPDATE placex SET (wikipedia, importance) =';
221     $sSQL .= '   (SELECT wikipedia, importance';
222     $sSQL .= '    FROM compute_importance(extratags, country_code, osm_type, osm_id));';
223     $sSQL .= 'UPDATE placex s SET wikipedia = d.wikipedia, importance = d.importance';
224     $sSQL .= ' FROM placex d';
225     $sSQL .= ' WHERE s.place_id = d.linked_place_id and d.wikipedia is not null';
226     $sSQL .= '       and (s.wikipedia is null or s.importance < d.importance);';
227     $sSQL .= 'ALTER TABLE placex ENABLE TRIGGER ALL;';
228     $oDB->exec($sSQL);
229 }
230
231 if ($aResult['import-osmosis'] || $aResult['import-osmosis-all']) {
232     $oCmd = (clone($oNominatimCmd))
233               ->addParams('replication')
234               ->addParams('--threads', $aResult['index-instances']);
235
236     if (!$aResult['import-osmosis-all']) {
237         $oCmd->addParams('--once');
238     }
239
240     if ($aResult['no-index']) {
241         $oCmd->addParams('--no-index');
242     }
243
244     exit($oCmd->run());
245 }