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 1392 - (hide annotations) (download) (as text)
Mon Jun 10 18:42:55 2013 UTC (11 years, 10 months ago) by amb
File MIME type: text/x-csrc
File size: 25437 byte(s)
Fix typo in program logging.

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     nodesx->fd=ReOpenFile(nodesx->filename);
139    
140     InvalidateNodeXCache(nodesx->cache);
141     #endif
142    
143 amb 1338 waysx->fd=ReOpenFile(waysx->filename);
144 amb 1342 relationsx->rrfd=ReOpenFile(relationsx->rrfilename);
145 amb 1341 relationsx->trfd=ReOpenFile(relationsx->trfilename);
146 amb 1338
147 amb 1317 /* Open the binary log file read-only and a new file writeable */
148    
149     oldfd=ReOpenFile(errorbinfilename);
150    
151     DeleteFile(errorbinfilename);
152    
153     newfd=OpenFileNew(errorbinfilename);
154    
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     finished=ReadFile(oldfd,&errorlogobject,sizeof(ErrorLogObject));
164    
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 1341 if(((errorlogobjects[0].type_id>>56)&0xff)=='N')
178     {
179     node_t node=(node_t)(errorlogobjects[0].type_id&(uint64_t)0x00ffffffffffffff);
180 amb 1338
181 amb 1341 lookup_lat_long_node(nodesx,node,&errorlat,&errorlon);
182     }
183     else if(((errorlogobjects[0].type_id>>56)&0xff)=='W')
184 amb 1317 {
185 amb 1341 way_t way=(way_t)(errorlogobjects[0].type_id&(uint64_t)0x00ffffffffffffff);
186 amb 1317
187 amb 1362 lookup_lat_long_way(waysx,nodesx,way,&errorlat,&errorlon,errorlogsx->number);
188 amb 1341 }
189     else if(((errorlogobjects[0].type_id>>56)&0xff)=='R')
190     {
191     relation_t relation=(relation_t)(errorlogobjects[0].type_id&(uint64_t)0x00ffffffffffffff);
192    
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     if(((errorlogobjects[i].type_id>>56)&0xff)=='N')
205 amb 1317 {
206 amb 1341 node_t node=(node_t)(errorlogobjects[i].type_id&(uint64_t)0x00ffffffffffffff);
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 1341 else if(((errorlogobjects[i].type_id>>56)&0xff)=='W') nways++;
214     else if(((errorlogobjects[i].type_id>>56)&0xff)=='R') nrelations++;
215 amb 1317 }
216 amb 1341
217     if(nways==0 && nrelations==0) /* only nodes */
218     ;
219     else if(ncoords) /* some good nodes, possibly ways and/or relations */
220     ;
221     else if(nways) /* no good nodes, possibly some good ways */
222 amb 1338 {
223 amb 1341 for(i=0;i<nerrorlogobjects;i++)
224     if(((errorlogobjects[i].type_id>>56)&0xff)=='W')
225     {
226     way_t way=(way_t)(errorlogobjects[i].type_id&(uint64_t)0x00ffffffffffffff);
227 amb 1338
228 amb 1362 if(lookup_lat_long_way(waysx,nodesx,way,&latitude[ncoords],&longitude[ncoords],errorlogsx->number))
229 amb 1341 ncoords++;
230     }
231     }
232 amb 1338
233 amb 1341 if(nrelations==0) /* only nodes and/or ways */
234     ;
235     else if(ncoords) /* some good nodes and/or ways, possibly relations */
236     ;
237     else /* if(nrelations) */
238     {
239     for(i=0;i<nerrorlogobjects;i++)
240     if(((errorlogobjects[i].type_id>>56)&0xff)=='R')
241     {
242     relation_t relation=(relation_t)(errorlogobjects[i].type_id&(uint64_t)0x00ffffffffffffff);
243 amb 1338
244 amb 1362 if(lookup_lat_long_relation(relationsx,waysx,nodesx,relation,&latitude[ncoords],&longitude[ncoords],errorlogsx->number))
245 amb 1341 ncoords++;
246     }
247     }
248 amb 1338
249 amb 1341 if(ncoords)
250     {
251     errorlat=0;
252     errorlon=0;
253 amb 1338
254 amb 1341 for(i=0;i<ncoords;i++)
255     {
256     errorlat+=latitude[i];
257     errorlon+=longitude[i];
258     }
259 amb 1338
260 amb 1341 errorlat/=ncoords;
261     errorlon/=ncoords;
262 amb 1338 }
263 amb 1341 else
264 amb 1338 {
265 amb 1341 errorlat=NO_LATLONG;
266     errorlon=NO_LATLONG;
267 amb 1338 }
268 amb 1317 }
269    
270     /* Write to file */
271    
272     errorlogx.offset=offset;
273     errorlogx.length=errorlogobject.offset-offset;
274    
275 amb 1338 errorlogx.latitude =errorlat;
276     errorlogx.longitude=errorlon;
277 amb 1317
278     WriteFile(newfd,&errorlogx,sizeof(ErrorLogX));
279    
280 amb 1362 errorlogsx->number++;
281 amb 1317
282     offset=errorlogobject.offset;
283     nerrorlogobjects=0;
284    
285 amb 1362 if(!(errorlogsx->number%10000))
286     printf_middle("Calculating Coordinates: Errors=%"Pindex_t,errorlogsx->number);
287 amb 1317 }
288    
289     /* Store for later */
290    
291     logassert(nerrorlogobjects<8,"Too many error log objects for one error message."); /* Only a limited amount of information stored. */
292    
293     errorlogobjects[nerrorlogobjects]=errorlogobject;
294    
295     nerrorlogobjects++;
296     }
297     while(!finished);
298    
299     /* Unmap from memory / close the files */
300    
301     #if !SLIM
302     nodesx->data=UnmapFile(nodesx->data);
303     #else
304     nodesx->fd=CloseFile(nodesx->fd);
305     #endif
306    
307 amb 1338 waysx->fd=CloseFile(waysx->fd);
308 amb 1342 relationsx->rrfd=CloseFile(relationsx->rrfd);
309 amb 1341 relationsx->trfd=CloseFile(relationsx->trfd);
310 amb 1338
311 amb 1317 CloseFile(oldfd);
312     CloseFile(newfd);
313    
314     /* Print the final message */
315    
316 amb 1362 printf_last("Calculated Coordinates: Errors=%"Pindex_t,errorlogsx->number);
317 amb 1317 }
318    
319    
320     /*++++++++++++++++++++++++++++++++++++++
321     Re-index the nodes that were kept.
322    
323     NodesX *nodesx The set of nodes to process (contains the filename and number of nodes).
324     ++++++++++++++++++++++++++++++++++++++*/
325    
326     static void reindex_nodes(NodesX *nodesx)
327     {
328     int fd;
329     index_t index=0;
330     NodeX nodex;
331    
332     nodesx->number=nodesx->knumber;
333    
334     nodesx->idata=(node_t*)malloc(nodesx->number*sizeof(node_t));
335    
336     /* Get the node id for each node in the file. */
337    
338     fd=ReOpenFile(nodesx->filename);
339    
340     while(!ReadFile(fd,&nodex,sizeof(NodeX)))
341     {
342     nodesx->idata[index]=nodex.id;
343    
344     index++;
345     }
346    
347     CloseFile(fd);
348     }
349    
350    
351     /*++++++++++++++++++++++++++++++++++++++
352     Re-index the ways that were kept.
353    
354     WaysX *waysx The set of ways to process (contains the filename and number of ways).
355     ++++++++++++++++++++++++++++++++++++++*/
356    
357     static void reindex_ways(WaysX *waysx)
358     {
359     int fd;
360     off_t size,position=0;
361     index_t index=0;
362    
363     waysx->number=waysx->knumber;
364    
365     waysx->idata=(way_t*)malloc(waysx->number*sizeof(way_t));
366     waysx->odata=(off_t*)malloc(waysx->number*sizeof(off_t));
367    
368     /* Get the way id and the offset for each way in the file */
369    
370     size=SizeFile(waysx->filename);
371    
372     fd=ReOpenFile(waysx->filename);
373    
374     while(position<size)
375     {
376 amb 1338 WayX wayx;
377 amb 1317 FILESORT_VARINT waysize;
378    
379     SeekReadFile(fd,&waysize,FILESORT_VARSIZE,position);
380 amb 1338 SeekReadFile(fd,&wayx,sizeof(WayX),position+FILESORT_VARSIZE);
381 amb 1317
382     waysx->idata[index]=wayx.id;
383 amb 1338 waysx->odata[index]=position+FILESORT_VARSIZE+sizeof(WayX);
384 amb 1317
385     index++;
386    
387     position+=waysize+FILESORT_VARSIZE;
388     }
389    
390     CloseFile(fd);
391     }
392    
393    
394     /*++++++++++++++++++++++++++++++++++++++
395     Re-index the relations that were kept.
396    
397 amb 1341 RelationsX *relationsx The set of relations to process (contains the filenames and numbers of relations).
398 amb 1317 ++++++++++++++++++++++++++++++++++++++*/
399    
400     static void reindex_relations(RelationsX *relationsx)
401     {
402 amb 1341 int fd;
403     off_t size,position=0;
404     index_t index;
405     TurnRelX turnrelx;
406    
407     /* Route relations */
408    
409 amb 1342 relationsx->rrnumber=relationsx->rrknumber;
410 amb 1341
411 amb 1342 relationsx->rridata=(relation_t*)malloc(relationsx->rrnumber*sizeof(relation_t));
412     relationsx->rrodata=(off_t*)malloc(relationsx->rrnumber*sizeof(off_t));
413 amb 1341
414     /* Get the relation id and the offset for each relation in the file */
415    
416 amb 1342 size=SizeFile(relationsx->rrfilename);
417 amb 1341
418 amb 1342 fd=ReOpenFile(relationsx->rrfilename);
419 amb 1341
420     index=0;
421    
422     while(position<size)
423     {
424     FILESORT_VARINT relationsize;
425     RouteRelX routerelx;
426    
427     SeekReadFile(fd,&relationsize,FILESORT_VARSIZE,position);
428     SeekReadFile(fd,&routerelx,sizeof(RouteRelX),position+FILESORT_VARSIZE);
429    
430 amb 1342 relationsx->rridata[index]=routerelx.id;
431     relationsx->rrodata[index]=position+FILESORT_VARSIZE+sizeof(RouteRelX);
432 amb 1341
433     index++;
434    
435     position+=relationsize+FILESORT_VARSIZE;
436     }
437    
438     CloseFile(fd);
439    
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     fd=ReOpenFile(relationsx->trfilename);
450    
451     index=0;
452    
453     while(!ReadFile(fd,&turnrelx,sizeof(TurnRelX)))
454     {
455     relationsx->tridata[index]=turnrelx.id;
456    
457     index++;
458     }
459    
460     CloseFile(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     SeekFile(waysx->fd,offset);
528    
529     /* Choose a random pair of adjacent nodes */
530    
531     if(ReadFile(waysx->fd,&node1,sizeof(node_t)) || node1==NO_NODE_ID)
532     return 0;
533    
534     if(ReadFile(waysx->fd,&node2,sizeof(node_t)) || node2==NO_NODE_ID)
535     return lookup_lat_long_node(nodesx,node1,latitude,longitude);
536    
537     prevnode=node2;
538    
539     while(!ReadFile(waysx->fd,&node,sizeof(node_t)) && node!=NO_NODE_ID)
540     {
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     SeekReadFile(relationsx->trfd,&turnrelx,sizeof(TurnRelX),index*sizeof(TurnRelX));
601    
602     if(lookup_lat_long_node(nodesx,turnrelx.via,latitude,longitude))
603     return 1;
604    
605     if(lookup_lat_long_way(waysx,nodesx,turnrelx.from,latitude,longitude,error))
606     return 1;
607    
608     if(lookup_lat_long_way(waysx,nodesx,turnrelx.to,latitude,longitude,error))
609     return 1;
610    
611     return 0;
612     }
613     }
614     else
615     {
616 amb 1370 int count;
617 amb 1342 off_t offset=relationsx->rrodata[index];
618 amb 1370 node_t node=NO_NODE_ID,tempnode;
619 amb 1341 way_t way=NO_WAY_ID,tempway;
620     relation_t relation=NO_RELATION_ID,temprelation;
621    
622 amb 1342 SeekFile(relationsx->rrfd,offset);
623 amb 1341
624 amb 1370 /* Choose a random node */
625    
626     count=0;
627    
628     while(!ReadFile(relationsx->rrfd,&tempnode,sizeof(node_t)) && tempnode!=NO_NODE_ID)
629     {
630     count++;
631    
632     if((error%count)==0) /* A 1/count chance */
633     node=tempnode;
634     }
635    
636     if(lookup_lat_long_node(nodesx,node,latitude,longitude))
637     return 1;
638    
639 amb 1341 /* Choose a random way */
640    
641 amb 1370 count=0;
642    
643 amb 1342 while(!ReadFile(relationsx->rrfd,&tempway,sizeof(way_t)) && tempway!=NO_WAY_ID)
644 amb 1341 {
645     count++;
646    
647     if((error%count)==0) /* A 1/count chance */
648     way=tempway;
649     }
650    
651     if(lookup_lat_long_way(waysx,nodesx,way,latitude,longitude,error))
652     return 1;
653    
654     /* Choose a random relation */
655    
656 amb 1370 count=0;
657    
658 amb 1342 while(!ReadFile(relationsx->rrfd,&temprelation,sizeof(relation_t)) && temprelation!=NO_RELATION_ID)
659 amb 1341 {
660     count++;
661    
662     if((error%count)==0) /* A 1/count chance */
663     relation=temprelation;
664     }
665    
666     return lookup_lat_long_relation(relationsx,waysx,nodesx,relation,latitude,longitude,error);
667     }
668     }
669    
670    
671     /*++++++++++++++++++++++++++++++++++++++
672 amb 1317 Sort the error logs geographically.
673 amb 1362
674     ErrorLogsX *errorlogsx The set of error logs to sort.
675 amb 1317 ++++++++++++++++++++++++++++++++++++++*/
676    
677 amb 1362 void SortErrorLogsGeographically(ErrorLogsX *errorlogsx)
678 amb 1317 {
679     int oldfd,newfd;
680 amb 1362 ll_bin_t lat_min_bin,lat_max_bin,lon_min_bin,lon_max_bin;
681 amb 1317
682     /* Print the start message */
683    
684     printf_first("Sorting Errors Geographically");
685    
686 amb 1362 /* Work out the range of data */
687    
688     lat_min=radians_to_latlong( 2);
689     lat_max=radians_to_latlong(-2);
690     lon_min=radians_to_latlong( 4);
691     lon_max=radians_to_latlong(-4);
692    
693 amb 1317 /* Re-open the file read-only and a new file writeable */
694    
695     oldfd=ReOpenFile(errorbinfilename);
696    
697     DeleteFile(errorbinfilename);
698    
699     newfd=OpenFileNew(errorbinfilename);
700    
701     /* Sort errors geographically */
702    
703 amb 1362 filesort_fixed(oldfd,newfd,sizeof(ErrorLogX),NULL,
704     (int (*)(const void*,const void*))sort_by_lat_long,
705     (int (*)(void*,index_t))measure_lat_long);
706 amb 1317
707     /* Close the files */
708    
709     CloseFile(oldfd);
710     CloseFile(newfd);
711    
712 amb 1362 /* Work out the number of bins */
713    
714     lat_min_bin=latlong_to_bin(lat_min);
715     lon_min_bin=latlong_to_bin(lon_min);
716     lat_max_bin=latlong_to_bin(lat_max);
717     lon_max_bin=latlong_to_bin(lon_max);
718    
719     errorlogsx->latzero=lat_min_bin;
720     errorlogsx->lonzero=lon_min_bin;
721    
722     errorlogsx->latbins=(lat_max_bin-lat_min_bin)+1;
723     errorlogsx->lonbins=(lon_max_bin-lon_min_bin)+1;
724    
725 amb 1317 /* Print the final message */
726    
727 amb 1392 printf_last("Sorted Errors Geographically: Errors=%"Pindex_t,errorlogsx->number);
728 amb 1317 }
729    
730    
731     /*++++++++++++++++++++++++++++++++++++++
732     Sort the errors into latitude and longitude order (first by longitude bin
733     number, then by latitude bin number and then by exact longitude and then by
734     exact latitude).
735    
736     int sort_by_lat_long Returns the comparison of the latitude and longitude fields.
737    
738     ErrorLogX *a The first error location.
739    
740     ErrorLogX *b The second error location.
741     ++++++++++++++++++++++++++++++++++++++*/
742    
743     static int sort_by_lat_long(ErrorLogX *a,ErrorLogX *b)
744     {
745     ll_bin_t a_lon=latlong_to_bin(a->longitude);
746     ll_bin_t b_lon=latlong_to_bin(b->longitude);
747    
748     if(a_lon<b_lon)
749     return(-1);
750     else if(a_lon>b_lon)
751     return(1);
752     else
753     {
754     ll_bin_t a_lat=latlong_to_bin(a->latitude);
755     ll_bin_t b_lat=latlong_to_bin(b->latitude);
756    
757     if(a_lat<b_lat)
758     return(-1);
759     else if(a_lat>b_lat)
760     return(1);
761     else
762     {
763     if(a->longitude<b->longitude)
764     return(-1);
765     else if(a->longitude>b->longitude)
766     return(1);
767     else
768     {
769     if(a->latitude<b->latitude)
770     return(-1);
771     else if(a->latitude>b->latitude)
772     return(1);
773     }
774    
775     return(FILESORT_PRESERVE_ORDER(a,b));
776     }
777     }
778     }
779    
780    
781     /*++++++++++++++++++++++++++++++++++++++
782 amb 1362 Measure the extent of the data.
783    
784     int measure_lat_long Return 1 if the value is to be kept, otherwise 0.
785    
786     ErrorLogX *errorlogx The error location.
787    
788     index_t index The number of sorted error locations that have already been written to the output file.
789     ++++++++++++++++++++++++++++++++++++++*/
790    
791     static int measure_lat_long(ErrorLogX *errorlogx,index_t index)
792     {
793     if(errorlogx->latitude!=NO_LATLONG)
794     {
795     if(errorlogx->latitude<lat_min)
796     lat_min=errorlogx->latitude;
797     if(errorlogx->latitude>lat_max)
798     lat_max=errorlogx->latitude;
799     if(errorlogx->longitude<lon_min)
800     lon_min=errorlogx->longitude;
801     if(errorlogx->longitude>lon_max)
802     lon_max=errorlogx->longitude;
803     }
804    
805     return(1);
806     }
807    
808    
809     /*++++++++++++++++++++++++++++++++++++++
810 amb 1317 Save the binary error log.
811    
812 amb 1362 ErrorLogsX *errorlogsx The set of error logs to write.
813 amb 1317
814     char *filename The name of the final file to write.
815     ++++++++++++++++++++++++++++++++++++++*/
816    
817 amb 1362 void SaveErrorLogs(ErrorLogsX *errorlogsx,char *filename)
818 amb 1317 {
819     ErrorLogsFile errorlogsfile;
820     ErrorLogX errorlogx;
821     int oldfd,newfd;
822     ll_bin2_t latlonbin=0,maxlatlonbins;
823     index_t *offsets;
824     index_t number=0,number_geo=0,number_nongeo=0;
825     off_t size;
826    
827     /* Print the start message */
828    
829     printf_first("Writing Errors: Geographical=0 Non-geographical=0");
830    
831     /* Allocate the memory for the geographical offsets array */
832    
833 amb 1362 offsets=(index_t*)malloc((errorlogsx->latbins*errorlogsx->lonbins+1)*sizeof(index_t));
834 amb 1317
835     logassert(offsets,"Failed to allocate memory (try using slim mode?)"); /* Check malloc() worked */
836    
837     latlonbin=0;
838    
839     /* Re-open the file */
840    
841     oldfd=ReOpenFile(errorbinfilename);
842    
843     newfd=OpenFileNew(filename);
844    
845     /* Write out the geographical errors */
846    
847 amb 1362 SeekFile(newfd,sizeof(ErrorLogsFile)+(errorlogsx->latbins*errorlogsx->lonbins+1)*sizeof(index_t));
848 amb 1317
849     while(!ReadFile(oldfd,&errorlogx,sizeof(ErrorLogX)))
850     {
851     ErrorLog errorlog={0};
852     ll_bin_t latbin,lonbin;
853     ll_bin2_t llbin;
854    
855     if(errorlogx.latitude==NO_LATLONG)
856     continue;
857    
858     /* Create the ErrorLog */
859    
860     errorlog.latoffset=latlong_to_off(errorlogx.latitude);
861     errorlog.lonoffset=latlong_to_off(errorlogx.longitude);
862    
863     errorlog.offset=errorlogx.offset;
864     errorlog.length=errorlogx.length;
865    
866     /* Work out the offsets */
867    
868 amb 1362 latbin=latlong_to_bin(errorlogx.latitude )-errorlogsx->latzero;
869     lonbin=latlong_to_bin(errorlogx.longitude)-errorlogsx->lonzero;
870     llbin=lonbin*errorlogsx->latbins+latbin;
871 amb 1317
872     for(;latlonbin<=llbin;latlonbin++)
873     offsets[latlonbin]=number_geo;
874    
875     /* Write the data */
876    
877     WriteFile(newfd,&errorlog,sizeof(ErrorLog));
878    
879     number_geo++;
880     number++;
881    
882     if(!(number%10000))
883     printf_middle("Writing Errors: Geographical=%"Pindex_t" Non-geographical=%"Pindex_t,number_geo,number_nongeo);
884     }
885    
886     /* Write out the non-geographical errors */
887    
888     SeekFile(oldfd,0);
889    
890     while(!ReadFile(oldfd,&errorlogx,sizeof(ErrorLogX)))
891     {
892     ErrorLog errorlog={0};
893    
894     if(errorlogx.latitude!=NO_LATLONG)
895     continue;
896    
897     /* Create the ErrorLog */
898    
899     errorlog.latoffset=0;
900     errorlog.lonoffset=0;
901    
902     errorlog.offset=errorlogx.offset;
903     errorlog.length=errorlogx.length;
904    
905     /* Write the data */
906    
907     WriteFile(newfd,&errorlog,sizeof(ErrorLog));
908    
909     number_nongeo++;
910     number++;
911    
912     if(!(number%10000))
913     printf_middle("Writing Errors: Geographical=%"Pindex_t" Non-geographical=%"Pindex_t,number_geo,number_nongeo);
914     }
915    
916     /* Close the input file */
917    
918     CloseFile(oldfd);
919    
920     DeleteFile(errorbinfilename);
921    
922     /* Append the text from the log file */
923    
924     size=SizeFile(errorlogfilename);
925    
926     oldfd=ReOpenFile(errorlogfilename);
927    
928     while(size)
929     {
930 amb 1321 int i;
931     char buffer[4096];
932 amb 1317 off_t chunksize=(size>sizeof(buffer)?sizeof(buffer):size);
933    
934     ReadFile(oldfd,buffer,chunksize);
935    
936 amb 1321 for(i=0;i<chunksize;i++)
937     if(buffer[i]=='\n')
938     buffer[i]=0;
939    
940 amb 1317 WriteFile(newfd,buffer,chunksize);
941    
942     size-=chunksize;
943     }
944    
945     CloseFile(oldfd);
946    
947     /* Finish off the offset indexing and write them out */
948    
949 amb 1362 maxlatlonbins=errorlogsx->latbins*errorlogsx->lonbins;
950 amb 1317
951     for(;latlonbin<=maxlatlonbins;latlonbin++)
952     offsets[latlonbin]=number_geo;
953    
954     SeekFile(newfd,sizeof(ErrorLogsFile));
955 amb 1362 WriteFile(newfd,offsets,(errorlogsx->latbins*errorlogsx->lonbins+1)*sizeof(index_t));
956 amb 1317
957     free(offsets);
958    
959     /* Write out the header structure */
960    
961     errorlogsfile.number =number;
962     errorlogsfile.number_geo =number_geo;
963     errorlogsfile.number_nongeo=number_nongeo;
964    
965 amb 1362 errorlogsfile.latbins=errorlogsx->latbins;
966     errorlogsfile.lonbins=errorlogsx->lonbins;
967 amb 1317
968 amb 1362 errorlogsfile.latzero=errorlogsx->latzero;
969     errorlogsfile.lonzero=errorlogsx->lonzero;
970 amb 1317
971     SeekFile(newfd,0);
972     WriteFile(newfd,&errorlogsfile,sizeof(ErrorLogsFile));
973    
974     CloseFile(newfd);
975    
976     /* Print the final message */
977    
978     printf_last("Wrote Errors: Geographical=%"Pindex_t" Non-geographical=%"Pindex_t,number_geo,number_nongeo);
979     }