]> git.openstreetmap.org Git - nominatim.git/blob - lib-php/admin/update.php
Merge remote-tracking branch 'upstream/master'
[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
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
109 function run($oCmd)
110 {
111     global $aCMDResult;
112     if ($aCMDResult['quiet'] ?? false) {
113         $oCmd->addParams('--quiet');
114     }
115     if ($aCMDResult['verbose'] ?? false) {
116         $oCmd->addParams('--verbose');
117     }
118     $oCmd->run(true);
119 }
120
121
122 if ($aResult['init-updates']) {
123     $oCmd = (clone($oNominatimCmd))->addParams('replication', '--init');
124
125     if ($aResult['no-update-functions']) {
126         $oCmd->addParams('--no-update-functions');
127     }
128
129     run($oCmd);
130 }
131
132 if ($aResult['check-for-updates']) {
133     exit((clone($oNominatimCmd))->addParams('replication', '--check-for-updates')->run());
134 }
135
136 if (isset($aResult['import-diff']) || isset($aResult['import-file'])) {
137     // import diffs and files directly (e.g. from osmosis --rri)
138     $sNextFile = isset($aResult['import-diff']) ? $aResult['import-diff'] : $aResult['import-file'];
139
140     if (!file_exists($sNextFile)) {
141         fail("Cannot open $sNextFile\n");
142     }
143
144     // Import the file
145     $oCMD = (clone $oOsm2pgsqlCmd)->addParams($sNextFile);
146     echo $oCMD->escapedCmd()."\n";
147     $iRet = $oCMD->run();
148
149     if ($iRet) {
150         fail("Error from osm2pgsql, $iRet\n");
151     }
152
153     // Don't update the import status - we don't know what this file contains
154 }
155
156 if ($aResult['calculate-postcodes']) {
157     run((clone($oNominatimCmd))->addParams('refresh', '--postcodes'));
158 }
159
160 $sTemporaryFile = CONST_InstallDir.'/osmosischange.osc';
161 $bHaveDiff = false;
162 $bUseOSMApi = isset($aResult['import-from-main-api']) && $aResult['import-from-main-api'];
163 $sContentURL = '';
164 if (isset($aResult['import-node']) && $aResult['import-node']) {
165     if ($bUseOSMApi) {
166         $sContentURL = 'https://www.openstreetmap.org/api/0.6/node/'.$aResult['import-node'];
167     } else {
168         $sContentURL = 'https://overpass-api.de/api/interpreter?data=node('.$aResult['import-node'].');out%20meta;';
169     }
170 }
171
172 if (isset($aResult['import-way']) && $aResult['import-way']) {
173     if ($bUseOSMApi) {
174         $sContentURL = 'https://www.openstreetmap.org/api/0.6/way/'.$aResult['import-way'].'/full';
175     } else {
176         $sContentURL = 'https://overpass-api.de/api/interpreter?data=(way('.$aResult['import-way'].');%3E;);out%20meta;';
177     }
178 }
179
180 if (isset($aResult['import-relation']) && $aResult['import-relation']) {
181     if ($bUseOSMApi) {
182         $sContentURL = 'https://www.openstreetmap.org/api/0.6/relation/'.$aResult['import-relation'].'/full';
183     } else {
184         $sContentURL = 'https://overpass-api.de/api/interpreter?data=(rel(id:'.$aResult['import-relation'].');%3E;);out%20meta;';
185     }
186 }
187
188 if ($sContentURL) {
189     file_put_contents($sTemporaryFile, file_get_contents($sContentURL));
190     $bHaveDiff = true;
191 }
192
193 if ($bHaveDiff) {
194     // import generated change file
195
196     $oCMD = (clone $oOsm2pgsqlCmd)->addParams($sTemporaryFile);
197     echo $oCMD->escapedCmd()."\n";
198
199     $iRet = $oCMD->run();
200     if ($iRet) {
201         fail("osm2pgsql exited with error level $iRet\n");
202     }
203 }
204
205 if ($aResult['recompute-word-counts']) {
206     run((clone($oNominatimCmd))->addParams('refresh', '--word-counts'));
207 }
208
209 if ($aResult['index']) {
210     run((clone $oNominatimCmd)
211         ->addParams('index', '--minrank', $aResult['index-rank'])
212         ->addParams('--threads', $aResult['index-instances']));
213 }
214
215 if ($aResult['update-address-levels']) {
216     run((clone($oNominatimCmd))->addParams('refresh', '--address-levels'));
217 }
218
219 if ($aResult['recompute-importance']) {
220     run((clone($oNominatimCmd))->addParams('refresh', '--importance'));
221 }
222
223 if ($aResult['import-osmosis'] || $aResult['import-osmosis-all']) {
224     $oCmd = (clone($oNominatimCmd))
225               ->addParams('replication')
226               ->addParams('--threads', $aResult['index-instances']);
227
228     if (!$aResult['import-osmosis-all']) {
229         $oCmd->addParams('--once');
230     }
231
232     if ($aResult['no-index']) {
233         $oCmd->addParams('--no-index');
234     }
235
236     run($oCmd);
237 }