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 1362 - (hide annotations) (download) (as text)
Sat Jun 1 11:10:24 2013 UTC (11 years, 10 months ago) by amb
File MIME type: text/x-csrc
File size: 25046 byte(s)
Make the functions for processing error logs more like the ones for nodes, ways
and relations.

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     int count=0;
617 amb 1342 off_t offset=relationsx->rrodata[index];
618 amb 1341 way_t way=NO_WAY_ID,tempway;
619     relation_t relation=NO_RELATION_ID,temprelation;
620    
621 amb 1342 SeekFile(relationsx->rrfd,offset);
622 amb 1341
623     /* Choose a random way */
624    
625 amb 1342 while(!ReadFile(relationsx->rrfd,&tempway,sizeof(way_t)) && tempway!=NO_WAY_ID)
626 amb 1341 {
627     count++;
628    
629     if((error%count)==0) /* A 1/count chance */
630     way=tempway;
631     }
632    
633     if(lookup_lat_long_way(waysx,nodesx,way,latitude,longitude,error))
634     return 1;
635    
636     /* Choose a random relation */
637    
638 amb 1342 while(!ReadFile(relationsx->rrfd,&temprelation,sizeof(relation_t)) && temprelation!=NO_RELATION_ID)
639 amb 1341 {
640     count++;
641    
642     if((error%count)==0) /* A 1/count chance */
643     relation=temprelation;
644     }
645    
646     return lookup_lat_long_relation(relationsx,waysx,nodesx,relation,latitude,longitude,error);
647     }
648     }
649    
650    
651     /*++++++++++++++++++++++++++++++++++++++
652 amb 1317 Sort the error logs geographically.
653 amb 1362
654     ErrorLogsX *errorlogsx The set of error logs to sort.
655 amb 1317 ++++++++++++++++++++++++++++++++++++++*/
656    
657 amb 1362 void SortErrorLogsGeographically(ErrorLogsX *errorlogsx)
658 amb 1317 {
659     int oldfd,newfd;
660 amb 1362 ll_bin_t lat_min_bin,lat_max_bin,lon_min_bin,lon_max_bin;
661 amb 1317
662     /* Print the start message */
663    
664     printf_first("Sorting Errors Geographically");
665    
666 amb 1362 /* Work out the range of data */
667    
668     lat_min=radians_to_latlong( 2);
669     lat_max=radians_to_latlong(-2);
670     lon_min=radians_to_latlong( 4);
671     lon_max=radians_to_latlong(-4);
672    
673 amb 1317 /* Re-open the file read-only and a new file writeable */
674    
675     oldfd=ReOpenFile(errorbinfilename);
676    
677     DeleteFile(errorbinfilename);
678    
679     newfd=OpenFileNew(errorbinfilename);
680    
681     /* Sort errors geographically */
682    
683 amb 1362 filesort_fixed(oldfd,newfd,sizeof(ErrorLogX),NULL,
684     (int (*)(const void*,const void*))sort_by_lat_long,
685     (int (*)(void*,index_t))measure_lat_long);
686 amb 1317
687     /* Close the files */
688    
689     CloseFile(oldfd);
690     CloseFile(newfd);
691    
692 amb 1362 /* Work out the number of bins */
693    
694     lat_min_bin=latlong_to_bin(lat_min);
695     lon_min_bin=latlong_to_bin(lon_min);
696     lat_max_bin=latlong_to_bin(lat_max);
697     lon_max_bin=latlong_to_bin(lon_max);
698    
699     errorlogsx->latzero=lat_min_bin;
700     errorlogsx->lonzero=lon_min_bin;
701    
702     errorlogsx->latbins=(lat_max_bin-lat_min_bin)+1;
703     errorlogsx->lonbins=(lon_max_bin-lon_min_bin)+1;
704    
705 amb 1317 /* Print the final message */
706    
707 amb 1362 printf_last("Sorted Errors Geographically: Error=%"Pindex_t,errorlogsx->number);
708 amb 1317 }
709    
710    
711     /*++++++++++++++++++++++++++++++++++++++
712     Sort the errors into latitude and longitude order (first by longitude bin
713     number, then by latitude bin number and then by exact longitude and then by
714     exact latitude).
715    
716     int sort_by_lat_long Returns the comparison of the latitude and longitude fields.
717    
718     ErrorLogX *a The first error location.
719    
720     ErrorLogX *b The second error location.
721     ++++++++++++++++++++++++++++++++++++++*/
722    
723     static int sort_by_lat_long(ErrorLogX *a,ErrorLogX *b)
724     {
725     ll_bin_t a_lon=latlong_to_bin(a->longitude);
726     ll_bin_t b_lon=latlong_to_bin(b->longitude);
727    
728     if(a_lon<b_lon)
729     return(-1);
730     else if(a_lon>b_lon)
731     return(1);
732     else
733     {
734     ll_bin_t a_lat=latlong_to_bin(a->latitude);
735     ll_bin_t b_lat=latlong_to_bin(b->latitude);
736    
737     if(a_lat<b_lat)
738     return(-1);
739     else if(a_lat>b_lat)
740     return(1);
741     else
742     {
743     if(a->longitude<b->longitude)
744     return(-1);
745     else if(a->longitude>b->longitude)
746     return(1);
747     else
748     {
749     if(a->latitude<b->latitude)
750     return(-1);
751     else if(a->latitude>b->latitude)
752     return(1);
753     }
754    
755     return(FILESORT_PRESERVE_ORDER(a,b));
756     }
757     }
758     }
759    
760    
761     /*++++++++++++++++++++++++++++++++++++++
762 amb 1362 Measure the extent of the data.
763    
764     int measure_lat_long Return 1 if the value is to be kept, otherwise 0.
765    
766     ErrorLogX *errorlogx The error location.
767    
768     index_t index The number of sorted error locations that have already been written to the output file.
769     ++++++++++++++++++++++++++++++++++++++*/
770    
771     static int measure_lat_long(ErrorLogX *errorlogx,index_t index)
772     {
773     if(errorlogx->latitude!=NO_LATLONG)
774     {
775     if(errorlogx->latitude<lat_min)
776     lat_min=errorlogx->latitude;
777     if(errorlogx->latitude>lat_max)
778     lat_max=errorlogx->latitude;
779     if(errorlogx->longitude<lon_min)
780     lon_min=errorlogx->longitude;
781     if(errorlogx->longitude>lon_max)
782     lon_max=errorlogx->longitude;
783     }
784    
785     return(1);
786     }
787    
788    
789     /*++++++++++++++++++++++++++++++++++++++
790 amb 1317 Save the binary error log.
791    
792 amb 1362 ErrorLogsX *errorlogsx The set of error logs to write.
793 amb 1317
794     char *filename The name of the final file to write.
795     ++++++++++++++++++++++++++++++++++++++*/
796    
797 amb 1362 void SaveErrorLogs(ErrorLogsX *errorlogsx,char *filename)
798 amb 1317 {
799     ErrorLogsFile errorlogsfile;
800     ErrorLogX errorlogx;
801     int oldfd,newfd;
802     ll_bin2_t latlonbin=0,maxlatlonbins;
803     index_t *offsets;
804     index_t number=0,number_geo=0,number_nongeo=0;
805     off_t size;
806    
807     /* Print the start message */
808    
809     printf_first("Writing Errors: Geographical=0 Non-geographical=0");
810    
811     /* Allocate the memory for the geographical offsets array */
812    
813 amb 1362 offsets=(index_t*)malloc((errorlogsx->latbins*errorlogsx->lonbins+1)*sizeof(index_t));
814 amb 1317
815     logassert(offsets,"Failed to allocate memory (try using slim mode?)"); /* Check malloc() worked */
816    
817     latlonbin=0;
818    
819     /* Re-open the file */
820    
821     oldfd=ReOpenFile(errorbinfilename);
822    
823     newfd=OpenFileNew(filename);
824    
825     /* Write out the geographical errors */
826    
827 amb 1362 SeekFile(newfd,sizeof(ErrorLogsFile)+(errorlogsx->latbins*errorlogsx->lonbins+1)*sizeof(index_t));
828 amb 1317
829     while(!ReadFile(oldfd,&errorlogx,sizeof(ErrorLogX)))
830     {
831     ErrorLog errorlog={0};
832     ll_bin_t latbin,lonbin;
833     ll_bin2_t llbin;
834    
835     if(errorlogx.latitude==NO_LATLONG)
836     continue;
837    
838     /* Create the ErrorLog */
839    
840     errorlog.latoffset=latlong_to_off(errorlogx.latitude);
841     errorlog.lonoffset=latlong_to_off(errorlogx.longitude);
842    
843     errorlog.offset=errorlogx.offset;
844     errorlog.length=errorlogx.length;
845    
846     /* Work out the offsets */
847    
848 amb 1362 latbin=latlong_to_bin(errorlogx.latitude )-errorlogsx->latzero;
849     lonbin=latlong_to_bin(errorlogx.longitude)-errorlogsx->lonzero;
850     llbin=lonbin*errorlogsx->latbins+latbin;
851 amb 1317
852     for(;latlonbin<=llbin;latlonbin++)
853     offsets[latlonbin]=number_geo;
854    
855     /* Write the data */
856    
857     WriteFile(newfd,&errorlog,sizeof(ErrorLog));
858    
859     number_geo++;
860     number++;
861    
862     if(!(number%10000))
863     printf_middle("Writing Errors: Geographical=%"Pindex_t" Non-geographical=%"Pindex_t,number_geo,number_nongeo);
864     }
865    
866     /* Write out the non-geographical errors */
867    
868     SeekFile(oldfd,0);
869    
870     while(!ReadFile(oldfd,&errorlogx,sizeof(ErrorLogX)))
871     {
872     ErrorLog errorlog={0};
873    
874     if(errorlogx.latitude!=NO_LATLONG)
875     continue;
876    
877     /* Create the ErrorLog */
878    
879     errorlog.latoffset=0;
880     errorlog.lonoffset=0;
881    
882     errorlog.offset=errorlogx.offset;
883     errorlog.length=errorlogx.length;
884    
885     /* Write the data */
886    
887     WriteFile(newfd,&errorlog,sizeof(ErrorLog));
888    
889     number_nongeo++;
890     number++;
891    
892     if(!(number%10000))
893     printf_middle("Writing Errors: Geographical=%"Pindex_t" Non-geographical=%"Pindex_t,number_geo,number_nongeo);
894     }
895    
896     /* Close the input file */
897    
898     CloseFile(oldfd);
899    
900     DeleteFile(errorbinfilename);
901    
902     /* Append the text from the log file */
903    
904     size=SizeFile(errorlogfilename);
905    
906     oldfd=ReOpenFile(errorlogfilename);
907    
908     while(size)
909     {
910 amb 1321 int i;
911     char buffer[4096];
912 amb 1317 off_t chunksize=(size>sizeof(buffer)?sizeof(buffer):size);
913    
914     ReadFile(oldfd,buffer,chunksize);
915    
916 amb 1321 for(i=0;i<chunksize;i++)
917     if(buffer[i]=='\n')
918     buffer[i]=0;
919    
920 amb 1317 WriteFile(newfd,buffer,chunksize);
921    
922     size-=chunksize;
923     }
924    
925     CloseFile(oldfd);
926    
927     /* Finish off the offset indexing and write them out */
928    
929 amb 1362 maxlatlonbins=errorlogsx->latbins*errorlogsx->lonbins;
930 amb 1317
931     for(;latlonbin<=maxlatlonbins;latlonbin++)
932     offsets[latlonbin]=number_geo;
933    
934     SeekFile(newfd,sizeof(ErrorLogsFile));
935 amb 1362 WriteFile(newfd,offsets,(errorlogsx->latbins*errorlogsx->lonbins+1)*sizeof(index_t));
936 amb 1317
937     free(offsets);
938    
939     /* Write out the header structure */
940    
941     errorlogsfile.number =number;
942     errorlogsfile.number_geo =number_geo;
943     errorlogsfile.number_nongeo=number_nongeo;
944    
945 amb 1362 errorlogsfile.latbins=errorlogsx->latbins;
946     errorlogsfile.lonbins=errorlogsx->lonbins;
947 amb 1317
948 amb 1362 errorlogsfile.latzero=errorlogsx->latzero;
949     errorlogsfile.lonzero=errorlogsx->lonzero;
950 amb 1317
951     SeekFile(newfd,0);
952     WriteFile(newfd,&errorlogsfile,sizeof(ErrorLogsFile));
953    
954     CloseFile(newfd);
955    
956     /* Print the final message */
957    
958     printf_last("Wrote Errors: Geographical=%"Pindex_t" Non-geographical=%"Pindex_t,number_geo,number_nongeo);
959     }