source: subversion/applications/utils/export/osm2pgsql/middle-ram.c @ 3210

Last change on this file since 3210 was 2827, checked in by jonb, 13 years ago

osm2pgsql - make experimental version current, move previous implementation to legacy

File size: 8.3 KB
Line 
1/* Implements the mid-layer processing for osm2pgsql
2 * using several PostgreSQL tables
3 *
4 * This layer stores data read in from the planet.osm file
5 * and is then read by the backend processing code to
6 * emit the final geometry-enabled output formats
7*/
8
9#include <stdio.h>
10#include <unistd.h>
11#include <stdlib.h>
12#include <string.h>
13#include <assert.h>
14
15#include <libpq-fe.h>
16
17#include "osmtypes.h"
18#include "middle.h"
19#include "middle-ram.h"
20
21#include "output-pgsql.h"
22
23/* Note: these are based on a current planet.osm file + 10%, increase them if needed */
24#define MAX_ID_NODE (31000000)
25#define MAX_ID_SEGMENT (27000000)
26#define MAX_ID_WAY (5000000)
27
28/* Store +-180 lattitude/longittude as fixed point 32bit number with maximum precision */
29/* Scale is chosen such that 360 * SCALE < 2^32          */
30/* scale = 1e7 is more 'human readable',  (1<<23) is better for computers, take your pick :-) */
31#define FIXED_POINT
32//#define SCALE 10000000
33#define SCALE 100
34#define DOUBLE_TO_FIX(x) ((x) * SCALE)
35#define FIX_TO_DOUBLE(x) (((double)x) / SCALE)
36
37struct ramNode {
38#ifdef FIXED_POINT
39    int lon;
40    int lat;
41#else 
42    double lon;
43    double lat;
44#endif
45      //struct keyval tags;
46};
47
48struct ramSegment {
49      int from;
50      int to;
51      //struct keyval tags;
52};
53
54struct ramWay {
55      struct keyval *tags;
56      int *segids;
57};
58
59static struct ramNode    *nodes;
60static struct ramSegment *segments;
61static struct ramWay     *ways;
62
63
64static int ram_nodes_set(int id, double lat, double lon, struct keyval *tags)
65{
66    //struct keyval *p;
67
68    if (id <= 0)
69        return 1;
70    if (id > MAX_ID_NODE) {
71        fprintf(stderr, "Discarding node with ID(%d) > MAX(%u)\n", id, MAX_ID_NODE);
72        return 1;
73    }
74
75#ifdef FIXED_POINT
76    nodes[id].lat = DOUBLE_TO_FIX(lat);
77    nodes[id].lon = DOUBLE_TO_FIX(lon);
78#else
79    nodes[id].lat = lat;
80    nodes[id].lon = lon;
81#endif
82
83#if 0
84    while ((p = popItem(tags)) != NULL)
85        pushItem(&nodes[id].tags, p);
86#else
87    /* FIXME: This is a performance hack which interferes with a clean middle / output separation */
88    out_pgsql.node(id, tags, lat, lon);
89    resetList(tags);
90#endif
91    return 0;
92}
93
94
95static int ram_nodes_get(struct osmNode *out, int id)
96{
97    if (id <= 0 || id > MAX_ID_NODE)
98        return 1;
99
100    if (!nodes[id].lat && !nodes[id].lon)
101        return 1;
102#ifdef FIXED_POINT
103    out->lat = FIX_TO_DOUBLE(nodes[id].lat);
104    out->lon = FIX_TO_DOUBLE(nodes[id].lon);
105#else
106    out->lat = nodes[id].lat;
107    out->lon = nodes[id].lon;
108#endif
109    return 0;
110}
111
112static int ram_segments_set(int id, int from, int to, struct keyval *tags)
113{
114    if (id <= 0)
115        return 1;
116    if (id > MAX_ID_SEGMENT) {
117        fprintf(stderr, "Discarding segment with ID(%d) > MAX(%u)\n", id, MAX_ID_SEGMENT);
118        return 1;
119    }
120
121    segments[id].from = from;
122    segments[id].to   = to;
123    resetList(tags);
124    return 0;
125}
126
127static int ram_segments_get(struct osmSegment *out, int id)
128{
129    if (id <= 0 || id > MAX_ID_SEGMENT)
130        return 1;
131
132    if (!segments[id].from && !segments[id].to)
133        return 1;
134
135    out->from = segments[id].from;
136    out->to   = segments[id].to;
137    return 0;
138}
139
140static int ram_ways_set(int id, struct keyval *segs, struct keyval *tags)
141{
142    struct keyval *p;
143    int *segids;
144    int segCount, i;
145
146    if (id <= 0)
147        return 1;
148
149    if (id > MAX_ID_WAY) {
150        fprintf(stderr, "Discarding way with ID(%d) > MAX(%u)\n", id, MAX_ID_WAY);
151        return 1;
152    }
153
154    segCount = countList(segs);
155    if (!segCount)
156        return 1;
157
158    if (ways[id].segids) {
159        free(ways[id].segids);
160        ways[id].segids = NULL;
161    }
162
163    segids = malloc(sizeof(int) * (segCount+1));
164    if (!segids) {
165        fprintf(stderr, "%s malloc failed\n", __FUNCTION__);
166        exit_nicely();
167    }
168
169    ways[id].segids = segids;
170    i = 0;
171    while ((p = popItem(segs)) != NULL) {
172        int seg_id = strtol(p->value, NULL, 10);
173        freeItem(p);
174        if (seg_id) /* id = 0 is used as list terminator */
175            segids[i++] = seg_id;
176    }
177    segids[i] = 0;
178 
179    if (!ways[id].tags) {
180        p = malloc(sizeof(struct keyval));
181        if (p) {
182            initList(p);
183            ways[id].tags = p;
184        } else {
185            fprintf(stderr, "%s malloc failed\n", __FUNCTION__);
186            exit_nicely();
187        }
188    } else
189        resetList(ways[id].tags);
190 
191    while ((p = popItem(tags)) != NULL)
192        pushItem(ways[id].tags, p);
193
194    return 0;
195}
196
197static struct osmSegLL *getSegLL(int *segids, int *segCount)
198{
199    struct osmSegment segment;
200    struct osmNode node;
201    int id;
202    int i, count = 0;
203    struct osmSegLL *segll;
204
205    while(segids[count])
206        count++;
207
208    segll = malloc(count * sizeof(struct osmSegLL));
209
210    if (!segll) {
211        *segCount = 0;
212        return NULL;
213    }
214 
215    count = 0;
216    i = 0;
217    while ((id = segids[i++]) != 0)
218    {
219        if (ram_segments_get(&segment, id))
220            continue;
221
222        if (ram_nodes_get(&node, segment.from))
223            continue;
224
225        segll[count].lon0 = node.lon;
226        segll[count].lat0 = node.lat;
227
228        if (ram_nodes_get(&node, segment.to))
229            continue;
230
231        segll[count].lon1 = node.lon;
232        segll[count].lat1 = node.lat;
233
234        count++;
235    }
236    *segCount = count;
237    return segll;
238}
239
240
241static void ram_iterate_ways(int (*callback)(int id, struct keyval *tags, struct osmSegLL *segll, int count))
242{
243    int i, count = 0, segCount = 0;
244    struct osmSegLL *segll;
245
246    fprintf(stderr, "\n");
247    for(i=MAX_ID_WAY; i>0; i--) {
248        if (ways[i].segids) {
249            count++;
250            if (count % 1000 == 0)
251                fprintf(stderr, "\rWriting way(%uk)", count/1000);
252
253            segll = getSegLL(ways[i].segids, &segCount);
254
255            if (segll) {
256                callback(i, ways[i].tags, segll, segCount);
257                free(segll);
258            }
259
260            if (ways[i].tags) {
261                resetList(ways[i].tags);
262                free(ways[i].tags);
263                ways[i].tags = NULL;
264            }
265            if (ways[i].segids) {
266                free(ways[i].segids);
267                ways[i].segids = NULL;
268            }
269        }
270    }
271}
272
273
274static void ram_analyze(void)
275{
276    /* No need */
277}
278
279static void ram_end(void)
280{
281    /* No need */
282}
283
284static int ram_start(int dropcreate)
285{
286//    int i;
287
288    fprintf(stderr, "Allocating memory for RAM storage\n");
289    if (!nodes) {
290        fprintf(stderr, "\tnodes(%zuMb)\n", (MAX_ID_NODE+1) * sizeof(struct ramNode) / 1000000);
291        nodes = calloc((MAX_ID_NODE+1), sizeof(struct ramNode));
292        if (!nodes) {
293            fprintf(stderr, "Error allocating nodes\n");
294            exit_nicely();
295        }
296#if 0
297        fprintf(stderr, "Initialising nodes\n");
298        for (i=0; i<=MAX_ID_NODE; i++)
299            initList(&nodes[i].tags);
300#endif
301    }
302    if (!segments) {
303        fprintf(stderr, "\tsegments(%zuMb)\n", (MAX_ID_SEGMENT+1) * sizeof(struct ramSegment) / 1000000);
304        segments = calloc((MAX_ID_SEGMENT+1), sizeof(struct ramSegment));
305        if (!segments) {
306            fprintf(stderr, "Error allocating segments\n");
307            exit_nicely();
308        }
309    }
310    if (!ways) {
311        fprintf(stderr, "\tways(%zuMb)\n", (MAX_ID_WAY+1) * sizeof(struct ramWay) / 1000000);
312        ways = calloc((MAX_ID_WAY+1), sizeof(struct ramWay));
313        if (!ways) {
314            fprintf(stderr, "Error allocating ways\n");
315            exit_nicely();
316        }
317    }
318
319    return 0;
320}
321
322static void ram_stop(void)
323{
324    int i;
325
326    if (nodes)
327        free(nodes);
328
329    if (segments)
330        free(segments);
331
332    if (ways) {
333        for (i=0; i<MAX_ID_WAY; i++) {
334            if (ways[i].tags) {
335                resetList(ways[i].tags);
336                free(ways[i].tags);
337            }
338            if (ways[i].segids)
339                free(ways[i].segids);
340        }
341        free(ways);
342    }
343    nodes = NULL;
344    segments = NULL;
345    ways = NULL;
346}
347 
348struct middle_t mid_ram = {
349        start:          ram_start,
350        stop:           ram_stop,
351        end:           ram_end,
352        cleanup:        ram_stop,
353        analyze:        ram_analyze,
354        segments_set:   ram_segments_set,
355        segments_get:   ram_segments_get,
356        nodes_set:      ram_nodes_set,
357        nodes_get:      ram_nodes_get,
358        ways_set:       ram_ways_set,
359//        ways_get:       ram_ways_get,
360//        iterate_nodes:  ram_iterate_nodes,
361        iterate_ways:   ram_iterate_ways
362};
Note: See TracBrowser for help on using the repository browser.