Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino
Annotation of /trunk/src/waysx.c
Parent Directory
|
Revision Log
Revision 2189 -
(hide annotations)
(download)
(as text)
Sun Sep 1 15:38:16 2024 UTC (6 months, 3 weeks ago) by amb
File MIME type: text/x-csrc
File size: 22301 byte(s)
Sun Sep 1 15:38:16 2024 UTC (6 months, 3 weeks ago) by amb
File MIME type: text/x-csrc
File size: 22301 byte(s)
Change some types and correct some comparisons that cause errors if index_t is changed to a 64-bit type (prompted by patch from a user).
1 | amb | 110 | /*************************************** |
2 | Extended Way data type functions. | ||
3 | amb | 151 | |
4 | Part of the Routino routing software. | ||
5 | amb | 110 | ******************/ /****************** |
6 | amb | 2189 | This file Copyright 2008-2015, 2018, 2019, 2020, 2022, 2024 Andrew M. Bishop |
7 | amb | 110 | |
8 | amb | 151 | This program is free software: you can redistribute it and/or modify |
9 | it under the terms of the GNU Affero General Public License as published by | ||
10 | the Free Software Foundation, either version 3 of the License, or | ||
11 | (at your option) any later version. | ||
12 | |||
13 | This program is distributed in the hope that it will be useful, | ||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | GNU Affero General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU Affero General Public License | ||
19 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
20 | amb | 110 | ***************************************/ |
21 | |||
22 | |||
23 | #include <stdlib.h> | ||
24 | #include <string.h> | ||
25 | |||
26 | amb | 955 | #include "types.h" |
27 | amb | 228 | #include "ways.h" |
28 | amb | 110 | |
29 | amb | 955 | #include "typesx.h" |
30 | amb | 1339 | #include "nodesx.h" |
31 | amb | 1092 | #include "segmentsx.h" |
32 | amb | 449 | #include "waysx.h" |
33 | amb | 110 | |
34 | amb | 449 | #include "files.h" |
35 | amb | 519 | #include "logging.h" |
36 | amb | 532 | #include "sorting.h" |
37 | amb | 449 | |
38 | |||
39 | amb | 680 | /* Global variables */ |
40 | amb | 110 | |
41 | amb | 289 | /*+ The command line '--tmpdir' option or its default value. +*/ |
42 | amb | 284 | extern char *option_tmpdirname; |
43 | amb | 110 | |
44 | amb | 680 | /* Local variables */ |
45 | |||
46 | amb | 1784 | /*+ Temporary file-local variables for use by the sort functions (re-initialised for each sort). +*/ |
47 | amb | 284 | static WaysX *sortwaysx; |
48 | amb | 1100 | static SegmentsX *sortsegmentsx; |
49 | amb | 284 | |
50 | amb | 1100 | /* Local functions */ |
51 | amb | 680 | |
52 | amb | 499 | static int sort_by_id(WayX *a,WayX *b); |
53 | amb | 1348 | static int deduplicate_and_index_by_id(WayX *wayx,index_t index); |
54 | amb | 1160 | |
55 | amb | 1348 | static int sort_by_name(char *a,char *b); |
56 | amb | 310 | |
57 | amb | 1114 | static int delete_unused(WayX *wayx,index_t index); |
58 | amb | 1160 | static int sort_by_name_and_prop_and_id(WayX *a,WayX *b); |
59 | amb | 1094 | static int deduplicate_and_index_by_compact_id(WayX *wayx,index_t index); |
60 | amb | 272 | |
61 | amb | 110 | |
62 | /*++++++++++++++++++++++++++++++++++++++ | ||
63 | amb | 326 | Allocate a new way list (create a new file or open an existing one). |
64 | amb | 110 | |
65 | WaysX *NewWayList Returns the way list. | ||
66 | amb | 326 | |
67 | amb | 1123 | int append Set to 1 if the file is to be opened for appending. |
68 | |||
69 | amb | 1139 | int readonly Set to 1 if the file is to be opened for reading. |
70 | amb | 110 | ++++++++++++++++++++++++++++++++++++++*/ |
71 | |||
72 | amb | 1158 | WaysX *NewWayList(int append,int readonly) |
73 | amb | 110 | { |
74 | WaysX *waysx; | ||
75 | |||
76 | amb | 1999 | waysx=(WaysX*)calloc_logassert(1,sizeof(WaysX)); |
77 | amb | 110 | |
78 | amb | 1999 | waysx->filename =(char*)malloc_logassert(strlen(option_tmpdirname)+32); |
79 | waysx->filename_tmp=(char*)malloc_logassert(strlen(option_tmpdirname)+32); /* allow %p to be up to 20 bytes */ | ||
80 | amb | 243 | |
81 | amb | 1120 | sprintf(waysx->filename ,"%s/waysx.parsed.mem",option_tmpdirname); |
82 | sprintf(waysx->filename_tmp,"%s/waysx.%p.tmp" ,option_tmpdirname,(void*)waysx); | ||
83 | amb | 262 | |
84 | amb | 1123 | if(append || readonly) |
85 | if(ExistsFile(waysx->filename)) | ||
86 | { | ||
87 | amb | 1405 | FILESORT_VARINT waysize; |
88 | amb | 1123 | int fd; |
89 | amb | 326 | |
90 | amb | 1405 | fd=ReOpenFileBuffered(waysx->filename); |
91 | amb | 326 | |
92 | amb | 1405 | while(!ReadFileBuffered(fd,&waysize,FILESORT_VARSIZE)) |
93 | amb | 1123 | { |
94 | amb | 1406 | SkipFileBuffered(fd,waysize); |
95 | amb | 326 | |
96 | amb | 1123 | waysx->number++; |
97 | } | ||
98 | |||
99 | amb | 1405 | CloseFileBuffered(fd); |
100 | amb | 1139 | |
101 | RenameFile(waysx->filename,waysx->filename_tmp); | ||
102 | amb | 326 | } |
103 | |||
104 | amb | 1123 | if(append) |
105 | amb | 1402 | waysx->fd=OpenFileBufferedAppend(waysx->filename_tmp); |
106 | amb | 1123 | else if(!readonly) |
107 | amb | 1402 | waysx->fd=OpenFileBufferedNew(waysx->filename_tmp); |
108 | amb | 326 | else |
109 | amb | 1123 | waysx->fd=-1; |
110 | amb | 326 | |
111 | amb | 1297 | #if SLIM |
112 | waysx->cache=NewWayXCache(); | ||
113 | amb | 1598 | log_malloc(waysx->cache,sizeof(*waysx->cache)); |
114 | amb | 1297 | #endif |
115 | amb | 262 | |
116 | amb | 2033 | waysx->ifilename_tmp=(char*)malloc_logassert(strlen(option_tmpdirname)+40); /* allow %p to be up to 20 bytes */ |
117 | waysx->ofilename_tmp=(char*)malloc_logassert(strlen(option_tmpdirname)+40); /* allow %p to be up to 20 bytes */ | ||
118 | amb | 1297 | |
119 | amb | 2033 | sprintf(waysx->ifilename_tmp,"%s/waysx.%p.idx.tmp",option_tmpdirname,(void*)waysx); |
120 | sprintf(waysx->ofilename_tmp,"%s/waysx.%p.off.tmp",option_tmpdirname,(void*)waysx); | ||
121 | |||
122 | amb | 1999 | waysx->nfilename_tmp=(char*)malloc_logassert(strlen(option_tmpdirname)+40); /* allow %p to be up to 20 bytes */ |
123 | amb | 1120 | |
124 | sprintf(waysx->nfilename_tmp,"%s/waynames.%p.tmp",option_tmpdirname,(void*)waysx); | ||
125 | |||
126 | amb | 110 | return(waysx); |
127 | } | ||
128 | |||
129 | |||
130 | /*++++++++++++++++++++++++++++++++++++++ | ||
131 | amb | 226 | Free a way list. |
132 | |||
133 | amb | 681 | WaysX *waysx The set of ways to be freed. |
134 | amb | 1151 | |
135 | amb | 1167 | int keep If set then the results file is to be kept. |
136 | amb | 226 | ++++++++++++++++++++++++++++++++++++++*/ |
137 | |||
138 | amb | 1167 | void FreeWayList(WaysX *waysx,int keep) |
139 | amb | 226 | { |
140 | amb | 1167 | if(keep) |
141 | amb | 1151 | RenameFile(waysx->filename_tmp,waysx->filename); |
142 | else | ||
143 | DeleteFile(waysx->filename_tmp); | ||
144 | amb | 1120 | |
145 | amb | 283 | free(waysx->filename); |
146 | amb | 1120 | free(waysx->filename_tmp); |
147 | amb | 262 | |
148 | amb | 2033 | DeleteFile(waysx->ifilename_tmp); |
149 | amb | 226 | |
150 | amb | 2033 | DeleteFile(waysx->ofilename_tmp); |
151 | amb | 1317 | |
152 | amb | 2033 | free(waysx->ifilename_tmp); |
153 | |||
154 | amb | 1093 | if(waysx->cdata) |
155 | amb | 1598 | { |
156 | log_free(waysx->cdata); | ||
157 | amb | 1093 | free(waysx->cdata); |
158 | amb | 1598 | } |
159 | amb | 1093 | |
160 | amb | 1120 | DeleteFile(waysx->nfilename_tmp); |
161 | amb | 326 | |
162 | amb | 1120 | free(waysx->nfilename_tmp); |
163 | amb | 226 | |
164 | amb | 1297 | #if SLIM |
165 | amb | 1598 | log_free(waysx->cache); |
166 | amb | 1297 | DeleteWayXCache(waysx->cache); |
167 | #endif | ||
168 | |||
169 | amb | 226 | free(waysx); |
170 | } | ||
171 | |||
172 | |||
173 | /*++++++++++++++++++++++++++++++++++++++ | ||
174 | amb | 493 | Append a single way to an unsorted way list. |
175 | amb | 203 | |
176 | amb | 682 | WaysX *waysx The set of ways to process. |
177 | amb | 110 | |
178 | amb | 262 | way_t id The ID of the way. |
179 | amb | 110 | |
180 | amb | 262 | Way *way The way data itself. |
181 | amb | 110 | |
182 | amb | 1338 | node_t *nodes The list of nodes for this way. |
183 | |||
184 | int nnodes The number of nodes for this way. | ||
185 | |||
186 | amb | 262 | const char *name The name or reference of the way. |
187 | ++++++++++++++++++++++++++++++++++++++*/ | ||
188 | amb | 110 | |
189 | amb | 1338 | void AppendWayList(WaysX *waysx,way_t id,Way *way,node_t *nodes,int nnodes,const char *name) |
190 | amb | 262 | { |
191 | amb | 2055 | WayX wayx={0}; |
192 | amb | 1974 | uint64_t longsize; |
193 | amb | 311 | FILESORT_VARINT size; |
194 | amb | 1338 | node_t nonode=NO_NODE_ID; |
195 | amb | 110 | |
196 | amb | 262 | wayx.id=id; |
197 | wayx.way=*way; | ||
198 | |||
199 | amb | 1959 | longsize=sizeof(WayX)+(nnodes+1)*sizeof(node_t)+strlen(name)+1; |
200 | amb | 310 | |
201 | amb | 2110 | if(longsize>=FILESORT_MAXINT) /* Ensure no overflow of FILESORT_VARINT integer */ |
202 | { | ||
203 | logerror("Way %"Pway_t" contains too much data; ignoring some nodes (or change FILESORT_VARINT to 32-bits?)\n",logerror_way(id)); | ||
204 | amb | 1959 | |
205 | amb | 2110 | nnodes=(FILESORT_MAXINT-(sizeof(WayX)+strlen(name)+1))/sizeof(node_t)-1; |
206 | |||
207 | longsize=sizeof(WayX)+(nnodes+1)*sizeof(node_t)+strlen(name)+1; | ||
208 | |||
209 | logassert(longsize<FILESORT_MAXINT,"Way still contains too much data (change FILESORT_VARINT to 32-bits?)\n"); | ||
210 | } | ||
211 | |||
212 | amb | 1959 | size=longsize; |
213 | |||
214 | amb | 1402 | WriteFileBuffered(waysx->fd,&size,FILESORT_VARSIZE); |
215 | WriteFileBuffered(waysx->fd,&wayx,sizeof(WayX)); | ||
216 | amb | 1338 | |
217 | amb | 1402 | WriteFileBuffered(waysx->fd,nodes ,nnodes*sizeof(node_t)); |
218 | WriteFileBuffered(waysx->fd,&nonode, sizeof(node_t)); | ||
219 | amb | 1338 | |
220 | amb | 1402 | WriteFileBuffered(waysx->fd,name,strlen(name)+1); |
221 | amb | 262 | |
222 | amb | 650 | waysx->number++; |
223 | amb | 466 | |
224 | amb | 1166 | logassert(waysx->number!=0,"Too many ways (change index_t to 64-bits?)"); /* Zero marks the high-water mark for ways. */ |
225 | amb | 110 | } |
226 | |||
227 | |||
228 | /*++++++++++++++++++++++++++++++++++++++ | ||
229 | amb | 1120 | Finish appending ways and change the filename over. |
230 | |||
231 | WaysX *waysx The ways that have been appended. | ||
232 | ++++++++++++++++++++++++++++++++++++++*/ | ||
233 | |||
234 | amb | 1151 | void FinishWayList(WaysX *waysx) |
235 | amb | 1120 | { |
236 | amb | 1136 | if(waysx->fd!=-1) |
237 | amb | 1402 | waysx->fd=CloseFileBuffered(waysx->fd); |
238 | amb | 1120 | } |
239 | |||
240 | |||
241 | /*++++++++++++++++++++++++++++++++++++++ | ||
242 | amb | 1160 | Find a particular way index. |
243 | |||
244 | index_t IndexWayX Returns the index of the extended way with the specified id. | ||
245 | |||
246 | WaysX *waysx The set of ways to process. | ||
247 | |||
248 | way_t id The way id to look for. | ||
249 | ++++++++++++++++++++++++++++++++++++++*/ | ||
250 | |||
251 | index_t IndexWayX(WaysX *waysx,way_t id) | ||
252 | { | ||
253 | index_t start=0; | ||
254 | index_t end=waysx->number-1; | ||
255 | index_t mid; | ||
256 | |||
257 | amb | 1198 | if(waysx->number==0) /* There are no ways */ |
258 | return(NO_WAY); | ||
259 | |||
260 | amb | 1160 | /* Binary search - search key exact match only is required. |
261 | * | ||
262 | amb | 2077 | * # <- start | Check mid and exit if it matches else move start or end. |
263 | amb | 1160 | * # | |
264 | * # | Since an exact match is wanted we can set end=mid-1 | ||
265 | amb | 2077 | * # <- mid | or start=mid+1 if we find that mid doesn't match. |
266 | amb | 1160 | * # | |
267 | * # | Eventually either end=start or end=start+1 and one of | ||
268 | amb | 2077 | * # <- end | start or end is the wanted one or neither is. |
269 | amb | 1160 | */ |
270 | |||
271 | amb | 2077 | while((end-start)>1) |
272 | amb | 1160 | { |
273 | amb | 1968 | mid=start+(end-start)/2; /* Choose mid point (avoid overflow) */ |
274 | amb | 1160 | |
275 | amb | 1198 | if(waysx->idata[mid]<id) /* Mid point is too low */ |
276 | start=mid+1; | ||
277 | else if(waysx->idata[mid]>id) /* Mid point is too high */ | ||
278 | amb | 2077 | end=mid-1; |
279 | amb | 1198 | else /* Mid point is correct */ |
280 | return(mid); | ||
281 | } | ||
282 | amb | 1160 | |
283 | amb | 1198 | if(waysx->idata[start]==id) /* Start is correct */ |
284 | return(start); | ||
285 | amb | 1160 | |
286 | amb | 1198 | if(waysx->idata[end]==id) /* End is correct */ |
287 | return(end); | ||
288 | amb | 1160 | |
289 | return(NO_WAY); | ||
290 | } | ||
291 | |||
292 | |||
293 | /*++++++++++++++++++++++++++++++++++++++ | ||
294 | amb | 224 | Sort the list of ways. |
295 | amb | 110 | |
296 | amb | 682 | WaysX *waysx The set of ways to process. |
297 | amb | 110 | ++++++++++++++++++++++++++++++++++++++*/ |
298 | |||
299 | amb | 682 | void SortWayList(WaysX *waysx) |
300 | amb | 110 | { |
301 | amb | 1129 | index_t xnumber; |
302 | amb | 555 | int fd; |
303 | amb | 1129 | |
304 | /* Print the start message */ | ||
305 | |||
306 | printf_first("Sorting Ways"); | ||
307 | |||
308 | /* Re-open the file read-only and a new file writeable */ | ||
309 | |||
310 | amb | 1699 | fd=ReplaceFileBuffered(waysx->filename_tmp,&waysx->fd); |
311 | amb | 1129 | |
312 | amb | 2033 | /* Open a file for the index */ |
313 | amb | 1348 | |
314 | amb | 2033 | waysx->ifd=OpenFileBufferedNew(waysx->ifilename_tmp); |
315 | amb | 1348 | |
316 | amb | 1129 | /* Sort the ways by ID and index them */ |
317 | |||
318 | amb | 1348 | sortwaysx=waysx; |
319 | |||
320 | amb | 1129 | xnumber=waysx->number; |
321 | |||
322 | waysx->number=filesort_vary(waysx->fd,fd,NULL, | ||
323 | (int (*)(const void*,const void*))sort_by_id, | ||
324 | amb | 1348 | (int (*)(void*,index_t))deduplicate_and_index_by_id); |
325 | amb | 1129 | |
326 | amb | 1361 | waysx->knumber=waysx->number; |
327 | |||
328 | amb | 1129 | /* Close the files */ |
329 | |||
330 | amb | 1409 | waysx->fd=CloseFileBuffered(waysx->fd); |
331 | CloseFileBuffered(fd); | ||
332 | amb | 1129 | |
333 | amb | 2033 | waysx->ifd=CloseFileBuffered(waysx->ifd); |
334 | |||
335 | amb | 1129 | /* Print the final message */ |
336 | |||
337 | printf_last("Sorted Ways: Ways=%"Pindex_t" Duplicates=%"Pindex_t,xnumber,xnumber-waysx->number); | ||
338 | } | ||
339 | |||
340 | |||
341 | /*++++++++++++++++++++++++++++++++++++++ | ||
342 | amb | 1160 | Sort the ways into id order. |
343 | |||
344 | int sort_by_id Returns the comparison of the id fields. | ||
345 | |||
346 | WayX *a The first extended way. | ||
347 | |||
348 | WayX *b The second extended way. | ||
349 | ++++++++++++++++++++++++++++++++++++++*/ | ||
350 | |||
351 | static int sort_by_id(WayX *a,WayX *b) | ||
352 | { | ||
353 | way_t a_id=a->id; | ||
354 | way_t b_id=b->id; | ||
355 | |||
356 | if(a_id<b_id) | ||
357 | return(-1); | ||
358 | else if(a_id>b_id) | ||
359 | return(1); | ||
360 | else | ||
361 | return(-FILESORT_PRESERVE_ORDER(a,b)); /* latest version first */ | ||
362 | } | ||
363 | |||
364 | |||
365 | /*++++++++++++++++++++++++++++++++++++++ | ||
366 | amb | 1348 | Discard duplicate ways and create and index of ids. |
367 | amb | 1160 | |
368 | amb | 1450 | int deduplicate_and_index_by_id Return 1 if the value is to be kept, otherwise 0. |
369 | amb | 1160 | |
370 | WayX *wayx The extended way. | ||
371 | |||
372 | index_t index The number of sorted ways that have already been written to the output file. | ||
373 | ++++++++++++++++++++++++++++++++++++++*/ | ||
374 | |||
375 | amb | 1348 | static int deduplicate_and_index_by_id(WayX *wayx,index_t index) |
376 | amb | 1160 | { |
377 | amb | 1784 | static way_t previd; /* internal variable (reset by first call in each sort; index==0) */ |
378 | amb | 1160 | |
379 | amb | 1784 | if(index==0 || wayx->id!=previd) |
380 | amb | 1160 | { |
381 | previd=wayx->id; | ||
382 | |||
383 | if(wayx->way.type==WAY_DELETED) | ||
384 | return(0); | ||
385 | else | ||
386 | amb | 1348 | { |
387 | amb | 2033 | WriteFileBuffered(sortwaysx->ifd,&wayx->id,sizeof(way_t)); |
388 | amb | 1348 | |
389 | amb | 1160 | return(1); |
390 | amb | 1348 | } |
391 | amb | 1160 | } |
392 | else | ||
393 | return(0); | ||
394 | } | ||
395 | |||
396 | |||
397 | /*++++++++++++++++++++++++++++++++++++++ | ||
398 | amb | 1348 | Split the ways into segments and way names. |
399 | amb | 1129 | |
400 | amb | 1450 | SegmentsX *SplitWays Returns the set of segments that have been created. |
401 | |||
402 | amb | 1129 | WaysX *waysx The set of ways to process. |
403 | amb | 1136 | |
404 | amb | 1349 | NodesX *nodesx The set of nodes to use. |
405 | |||
406 | amb | 1167 | int keep If set to 1 then keep the old data file otherwise delete it. |
407 | amb | 1129 | ++++++++++++++++++++++++++++++++++++++*/ |
408 | |||
409 | amb | 1349 | SegmentsX *SplitWays(WaysX *waysx,NodesX *nodesx,int keep) |
410 | amb | 1129 | { |
411 | amb | 1339 | SegmentsX *segmentsx; |
412 | amb | 1129 | index_t i; |
413 | amb | 1348 | int fd,nfd; |
414 | amb | 1339 | char *name=NULL; |
415 | amb | 1974 | uint32_t namelen=0; |
416 | amb | 110 | |
417 | amb | 266 | /* Print the start message */ |
418 | |||
419 | amb | 1348 | printf_first("Splitting Ways: Ways=0 Segments=0"); |
420 | amb | 110 | |
421 | amb | 1339 | segmentsx=NewSegmentList(); |
422 | |||
423 | amb | 555 | /* Re-open the file read-only and a new file writeable */ |
424 | |||
425 | amb | 1167 | if(keep) |
426 | amb | 1699 | { |
427 | amb | 1136 | RenameFile(waysx->filename_tmp,waysx->filename); |
428 | amb | 1699 | |
429 | waysx->fd=ReOpenFileBuffered(waysx->filename); | ||
430 | |||
431 | fd=OpenFileBufferedNew(waysx->filename_tmp); | ||
432 | } | ||
433 | amb | 1136 | else |
434 | amb | 1699 | fd=ReplaceFileBuffered(waysx->filename_tmp,&waysx->fd); |
435 | amb | 262 | |
436 | amb | 1405 | nfd=OpenFileBufferedNew(waysx->nfilename_tmp); |
437 | amb | 1339 | |
438 | amb | 2033 | /* Map the index into memory */ |
439 | |||
440 | nodesx->idata=MapFile(nodesx->ifilename_tmp); | ||
441 | waysx->idata =MapFile(waysx->ifilename_tmp); | ||
442 | |||
443 | amb | 1348 | /* Loop through the ways and create the segments and way names */ |
444 | |||
445 | amb | 1339 | for(i=0;i<waysx->number;i++) |
446 | { | ||
447 | WayX wayx; | ||
448 | FILESORT_VARINT size; | ||
449 | node_t node,prevnode=NO_NODE_ID; | ||
450 | amb | 1349 | index_t index,previndex=NO_NODE; |
451 | amb | 1339 | |
452 | amb | 1405 | ReadFileBuffered(waysx->fd,&size,FILESORT_VARSIZE); |
453 | amb | 1339 | |
454 | amb | 1405 | ReadFileBuffered(waysx->fd,&wayx,sizeof(WayX)); |
455 | amb | 1339 | |
456 | amb | 1989 | waysx->transports|=wayx.way.allow; |
457 | amb | 1380 | |
458 | amb | 1405 | while(!ReadFileBuffered(waysx->fd,&node,sizeof(node_t)) && node!=NO_NODE_ID) |
459 | amb | 1339 | { |
460 | amb | 1349 | index=IndexNodeX(nodesx,node); |
461 | |||
462 | if(prevnode==node) | ||
463 | { | ||
464 | amb | 1612 | logerror("Way %"Pway_t" contains node %"Pnode_t" that is connected to itself.\n",logerror_way(waysx->idata[i]),logerror_node(node)); |
465 | amb | 1349 | } |
466 | else if(index==NO_NODE) | ||
467 | { | ||
468 | amb | 1612 | logerror("Way %"Pway_t" contains node %"Pnode_t" that does not exist in the Routino database.\n",logerror_way(waysx->idata[i]),logerror_node(node)); |
469 | amb | 1349 | } |
470 | else if(previndex==NO_NODE) | ||
471 | amb | 1347 | ; |
472 | else | ||
473 | amb | 1339 | { |
474 | distance_t segment_flags=0; | ||
475 | |||
476 | if(wayx.way.type&Highway_OneWay) | ||
477 | segment_flags|=ONEWAY_1TO2; | ||
478 | |||
479 | if(wayx.way.type&Highway_Area) | ||
480 | segment_flags|=SEGMENT_AREA; | ||
481 | |||
482 | amb | 1427 | AppendSegmentList(segmentsx,i,previndex,index,segment_flags); |
483 | amb | 1339 | } |
484 | |||
485 | prevnode=node; | ||
486 | amb | 1349 | previndex=index; |
487 | amb | 1339 | |
488 | size-=sizeof(node_t); | ||
489 | } | ||
490 | |||
491 | amb | 1348 | size-=sizeof(node_t)+sizeof(WayX); |
492 | amb | 1339 | |
493 | if(namelen<size) | ||
494 | amb | 1999 | name=(char*)realloc_logassert((void*)name,namelen=size); |
495 | amb | 1339 | |
496 | amb | 1405 | ReadFileBuffered(waysx->fd,name,size); |
497 | amb | 1339 | |
498 | amb | 1405 | WriteFileBuffered(fd,&wayx,sizeof(WayX)); |
499 | amb | 1339 | |
500 | amb | 1348 | size+=sizeof(index_t); |
501 | |||
502 | amb | 1405 | WriteFileBuffered(nfd,&size,FILESORT_VARSIZE); |
503 | WriteFileBuffered(nfd,&i,sizeof(index_t)); | ||
504 | WriteFileBuffered(nfd,name,size-sizeof(index_t)); | ||
505 | amb | 1348 | |
506 | amb | 1339 | if(!((i+1)%1000)) |
507 | amb | 1348 | printf_middle("Splitting Ways: Ways=%"Pindex_t" Segments=%"Pindex_t,i+1,segmentsx->number); |
508 | amb | 1339 | } |
509 | |||
510 | FinishSegmentList(segmentsx); | ||
511 | |||
512 | if(name) free(name); | ||
513 | |||
514 | /* Close the files */ | ||
515 | |||
516 | amb | 1405 | waysx->fd=CloseFileBuffered(waysx->fd); |
517 | CloseFileBuffered(fd); | ||
518 | amb | 1339 | |
519 | amb | 1405 | CloseFileBuffered(nfd); |
520 | amb | 1348 | |
521 | amb | 2033 | /* Unmap the index from memory */ |
522 | |||
523 | nodesx->idata=UnmapFile(nodesx->idata); | ||
524 | waysx->idata =UnmapFile(waysx->idata); | ||
525 | |||
526 | amb | 1339 | /* Print the final message */ |
527 | |||
528 | amb | 1355 | printf_last("Split Ways: Ways=%"Pindex_t" Segments=%"Pindex_t,waysx->number,segmentsx->number); |
529 | amb | 1339 | |
530 | return(segmentsx); | ||
531 | } | ||
532 | |||
533 | |||
534 | |||
535 | /*++++++++++++++++++++++++++++++++++++++ | ||
536 | amb | 1348 | Sort the way names and assign the offsets to the ways. |
537 | amb | 1339 | |
538 | WaysX *waysx The set of ways to process. | ||
539 | ++++++++++++++++++++++++++++++++++++++*/ | ||
540 | |||
541 | amb | 1348 | void SortWayNames(WaysX *waysx) |
542 | amb | 1339 | { |
543 | amb | 2189 | index_t i,nnames=0; |
544 | amb | 1348 | int nfd; |
545 | amb | 1339 | char *names[2]={NULL,NULL}; |
546 | amb | 1974 | uint32_t namelen[2]={0,0}; |
547 | amb | 1339 | uint32_t lastlength=0; |
548 | |||
549 | /* Print the start message */ | ||
550 | |||
551 | amb | 1348 | printf_first("Sorting Way Names"); |
552 | amb | 1339 | |
553 | amb | 1348 | /* Re-open the file read-only and new file writeable */ |
554 | amb | 1339 | |
555 | amb | 1699 | nfd=ReplaceFileBuffered(waysx->nfilename_tmp,&waysx->nfd); |
556 | amb | 1339 | |
557 | amb | 1348 | /* Sort the way names */ |
558 | amb | 310 | |
559 | amb | 1348 | waysx->nlength=0; |
560 | amb | 310 | |
561 | amb | 1348 | filesort_vary(waysx->nfd,nfd,NULL, |
562 | (int (*)(const void*,const void*))sort_by_name, | ||
563 | NULL); | ||
564 | |||
565 | amb | 310 | /* Close the files */ |
566 | |||
567 | amb | 1409 | waysx->nfd=CloseFileBuffered(waysx->nfd); |
568 | CloseFileBuffered(nfd); | ||
569 | amb | 310 | |
570 | /* Print the final message */ | ||
571 | |||
572 | amb | 1348 | printf_last("Sorted Way Names: Ways=%"Pindex_t,waysx->number); |
573 | amb | 310 | |
574 | |||
575 | amb | 1420 | /* Print the start message */ |
576 | |||
577 | printf_first("Updating Ways with Names: Ways=0 Names=0"); | ||
578 | |||
579 | amb | 2033 | /* Map into memory / open the file */ |
580 | amb | 1420 | |
581 | amb | 1348 | #if !SLIM |
582 | waysx->data=MapFileWriteable(waysx->filename_tmp); | ||
583 | #else | ||
584 | amb | 1414 | waysx->fd=SlimMapFileWriteable(waysx->filename_tmp); |
585 | amb | 1348 | #endif |
586 | |||
587 | /* Re-open the file read-only and new file writeable */ | ||
588 | amb | 310 | |
589 | amb | 1699 | nfd=ReplaceFileBuffered(waysx->nfilename_tmp,&waysx->nfd); |
590 | amb | 310 | |
591 | amb | 1355 | /* Update the ways and de-duplicate the names */ |
592 | amb | 310 | |
593 | amb | 650 | for(i=0;i<waysx->number;i++) |
594 | amb | 310 | { |
595 | amb | 1348 | WayX *wayx; |
596 | index_t index; | ||
597 | amb | 311 | FILESORT_VARINT size; |
598 | amb | 310 | |
599 | amb | 1405 | ReadFileBuffered(waysx->nfd,&size,FILESORT_VARSIZE); |
600 | amb | 310 | |
601 | if(namelen[nnames%2]<size) | ||
602 | amb | 1999 | names[nnames%2]=(char*)realloc_logassert((void*)names[nnames%2],namelen[nnames%2]=size); |
603 | amb | 310 | |
604 | amb | 1405 | ReadFileBuffered(waysx->nfd,&index,sizeof(index_t)); |
605 | ReadFileBuffered(waysx->nfd,names[nnames%2],size-sizeof(index_t)); | ||
606 | amb | 310 | |
607 | if(nnames==0 || strcmp(names[0],names[1])) | ||
608 | { | ||
609 | amb | 1405 | WriteFileBuffered(nfd,names[nnames%2],size-sizeof(index_t)); |
610 | amb | 310 | |
611 | lastlength=waysx->nlength; | ||
612 | amb | 1348 | waysx->nlength+=size-sizeof(index_t); |
613 | amb | 310 | |
614 | nnames++; | ||
615 | } | ||
616 | |||
617 | amb | 1348 | wayx=LookupWayX(waysx,index,1); |
618 | amb | 310 | |
619 | amb | 1348 | wayx->way.name=lastlength; |
620 | amb | 310 | |
621 | amb | 1348 | PutBackWayX(waysx,wayx); |
622 | |||
623 | amb | 757 | if(!((i+1)%1000)) |
624 | amb | 1348 | printf_middle("Updating Ways with Names: Ways=%"Pindex_t" Names=%"Pindex_t,i+1,nnames); |
625 | amb | 310 | } |
626 | |||
627 | if(names[0]) free(names[0]); | ||
628 | if(names[1]) free(names[1]); | ||
629 | |||
630 | /* Close the files */ | ||
631 | |||
632 | amb | 1405 | waysx->nfd=CloseFileBuffered(waysx->nfd); |
633 | CloseFileBuffered(nfd); | ||
634 | amb | 310 | |
635 | amb | 1348 | /* Unmap from memory / close the files */ |
636 | amb | 310 | |
637 | amb | 1348 | #if !SLIM |
638 | waysx->data=UnmapFile(waysx->data); | ||
639 | #else | ||
640 | amb | 1414 | waysx->fd=SlimUnmapFile(waysx->fd); |
641 | amb | 1348 | #endif |
642 | amb | 1420 | |
643 | /* Print the final message */ | ||
644 | |||
645 | printf_last("Updated Ways with Names: Ways=%"Pindex_t" Names=%"Pindex_t,waysx->number,nnames); | ||
646 | amb | 499 | } |
647 | |||
648 | |||
649 | /*++++++++++++++++++++++++++++++++++++++ | ||
650 | amb | 1348 | Sort the ways into name order. |
651 | amb | 1160 | |
652 | int sort_by_name Returns the comparison of the name fields. | ||
653 | |||
654 | amb | 1348 | char *a The first way name. |
655 | amb | 1160 | |
656 | amb | 1348 | char *b The second way name. |
657 | amb | 1160 | ++++++++++++++++++++++++++++++++++++++*/ |
658 | |||
659 | amb | 1348 | static int sort_by_name(char *a,char *b) |
660 | amb | 1160 | { |
661 | int compare; | ||
662 | amb | 1348 | char *a_name=a+sizeof(index_t); |
663 | char *b_name=b+sizeof(index_t); | ||
664 | amb | 1160 | |
665 | compare=strcmp(a_name,b_name); | ||
666 | |||
667 | if(compare) | ||
668 | return(compare); | ||
669 | else | ||
670 | return(FILESORT_PRESERVE_ORDER(a,b)); | ||
671 | } | ||
672 | |||
673 | |||
674 | /*++++++++++++++++++++++++++++++++++++++ | ||
675 | amb | 1100 | Compact the way list, removing duplicated ways and unused ways. |
676 | amb | 499 | |
677 | amb | 1100 | WaysX *waysx The set of ways to process. |
678 | amb | 1092 | |
679 | amb | 1100 | SegmentsX *segmentsx The set of segments to check. |
680 | amb | 499 | ++++++++++++++++++++++++++++++++++++++*/ |
681 | |||
682 | amb | 1100 | void CompactWayList(WaysX *waysx,SegmentsX *segmentsx) |
683 | amb | 499 | { |
684 | amb | 1100 | int fd; |
685 | index_t cnumber; | ||
686 | amb | 499 | |
687 | amb | 1208 | if(waysx->number==0) |
688 | return; | ||
689 | |||
690 | amb | 499 | /* Print the start message */ |
691 | |||
692 | amb | 1094 | printf_first("Sorting Ways and Compacting"); |
693 | amb | 1092 | |
694 | amb | 1093 | /* Allocate the array of indexes */ |
695 | amb | 499 | |
696 | amb | 1999 | waysx->cdata=(index_t*)malloc_logassert(waysx->number*sizeof(index_t)); |
697 | amb | 1598 | log_malloc(waysx->cdata,waysx->number*sizeof(index_t)); |
698 | amb | 499 | |
699 | amb | 1100 | /* Re-open the file read-only and a new file writeable */ |
700 | amb | 499 | |
701 | amb | 1699 | fd=ReplaceFileBuffered(waysx->filename_tmp,&waysx->fd); |
702 | amb | 1093 | |
703 | amb | 1094 | /* Sort the ways to allow compacting according to the properties */ |
704 | amb | 499 | |
705 | amb | 1094 | sortwaysx=waysx; |
706 | amb | 1100 | sortsegmentsx=segmentsx; |
707 | amb | 499 | |
708 | amb | 1114 | cnumber=filesort_fixed(waysx->fd,fd,sizeof(WayX),(int (*)(void*,index_t))delete_unused, |
709 | amb | 1106 | (int (*)(const void*,const void*))sort_by_name_and_prop_and_id, |
710 | (int (*)(void*,index_t))deduplicate_and_index_by_compact_id); | ||
711 | amb | 499 | |
712 | amb | 1100 | /* Close the files */ |
713 | amb | 499 | |
714 | amb | 1409 | waysx->fd=CloseFileBuffered(waysx->fd); |
715 | CloseFileBuffered(fd); | ||
716 | amb | 499 | |
717 | amb | 1420 | /* Free the data */ |
718 | |||
719 | amb | 1598 | log_free(segmentsx->usedway); |
720 | amb | 1420 | free(segmentsx->usedway); |
721 | segmentsx->usedway=NULL; | ||
722 | |||
723 | amb | 499 | /* Print the final message */ |
724 | |||
725 | amb | 1100 | printf_last("Sorted and Compacted Ways: Ways=%"Pindex_t" Unique=%"Pindex_t,waysx->number,cnumber); |
726 | waysx->number=cnumber; | ||
727 | amb | 224 | } |
728 | |||
729 | |||
730 | /*++++++++++++++++++++++++++++++++++++++ | ||
731 | amb | 1160 | Delete the ways that are no longer being used. |
732 | amb | 224 | |
733 | amb | 1160 | int delete_unused Return 1 if the value is to be kept, otherwise 0. |
734 | amb | 262 | |
735 | amb | 1160 | WayX *wayx The extended way. |
736 | amb | 262 | |
737 | amb | 1160 | index_t index The number of unsorted ways that have been read from the input file. |
738 | amb | 262 | ++++++++++++++++++++++++++++++++++++++*/ |
739 | |||
740 | amb | 1160 | static int delete_unused(WayX *wayx,index_t index) |
741 | amb | 262 | { |
742 | amb | 1160 | if(sortsegmentsx && !IsBitSet(sortsegmentsx->usedway,index)) |
743 | { | ||
744 | sortwaysx->cdata[index]=NO_WAY; | ||
745 | amb | 262 | |
746 | amb | 1160 | return(0); |
747 | } | ||
748 | amb | 262 | else |
749 | amb | 1160 | { |
750 | wayx->id=index; | ||
751 | amb | 262 | |
752 | amb | 1160 | return(1); |
753 | } | ||
754 | amb | 499 | } |
755 | |||
756 | |||
757 | /*++++++++++++++++++++++++++++++++++++++ | ||
758 | Sort the ways into name, properties and id order. | ||
759 | |||
760 | int sort_by_name_and_prop_and_id Returns the comparison of the name, properties and id fields. | ||
761 | |||
762 | WayX *a The first extended Way. | ||
763 | |||
764 | WayX *b The second extended Way. | ||
765 | ++++++++++++++++++++++++++++++++++++++*/ | ||
766 | |||
767 | static int sort_by_name_and_prop_and_id(WayX *a,WayX *b) | ||
768 | { | ||
769 | int compare; | ||
770 | index_t a_name=a->way.name; | ||
771 | index_t b_name=b->way.name; | ||
772 | |||
773 | if(a_name<b_name) | ||
774 | return(-1); | ||
775 | else if(a_name>b_name) | ||
776 | return(1); | ||
777 | |||
778 | amb | 310 | compare=WaysCompare(&a->way,&b->way); |
779 | |||
780 | if(compare) | ||
781 | return(compare); | ||
782 | |||
783 | return(sort_by_id(a,b)); | ||
784 | } | ||
785 | |||
786 | |||
787 | /*++++++++++++++++++++++++++++++++++++++ | ||
788 | amb | 1113 | Create the index of compacted Way identifiers and ignore Ways with duplicated properties. |
789 | |||
790 | int deduplicate_and_index_by_compact_id Return 1 if the value is to be kept, otherwise 0. | ||
791 | |||
792 | WayX *wayx The extended way. | ||
793 | |||
794 | index_t index The number of sorted ways that have already been written to the output file. | ||
795 | ++++++++++++++++++++++++++++++++++++++*/ | ||
796 | |||
797 | static int deduplicate_and_index_by_compact_id(WayX *wayx,index_t index) | ||
798 | { | ||
799 | amb | 1784 | static Way lastway; /* internal variable (reset by first call in each sort; index==0) */ |
800 | amb | 1113 | |
801 | amb | 1100 | if(index==0 || wayx->way.name!=lastway.name || WaysCompare(&lastway,&wayx->way)) |
802 | amb | 1094 | { |
803 | amb | 1100 | lastway=wayx->way; |
804 | amb | 1094 | |
805 | amb | 1100 | sortwaysx->cdata[wayx->id]=index; |
806 | amb | 1094 | |
807 | amb | 1100 | return(1); |
808 | amb | 1094 | } |
809 | amb | 1100 | else |
810 | { | ||
811 | sortwaysx->cdata[wayx->id]=index-1; | ||
812 | amb | 1094 | |
813 | amb | 1100 | return(0); |
814 | } | ||
815 | amb | 1094 | } |
816 | |||
817 | |||
818 | /*++++++++++++++++++++++++++++++++++++++ | ||
819 | amb | 285 | Save the way list to a file. |
820 | |||
821 | amb | 682 | WaysX *waysx The set of ways to save. |
822 | amb | 285 | |
823 | const char *filename The name of the file to save. | ||
824 | ++++++++++++++++++++++++++++++++++++++*/ | ||
825 | |||
826 | amb | 682 | void SaveWayList(WaysX *waysx,const char *filename) |
827 | amb | 285 | { |
828 | index_t i; | ||
829 | amb | 555 | int fd; |
830 | amb | 1302 | index_t position=0; |
831 | amb | 1104 | WayX wayx; |
832 | amb | 499 | WaysFile waysfile={0}; |
833 | amb | 529 | highways_t highways=0; |
834 | amb | 1991 | transports_t transports=0; |
835 | properties_t properties=0; | ||
836 | amb | 285 | |
837 | amb | 461 | /* Print the start message */ |
838 | |||
839 | amb | 519 | printf_first("Writing Ways: Ways=0"); |
840 | amb | 285 | |
841 | amb | 1104 | /* Re-open the files */ |
842 | amb | 461 | |
843 | amb | 1408 | waysx->fd=ReOpenFileBuffered(waysx->filename_tmp); |
844 | waysx->nfd=ReOpenFileBuffered(waysx->nfilename_tmp); | ||
845 | amb | 285 | |
846 | amb | 461 | /* Write out the ways data */ |
847 | amb | 285 | |
848 | amb | 1408 | fd=OpenFileBufferedNew(filename); |
849 | amb | 285 | |
850 | amb | 1408 | SeekFileBuffered(fd,sizeof(WaysFile)); |
851 | amb | 285 | |
852 | for(i=0;i<waysx->number;i++) | ||
853 | { | ||
854 | amb | 1408 | ReadFileBuffered(waysx->fd,&wayx,sizeof(WayX)); |
855 | amb | 285 | |
856 | amb | 1991 | highways |=HIGHWAYS(wayx.way.type); |
857 | transports|=wayx.way.allow; | ||
858 | properties|=wayx.way.props; | ||
859 | amb | 398 | |
860 | amb | 1408 | WriteFileBuffered(fd,&wayx.way,sizeof(Way)); |
861 | amb | 309 | |
862 | amb | 757 | if(!((i+1)%1000)) |
863 | amb | 790 | printf_middle("Writing Ways: Ways=%"Pindex_t,i+1); |
864 | amb | 285 | } |
865 | |||
866 | amb | 461 | /* Write out the ways names */ |
867 | amb | 285 | |
868 | amb | 1741 | SeekFileBuffered(fd,sizeof(WaysFile)+(offset_t)waysx->number*sizeof(Way)); |
869 | amb | 461 | |
870 | amb | 309 | while(position<waysx->nlength) |
871 | { | ||
872 | amb | 1302 | size_t len=1024; |
873 | amb | 309 | char temp[1024]; |
874 | |||
875 | if((waysx->nlength-position)<1024) | ||
876 | len=waysx->nlength-position; | ||
877 | |||
878 | amb | 1408 | ReadFileBuffered(waysx->nfd,temp,len); |
879 | amb | 1104 | |
880 | amb | 1408 | WriteFileBuffered(fd,temp,len); |
881 | amb | 309 | |
882 | position+=len; | ||
883 | } | ||
884 | |||
885 | amb | 1104 | /* Close the files */ |
886 | amb | 309 | |
887 | amb | 1408 | waysx->fd=CloseFileBuffered(waysx->fd); |
888 | waysx->nfd=CloseFileBuffered(waysx->nfd); | ||
889 | amb | 555 | |
890 | amb | 461 | /* Write out the header structure */ |
891 | |||
892 | amb | 1100 | waysfile.number =waysx->number; |
893 | amb | 461 | |
894 | amb | 1989 | waysfile.highways =highways; |
895 | amb | 1991 | waysfile.transports=transports; |
896 | waysfile.properties=properties; | ||
897 | amb | 461 | |
898 | amb | 1408 | SeekFileBuffered(fd,0); |
899 | WriteFileBuffered(fd,&waysfile,sizeof(WaysFile)); | ||
900 | amb | 461 | |
901 | amb | 1408 | CloseFileBuffered(fd); |
902 | amb | 285 | |
903 | amb | 461 | /* Print the final message */ |
904 | |||
905 | amb | 1100 | printf_last("Wrote Ways: Ways=%"Pindex_t,waysx->number); |
906 | amb | 285 | } |
Properties
Name | Value |
---|---|
cvs:description | Extended ways functions. |