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

Last change on this file since 26665 was 26665, checked in by apmon, 8 years ago

[osm2pgsql] allocate node cache in one big chunk instead of small pieces

This is a patch by Hartmut Holzgraefe ( https://github.com/hholzgra/osm2pgsql/commit/9f05f1b925751eca657bbd7fa6cbac937f7756d2 ),
adapted to add a command-line switch to revert to the old behavior

Allocating the node cache in small chunks causes the memory not to be returned to the operating system after it is free()ed,
as it is using a different internal allocation strategy (not mmap based).

With the new (default) behavior the entire node cache is allocated in one single malloc call.

At least on Linux, physical memory is still only allocated in chunks when it is needed and only virtual memory is reserved in one chunk.
So apart from the correct freeing of memory during the indexing stage, behavior doesn't change.
Other operating systems might behave differently though, which is why the old strategy can still be selected via a command line switch.

  • Property svn:keywords set to Rev
File size: 23.8 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#include "config.h"
27
28#define _GNU_SOURCE
29#include <stdio.h>
30#include <unistd.h>
31#include <stdlib.h>
32#include <string.h>
33#include <assert.h>
34#include <getopt.h>
35#include <libgen.h>
36#include <time.h>
37
38#include <libpq-fe.h>
39
40#include <libxml/xmlstring.h>
41#include <libxml/xmlreader.h>
42
43#include "osmtypes.h"
44#include "build_geometry.h"
45#include "middle-pgsql.h"
46#include "middle-ram.h"
47#include "output-pgsql.h"
48#include "output-gazetteer.h"
49#include "output-null.h"
50#include "sanitizer.h"
51#include "reprojection.h"
52#include "text-tree.h"
53#include "input.h"
54#include "sprompt.h"
55#include "parse-xml2.h"
56#include "parse-primitive.h"
57
58#ifdef BUILD_READER_PBF
59#  include "parse-pbf.h"
60#endif
61
62#define INIT_MAX_MEMBERS 64
63#define INIT_MAX_NODES  4096
64
65int verbose;
66
67// Data structure carrying all parsing related variables
68static struct osmdata_t osmdata = { 
69  .filetype = FILETYPE_NONE,
70  .action   = ACTION_NONE,
71  .bbox     = NULL
72};
73
74
75static int parse_bbox(struct osmdata_t *osmdata)
76{
77    int n;
78
79    if (!osmdata->bbox)
80        return 0;
81
82    n = sscanf(osmdata->bbox, "%lf,%lf,%lf,%lf", &(osmdata->minlon), &(osmdata->minlat), &(osmdata->maxlon), &(osmdata->maxlat));
83    if (n != 4) {
84        fprintf(stderr, "Bounding box must be specified like: minlon,minlat,maxlon,maxlat\n");
85        return 1;
86    }
87    if (osmdata->maxlon <= osmdata->minlon) {
88        fprintf(stderr, "Bounding box failed due to maxlon <= minlon\n");
89        return 1;
90    }
91    if (osmdata->maxlat <= osmdata->minlat) {
92        fprintf(stderr, "Bounding box failed due to maxlat <= minlat\n");
93        return 1;
94    }
95    printf("Applying Bounding box: %f,%f to %f,%f\n", osmdata->minlon, osmdata->minlat, osmdata->maxlon, osmdata->maxlat);
96    return 0;
97}
98
99
100
101void exit_nicely()
102{
103    fprintf(stderr, "Error occurred, cleaning up\n");
104    osmdata.out->cleanup();
105    exit(1);
106}
107 
108static void short_usage(char *arg0)
109{
110    const char *name = basename(arg0);
111
112    fprintf(stderr, "Usage error. For further information see:\n");
113    fprintf(stderr, "\t%s -h|--help\n", name);
114}
115
116static void long_usage(char *arg0)
117{
118    int i;
119    const char *name = basename(arg0);
120
121    printf("Usage:\n");
122    printf("\t%s [options] planet.osm\n", name);
123    printf("\t%s [options] planet.osm.{gz,bz2}\n", name);
124    printf("\t%s [options] file1.osm file2.osm file3.osm\n", name);
125    printf("\nThis will import the data from the OSM file(s) into a PostgreSQL database\n");
126    printf("suitable for use by the Mapnik renderer\n");
127    printf("\nOptions:\n");
128    printf("   -a|--append\t\tAdd the OSM file into the database without removing\n");
129    printf("              \t\texisting data.\n");
130    printf("   -b|--bbox\t\tApply a bounding box filter on the imported data\n");
131    printf("              \t\tMust be specified as: minlon,minlat,maxlon,maxlat\n");
132    printf("              \t\te.g. --bbox -0.5,51.25,0.5,51.75\n");
133    printf("   -c|--create\t\tRemove existing data from the database. This is the \n");
134    printf("              \t\tdefault if --append is not specified.\n");
135    printf("   -d|--database\tThe name of the PostgreSQL database to connect\n");
136    printf("              \t\tto (default: gis).\n");
137    printf("   -i|--tablespace-index\tThe name of the PostgreSQL tablespace where\n");
138    printf("              \t\tall indexes will be created.\n");
139    printf("              \t\tThe following options allow more fine-grained control:\n");
140    printf("      --tablespace-main-data \ttablespace for main tables\n");
141    printf("      --tablespace-main-index\ttablespace for main table indexes\n");
142    printf("      --tablespace-slim-data \ttablespace for slim mode tables\n");
143    printf("      --tablespace-slim-index\ttablespace for slim mode indexes\n");
144    printf("              \t\t(if unset, use db's default; -i is equivalent to setting\n");
145    printf("              \t\t--tablespace-main-index and --tablespace-slim-index)\n");
146    printf("   -l|--latlong\t\tStore data in degrees of latitude & longitude.\n");
147    printf("   -m|--merc\t\tStore data in proper spherical mercator (default)\n");
148    printf("   -M|--oldmerc\t\tStore data in the legacy OSM mercator format\n");
149    printf("   -E|--proj num\tUse projection EPSG:num\n");
150    printf("   -u|--utf8-sanitize\tRepair bad UTF8 input data (present in planet\n");
151    printf("                \tdumps prior to August 2007). Adds about 10%% overhead.\n");
152    printf("   -p|--prefix\t\tPrefix for table names (default planet_osm)\n");
153    printf("   -s|--slim\t\tStore temporary data in the database. This greatly\n");
154    printf("            \t\treduces the RAM usage but is much slower.\n");
155
156    if (sizeof(int*) == 4) {
157        printf("            \t\tYou are running this on 32bit system, so at most\n");
158        printf("            \t\t3GB of RAM will be used. If you encounter unexpected\n");
159        printf("            \t\texceptions during import, you should try this switch.\n");
160    }
161   
162    printf("   -S|--style\t\tLocation of the style file. Defaults to " OSM2PGSQL_DATADIR "/default.style\n");
163    printf("   -C|--cache\t\tOnly for slim mode: Use upto this many MB for caching nodes\n");
164    printf("             \t\tDefault is 800\n");
165    printf("   -U|--username\tPostgresql user name\n");
166    printf("             \t\tpassword can be given by prompt or PGPASS environment variable.\n");
167    printf("   -W|--password\tForce password prompt.\n");
168    printf("   -H|--host\t\tDatabase server hostname or socket location.\n");
169    printf("   -P|--port\t\tDatabase server port.\n");
170    printf("   -e|--expire-tiles [min_zoom-]max_zoom\tCreate a tile expiry list.\n");
171    printf("   -o|--expire-output filename\tOutput filename for expired tiles list.\n");
172    printf("   -r|--input-reader\tInput frontend.\n");
173    printf("              \t\tlibxml2   - Parse XML using libxml2. (default)\n");
174    printf("              \t\tprimitive - Primitive XML parsing.\n");
175#ifdef BUILD_READER_PBF
176    printf("              \t\tpbf       - OSM binary format.\n");
177#endif
178    printf("   -O|--output\t\tOutput backend.\n");
179    printf("              \t\tpgsql - Output to a PostGIS database. (default)\n");
180    printf("              \t\tgazetteer - Output to a PostGIS database suitable for gazetteer\n");
181    printf("              \t\tnull  - No output. Useful for testing.\n");
182    printf("   -x|--extra-attributes\n");
183    printf("              \t\tInclude attributes for each object in the database.\n");
184    printf("              \t\tThis includes the username, userid, timestamp and version.\n"); 
185    printf("              \t\tNote: this option also requires additional entries in your style file.\n"); 
186    printf("   -k|--hstore\t\tAdd tags without column to an additional hstore (key/value) column to postgresql tables\n");
187    printf("   -j|--hstore-all\tAdd all tags to an additional hstore (key/value) column in postgresql tables\n");
188    printf("   -z|--hstore-column\tAdd an additional hstore (key/value) column containing all tags\n");
189    printf("                     \tthat start with the specified string, eg --hstore-column \"name:\" will\n");
190    printf("                     \tproduce an extra hstore column that contains all name:xx tags\n");
191    printf("   -G|--multi-geometry\tGenerate multi-geometry features in postgresql tables.\n");
192    printf("   -K|--keep-coastlines\tKeep coastline data rather than filtering it out.\n");
193    printf("              \t\tBy default natural=coastline tagged data will be discarded based on the\n");
194    printf("              \t\tassumption that post-processed Coastline Checker shapefiles will be used.\n");
195    printf("   -I|--disable-parallel-indexing\t\tDisable indexing all tables concurrently.\n");
196    printf("      --alloc-chunk\t\tAllocate node cache in chunks rather than as a whole.\n");
197    printf("   -h|--help\t\tHelp information.\n");
198    printf("   -v|--verbose\t\tVerbose output.\n");
199    printf("\n");
200    if(!verbose)
201    {
202        printf("Add -v to display supported projections.\n");
203        printf("Use -E to access any espg projections (usually in /usr/share/proj/epsg)\n" );
204    }
205    else
206    {
207        printf("Supported projections:\n" );
208        for(i=0; i<PROJ_COUNT; i++ )
209        {
210            printf( "%-20s(%2s) SRS:%6d %s\n", 
211                    Projection_Info[i].descr, Projection_Info[i].option, Projection_Info[i].srs, Projection_Info[i].proj4text);
212        }
213    }
214}
215
216const char *build_conninfo(const char *db, const char *username, const char *password, const char *host, const char *port)
217{
218    static char conninfo[1024];
219
220    conninfo[0]='\0';
221    strcat(conninfo, "dbname='");
222    strcat(conninfo, db);
223    strcat(conninfo, "'");
224
225    if (username) {
226        strcat(conninfo, " user='");
227        strcat(conninfo, username);
228        strcat(conninfo, "'");
229    }
230    if (password) {
231        strcat(conninfo, " password='");
232        strcat(conninfo, password);
233        strcat(conninfo, "'");
234    }
235    if (host) {
236        strcat(conninfo, " host='");
237        strcat(conninfo, host);
238        strcat(conninfo, "'");
239    }
240    if (port) {
241        strcat(conninfo, " port='");
242        strcat(conninfo, port);
243        strcat(conninfo, "'");
244    }
245
246    return conninfo;
247}
248
249void realloc_nodes(struct osmdata_t *osmdata)
250{
251  if( osmdata->nd_max == 0 )
252    osmdata->nd_max = INIT_MAX_NODES;
253  else
254    osmdata->nd_max <<= 1;
255   
256  osmdata->nds = realloc( osmdata->nds, osmdata->nd_max * sizeof( osmdata->nds[0] ) );
257  if( !osmdata->nds )
258  {
259    fprintf( stderr, "Failed to expand node list to %d\n", osmdata->nd_max );
260    exit_nicely();
261  }
262}
263
264void realloc_members(struct osmdata_t *osmdata)
265{
266  if( osmdata->member_max == 0 )
267    osmdata->member_max = INIT_MAX_NODES;
268  else
269    osmdata->member_max <<= 1;
270   
271  osmdata->members = realloc( osmdata->members, osmdata->member_max * sizeof( osmdata->members[0] ) );
272  if( !osmdata->members )
273  {
274    fprintf( stderr, "Failed to expand member list to %d\n", osmdata->member_max );
275    exit_nicely();
276  }
277}
278
279void resetMembers(struct osmdata_t *osmdata)
280{
281  for(unsigned i = 0; i < osmdata->member_count; i++ )
282    free( osmdata->members[i].role );
283}
284
285void printStatus(struct osmdata_t *osmdata)
286{
287    time_t now;
288    time(&now);
289    time_t end_nodes = osmdata->start_way > 0 ? osmdata->start_way : now;
290    time_t end_way = osmdata->start_rel > 0 ? osmdata->start_rel : now;
291    time_t end_rel =  now;
292    fprintf(stderr, "\rProcessing: Node(%" PRIdOSMID "k %.1fk/s) Way(%" PRIdOSMID "k %.2fk/s) Relation(%" PRIdOSMID " %.2f/s)",
293            osmdata->count_node/1000,
294            (double)osmdata->count_node/1000.0/((int)(end_nodes - osmdata->start_node) > 0 ? (double)(end_nodes - osmdata->start_node) : 1.0),
295            osmdata->count_way/1000,
296            osmdata->count_way > 0 ? (double)osmdata->count_way/1000.0/
297            ((double)(end_way - osmdata->start_way) > 0.0 ? (double)(end_way - osmdata->start_way) : 1.0) : 0.0,
298            osmdata->count_rel,
299            osmdata->count_rel > 0 ? (double)osmdata->count_rel/
300            ((double)(end_rel - osmdata->start_rel) > 0.0 ? (double)(end_rel - osmdata->start_rel) : 1.0) : 0.0);
301}
302
303int node_wanted(struct osmdata_t *osmdata, double lat, double lon)
304{
305    if (!osmdata->bbox)
306        return 1;
307
308    if (lat < osmdata->minlat || lat > osmdata->maxlat)
309        return 0;
310    if (lon < osmdata->minlon || lon > osmdata->maxlon)
311        return 0;
312    return 1;
313}
314
315int main(int argc, char *argv[])
316{
317    int append=0;
318    int create=0;
319    int slim=0;
320    int sanitize=0;
321    int long_usage_bool=0;
322    int pass_prompt=0;
323    int projection = PROJ_SPHERE_MERC;
324    int expire_tiles_zoom = -1;
325    int expire_tiles_zoom_min = -1;
326    int enable_hstore = HSTORE_NONE;
327    int enable_multi = 0;
328    int parallel_indexing = 1;
329    int alloc_chunkwise = 0;
330    const char *expire_tiles_filename = "dirty_tiles";
331    const char *db = "gis";
332    const char *username=NULL;
333    const char *host=NULL;
334    const char *password=NULL;
335    const char *port = "5432";
336    const char *tblsmain_index = NULL; // no default TABLESPACE for index on main tables
337    const char *tblsmain_data = NULL;  // no default TABLESPACE for main tables
338    const char *tblsslim_index = NULL; // no default TABLESPACE for index on slim mode tables
339    const char *tblsslim_data = NULL;  // no default TABLESPACE for slim mode tables
340    const char *conninfo = NULL;
341    const char *prefix = "planet_osm";
342    const char *style = OSM2PGSQL_DATADIR "/default.style";
343    const char *temparg;
344    const char *output_backend = "pgsql";
345    const char *input_reader = "auto";
346    const char **hstore_columns = NULL;
347    int n_hstore_columns = 0;
348    int keep_coastlines=0;
349    int cache = 800;
350    struct output_options options;
351    PGconn *sql_conn;
352   
353    int (*streamFile)(char *, int, struct osmdata_t *);
354
355    printf("osm2pgsql SVN version %s (%lubit id space)\n\n", VERSION, 8 * sizeof(osmid_t));
356
357    while (1) {
358        int c, option_index = 0;
359        static struct option long_options[] = {
360            {"append",   0, 0, 'a'},
361            {"bbox",     1, 0, 'b'},
362            {"create",   0, 0, 'c'},
363            {"database", 1, 0, 'd'},
364            {"latlong",  0, 0, 'l'},
365            {"verbose",  0, 0, 'v'},
366            {"slim",     0, 0, 's'},
367            {"prefix",   1, 0, 'p'},
368            {"proj",     1, 0, 'E'},
369            {"merc",     0, 0, 'm'},
370            {"oldmerc",  0, 0, 'M'},
371            {"utf8-sanitize", 0, 0, 'u'},
372            {"cache",    1, 0, 'C'},
373            {"username", 1, 0, 'U'},
374            {"password", 0, 0, 'W'},
375            {"host",     1, 0, 'H'},
376            {"port",     1, 0, 'P'},
377            {"tablespace-index", 1, 0, 'i'},
378            {"tablespace-slim-data", 1, 0, 200},
379            {"tablespace-slim-index", 1, 0, 201},
380            {"tablespace-main-data", 1, 0, 202},
381            {"tablespace-main-index", 1, 0, 203},
382            {"help",     0, 0, 'h'},
383            {"style",    1, 0, 'S'},
384            {"expire-tiles", 1, 0, 'e'},
385            {"expire-output", 1, 0, 'o'},
386            {"output",   1, 0, 'O'},
387            {"extra-attributes", 0, 0, 'x'},
388            {"hstore", 0, 0, 'k'},
389            {"hstore-all", 0, 0, 'j'},
390            {"hstore-column", 1, 0, 'z'},
391            {"multi-geometry", 0, 0, 'G'},
392            {"keep-coastlines", 0, 0, 'K'},
393            {"input-reader", 1, 0, 'r'},
394            {"version", 0, 0, 'V'},
395            {"disable-parallel-indexing", 0, 0, 'I'},
396            {"alloc-chunk", 0, 0, 204},
397            {0, 0, 0, 0}
398        };
399
400        c = getopt_long (argc, argv, "ab:cd:KhlmMp:suvU:WH:P:i:IE:C:S:e:o:O:xkjGz:r:V", long_options, &option_index);
401        if (c == -1)
402            break;
403
404        switch (c) {
405            case 'a': append=1;   break;
406            case 'b': osmdata.bbox=optarg; break;
407            case 'c': create=1;   break;
408            case 'v': verbose=1;  break;
409            case 's': slim=1;     break;
410            case 'K': keep_coastlines=1;     break;
411            case 'u': sanitize=1; break;
412            case 'l': projection=PROJ_LATLONG;  break;
413            case 'm': projection=PROJ_SPHERE_MERC; break;
414            case 'M': projection=PROJ_MERC; break;
415            case 'E': projection=-atoi(optarg); break;
416            case 'p': prefix=optarg; break;
417            case 'd': db=optarg;  break;
418            case 'C': cache = atoi(optarg); break;
419            case 'U': username=optarg; break;
420            case 'W': pass_prompt=1; break;
421            case 'H': host=optarg; break;
422            case 'P': port=optarg; break;
423            case 'S': style=optarg; break;
424            case 'i': tblsmain_index=tblsslim_index=optarg; break;
425            case 200: tblsslim_data=optarg; break;   
426            case 201: tblsslim_index=optarg; break;   
427            case 202: tblsmain_data=optarg; break;   
428            case 203: tblsmain_index=optarg; break;   
429            case 'e':
430                expire_tiles_zoom_min = atoi(optarg);
431                temparg = strchr(optarg, '-');
432                if (temparg) expire_tiles_zoom = atoi(temparg + 1);
433                if (expire_tiles_zoom < expire_tiles_zoom_min) expire_tiles_zoom = expire_tiles_zoom_min;
434                break;
435            case 'o': expire_tiles_filename=optarg; break;
436            case 'O': output_backend = optarg; break;
437            case 'x': osmdata.extra_attributes=1; break;
438            case 'k': enable_hstore=HSTORE_NORM; break;
439            case 'j': enable_hstore=HSTORE_ALL; break;
440            case 'z': 
441                n_hstore_columns++;
442                hstore_columns = (const char**)realloc(hstore_columns, sizeof(&n_hstore_columns) * n_hstore_columns);
443                hstore_columns[n_hstore_columns-1] = optarg;
444                break;
445            case 'G': enable_multi=1; break;
446            case 'r': input_reader = optarg; break;
447            case 'h': long_usage_bool=1; break;
448            case 'I': 
449#ifdef HAVE_PTHREAD
450                parallel_indexing=0; 
451#endif
452                break;
453            case 204: alloc_chunkwise=1; break;
454            case 'V': exit(EXIT_SUCCESS);
455            case '?':
456            default:
457                short_usage(argv[0]);
458                exit(EXIT_FAILURE);
459        }
460    }
461
462    if (long_usage_bool) {
463        long_usage(argv[0]);
464        exit(EXIT_SUCCESS);
465    }
466
467    if (argc == optind) {  // No non-switch arguments
468        short_usage(argv[0]);
469        exit(EXIT_FAILURE);
470    }
471
472    if (append && create) {
473        fprintf(stderr, "Error: --append and --create options can not be used at the same time!\n");
474        exit(EXIT_FAILURE);
475    }
476
477    if (cache < 0) cache = 0;
478
479    if (pass_prompt)
480        password = simple_prompt("Password:", 100, 0);
481    else {
482        password = getenv("PGPASS");
483    }   
484       
485
486    conninfo = build_conninfo(db, username, password, host, port);
487    sql_conn = PQconnectdb(conninfo);
488    if (PQstatus(sql_conn) != CONNECTION_OK) {
489        fprintf(stderr, "Connection to database failed: %s\n", PQerrorMessage(sql_conn));
490        exit(EXIT_FAILURE);
491    }
492    PQfinish(sql_conn);
493
494    text_init();
495    initList(&osmdata.tags);
496
497    osmdata.count_node = osmdata.max_node = 0;
498    osmdata.count_way  = osmdata.max_way  = 0;
499    osmdata.count_rel  = osmdata.max_rel  = 0;
500
501    LIBXML_TEST_VERSION
502
503    project_init(projection);
504    fprintf(stderr, "Using projection SRS %d (%s)\n", 
505        project_getprojinfo()->srs, project_getprojinfo()->descr );
506
507    if (parse_bbox(&osmdata))
508        return 1;
509
510    options.conninfo = conninfo;
511    options.prefix = prefix;
512    options.append = append;
513    options.slim = slim;
514    options.projection = project_getprojinfo()->srs;
515    options.scale = (projection==PROJ_LATLONG)?10000000:100;
516    options.mid = slim ? &mid_pgsql : &mid_ram;
517    options.cache = cache;
518    options.style = style;
519    options.tblsmain_index = tblsmain_index;
520    options.tblsmain_data = tblsmain_data;
521    options.tblsslim_index = tblsslim_index;
522    options.tblsslim_data = tblsslim_data;
523    options.expire_tiles_zoom = expire_tiles_zoom;
524    options.expire_tiles_zoom_min = expire_tiles_zoom_min;
525    options.expire_tiles_filename = expire_tiles_filename;
526    options.enable_multi = enable_multi;
527    options.enable_hstore = enable_hstore;
528    options.hstore_columns = hstore_columns;
529    options.n_hstore_columns = n_hstore_columns;
530    options.keep_coastlines = keep_coastlines;
531    options.parallel_indexing = parallel_indexing;
532    options.alloc_chunkwise = alloc_chunkwise;
533
534    if (strcmp("pgsql", output_backend) == 0) {
535      osmdata.out = &out_pgsql;
536    } else if (strcmp("gazetteer", output_backend) == 0) {
537      osmdata.out = &out_gazetteer;
538    } else if (strcmp("null", output_backend) == 0) {
539      osmdata.out = &out_null;
540    } else {
541      fprintf(stderr, "Output backend `%s' not recognised. Should be one of [pgsql, gazetteer, null].\n", output_backend);
542      exit(EXIT_FAILURE);
543    }
544
545    if (strcmp("auto", input_reader) != 0) {
546      if (strcmp("libxml2", input_reader) == 0) {
547        streamFile = &streamFileXML2;
548      } else if (strcmp("primitive", input_reader) == 0) {
549        streamFile = &streamFilePrimitive;
550#ifdef BUILD_READER_PBF
551      } else if (strcmp("pbf", input_reader) == 0) {
552        streamFile = &streamFilePbf;
553#endif
554      } else {
555        fprintf(stderr, "Input parser `%s' not recognised. Should be one of [libxml2, primitive"
556#ifdef BUILD_READER_PBF
557              ", pbf"
558#endif
559              "].\n", input_reader);
560      exit(EXIT_FAILURE);
561      }
562    }
563
564    time_t overall_start, overall_end;
565    time(&overall_start);
566
567    osmdata.out->start(&options);
568
569    realloc_nodes(&osmdata);
570    realloc_members(&osmdata);
571
572    if (sizeof(int*) == 4 && options.slim != 1) {
573        fprintf(stderr, "\n!! You are running this on 32bit system, so at most\n");
574        fprintf(stderr, "!! 3GB of RAM can be used. If you encounter unexpected\n");
575        fprintf(stderr, "!! exceptions during import, you should try running in slim\n");
576        fprintf(stderr, "!! mode using parameter -s.\n");
577    }
578
579    while (optind < argc) {
580        /* if input_reader is not forced by -r switch try to auto-detect it
581           by file extension */
582        if (strcmp("auto", input_reader) == 0) {
583#ifdef BUILD_READER_PBF
584          if (strcasecmp(".pbf",argv[optind]+strlen(argv[optind])-4) == 0) {
585            streamFile = &streamFilePbf;
586          } else {
587            streamFile = &streamFileXML2;
588          }
589#else
590          streamFile = &streamFileXML2;
591#endif
592        }
593        time_t start, end;
594
595        fprintf(stderr, "\nReading in file: %s\n", argv[optind]);
596        time(&start);
597        if (streamFile(argv[optind], sanitize, &osmdata) != 0)
598            exit_nicely();
599        time(&end);
600        fprintf(stderr, "  parse time: %ds\n", (int)(end - start));
601        optind++;
602    }
603
604    xmlCleanupParser();
605    xmlMemoryDump();
606   
607    if (osmdata.count_node || osmdata.count_way || osmdata.count_rel) {
608        time_t now;
609        time(&now);
610        time_t end_nodes = osmdata.start_way > 0 ? osmdata.start_way : now;
611        time_t end_way = osmdata.start_rel > 0 ? osmdata.start_rel : now;
612        time_t end_rel =  now;
613        fprintf(stderr, "\n");
614        fprintf(stderr, "Node stats: total(%" PRIdOSMID "), max(%" PRIdOSMID ") in %is\n", osmdata.count_node, osmdata.max_node,
615                osmdata.count_node > 0 ? (int)(end_nodes - osmdata.start_node) : 0);
616        fprintf(stderr, "Way stats: total(%" PRIdOSMID "), max(%" PRIdOSMID ") in %is\n", osmdata.count_way, osmdata.max_way,
617                osmdata.count_way > 0 ? (int)(end_way - osmdata.start_way) : 0);
618        fprintf(stderr, "Relation stats: total(%" PRIdOSMID "), max(%" PRIdOSMID ") in %is\n", osmdata.count_rel, osmdata.max_rel,
619                osmdata.count_rel > 0 ? (int)(end_rel - osmdata.start_rel) : 0);
620    }
621    osmdata.out->stop();
622   
623    free(osmdata.nds);
624    free(osmdata.members);
625   
626    // free the column pointer buffer
627    free(hstore_columns);
628
629    project_exit();
630    text_exit();
631    fprintf(stderr, "\n");
632    time(&overall_end);
633    fprintf(stderr, "Osm2pgsql took %ds overall\n", (int)(overall_end - overall_start));
634
635    return 0;
636}
Note: See TracBrowser for help on using the repository browser.