2 @define('CONST_LibDir', dirname(dirname(__FILE__)));
4 require_once(CONST_LibDir.'/init-cmd.php');
5 require_once(CONST_LibDir.'/setup_functions.php');
6 require_once(CONST_LibDir.'/setup/SetupClass.php');
8 ini_set('memory_limit', '800M');
10 use Nominatim\Setup\SetupFunctions as SetupFunctions;
12 // (long-opt, short-opt, min-occurs, max-occurs, num-arguments, num-arguments, type, help)
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'),
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'),
27 array('calculate-postcodes', '', 0, 1, 0, 0, 'bool', 'Update postcode centroid table'),
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'),
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'),
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)'),
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'),
46 array('project-dir', '', 0, 1, 1, 1, 'realpath', 'Base directory of the Nominatim installation (default: .)'),
49 getCmdOpt($_SERVER['argv'], $aCMDOptions, $aResult, true, true);
51 loadSettings($aCMDResult['project-dir'] ?? getcwd());
54 if (!isset($aResult['index-instances'])) $aResult['index-instances'] = 1;
56 if (!isset($aResult['index-rank'])) $aResult['index-rank'] = 0;
58 date_default_timezone_set('Etc/UTC');
60 $oDB = new Nominatim\DB();
62 $fPostgresVersion = $oDB->getPostgresVersion();
64 $aDSNInfo = Nominatim\DB::parseDSN(getSetting('DATABASE_DSN'));
65 if (!isset($aDSNInfo['port']) || !$aDSNInfo['port']) $aDSNInfo['port'] = 5432;
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";
74 $oOsm2pgsqlCmd = (new \Nominatim\Shell(getOsm2pgsqlBinary()))
75 ->addParams('--hstore')
76 ->addParams('--latlong')
77 ->addParams('--append')
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']);
88 if (isset($aDSNInfo['hostspec']) && $aDSNInfo['hostspec']) {
89 $oOsm2pgsqlCmd->addParams('--host', $aDSNInfo['hostspec']);
91 if (isset($aDSNInfo['username']) && $aDSNInfo['username']) {
92 $oOsm2pgsqlCmd->addParams('--user', $aDSNInfo['username']);
94 if (isset($aDSNInfo['password']) && $aDSNInfo['password']) {
95 $oOsm2pgsqlCmd->addEnvPair('PGPASSWORD', $aDSNInfo['password']);
97 if (getSetting('FLATNODE_FILE')) {
98 $oOsm2pgsqlCmd->addParams('--flat-nodes', getSetting('FLATNODE_FILE'));
100 if ($fPostgresVersion >= 11.0) {
101 $oOsm2pgsqlCmd->addEnvPair(
103 '-c jit=off -c max_parallel_workers_per_gather=0'
107 $oNominatimCmd = new \Nominatim\Shell(getSetting('NOMINATIM_TOOL'));
112 if ($aCMDResult['quiet'] ?? false) {
113 $oCmd->addParams('--quiet');
115 if ($aCMDResult['verbose'] ?? false) {
116 $oCmd->addParams('--verbose');
122 if ($aResult['init-updates']) {
123 $oCmd = (clone($oNominatimCmd))->addParams('replication', '--init');
125 if ($aResult['no-update-functions']) {
126 $oCmd->addParams('--no-update-functions');
132 if ($aResult['check-for-updates']) {
133 exit((clone($oNominatimCmd))->addParams('replication', '--check-for-updates')->run());
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'];
140 if (!file_exists($sNextFile)) {
141 fail("Cannot open $sNextFile\n");
145 $oCMD = (clone $oOsm2pgsqlCmd)->addParams($sNextFile);
146 echo $oCMD->escapedCmd()."\n";
147 $iRet = $oCMD->run();
150 fail("Error from osm2pgsql, $iRet\n");
153 // Don't update the import status - we don't know what this file contains
156 if ($aResult['calculate-postcodes']) {
157 run((clone($oNominatimCmd))->addParams('refresh', '--postcodes'));
160 $sTemporaryFile = CONST_InstallDir.'/osmosischange.osc';
162 $bUseOSMApi = isset($aResult['import-from-main-api']) && $aResult['import-from-main-api'];
164 if (isset($aResult['import-node']) && $aResult['import-node']) {
166 $sContentURL = 'https://www.openstreetmap.org/api/0.6/node/'.$aResult['import-node'];
168 $sContentURL = 'https://overpass-api.de/api/interpreter?data=node('.$aResult['import-node'].');out%20meta;';
172 if (isset($aResult['import-way']) && $aResult['import-way']) {
174 $sContentURL = 'https://www.openstreetmap.org/api/0.6/way/'.$aResult['import-way'].'/full';
176 $sContentURL = 'https://overpass-api.de/api/interpreter?data=(way('.$aResult['import-way'].');%3E;);out%20meta;';
180 if (isset($aResult['import-relation']) && $aResult['import-relation']) {
182 $sContentURL = 'https://www.openstreetmap.org/api/0.6/relation/'.$aResult['import-relation'].'/full';
184 $sContentURL = 'https://overpass-api.de/api/interpreter?data=(rel(id:'.$aResult['import-relation'].');%3E;);out%20meta;';
189 file_put_contents($sTemporaryFile, file_get_contents($sContentURL));
194 // import generated change file
196 $oCMD = (clone $oOsm2pgsqlCmd)->addParams($sTemporaryFile);
197 echo $oCMD->escapedCmd()."\n";
199 $iRet = $oCMD->run();
201 fail("osm2pgsql exited with error level $iRet\n");
205 if ($aResult['recompute-word-counts']) {
206 run((clone($oNominatimCmd))->addParams('refresh', '--word-counts'));
209 if ($aResult['index']) {
210 run((clone $oNominatimCmd)
211 ->addParams('index', '--minrank', $aResult['index-rank'])
212 ->addParams('--threads', $aResult['index-instances']));
215 if ($aResult['update-address-levels']) {
216 run((clone($oNominatimCmd))->addParams('refresh', '--address-levels'));
219 if ($aResult['recompute-importance']) {
220 run((clone($oNominatimCmd))->addParams('refresh', '--importance'));
223 if ($aResult['import-osmosis'] || $aResult['import-osmosis-all']) {
224 $oCmd = (clone($oNominatimCmd))
225 ->addParams('replication')
226 ->addParams('--threads', $aResult['index-instances']);
228 if (!$aResult['import-osmosis-all']) {
229 $oCmd->addParams('--once');
232 if ($aResult['no-index']) {
233 $oCmd->addParams('--no-index');