source: subversion/applications/utils/export/osm2pgsql/osm2pgsql.c @ 13668

Last change on this file since 13668 was 13668, checked in by stevehill, 11 years ago

Replace the in-memory dirty tile store with something a bit more efficient.

Also adds support for specifying a range of zoom levels - i.e. "-o 0-17". The output dirty tile list will use the lowest zoom level which accurately describes the tiles which have been expired.

  • Property svn:keywords set to Rev
File size: 23.9 KB
Line 
1/*
2#-----------------------------------------------------------------------------
3# osm2pgsql - converts planet.osm file into PostgreSQL
4# compatible output suitable to be rendered by mapnik
5# Use: osm2pgsql planet.osm.bz2
6#-----------------------------------------------------------------------------
7# Original Python implementation by Artem Pavlenko
8# Re-implementation by Jon Burgess, Copyright 2006
9#
10# This program is free software; you can redistribute it and/or
11# modify it under the terms of the GNU General Public License
12# as published by the Free Software Foundation; either version 2
13# of the License, or (at your option) any later version.
14#
15# This program is distributed in the hope that it will be useful,
16# but WITHOUT ANY WARRANTY; without even the implied warranty of
17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18# GNU General Public License for more details.
19#
20# You should have received a copy of the GNU General Public License
21# along with this program; if not, write to the Free Software
22# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
23#-----------------------------------------------------------------------------
24*/
25
26#define _GNU_SOURCE
27#include <stdio.h>
28#include <unistd.h>
29#include <stdlib.h>
30#include <string.h>
31#include <assert.h>
32#include <getopt.h>
33
34#include <libpq-fe.h>
35
36#include <libxml/xmlstring.h>
37#include <libxml/xmlreader.h>
38
39#include "osmtypes.h"
40#include "build_geometry.h"
41#include "keyvals.h"
42#include "middle-pgsql.h"
43#include "middle-ram.h"
44#include "output-pgsql.h"
45#include "sanitizer.h"
46#include "reprojection.h"
47#include "text-tree.h"
48#include "input.h"
49#include "sprompt.h"
50
51typedef enum { FILETYPE_NONE, FILETYPE_OSM, FILETYPE_OSMCHANGE, FILETYPE_PLANETDIFF } filetypes_t;
52typedef enum { ACTION_NONE, ACTION_CREATE, ACTION_MODIFY, ACTION_DELETE } actions_t;
53
54static int count_node,    max_node;
55static int count_way,     max_way;
56static int count_rel,     max_rel;
57
58struct output_t *out;
59
60/* Since {node,way} elements are not nested we can guarantee the
61   values in an end tag must match those of the corresponding
62   start tag and can therefore be cached.
63*/
64static double node_lon, node_lat;
65static struct keyval tags;
66static int *nds;
67static int nd_count, nd_max;
68static struct member *members;
69static int member_count, member_max;
70static int osm_id;
71
72#define INIT_MAX_MEMBERS 64
73#define INIT_MAX_NODES  4096
74
75int verbose;
76static void realloc_nodes();
77static void realloc_members();
78
79// Bounding box to filter imported data
80const char *bbox = NULL;
81static double minlon, minlat, maxlon, maxlat;
82
83static void printStatus(void)
84{
85    fprintf(stderr, "\rProcessing: Node(%dk) Way(%dk) Relation(%dk)",
86            count_node/1000, count_way/1000, count_rel/1000);
87}
88
89static int parse_bbox(void)
90{
91    int n;
92
93    if (!bbox)
94        return 0;
95
96    n = sscanf(bbox, "%lf,%lf,%lf,%lf", &minlon, &minlat, &maxlon, &maxlat);
97    if (n != 4) {
98        fprintf(stderr, "Bounding box must be specified like: minlon,minlat,maxlon,maxlat\n");
99        return 1;
100    }
101    if (maxlon <= minlon) {
102        fprintf(stderr, "Bounding box failed due to maxlon <= minlon\n");
103        return 1;
104    }
105    if (maxlat <= minlat) {
106        fprintf(stderr, "Bounding box failed due to maxlat <= minlat\n");
107        return 1;
108    }
109    printf("Applying Bounding box: %f,%f to %f,%f\n", minlon,minlat,maxlon,maxlat);
110    return 0;
111}
112
113static int node_wanted(double lat, double lon)
114{
115    if (!bbox)
116        return 1;
117
118    if (lat < minlat || lat > maxlat)
119        return 0;
120    if (lon < minlon || lon > maxlon)
121        return 0;
122    return 1;
123}
124
125static filetypes_t filetype = FILETYPE_NONE;
126static actions_t action = ACTION_NONE;
127
128/* Parses the action="foo" tags in JOSM change files. Obvisouly not useful from osmChange files */
129static actions_t ParseAction( xmlTextReaderPtr reader )
130{
131    if( filetype == FILETYPE_OSMCHANGE || filetype == FILETYPE_PLANETDIFF )
132        return action;
133    actions_t new_action = ACTION_NONE;
134    xmlChar *action = xmlTextReaderGetAttribute( reader, BAD_CAST "action" );
135    if( action == NULL )
136        new_action = ACTION_CREATE;
137    else if( strcmp((char *)action, "modify") == 0 )
138        new_action = ACTION_MODIFY;
139    else if( strcmp((char *)action, "delete") == 0 )
140        new_action = ACTION_DELETE;
141    else
142    {
143        fprintf( stderr, "Unknown value for action: %s\n", (char*)action );
144        exit_nicely();
145    }
146    return new_action;
147}
148
149void StartElement(xmlTextReaderPtr reader, const xmlChar *name)
150{
151    xmlChar *xid, *xlat, *xlon, *xk, *xv, *xrole, *xtype;
152    char *k;
153
154    if (filetype == FILETYPE_NONE)
155    {
156        if (xmlStrEqual(name, BAD_CAST "osm"))
157        {
158            filetype = FILETYPE_OSM;
159            action = ACTION_CREATE;
160        }
161        else if (xmlStrEqual(name, BAD_CAST "osmChange"))
162        {
163            filetype = FILETYPE_OSMCHANGE;
164            action = ACTION_NONE;
165        }
166        else if (xmlStrEqual(name, BAD_CAST "planetdiff"))
167        {
168            filetype = FILETYPE_PLANETDIFF;
169            action = ACTION_NONE;
170        }
171        else
172        {
173            fprintf( stderr, "Unknown XML document type: %s\n", name );
174            exit_nicely();
175        }
176        return;
177    }
178   
179    if (xmlStrEqual(name, BAD_CAST "node")) {
180        xid  = xmlTextReaderGetAttribute(reader, BAD_CAST "id");
181        xlon = xmlTextReaderGetAttribute(reader, BAD_CAST "lon");
182        xlat = xmlTextReaderGetAttribute(reader, BAD_CAST "lat");
183        assert(xid); assert(xlon); assert(xlat);
184
185        osm_id  = strtol((char *)xid, NULL, 10);
186        node_lon = strtod((char *)xlon, NULL);
187        node_lat = strtod((char *)xlat, NULL);
188        action = ParseAction( reader );
189
190        if (osm_id > max_node)
191            max_node = osm_id;
192
193        count_node++;
194        if (count_node%10000 == 0)
195            printStatus();
196
197        xmlFree(xid);
198        xmlFree(xlon);
199        xmlFree(xlat);
200    } else if (xmlStrEqual(name, BAD_CAST "tag")) {
201        xk = xmlTextReaderGetAttribute(reader, BAD_CAST "k");
202        assert(xk);
203
204        /* 'created_by' and 'source' are common and not interesting to mapnik renderer */
205        if (strcmp((char *)xk, "created_by") && strcmp((char *)xk, "source")) {
206            char *p;
207            xv = xmlTextReaderGetAttribute(reader, BAD_CAST "v");
208            assert(xv);
209            k  = (char *)xmlStrdup(xk);
210            while ((p = strchr(k, ' ')))
211                *p = '_';
212
213            addItem(&tags, k, (char *)xv, 0);
214            xmlFree(k);
215            xmlFree(xv);
216        }
217        xmlFree(xk);
218    } else if (xmlStrEqual(name, BAD_CAST "way")) {
219        xid  = xmlTextReaderGetAttribute(reader, BAD_CAST "id");
220        assert(xid);
221        osm_id   = strtol((char *)xid, NULL, 10);
222        action = ParseAction( reader );
223
224        if (osm_id > max_way)
225            max_way = osm_id;
226
227        count_way++;
228        if (count_way%1000 == 0)
229            printStatus();
230
231        nd_count = 0;
232        xmlFree(xid);
233    } else if (xmlStrEqual(name, BAD_CAST "nd")) {
234        xid  = xmlTextReaderGetAttribute(reader, BAD_CAST "ref");
235        assert(xid);
236
237        nds[nd_count++] = strtol( (char *)xid, NULL, 10 );
238
239        if( nd_count >= nd_max )
240          realloc_nodes();
241        xmlFree(xid);
242    } else if (xmlStrEqual(name, BAD_CAST "relation")) {
243        xid  = xmlTextReaderGetAttribute(reader, BAD_CAST "id");
244        assert(xid);
245        osm_id   = strtol((char *)xid, NULL, 10);
246        action = ParseAction( reader );
247
248        if (osm_id > max_rel)
249            max_rel = osm_id;
250
251        count_rel++;
252        if (count_rel%1000 == 0)
253            printStatus();
254
255        member_count = 0;
256        xmlFree(xid);
257    } else if (xmlStrEqual(name, BAD_CAST "member")) {
258        xrole = xmlTextReaderGetAttribute(reader, BAD_CAST "role");
259        assert(xrole);
260
261        xtype = xmlTextReaderGetAttribute(reader, BAD_CAST "type");
262        assert(xtype);
263
264        xid  = xmlTextReaderGetAttribute(reader, BAD_CAST "ref");
265        assert(xid);
266
267        members[member_count].id   = strtol( (char *)xid, NULL, 0 );
268        members[member_count].role = strdup( (char *)xrole );
269       
270        /* Currently we are only interested in 'way' members since these form polygons with holes */
271        if (xmlStrEqual(xtype, BAD_CAST "way"))
272            members[member_count].type = OSMTYPE_WAY;
273        if (xmlStrEqual(xtype, BAD_CAST "node"))
274            members[member_count].type = OSMTYPE_NODE;
275        if (xmlStrEqual(xtype, BAD_CAST "relation"))
276            members[member_count].type = OSMTYPE_RELATION;
277        member_count++;
278
279        if( member_count >= member_max )
280          realloc_members();
281        xmlFree(xid);
282        xmlFree(xrole);
283        xmlFree(xtype);
284    } else if (xmlStrEqual(name, BAD_CAST "add") ||
285               xmlStrEqual(name, BAD_CAST "create")) {
286        action = ACTION_CREATE;
287        action = ACTION_MODIFY; // Turns all creates into modifies, makes it resiliant against inconsistant snapshots.
288    } else if (xmlStrEqual(name, BAD_CAST "modify")) {
289        action = ACTION_MODIFY;
290    } else if (xmlStrEqual(name, BAD_CAST "delete")) {
291        action = ACTION_DELETE;
292    } else if (xmlStrEqual(name, BAD_CAST "bound")) {
293        /* ignore */
294    } else if (xmlStrEqual(name, BAD_CAST "bounds")) {
295        /* ignore */
296    } else {
297        fprintf(stderr, "%s: Unknown element name: %s\n", __FUNCTION__, name);
298    }
299}
300
301static void resetMembers()
302{
303  int i;
304  for(i=0; i<member_count; i++ )
305    free( members[i].role );
306}
307
308void EndElement(const xmlChar *name)
309{
310    if (xmlStrEqual(name, BAD_CAST "node")) {
311        if (node_wanted(node_lat, node_lon)) {
312            reproject(&node_lat, &node_lon);
313            if( action == ACTION_CREATE )
314                out->node_add(osm_id, node_lat, node_lon, &tags);
315            else if( action == ACTION_MODIFY )
316                out->node_modify(osm_id, node_lat, node_lon, &tags);
317            else if( action == ACTION_DELETE )
318                out->node_delete(osm_id);
319            else
320            {
321                fprintf( stderr, "Don't know action for node %d\n", osm_id );
322                exit_nicely();
323            }
324        }
325        resetList(&tags);
326    } else if (xmlStrEqual(name, BAD_CAST "way")) {
327        if( action == ACTION_CREATE )
328            out->way_add(osm_id, nds, nd_count, &tags );
329        else if( action == ACTION_MODIFY )
330            out->way_modify(osm_id, nds, nd_count, &tags );
331        else if( action == ACTION_DELETE )
332            out->way_delete(osm_id);
333        else
334        {
335            fprintf( stderr, "Don't know action for way %d\n", osm_id );
336            exit_nicely();
337        }
338        resetList(&tags);
339    } else if (xmlStrEqual(name, BAD_CAST "relation")) {
340        if( action == ACTION_CREATE )
341            out->relation_add(osm_id, members, member_count, &tags);
342        else if( action == ACTION_MODIFY )
343            out->relation_modify(osm_id, members, member_count, &tags);
344        else if( action == ACTION_DELETE )
345            out->relation_delete(osm_id);
346        else
347        {
348            fprintf( stderr, "Don't know action for relation %d\n", osm_id );
349            exit_nicely();
350        }
351        resetList(&tags);
352        resetMembers();
353    } else if (xmlStrEqual(name, BAD_CAST "tag")) {
354        /* ignore */
355    } else if (xmlStrEqual(name, BAD_CAST "nd")) {
356        /* ignore */
357    } else if (xmlStrEqual(name, BAD_CAST "member")) {
358        /* ignore */
359    } else if (xmlStrEqual(name, BAD_CAST "osm")) {
360        printStatus();
361        filetype = FILETYPE_NONE;
362    } else if (xmlStrEqual(name, BAD_CAST "osmChange")) {
363        printStatus();
364        filetype = FILETYPE_NONE;
365    } else if (xmlStrEqual(name, BAD_CAST "planetdiff")) {
366        printStatus();
367        filetype = FILETYPE_NONE;
368    } else if (xmlStrEqual(name, BAD_CAST "bound")) {
369        /* ignore */
370    } else if (xmlStrEqual(name, BAD_CAST "bounds")) {
371        /* ignore */
372    } else if (xmlStrEqual(name, BAD_CAST "add")) {
373        action = ACTION_NONE;
374    } else if (xmlStrEqual(name, BAD_CAST "create")) {
375        action = ACTION_NONE;
376    } else if (xmlStrEqual(name, BAD_CAST "modify")) {
377        action = ACTION_NONE;
378    } else if (xmlStrEqual(name, BAD_CAST "delete")) {
379        action = ACTION_NONE;
380    } else {
381        fprintf(stderr, "%s: Unknown element name: %s\n", __FUNCTION__, name);
382    }
383}
384
385static void processNode(xmlTextReaderPtr reader) {
386    xmlChar *name;
387    name = xmlTextReaderName(reader);
388    if (name == NULL)
389        name = xmlStrdup(BAD_CAST "--");
390       
391    switch(xmlTextReaderNodeType(reader)) {
392        case XML_READER_TYPE_ELEMENT:
393            StartElement(reader, name);
394            if (xmlTextReaderIsEmptyElement(reader))
395                EndElement(name); /* No end_element for self closing tags! */
396            break;
397        case XML_READER_TYPE_END_ELEMENT:
398            EndElement(name);
399            break;
400        case XML_READER_TYPE_SIGNIFICANT_WHITESPACE:
401            /* Ignore */
402            break;
403        default:
404            fprintf(stderr, "Unknown node type %d\n", xmlTextReaderNodeType(reader));
405            break;
406    }
407
408    xmlFree(name);
409}
410
411static int streamFile(char *filename, int sanitize) {
412    xmlTextReaderPtr reader;
413    int ret = 0;
414
415    if (sanitize)
416        reader = sanitizerOpen(filename);
417    else
418        reader = inputUTF8(filename);
419
420    if (reader != NULL) {
421        ret = xmlTextReaderRead(reader);
422        while (ret == 1) {
423            processNode(reader);
424            ret = xmlTextReaderRead(reader);
425        }
426
427        if (ret != 0) {
428            fprintf(stderr, "%s : failed to parse\n", filename);
429            return ret;
430        }
431
432        xmlFreeTextReader(reader);
433    } else {
434        fprintf(stderr, "Unable to open %s\n", filename);
435        return 1;
436    }
437    return 0;
438}
439
440void exit_nicely(void)
441{
442    fprintf(stderr, "Error occurred, cleaning up\n");
443    out->cleanup();
444    exit(1);
445}
446 
447static void usage(const char *arg0)
448{
449    int i;
450    const char *name = basename(arg0);
451
452    fprintf(stderr, "Usage:\n");
453    fprintf(stderr, "\t%s [options] planet.osm\n", name);
454    fprintf(stderr, "\t%s [options] planet.osm.{gz,bz2}\n", name);
455    fprintf(stderr, "\t%s [options] file1.osm file2.osm file3.osm\n", name);
456    fprintf(stderr, "\nThis will import the data from the OSM file(s) into a PostgreSQL database\n");
457    fprintf(stderr, "suitable for use by the Mapnik renderer\n");
458    fprintf(stderr, "\nOptions:\n");
459    fprintf(stderr, "   -a|--append\t\tAdd the OSM file into the database without removing\n");
460    fprintf(stderr, "              \t\texisting data.\n");
461    fprintf(stderr, "   -b|--bbox\t\tApply a bounding box filter on the imported data\n");
462    fprintf(stderr, "              \t\tMust be specified as: minlon,minlat,maxlon,maxlat\n");
463    fprintf(stderr, "              \t\te.g. --bbox -0.5,51.25,0.5,51.75\n");
464    fprintf(stderr, "   -c|--create\t\tRemove existing data from the database. This is the \n");
465    fprintf(stderr, "              \t\tdefault if --append is not specified.\n");
466    fprintf(stderr, "   -d|--database\tThe name of the PostgreSQL database to connect\n");
467    fprintf(stderr, "                \tto (default: gis).\n");
468    fprintf(stderr, "   -l|--latlong\t\tStore data in degrees of latitude & longitude.\n");
469    fprintf(stderr, "   -m|--merc\t\tStore data in proper spherical mercator (default)\n");
470    fprintf(stderr, "   -M|--oldmerc\t\tStore data in the legacy OSM mercator format\n");
471    fprintf(stderr, "   -E|--proj num\tUse projection EPSG:num\n");
472    fprintf(stderr, "   -u|--utf8-sanitize\tRepair bad UTF8 input data (present in planet\n");
473    fprintf(stderr, "                \tdumps prior to August 2007). Adds about 10%% overhead.\n");
474    fprintf(stderr, "   -p|--prefix\t\tPrefix for table names (default planet_osm)\n");
475    fprintf(stderr, "   -s|--slim\t\tStore temporary data in the database. This greatly\n");
476    fprintf(stderr, "            \t\treduces the RAM usage but is much slower.\n");
477    fprintf(stderr, "   -S|--style\t\tLocation of the style file. Defaults to ./default.style\n");
478    fprintf(stderr, "   -C|--cache\t\tOnly for slim mode: Use upto this many MB for caching nodes\n");
479    fprintf(stderr, "             \t\tDefault is 800\n");
480    fprintf(stderr, "   -U|--username\tPostgresql user name.\n");
481    fprintf(stderr, "   -W|--password\tForce password prompt.\n");
482    fprintf(stderr, "   -H|--host\t\tDatabase server hostname or socket location.\n");
483    fprintf(stderr, "   -P|--port\t\tDatabase server port.\n");
484    fprintf(stderr, "   -e|--expire-tiles [min_zoom-]max_zoom\tCreate a tile expiry list.\n");
485    fprintf(stderr, "   -o|--expire-output filename\tOutput filename for expired tiles list.\n");
486    fprintf(stderr, "   -h|--help\t\tHelp information.\n");
487    fprintf(stderr, "   -v|--verbose\t\tVerbose output.\n");
488    fprintf(stderr, "\n");
489    if(!verbose)
490    {
491        fprintf(stderr, "Add -v to display supported projections.\n");
492        fprintf(stderr, "Use -E to access any espg projections (usually in /usr/share/proj/epsg)\n" );
493    }
494    else
495    {
496        fprintf(stderr, "Supported projections:\n" );
497        for(i=0; i<PROJ_COUNT; i++ )
498        {
499            fprintf( stderr, "%-20s(%2s) SRS:%6d %s\n", 
500                    Projection_Info[i].descr, Projection_Info[i].option, Projection_Info[i].srs, Projection_Info[i].proj4text);
501        }
502    }
503}
504
505const char *build_conninfo(const char *db, const char *username, const char *password, const char *host, const char *port)
506{
507    static char conninfo[1024];
508
509    conninfo[0]='\0';
510    strcat(conninfo, "dbname='");
511    strcat(conninfo, db);
512    strcat(conninfo, "'");
513
514    if (username) {
515        strcat(conninfo, " user='");
516        strcat(conninfo, username);
517        strcat(conninfo, "'");
518    }
519    if (password) {
520        strcat(conninfo, " password='");
521        strcat(conninfo, password);
522        strcat(conninfo, "'");
523    }
524    if (host) {
525        strcat(conninfo, " host='");
526        strcat(conninfo, host);
527        strcat(conninfo, "'");
528    }
529    if (port) {
530        strcat(conninfo, " port='");
531        strcat(conninfo, port);
532        strcat(conninfo, "'");
533    }
534
535    return conninfo;
536}
537
538static void realloc_nodes()
539{
540  if( nd_max == 0 )
541    nd_max = INIT_MAX_NODES;
542  else
543    nd_max <<= 1;
544   
545  nds = realloc( nds, nd_max * sizeof( nds[0] ) );
546  if( !nds )
547  {
548    fprintf( stderr, "Failed to expand node list to %d\n", nd_max );
549    exit_nicely();
550  }
551}
552
553static void realloc_members()
554{
555  if( member_max == 0 )
556    member_max = INIT_MAX_NODES;
557  else
558    member_max <<= 1;
559   
560  members = realloc( members, member_max * sizeof( members[0] ) );
561  if( !members )
562  {
563    fprintf( stderr, "Failed to expand member list to %d\n", member_max );
564    exit_nicely();
565  }
566}
567
568int main(int argc, char *argv[])
569{
570    int append=0;
571    int create=0;
572    int slim=0;
573    int sanitize=0;
574    int pass_prompt=0;
575    int projection = PROJ_SPHERE_MERC;
576    int expire_tiles_zoom = -1;
577    int expire_tiles_zoom_min = -1;
578    const char *expire_tiles_filename = "dirty_tiles";
579    const char *db = "gis";
580    const char *username=NULL;
581    const char *host=NULL;
582    const char *password=NULL;
583    const char *port = "5432";
584    const char *conninfo = NULL;
585    const char *prefix = "planet_osm";
586    const char *style = "./default.style";
587    const char *temparg;
588    int cache = 800;
589    struct output_options options;
590    PGconn *sql_conn;
591
592    fprintf(stderr, "osm2pgsql SVN version %s $Rev: 13668 $ \n\n", VERSION);
593
594    while (1) {
595        int c, option_index = 0;
596        static struct option long_options[] = {
597            {"append",   0, 0, 'a'},
598            {"bbox",     1, 0, 'b'},
599            {"create",   0, 0, 'c'},
600            {"database", 1, 0, 'd'},
601            {"latlong",  0, 0, 'l'},
602            {"verbose",  0, 0, 'v'},
603            {"slim",     0, 0, 's'},
604            {"prefix",   1, 0, 'p'},
605            {"proj",     1, 0, 'E'},
606            {"merc",     0, 0, 'm'},
607            {"oldmerc",  0, 0, 'M'},
608            {"utf8-sanitize", 0, 0, 'u'},
609            {"cache",    1, 0, 'C'},
610            {"username", 1, 0, 'U'},
611            {"password", 0, 0, 'W'},
612            {"host",     1, 0, 'H'},
613            {"port",     1, 0, 'P'},
614            {"help",     0, 0, 'h'},
615            {"style",    1, 0, 'S'},
616            {"expire-tiles", 1, 0, 'e'},
617            {"expire-output", 1, 0, 'o'},
618            {0, 0, 0, 0}
619        };
620
621        c = getopt_long (argc, argv, "ab:cd:hlmMp:suvU:WH:P:E:C:S:e:o:", long_options, &option_index);
622        if (c == -1)
623            break;
624
625        switch (c) {
626            case 'a': append=1;   break;
627            case 'b': bbox=optarg; break;
628            case 'c': create=1;   break;
629            case 'v': verbose=1;  break;
630            case 's': slim=1;     break;
631            case 'u': sanitize=1; break;
632            case 'l': projection=PROJ_LATLONG;  break;
633            case 'm': projection=PROJ_SPHERE_MERC; break;
634            case 'M': projection=PROJ_MERC; break;
635            case 'E': projection=-atoi(optarg); break;
636            case 'p': prefix=optarg; break;
637            case 'd': db=optarg;  break;
638            case 'C': cache = atoi(optarg); break;
639            case 'U': username=optarg; break;
640            case 'W': pass_prompt=1; break;
641            case 'H': host=optarg; break;
642            case 'P': port=optarg; break;
643            case 'S': style=optarg; break;
644            case 'e':
645                expire_tiles_zoom_min = atoi(optarg);
646                temparg = strchr(optarg, '-');
647                if (temparg) expire_tiles_zoom = atoi(temparg + 1);
648                if (expire_tiles_zoom < expire_tiles_zoom_min) expire_tiles_zoom = expire_tiles_zoom_min;
649                break;
650            case 'o': expire_tiles_filename=optarg; break;
651
652            case 'h':
653            case '?':
654            default:
655                usage(argv[0]);
656                exit(EXIT_FAILURE);
657        }
658    }
659
660    if (argc == optind) {  // No non-switch arguments
661        usage(argv[0]);
662        exit(EXIT_FAILURE);
663    }
664
665    if (append && create) {
666        fprintf(stderr, "Error: --append and --create options can not be used at the same time!\n");
667        exit(EXIT_FAILURE);
668    }
669
670    if ((expire_tiles_zoom >= 0) && (projection != PROJ_SPHERE_MERC)) {
671        fprintf(stderr, "Error: --expire-tiles can only be used with spherical mercator projection!\n");
672        exit(EXIT_FAILURE);
673    }
674   
675    if( cache < 0 ) cache = 0;
676
677    if (pass_prompt)
678        password = simple_prompt("Password:", 100, 0);
679
680    conninfo = build_conninfo(db, username, password, host, port);
681    sql_conn = PQconnectdb(conninfo);
682    if (PQstatus(sql_conn) != CONNECTION_OK) {
683        fprintf(stderr, "Connection to database failed: %s\n", PQerrorMessage(sql_conn));
684        exit(EXIT_FAILURE);
685    }
686    PQfinish(sql_conn);
687
688    text_init();
689    initList(&tags);
690
691    count_node = max_node = 0;
692    count_way = max_way = 0;
693    count_rel = max_rel = 0;
694
695    LIBXML_TEST_VERSION
696
697    project_init(projection);
698    fprintf(stderr, "Using projection SRS %d (%s)\n", 
699        project_getprojinfo()->srs, project_getprojinfo()->descr );
700
701    if (parse_bbox())
702        return 1;
703
704    options.conninfo = conninfo;
705    options.prefix = prefix;
706    options.append = append;
707    options.slim = slim;
708    options.projection = project_getprojinfo()->srs;
709    options.scale = (projection==PROJ_LATLONG)?10000000:100;
710    options.mid = slim ? &mid_pgsql : &mid_ram;
711    options.cache = cache;
712    options.style = style;
713    options.expire_tiles_zoom = expire_tiles_zoom;
714    options.expire_tiles_zoom_min = expire_tiles_zoom_min;
715    options.expire_tiles_filename = expire_tiles_filename;
716    out = &out_pgsql;
717
718    out->start(&options);
719
720    realloc_nodes();
721    realloc_members();
722
723    while (optind < argc) {
724        fprintf(stderr, "\nReading in file: %s\n", argv[optind]);
725        if (streamFile(argv[optind], sanitize) != 0)
726            exit_nicely();
727        optind++;
728    }
729
730    xmlCleanupParser();
731    xmlMemoryDump();
732   
733    if (count_node || count_way || count_rel) {
734        fprintf(stderr, "\n");
735        fprintf(stderr, "Node stats: total(%d), max(%d)\n", count_node, max_node);
736        fprintf(stderr, "Way stats: total(%d), max(%d)\n", count_way, max_way);
737        fprintf(stderr, "Relation stats: total(%d), max(%d)\n", count_rel, max_rel);
738    }
739    out->stop();
740   
741    free(nds);
742    free(members);
743
744    project_exit();
745    text_exit();
746    fprintf(stderr, "\n");
747
748    return 0;
749}
Note: See TracBrowser for help on using the repository browser.