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/errorlogx.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1414 - (hide annotations) (download) (as text)
Sat Jun 22 18:49:33 2013 UTC (11 years, 9 months ago) by amb
File MIME type: text/x-csrc
File size: 25520 byte(s)
Use SlimMapFile() and SlimUnmapFile() as the function names for the slim mode of
operation to open and close the files (to hide the fact that they are files
being opened for reading or writing unbuffered).

1 amb 1317 /***************************************
2 amb 1319 Error log processing functions.
3 amb 1317
4     Part of the Routino routing software.
5     ******************/ /******************
6     This file Copyright 2013 Andrew M. Bishop
7    
8     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     ***************************************/
21    
22    
23     #include "typesx.h"
24     #include "nodesx.h"
25     #include "waysx.h"
26     #include "relationsx.h"
27    
28 amb 1320 #include "errorlogx.h"
29     #include "errorlog.h"
30    
31 amb 1317 #include "files.h"
32     #include "sorting.h"
33    
34    
35 amb 1362 /* Global variables */
36 amb 1317
37     /*+ The name of the error log file. +*/
38     extern char *errorlogfilename;
39    
40     /*+ The name of the binary error log file. +*/
41     extern char *errorbinfilename;
42    
43 amb 1362 /* Local variables */
44 amb 1317
45 amb 1362 /*+ Temporary file-local variables for use by the sort functions. +*/
46     static latlong_t lat_min,lat_max,lon_min,lon_max;
47    
48 amb 1317 /* Local functions */
49    
50     static void reindex_nodes(NodesX *nodesx);
51     static void reindex_ways(WaysX *waysx);
52     static void reindex_relations(RelationsX *relationsx);
53 amb 1341
54     static int lookup_lat_long_node(NodesX *nodesx,node_t node,latlong_t *latitude,latlong_t *longitude);
55     static int lookup_lat_long_way(WaysX *waysx,NodesX *nodesx,way_t way,latlong_t *latitude,latlong_t *longitude,index_t error);
56     static int lookup_lat_long_relation(RelationsX *relationsx,WaysX *waysx,NodesX *nodesx,relation_t relation,latlong_t *latitude,latlong_t *longitude,index_t error);
57    
58 amb 1317 static int sort_by_lat_long(ErrorLogX *a,ErrorLogX *b);
59 amb 1362 static int measure_lat_long(ErrorLogX *errorlogx,index_t index);
60 amb 1317
61    
62     /*++++++++++++++++++++++++++++++++++++++
63 amb 1362 Allocate a new error log list (create a new file).
64    
65     ErrorLogsX *NewErrorLogList Returns a pointer to the error log list.
66     ++++++++++++++++++++++++++++++++++++++*/
67    
68     ErrorLogsX *NewErrorLogList(void)
69     {
70     ErrorLogsX *errorlogsx;
71    
72     errorlogsx=(ErrorLogsX*)calloc(1,sizeof(ErrorLogsX));
73    
74     logassert(errorlogsx,"Failed to allocate memory (try using slim mode?)"); /* Check calloc() worked */
75    
76     return(errorlogsx);
77     }
78    
79    
80     /*++++++++++++++++++++++++++++++++++++++
81     Free an error log list.
82    
83     ErrorLogsX *errorlogsx The set of error logs to be freed.
84     ++++++++++++++++++++++++++++++++++++++*/
85    
86     void FreeErrorLogList(ErrorLogsX *errorlogsx)
87     {
88     free(errorlogsx);
89     }
90    
91    
92     /*++++++++++++++++++++++++++++++++++++++
93 amb 1317 Process the binary error log.
94    
95 amb 1362 ErrorLogsX *errorlogsx The set of error logs to update.
96    
97 amb 1317 NodesX *nodesx The set of nodes.
98    
99     WaysX *waysx The set of ways.
100    
101     RelationsX *relationsx The set of relations.
102     ++++++++++++++++++++++++++++++++++++++*/
103    
104 amb 1362 void ProcessErrorLogs(ErrorLogsX *errorlogsx,NodesX *nodesx,WaysX *waysx,RelationsX *relationsx)
105 amb 1317 {
106     int oldfd,newfd;
107     uint32_t offset=0;
108     int nerrorlogobjects=0;
109     int finished;
110     ErrorLogObject errorlogobjects[8];
111    
112     /* Re-index the nodes, ways and relations */
113    
114 amb 1341 printf_first("Re-indexing the Data: Nodes=0 Ways=0 Route-Relations=0 Turn-Relations=0");
115 amb 1317
116     reindex_nodes(nodesx);
117    
118 amb 1341 printf_middle("Re-indexing the Data: Nodes=%"Pindex_t" Ways=0 Route-Relations=0 Turn-Relations=0",nodesx->number);
119 amb 1317
120     reindex_ways(waysx);
121    
122 amb 1341 printf_middle("Re-indexing the Data: Nodes=%"Pindex_t" Ways=%"Pindex_t" Route-Relations=0 Turn-Relations=0",nodesx->number,waysx->number);
123 amb 1317
124     reindex_relations(relationsx);
125    
126 amb 1342 printf_last("Re-indexed the Data: Nodes=%"Pindex_t" Ways=%"Pindex_t" Route-Relations=%"Pindex_t" Turn-Relations=%"Pindex_t,nodesx->number,waysx->number,relationsx->rrnumber,relationsx->trnumber);
127 amb 1317
128    
129     /* Print the start message */
130    
131     printf_first("Calculating Coordinates: Errors=0");
132    
133     /* Map into memory / open the files */
134    
135     #if !SLIM
136     nodesx->data=MapFile(nodesx->filename);
137     #else
138 amb 1414 nodesx->fd=SlimMapFile(nodesx->filename);
139 amb 1317
140     InvalidateNodeXCache(nodesx->cache);
141     #endif
142    
143 amb 1410 waysx->fd=ReOpenFileBuffered(waysx->filename);
144     relationsx->rrfd=ReOpenFileBuffered(relationsx->rrfilename);
145     relationsx->trfd=ReOpenFileBuffered(relationsx->trfilename);
146 amb 1338
147 amb 1317 /* Open the binary log file read-only and a new file writeable */
148    
149 amb 1408 oldfd=ReOpenFileBuffered(errorbinfilename);
150 amb 1317
151     DeleteFile(errorbinfilename);
152    
153 amb 1408 newfd=OpenFileBufferedNew(errorbinfilename);
154 amb 1317
155     /* Loop through the file and merge the raw data into coordinates */
156    
157 amb 1362 errorlogsx->number=0;
158 amb 1317
159     do
160     {
161     ErrorLogObject errorlogobject;
162    
163 amb 1408 finished=ReadFileBuffered(oldfd,&errorlogobject,sizeof(ErrorLogObject));
164 amb 1317
165     if(finished)
166     errorlogobject.offset=SizeFile(errorlogfilename);
167    
168     if(offset!=errorlogobject.offset)
169     {
170     ErrorLogX errorlogx;
171 amb 1341 latlong_t errorlat=NO_LATLONG,errorlon=NO_LATLONG;
172 amb 1317
173     /* Calculate suitable coordinates */
174    
175 amb 1341 if(nerrorlogobjects==1)
176 amb 1317 {
177 amb 1395 if(errorlogobjects[0].type=='N')
178 amb 1341 {
179 amb 1395 node_t node=(node_t)errorlogobjects[0].id;
180 amb 1338
181 amb 1341 lookup_lat_long_node(nodesx,node,&errorlat,&errorlon);
182     }
183 amb 1395 else if(errorlogobjects[0].type=='W')
184 amb 1317 {
185 amb 1395 way_t way=(way_t)errorlogobjects[0].id;
186 amb 1317
187 amb 1362 lookup_lat_long_way(waysx,nodesx,way,&errorlat,&errorlon,errorlogsx->number);
188 amb 1341 }
189 amb 1395 else if(errorlogobjects[0].type=='R')
190 amb 1341 {
191 amb 1395 relation_t relation=(relation_t)errorlogobjects[0].type;
192 amb 1341
193 amb 1362 lookup_lat_long_relation(relationsx,waysx,nodesx,relation,&errorlat,&errorlon,errorlogsx->number);
194 amb 1341 }
195     }
196     else
197     {
198     latlong_t latitude[8],longitude[8];
199     int i;
200     int ncoords=0,nnodes=0,nways=0,nrelations=0;
201    
202     for(i=0;i<nerrorlogobjects;i++)
203     {
204 amb 1395 if(errorlogobjects[i].type=='N')
205 amb 1317 {
206 amb 1395 node_t node=(node_t)errorlogobjects[i].id;
207 amb 1317
208 amb 1341 if(lookup_lat_long_node(nodesx,node,&latitude[ncoords],&longitude[ncoords]))
209     ncoords++;
210 amb 1338
211     nnodes++;
212 amb 1317 }
213 amb 1395 else if(errorlogobjects[i].type=='W')
214     nways++;
215     else if(errorlogobjects[i].type=='R')
216     nrelations++;
217 amb 1317 }
218 amb 1341
219     if(nways==0 && nrelations==0) /* only nodes */
220     ;
221     else if(ncoords) /* some good nodes, possibly ways and/or relations */
222     ;
223     else if(nways) /* no good nodes, possibly some good ways */
224 amb 1338 {
225 amb 1341 for(i=0;i<nerrorlogobjects;i++)
226 amb 1395 if(errorlogobjects[i].type=='W')
227 amb 1341 {
228 amb 1395 way_t way=(way_t)errorlogobjects[i].id;
229 amb 1338
230 amb 1362 if(lookup_lat_long_way(waysx,nodesx,way,&latitude[ncoords],&longitude[ncoords],errorlogsx->number))
231 amb 1341 ncoords++;
232     }
233     }
234 amb 1338
235 amb 1341 if(nrelations==0) /* only nodes and/or ways */
236     ;
237     else if(ncoords) /* some good nodes and/or ways, possibly relations */
238     ;
239     else /* if(nrelations) */
240     {
241     for(i=0;i<nerrorlogobjects;i++)
242 amb 1395 if(errorlogobjects[i].type=='R')
243 amb 1341 {
244 amb 1395 relation_t relation=(relation_t)errorlogobjects[i].id;
245 amb 1338
246 amb 1362 if(lookup_lat_long_relation(relationsx,waysx,nodesx,relation,&latitude[ncoords],&longitude[ncoords],errorlogsx->number))
247 amb 1341 ncoords++;
248     }
249     }
250 amb 1338
251 amb 1341 if(ncoords)
252     {
253     errorlat=0;
254     errorlon=0;
255 amb 1338
256 amb 1341 for(i=0;i<ncoords;i++)
257     {
258     errorlat+=latitude[i];
259     errorlon+=longitude[i];
260     }
261 amb 1338
262 amb 1341 errorlat/=ncoords;
263     errorlon/=ncoords;
264 amb 1338 }
265 amb 1341 else
266 amb 1338 {
267 amb 1341 errorlat=NO_LATLONG;
268     errorlon=NO_LATLONG;
269 amb 1338 }
270 amb 1317 }
271    
272     /* Write to file */
273    
274     errorlogx.offset=offset;
275     errorlogx.length=errorlogobject.offset-offset;
276    
277 amb 1338 errorlogx.latitude =errorlat;
278     errorlogx.longitude=errorlon;
279 amb 1317
280 amb 1408 WriteFileBuffered(newfd,&errorlogx,sizeof(ErrorLogX));
281 amb 1317
282 amb 1362 errorlogsx->number++;
283 amb 1317
284     offset=errorlogobject.offset;
285     nerrorlogobjects=0;
286    
287 amb 1362 if(!(errorlogsx->number%10000))
288     printf_middle("Calculating Coordinates: Errors=%"Pindex_t,errorlogsx->number);
289 amb 1317 }
290    
291     /* Store for later */
292    
293     logassert(nerrorlogobjects<8,"Too many error log objects for one error message."); /* Only a limited amount of information stored. */
294    
295     errorlogobjects[nerrorlogobjects]=errorlogobject;
296    
297     nerrorlogobjects++;
298     }
299     while(!finished);
300    
301     /* Unmap from memory / close the files */
302    
303     #if !SLIM
304     nodesx->data=UnmapFile(nodesx->data);
305     #else
306 amb 1414 nodesx->fd=SlimUnmapFile(nodesx->fd);
307 amb 1317 #endif
308    
309 amb 1410 waysx->fd=CloseFileBuffered(waysx->fd);
310     relationsx->rrfd=CloseFileBuffered(relationsx->rrfd);
311     relationsx->trfd=CloseFileBuffered(relationsx->trfd);
312 amb 1338
313 amb 1408 CloseFileBuffered(oldfd);
314     CloseFileBuffered(newfd);
315 amb 1317
316     /* Print the final message */
317    
318 amb 1362 printf_last("Calculated Coordinates: Errors=%"Pindex_t,errorlogsx->number);
319 amb 1317 }
320    
321    
322     /*++++++++++++++++++++++++++++++++++++++
323     Re-index the nodes that were kept.
324    
325     NodesX *nodesx The set of nodes to process (contains the filename and number of nodes).
326     ++++++++++++++++++++++++++++++++++++++*/
327    
328     static void reindex_nodes(NodesX *nodesx)
329     {
330     int fd;
331     index_t index=0;
332     NodeX nodex;
333    
334     nodesx->number=nodesx->knumber;
335    
336     nodesx->idata=(node_t*)malloc(nodesx->number*sizeof(node_t));
337    
338     /* Get the node id for each node in the file. */
339    
340 amb 1408 fd=ReOpenFileBuffered(nodesx->filename);
341 amb 1317
342 amb 1408 while(!ReadFileBuffered(fd,&nodex,sizeof(NodeX)))
343 amb 1317 {
344     nodesx->idata[index]=nodex.id;
345    
346     index++;
347     }
348    
349 amb 1408 CloseFileBuffered(fd);
350 amb 1317 }
351    
352    
353     /*++++++++++++++++++++++++++++++++++++++
354     Re-index the ways that were kept.
355    
356     WaysX *waysx The set of ways to process (contains the filename and number of ways).
357     ++++++++++++++++++++++++++++++++++++++*/
358    
359     static void reindex_ways(WaysX *waysx)
360     {
361 amb 1405 FILESORT_VARINT waysize;
362 amb 1317 int fd;
363 amb 1405 off_t position=0;
364 amb 1317 index_t index=0;
365    
366     waysx->number=waysx->knumber;
367    
368     waysx->idata=(way_t*)malloc(waysx->number*sizeof(way_t));
369     waysx->odata=(off_t*)malloc(waysx->number*sizeof(off_t));
370    
371     /* Get the way id and the offset for each way in the file */
372    
373 amb 1405 fd=ReOpenFileBuffered(waysx->filename);
374 amb 1317
375 amb 1405 while(!ReadFileBuffered(fd,&waysize,FILESORT_VARSIZE))
376 amb 1317 {
377 amb 1338 WayX wayx;
378 amb 1317
379 amb 1405 ReadFileBuffered(fd,&wayx,sizeof(WayX));
380 amb 1317
381     waysx->idata[index]=wayx.id;
382 amb 1338 waysx->odata[index]=position+FILESORT_VARSIZE+sizeof(WayX);
383 amb 1317
384     index++;
385    
386 amb 1406 SkipFileBuffered(fd,waysize-sizeof(WayX));
387 amb 1405
388 amb 1317 position+=waysize+FILESORT_VARSIZE;
389     }
390    
391 amb 1405 CloseFileBuffered(fd);
392 amb 1317 }
393    
394    
395     /*++++++++++++++++++++++++++++++++++++++
396     Re-index the relations that were kept.
397    
398 amb 1341 RelationsX *relationsx The set of relations to process (contains the filenames and numbers of relations).
399 amb 1317 ++++++++++++++++++++++++++++++++++++++*/
400    
401     static void reindex_relations(RelationsX *relationsx)
402     {
403 amb 1405 FILESORT_VARINT relationsize;
404 amb 1341 int fd;
405 amb 1405 off_t position=0;
406 amb 1341 index_t index;
407     TurnRelX turnrelx;
408    
409     /* Route relations */
410    
411 amb 1342 relationsx->rrnumber=relationsx->rrknumber;
412 amb 1341
413 amb 1342 relationsx->rridata=(relation_t*)malloc(relationsx->rrnumber*sizeof(relation_t));
414     relationsx->rrodata=(off_t*)malloc(relationsx->rrnumber*sizeof(off_t));
415 amb 1341
416     /* Get the relation id and the offset for each relation in the file */
417    
418 amb 1405 fd=ReOpenFileBuffered(relationsx->rrfilename);
419 amb 1341
420     index=0;
421    
422 amb 1405 while(!ReadFileBuffered(fd,&relationsize,FILESORT_VARSIZE))
423 amb 1341 {
424     RouteRelX routerelx;
425    
426 amb 1405 ReadFileBuffered(fd,&routerelx,sizeof(RouteRelX));
427 amb 1341
428 amb 1342 relationsx->rridata[index]=routerelx.id;
429     relationsx->rrodata[index]=position+FILESORT_VARSIZE+sizeof(RouteRelX);
430 amb 1341
431     index++;
432    
433 amb 1406 SkipFileBuffered(fd,relationsize-sizeof(RouteRelX));
434 amb 1405
435 amb 1341 position+=relationsize+FILESORT_VARSIZE;
436     }
437    
438 amb 1405 CloseFileBuffered(fd);
439 amb 1341
440    
441     /* Turn relations */
442    
443     relationsx->trnumber=relationsx->trknumber;
444    
445     relationsx->tridata=(relation_t*)malloc(relationsx->trnumber*sizeof(relation_t));
446    
447     /* Get the relation id and the offset for each relation in the file */
448    
449 amb 1405 fd=ReOpenFileBuffered(relationsx->trfilename);
450 amb 1341
451     index=0;
452    
453 amb 1405 while(!ReadFileBuffered(fd,&turnrelx,sizeof(TurnRelX)))
454 amb 1341 {
455     relationsx->tridata[index]=turnrelx.id;
456    
457     index++;
458     }
459    
460 amb 1405 CloseFileBuffered(fd);
461 amb 1317 }
462    
463    
464     /*++++++++++++++++++++++++++++++++++++++
465 amb 1341 Lookup a node's latitude and longitude.
466    
467     int lookup_lat_long_node Returns 1 if a node was found.
468    
469     NodesX *nodesx The set of nodes to use.
470    
471     node_t node The node number.
472    
473     latlong_t *latitude Returns the latitude.
474    
475     latlong_t *longitude Returns the longitude.
476     ++++++++++++++++++++++++++++++++++++++*/
477    
478     static int lookup_lat_long_node(NodesX *nodesx,node_t node,latlong_t *latitude,latlong_t *longitude)
479     {
480     index_t index=IndexNodeX(nodesx,node);
481    
482     if(index==NO_NODE)
483     return 0;
484     else
485     {
486     NodeX *nodex=LookupNodeX(nodesx,index,1);
487    
488     *latitude =nodex->latitude;
489     *longitude=nodex->longitude;
490    
491     return 1;
492     }
493     }
494    
495    
496     /*++++++++++++++++++++++++++++++++++++++
497     Lookup a way's latitude and longitude.
498    
499     int lookup_lat_long_way Returns 1 if a way was found.
500    
501     WaysX *waysx The set of ways to use.
502    
503     NodesX *nodesx The set of nodes to use.
504    
505     way_t way The way number.
506    
507     latlong_t *latitude Returns the latitude.
508    
509     latlong_t *longitude Returns the longitude.
510    
511     index_t error The index of the error in the complete set of errors.
512     ++++++++++++++++++++++++++++++++++++++*/
513    
514     static int lookup_lat_long_way(WaysX *waysx,NodesX *nodesx,way_t way,latlong_t *latitude,latlong_t *longitude,index_t error)
515     {
516     index_t index=IndexWayX(waysx,way);
517    
518     if(index==NO_WAY)
519     return 0;
520     else
521     {
522     int count=1;
523     off_t offset=waysx->odata[index];
524     node_t node1,node2,prevnode,node;
525     latlong_t latitude1,longitude1,latitude2,longitude2;
526    
527 amb 1410 SeekFileBuffered(waysx->fd,offset);
528 amb 1341
529     /* Choose a random pair of adjacent nodes */
530    
531 amb 1410 if(ReadFileBuffered(waysx->fd,&node1,sizeof(node_t)) || node1==NO_NODE_ID)
532 amb 1341 return 0;
533    
534 amb 1410 if(ReadFileBuffered(waysx->fd,&node2,sizeof(node_t)) || node2==NO_NODE_ID)
535 amb 1341 return lookup_lat_long_node(nodesx,node1,latitude,longitude);
536    
537     prevnode=node2;
538    
539 amb 1410 while(!ReadFileBuffered(waysx->fd,&node,sizeof(node_t)) && node!=NO_NODE_ID)
540 amb 1341 {
541     count++;
542    
543     if((error%count)==0) /* A 1/count chance */
544     {
545     node1=prevnode;
546     node2=node;
547     }
548    
549     prevnode=node;
550     }
551    
552     if(!lookup_lat_long_node(nodesx,node1,&latitude1,&longitude1))
553     return lookup_lat_long_node(nodesx,node2,latitude,longitude);
554    
555     if(!lookup_lat_long_node(nodesx,node2,&latitude2,&longitude2))
556     return lookup_lat_long_node(nodesx,node1,latitude,longitude);
557    
558     *latitude =(latitude1 +latitude2 )/2;
559     *longitude=(longitude1+longitude2)/2;
560    
561     return 1;
562     }
563     }
564    
565    
566     /*++++++++++++++++++++++++++++++++++++++
567     Lookup a relation's latitude and longitude.
568    
569     int lookup_lat_long_relation Returns 1 if a relation was found.
570    
571     RelationsX *relationsx The set of relations to use.
572    
573     WaysX *waysx The set of ways to use.
574    
575     NodesX *nodesx The set of nodes to use.
576    
577     relation_t relation The relation number.
578    
579     latlong_t *latitude Returns the latitude.
580    
581     latlong_t *longitude Returns the longitude.
582    
583     index_t error The index of the error in the complete set of errors.
584     ++++++++++++++++++++++++++++++++++++++*/
585    
586     static int lookup_lat_long_relation(RelationsX *relationsx,WaysX *waysx,NodesX *nodesx,relation_t relation,latlong_t *latitude,latlong_t *longitude,index_t error)
587     {
588     index_t index=IndexRouteRelX(relationsx,relation);
589    
590     if(index==NO_RELATION)
591     {
592     index=IndexTurnRelX(relationsx,relation);
593    
594     if(index==NO_RELATION)
595     return 0;
596     else
597     {
598     TurnRelX turnrelx;
599    
600 amb 1410 SeekFileBuffered(relationsx->trfd,index*sizeof(TurnRelX));
601     ReadFileBuffered(relationsx->trfd,&turnrelx,sizeof(TurnRelX));
602 amb 1341
603     if(lookup_lat_long_node(nodesx,turnrelx.via,latitude,longitude))
604     return 1;
605    
606     if(lookup_lat_long_way(waysx,nodesx,turnrelx.from,latitude,longitude,error))
607     return 1;
608    
609     if(lookup_lat_long_way(waysx,nodesx,turnrelx.to,latitude,longitude,error))
610     return 1;
611    
612     return 0;
613     }
614     }
615     else
616     {
617 amb 1370 int count;
618 amb 1342 off_t offset=relationsx->rrodata[index];
619 amb 1370 node_t node=NO_NODE_ID,tempnode;
620 amb 1341 way_t way=NO_WAY_ID,tempway;
621     relation_t relation=NO_RELATION_ID,temprelation;
622    
623 amb 1410 SeekFileBuffered(relationsx->rrfd,offset);
624 amb 1341
625 amb 1370 /* Choose a random node */
626    
627     count=0;
628    
629 amb 1410 while(!ReadFileBuffered(relationsx->rrfd,&tempnode,sizeof(node_t)) && tempnode!=NO_NODE_ID)
630 amb 1370 {
631     count++;
632    
633     if((error%count)==0) /* A 1/count chance */
634     node=tempnode;
635     }
636    
637     if(lookup_lat_long_node(nodesx,node,latitude,longitude))
638     return 1;
639    
640 amb 1341 /* Choose a random way */
641    
642 amb 1370 count=0;
643    
644 amb 1410 while(!ReadFileBuffered(relationsx->rrfd,&tempway,sizeof(way_t)) && tempway!=NO_WAY_ID)
645 amb 1341 {
646     count++;
647    
648     if((error%count)==0) /* A 1/count chance */
649     way=tempway;
650     }
651    
652     if(lookup_lat_long_way(waysx,nodesx,way,latitude,longitude,error))
653     return 1;
654    
655     /* Choose a random relation */
656    
657 amb 1370 count=0;
658    
659 amb 1410 while(!ReadFileBuffered(relationsx->rrfd,&temprelation,sizeof(relation_t)) && temprelation!=NO_RELATION_ID)
660 amb 1341 {
661     count++;
662    
663     if((error%count)==0) /* A 1/count chance */
664     relation=temprelation;
665     }
666    
667     return lookup_lat_long_relation(relationsx,waysx,nodesx,relation,latitude,longitude,error);
668     }
669     }
670    
671    
672     /*++++++++++++++++++++++++++++++++++++++
673 amb 1317 Sort the error logs geographically.
674 amb 1362
675     ErrorLogsX *errorlogsx The set of error logs to sort.
676 amb 1317 ++++++++++++++++++++++++++++++++++++++*/
677    
678 amb 1362 void SortErrorLogsGeographically(ErrorLogsX *errorlogsx)
679 amb 1317 {
680     int oldfd,newfd;
681 amb 1362 ll_bin_t lat_min_bin,lat_max_bin,lon_min_bin,lon_max_bin;
682 amb 1317
683     /* Print the start message */
684    
685     printf_first("Sorting Errors Geographically");
686    
687 amb 1362 /* Work out the range of data */
688    
689     lat_min=radians_to_latlong( 2);
690     lat_max=radians_to_latlong(-2);
691     lon_min=radians_to_latlong( 4);
692     lon_max=radians_to_latlong(-4);
693    
694 amb 1317 /* Re-open the file read-only and a new file writeable */
695    
696 amb 1409 oldfd=ReOpenFileBuffered(errorbinfilename);
697 amb 1317
698     DeleteFile(errorbinfilename);
699    
700 amb 1409 newfd=OpenFileBufferedNew(errorbinfilename);
701 amb 1317
702     /* Sort errors geographically */
703    
704 amb 1362 filesort_fixed(oldfd,newfd,sizeof(ErrorLogX),NULL,
705     (int (*)(const void*,const void*))sort_by_lat_long,
706     (int (*)(void*,index_t))measure_lat_long);
707 amb 1317
708     /* Close the files */
709    
710 amb 1409 CloseFileBuffered(oldfd);
711     CloseFileBuffered(newfd);
712 amb 1317
713 amb 1362 /* Work out the number of bins */
714    
715     lat_min_bin=latlong_to_bin(lat_min);
716     lon_min_bin=latlong_to_bin(lon_min);
717     lat_max_bin=latlong_to_bin(lat_max);
718     lon_max_bin=latlong_to_bin(lon_max);
719    
720     errorlogsx->latzero=lat_min_bin;
721     errorlogsx->lonzero=lon_min_bin;
722    
723     errorlogsx->latbins=(lat_max_bin-lat_min_bin)+1;
724     errorlogsx->lonbins=(lon_max_bin-lon_min_bin)+1;
725    
726 amb 1317 /* Print the final message */
727    
728 amb 1392 printf_last("Sorted Errors Geographically: Errors=%"Pindex_t,errorlogsx->number);
729 amb 1317 }
730    
731    
732     /*++++++++++++++++++++++++++++++++++++++
733     Sort the errors into latitude and longitude order (first by longitude bin
734     number, then by latitude bin number and then by exact longitude and then by
735     exact latitude).
736    
737     int sort_by_lat_long Returns the comparison of the latitude and longitude fields.
738    
739     ErrorLogX *a The first error location.
740    
741     ErrorLogX *b The second error location.
742     ++++++++++++++++++++++++++++++++++++++*/
743    
744     static int sort_by_lat_long(ErrorLogX *a,ErrorLogX *b)
745     {
746     ll_bin_t a_lon=latlong_to_bin(a->longitude);
747     ll_bin_t b_lon=latlong_to_bin(b->longitude);
748    
749     if(a_lon<b_lon)
750     return(-1);
751     else if(a_lon>b_lon)
752     return(1);
753     else
754     {
755     ll_bin_t a_lat=latlong_to_bin(a->latitude);
756     ll_bin_t b_lat=latlong_to_bin(b->latitude);
757    
758     if(a_lat<b_lat)
759     return(-1);
760     else if(a_lat>b_lat)
761     return(1);
762     else
763     {
764     if(a->longitude<b->longitude)
765     return(-1);
766     else if(a->longitude>b->longitude)
767     return(1);
768     else
769     {
770     if(a->latitude<b->latitude)
771     return(-1);
772     else if(a->latitude>b->latitude)
773     return(1);
774     }
775    
776     return(FILESORT_PRESERVE_ORDER(a,b));
777     }
778     }
779     }
780    
781    
782     /*++++++++++++++++++++++++++++++++++++++
783 amb 1362 Measure the extent of the data.
784    
785     int measure_lat_long Return 1 if the value is to be kept, otherwise 0.
786    
787     ErrorLogX *errorlogx The error location.
788    
789     index_t index The number of sorted error locations that have already been written to the output file.
790     ++++++++++++++++++++++++++++++++++++++*/
791    
792     static int measure_lat_long(ErrorLogX *errorlogx,index_t index)
793     {
794     if(errorlogx->latitude!=NO_LATLONG)
795     {
796     if(errorlogx->latitude<lat_min)
797     lat_min=errorlogx->latitude;
798     if(errorlogx->latitude>lat_max)
799     lat_max=errorlogx->latitude;
800     if(errorlogx->longitude<lon_min)
801     lon_min=errorlogx->longitude;
802     if(errorlogx->longitude>lon_max)
803     lon_max=errorlogx->longitude;
804     }
805    
806     return(1);
807     }
808    
809    
810     /*++++++++++++++++++++++++++++++++++++++
811 amb 1317 Save the binary error log.
812    
813 amb 1362 ErrorLogsX *errorlogsx The set of error logs to write.
814 amb 1317
815     char *filename The name of the final file to write.
816     ++++++++++++++++++++++++++++++++++++++*/
817    
818 amb 1362 void SaveErrorLogs(ErrorLogsX *errorlogsx,char *filename)
819 amb 1317 {
820     ErrorLogsFile errorlogsfile;
821     ErrorLogX errorlogx;
822     int oldfd,newfd;
823     ll_bin2_t latlonbin=0,maxlatlonbins;
824     index_t *offsets;
825     index_t number=0,number_geo=0,number_nongeo=0;
826     off_t size;
827    
828     /* Print the start message */
829    
830     printf_first("Writing Errors: Geographical=0 Non-geographical=0");
831    
832     /* Allocate the memory for the geographical offsets array */
833    
834 amb 1362 offsets=(index_t*)malloc((errorlogsx->latbins*errorlogsx->lonbins+1)*sizeof(index_t));
835 amb 1317
836     logassert(offsets,"Failed to allocate memory (try using slim mode?)"); /* Check malloc() worked */
837    
838     latlonbin=0;
839    
840     /* Re-open the file */
841    
842 amb 1408 oldfd=ReOpenFileBuffered(errorbinfilename);
843 amb 1317
844 amb 1408 newfd=OpenFileBufferedNew(filename);
845 amb 1317
846     /* Write out the geographical errors */
847    
848 amb 1408 SeekFileBuffered(newfd,sizeof(ErrorLogsFile)+(errorlogsx->latbins*errorlogsx->lonbins+1)*sizeof(index_t));
849 amb 1317
850 amb 1408 while(!ReadFileBuffered(oldfd,&errorlogx,sizeof(ErrorLogX)))
851 amb 1317 {
852     ErrorLog errorlog={0};
853     ll_bin_t latbin,lonbin;
854     ll_bin2_t llbin;
855    
856     if(errorlogx.latitude==NO_LATLONG)
857     continue;
858    
859     /* Create the ErrorLog */
860    
861     errorlog.latoffset=latlong_to_off(errorlogx.latitude);
862     errorlog.lonoffset=latlong_to_off(errorlogx.longitude);
863    
864     errorlog.offset=errorlogx.offset;
865     errorlog.length=errorlogx.length;
866    
867     /* Work out the offsets */
868    
869 amb 1362 latbin=latlong_to_bin(errorlogx.latitude )-errorlogsx->latzero;
870     lonbin=latlong_to_bin(errorlogx.longitude)-errorlogsx->lonzero;
871     llbin=lonbin*errorlogsx->latbins+latbin;
872 amb 1317
873     for(;latlonbin<=llbin;latlonbin++)
874     offsets[latlonbin]=number_geo;
875    
876     /* Write the data */
877    
878 amb 1408 WriteFileBuffered(newfd,&errorlog,sizeof(ErrorLog));
879 amb 1317
880     number_geo++;
881     number++;
882    
883     if(!(number%10000))
884     printf_middle("Writing Errors: Geographical=%"Pindex_t" Non-geographical=%"Pindex_t,number_geo,number_nongeo);
885     }
886    
887     /* Write out the non-geographical errors */
888    
889 amb 1408 SeekFileBuffered(oldfd,0);
890 amb 1317
891 amb 1408 while(!ReadFileBuffered(oldfd,&errorlogx,sizeof(ErrorLogX)))
892 amb 1317 {
893     ErrorLog errorlog={0};
894    
895     if(errorlogx.latitude!=NO_LATLONG)
896     continue;
897    
898     /* Create the ErrorLog */
899    
900     errorlog.latoffset=0;
901     errorlog.lonoffset=0;
902    
903     errorlog.offset=errorlogx.offset;
904     errorlog.length=errorlogx.length;
905    
906     /* Write the data */
907    
908 amb 1408 WriteFileBuffered(newfd,&errorlog,sizeof(ErrorLog));
909 amb 1317
910     number_nongeo++;
911     number++;
912    
913     if(!(number%10000))
914     printf_middle("Writing Errors: Geographical=%"Pindex_t" Non-geographical=%"Pindex_t,number_geo,number_nongeo);
915     }
916    
917     /* Close the input file */
918    
919 amb 1408 CloseFileBuffered(oldfd);
920 amb 1317
921     DeleteFile(errorbinfilename);
922    
923     /* Append the text from the log file */
924    
925     size=SizeFile(errorlogfilename);
926    
927 amb 1413 oldfd=ReOpenFileBuffered(errorlogfilename);
928 amb 1317
929     while(size)
930     {
931 amb 1321 int i;
932     char buffer[4096];
933 amb 1317 off_t chunksize=(size>sizeof(buffer)?sizeof(buffer):size);
934    
935 amb 1413 ReadFileBuffered(oldfd,buffer,chunksize);
936 amb 1317
937 amb 1321 for(i=0;i<chunksize;i++)
938     if(buffer[i]=='\n')
939     buffer[i]=0;
940    
941 amb 1408 WriteFileBuffered(newfd,buffer,chunksize);
942 amb 1317
943     size-=chunksize;
944     }
945    
946 amb 1413 CloseFileBuffered(oldfd);
947 amb 1317
948     /* Finish off the offset indexing and write them out */
949    
950 amb 1362 maxlatlonbins=errorlogsx->latbins*errorlogsx->lonbins;
951 amb 1317
952     for(;latlonbin<=maxlatlonbins;latlonbin++)
953     offsets[latlonbin]=number_geo;
954    
955 amb 1408 SeekFileBuffered(newfd,sizeof(ErrorLogsFile));
956     WriteFileBuffered(newfd,offsets,(errorlogsx->latbins*errorlogsx->lonbins+1)*sizeof(index_t));
957 amb 1317
958     free(offsets);
959    
960     /* Write out the header structure */
961    
962     errorlogsfile.number =number;
963     errorlogsfile.number_geo =number_geo;
964     errorlogsfile.number_nongeo=number_nongeo;
965    
966 amb 1362 errorlogsfile.latbins=errorlogsx->latbins;
967     errorlogsfile.lonbins=errorlogsx->lonbins;
968 amb 1317
969 amb 1362 errorlogsfile.latzero=errorlogsx->latzero;
970     errorlogsfile.lonzero=errorlogsx->lonzero;
971 amb 1317
972 amb 1408 SeekFileBuffered(newfd,0);
973     WriteFileBuffered(newfd,&errorlogsfile,sizeof(ErrorLogsFile));
974 amb 1317
975 amb 1408 CloseFileBuffered(newfd);
976 amb 1317
977     /* Print the final message */
978    
979     printf_last("Wrote Errors: Geographical=%"Pindex_t" Non-geographical=%"Pindex_t,number_geo,number_nongeo);
980     }