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