]> git.openstreetmap.org Git - nominatim.git/blob - utils/setup.php
tigger data import
[nominatim.git] / utils / setup.php
1 #!/usr/bin/php -Cq
2 <?php
3
4         require_once(dirname(dirname(__FILE__)).'/lib/init-cmd.php');
5         ini_set('memory_limit', '800M');
6
7         $aCMDOptions = array(
8                 "Create and setup nominatim search system",
9                 array('help', 'h', 0, 1, 0, 0, false, 'Show Help'),
10                 array('quiet', 'q', 0, 1, 0, 0, 'bool', 'Quiet output'),
11                 array('verbose', 'v', 0, 1, 0, 0, 'bool', 'Verbose output'),
12
13                 array('osm-file', '', 0, 1, 1, 1, 'realpath', 'File to import'),
14                 array('threads', '', 0, 1, 1, 1, 'int', 'Number of threads (where possible)'),
15
16                 array('all', '', 0, 1, 0, 0, 'bool', 'Do the complete process'),
17
18                 array('create-db', '', 0, 1, 0, 0, 'bool', 'Create nominatim db'),
19                 array('setup-db', '', 0, 1, 0, 0, 'bool', 'Build a blank nominatim db'),
20                 array('import-data', '', 0, 1, 0, 0, 'bool', 'Import a osm file'),
21                 array('create-functions', '', 0, 1, 0, 0, 'bool', 'Create functions'),
22                 array('create-tables', '', 0, 1, 0, 0, 'bool', 'Create main tables'),
23                 array('create-partitions', '', 0, 1, 0, 0, 'bool', 'Create required partition tables and triggers'),
24                 array('load-data', '', 0, 1, 0, 0, 'bool', 'Copy data to live tables from import table'),
25         );
26         getCmdOpt($_SERVER['argv'], $aCMDOptions, $aCMDResult, true, true);
27
28         $bDidSomething = false;
29
30         if ($aCMDResult['create-db'] || $aCMDResult['all'])
31         {
32                 $bDidSomething = true;
33                 $oDB =& DB::connect(CONST_Database_DSN, false);
34                 if (!PEAR::isError($oDB))
35                 {
36                         fail('database already exists');
37                 }
38                 passthru('createdb nominatim');
39         }
40
41         if ($aCMDResult['create-db'] || $aCMDResult['all'])
42         {
43                 $bDidSomething = true;
44                 // TODO: path detection, detection memory, etc.
45
46                 $oDB =& getDB();
47                 passthru('createlang plpgsql nominatim');
48                 pgsqlRunScriptFile(CONST_Path_Postgresql_Contrib.'/_int.sql');
49                 pgsqlRunScriptFile(CONST_Path_Postgresql_Contrib.'/hstore.sql');
50                 pgsqlRunScriptFile(CONST_Path_Postgresql_Postgis.'/postgis.sql');
51                 pgsqlRunScriptFile(CONST_Path_Postgresql_Postgis.'/spatial_ref_sys.sql');
52                 pgsqlRunScriptFile(CONST_BasePath.'/data/country_name.sql');
53                 pgsqlRunScriptFile(CONST_BasePath.'/data/country_naturaleathdata.sql');
54                 pgsqlRunScriptFile(CONST_BasePath.'/data/country_osm_grid.sql');
55                 pgsqlRunScriptFile(CONST_BasePath.'/data/gb_postcode.sql');
56                 pgsqlRunScriptFile(CONST_BasePath.'/data/us_statecounty.sql');
57                 pgsqlRunScriptFile(CONST_BasePath.'/data/us_state.sql');
58                 pgsqlRunScriptFile(CONST_BasePath.'/data/worldboundaries.sql');
59         }
60
61         if ($aCMDResult['import-data'] || $aCMDResult['all'])
62         {
63                 $bDidSomething = true;
64                 passthru(CONST_BasePath.'/osm2pgsql/osm2pgsql -lsc -O gazetteer -C 10000 --hstore -d nominatim '.$aCMDResult['osm-file']);
65         }
66
67         if ($aCMDResult['create-functions'] || $aCMDResult['all'])
68         {
69                 $bDidSomething = true;
70                 if (!file_exists(CONST_BasePath.'/module/nominatim.so')) fail("nominatim module not built");
71                 $sTemplate = file_get_contents(CONST_BasePath.'/sql/functions.sql');
72                 $sTemplate = str_replace('{modulepath}',CONST_BasePath.'/module', $sTemplate);
73                 pgsqlRunScript($sTemplate);
74         }
75
76         if ($aCMDResult['create-tables'] || $aCMDResult['all'])
77         {
78                 $bDidSomething = true;
79                 pgsqlRunScriptFile(CONST_BasePath.'/sql/tables.sql');
80
81                 // re-run the functions
82                 $sTemplate = file_get_contents(CONST_BasePath.'/sql/functions.sql');
83                 $sTemplate = str_replace('{modulepath}',CONST_BasePath.'/module', $sTemplate);
84                 pgsqlRunScript($sTemplate);
85         }
86
87         if ($aCMDResult['create-partitions'] || $aCMDResult['all'])
88         {
89                 $bDidSomething = true;
90                 $oDB =& getDB();
91                 $sSQL = 'select partition from country_name order by country_code';
92                 $aPartitions = $oDB->getCol($sSQL);
93                 if (PEAR::isError($aPartitions))
94                 {
95                         fail($aPartitions->getMessage());
96                 }
97                 $aPartitions[] = 0;
98
99                 $sTemplate = file_get_contents(CONST_BasePath.'/sql/partitions.src.sql');
100                 preg_match_all('#^-- start(.*?)^-- end#ms', $sTemplate, $aMatches, PREG_SET_ORDER);
101                 foreach($aMatches as $aMatch)
102                 {
103                         $sResult = '';
104                         foreach($aPartitions as $sPartitionName)
105                         {
106                                 $sResult .= str_replace('-partition-', $sPartitionName, $aMatch[1]);
107                         }
108                         $sTemplate = str_replace($aMatch[0], $sResult, $sTemplate);
109                 }
110                 pgsqlRunScript($sTemplate);
111         }
112
113         if ($aCMDResult['load-data'] || $aCMDResult['all'])
114         {
115                 $bDidSomething = true;
116
117                 $oDB =& getDB();
118                 if (!pg_query($oDB->connection, 'TRUNCATE word')) fail(pg_last_error($oDB->connection));
119                 echo '.';
120                 if (!pg_query($oDB->connection, 'TRUNCATE placex')) fail(pg_last_error($oDB->connection));
121                 echo '.';
122                 if (!pg_query($oDB->connection, 'TRUNCATE place_addressline')) fail(pg_last_error($oDB->connection));
123                 echo '.';
124                 if (!pg_query($oDB->connection, 'TRUNCATE place_boundingbox')) fail(pg_last_error($oDB->connection));
125                 echo '.';
126                 if (!pg_query($oDB->connection, 'TRUNCATE location_area')) fail(pg_last_error($oDB->connection));
127                 echo '.';
128                 if (!pg_query($oDB->connection, 'TRUNCATE search_name')) fail(pg_last_error($oDB->connection));
129                 echo '.';
130                 if (!pg_query($oDB->connection, 'TRUNCATE search_name_blank')) fail(pg_last_error($oDB->connection));
131                 echo '.';
132                 if (!pg_query($oDB->connection, 'DROP SEQUENCE seq_place')) fail(pg_last_error($oDB->connection));
133                 echo '.';
134                 if (!pg_query($oDB->connection, 'CREATE SEQUENCE seq_place start 100000')) fail(pg_last_error($oDB->connection));
135                 echo '.';
136
137                 // This is a pretty hard core defult - the number of processors in the box - 1
138                 $iInstances = isset($aCMDResult['threads'])?$aCMDResult['threads']:(getProcessorCount()-1);
139                 if ($iInstances < 1)
140                 {
141                         $iInstances = 1;
142                         echo "WARNING: reseting threads to $iInstances\n";
143                 }
144                 if ($iInstances > getProcessorCount())
145                 {
146                         $iInstances = getProcessorCount();
147                         echo "WARNING: reseting threads to $iInstances\n";
148                 }
149
150                 $aDBInstances = array();
151                 for($i = 0; $i < $iInstances; $i++)
152                 {
153                         $aDBInstances[$i] =& getDB(true);
154                         $sSQL = 'insert into placex (osm_type, osm_id, class, type, name, admin_level, ';
155                         $sSQL .= 'housenumber, street, isin, postcode, country_code, extratags, ';
156                         $sSQL .= 'geometry) select * from place where osm_id % '.$iInstances.' = '.$i;
157                         if ($aCMDResult['verbose']) echo "$sSQL\n";
158                         if (!pg_send_query($aDBInstances[$i]->connection, $sSQL)) fail(pg_last_error($oDB->connection));
159                 }
160                 $bAnyBusy = true;
161                 while($bAnyBusy)
162                 {
163                         $bAnyBusy = false;
164                         for($i = 0; $i < $iInstances; $i++)
165                         {
166                                 if (pg_connection_busy($aDBInstances[$i]->connection)) $bAnyBusy = true;
167                         }
168                         sleep(1);
169                         echo '.';
170                 }
171                 echo "\n";
172         }
173
174         if (!$bDidSomething)
175         {
176                 showUsage($aCMDOptions, true);
177         }
178
179         function pgsqlRunScriptFile($sFilename)
180         {
181                 if (!file_exists($sFilename)) fail('unable to find '.$sFilename);
182
183                 // Convert database DSN to psql paramaters
184                 $aDSNInfo = DB::parseDSN(CONST_Database_DSN);
185                 $sCMD = 'psql -f '.$sFilename.' '.$aDSNInfo['database'];
186
187                 $aDescriptors = array(
188                         0 => array('pipe', 'r'),
189                         1 => array('pipe', 'w'),
190                         2 => array('file', '/dev/null', 'a')
191                 );
192                 $ahPipes = null;
193                 $hProcess = proc_open($sCMD, $aDescriptors, $ahPipes);
194                 if (!is_resource($hProcess)) fail('unable to start pgsql');
195
196                 fclose($ahPipes[0]);
197
198                 // TODO: error checking
199                 while(!feof($ahPipes[1]))
200                 {
201                         echo fread($ahPipes[1], 4096);
202                 }
203                 fclose($ahPipes[1]);
204
205                 proc_close($hProcess);
206         }
207
208         function pgsqlRunScript($sScript)
209         {
210                 // Convert database DSN to psql paramaters
211                 $aDSNInfo = DB::parseDSN(CONST_Database_DSN);
212                 $sCMD = 'psql '.$aDSNInfo['database'];
213
214                 $aDescriptors = array(
215                         0 => array('pipe', 'r'),
216                         1 => array('pipe', 'w'),
217                         2 => array('file', '/dev/null', 'a')
218                 );
219                 $ahPipes = null;
220                 $hProcess = proc_open($sCMD, $aDescriptors, $ahPipes);
221                 if (!is_resource($hProcess)) fail('unable to start pgsql');
222
223                 fwrite($ahPipes[0], $sScript);
224                 fclose($ahPipes[0]);
225
226                 // TODO: error checking
227                 while(!feof($ahPipes[1]))
228                 {
229                         echo fread($ahPipes[1], 4096);
230                 }
231                 fclose($ahPipes[1]);
232
233                 proc_close($hProcess);
234         }