Routino SVN Repository Browser

Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino

ViewVC logotype

Annotation of /trunk/src/waysx.c

Parent Directory Parent Directory | Revision Log 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)
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.