Routino SVN Repository Browser

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

ViewVC logotype

Contents of /trunk/src/errorlogx.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1413 - (show annotations) (download) (as text)
Sat Jun 22 18:46:44 2013 UTC (11 years, 8 months ago) by amb
File MIME type: text/x-csrc
File size: 25535 byte(s)
Use buffered file accesses for appending the error strings to the binary file.

1 /***************************************
2 Error log processing functions.
3
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 #include "errorlogx.h"
29 #include "errorlog.h"
30
31 #include "files.h"
32 #include "sorting.h"
33
34
35 /* Global variables */
36
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 /* Local variables */
44
45 /*+ Temporary file-local variables for use by the sort functions. +*/
46 static latlong_t lat_min,lat_max,lon_min,lon_max;
47
48 /* 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
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 static int sort_by_lat_long(ErrorLogX *a,ErrorLogX *b);
59 static int measure_lat_long(ErrorLogX *errorlogx,index_t index);
60
61
62 /*++++++++++++++++++++++++++++++++++++++
63 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 Process the binary error log.
94
95 ErrorLogsX *errorlogsx The set of error logs to update.
96
97 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 void ProcessErrorLogs(ErrorLogsX *errorlogsx,NodesX *nodesx,WaysX *waysx,RelationsX *relationsx)
105 {
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 printf_first("Re-indexing the Data: Nodes=0 Ways=0 Route-Relations=0 Turn-Relations=0");
115
116 reindex_nodes(nodesx);
117
118 printf_middle("Re-indexing the Data: Nodes=%"Pindex_t" Ways=0 Route-Relations=0 Turn-Relations=0",nodesx->number);
119
120 reindex_ways(waysx);
121
122 printf_middle("Re-indexing the Data: Nodes=%"Pindex_t" Ways=%"Pindex_t" Route-Relations=0 Turn-Relations=0",nodesx->number,waysx->number);
123
124 reindex_relations(relationsx);
125
126 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
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=ReOpenFileUnbuffered(nodesx->filename);
139
140 InvalidateNodeXCache(nodesx->cache);
141 #endif
142
143 waysx->fd=ReOpenFileBuffered(waysx->filename);
144 relationsx->rrfd=ReOpenFileBuffered(relationsx->rrfilename);
145 relationsx->trfd=ReOpenFileBuffered(relationsx->trfilename);
146
147 /* Open the binary log file read-only and a new file writeable */
148
149 oldfd=ReOpenFileBuffered(errorbinfilename);
150
151 DeleteFile(errorbinfilename);
152
153 newfd=OpenFileBufferedNew(errorbinfilename);
154
155 /* Loop through the file and merge the raw data into coordinates */
156
157 errorlogsx->number=0;
158
159 do
160 {
161 ErrorLogObject errorlogobject;
162
163 finished=ReadFileBuffered(oldfd,&errorlogobject,sizeof(ErrorLogObject));
164
165 if(finished)
166 errorlogobject.offset=SizeFile(errorlogfilename);
167
168 if(offset!=errorlogobject.offset)
169 {
170 ErrorLogX errorlogx;
171 latlong_t errorlat=NO_LATLONG,errorlon=NO_LATLONG;
172
173 /* Calculate suitable coordinates */
174
175 if(nerrorlogobjects==1)
176 {
177 if(errorlogobjects[0].type=='N')
178 {
179 node_t node=(node_t)errorlogobjects[0].id;
180
181 lookup_lat_long_node(nodesx,node,&errorlat,&errorlon);
182 }
183 else if(errorlogobjects[0].type=='W')
184 {
185 way_t way=(way_t)errorlogobjects[0].id;
186
187 lookup_lat_long_way(waysx,nodesx,way,&errorlat,&errorlon,errorlogsx->number);
188 }
189 else if(errorlogobjects[0].type=='R')
190 {
191 relation_t relation=(relation_t)errorlogobjects[0].type;
192
193 lookup_lat_long_relation(relationsx,waysx,nodesx,relation,&errorlat,&errorlon,errorlogsx->number);
194 }
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=='N')
205 {
206 node_t node=(node_t)errorlogobjects[i].id;
207
208 if(lookup_lat_long_node(nodesx,node,&latitude[ncoords],&longitude[ncoords]))
209 ncoords++;
210
211 nnodes++;
212 }
213 else if(errorlogobjects[i].type=='W')
214 nways++;
215 else if(errorlogobjects[i].type=='R')
216 nrelations++;
217 }
218
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 {
225 for(i=0;i<nerrorlogobjects;i++)
226 if(errorlogobjects[i].type=='W')
227 {
228 way_t way=(way_t)errorlogobjects[i].id;
229
230 if(lookup_lat_long_way(waysx,nodesx,way,&latitude[ncoords],&longitude[ncoords],errorlogsx->number))
231 ncoords++;
232 }
233 }
234
235 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 if(errorlogobjects[i].type=='R')
243 {
244 relation_t relation=(relation_t)errorlogobjects[i].id;
245
246 if(lookup_lat_long_relation(relationsx,waysx,nodesx,relation,&latitude[ncoords],&longitude[ncoords],errorlogsx->number))
247 ncoords++;
248 }
249 }
250
251 if(ncoords)
252 {
253 errorlat=0;
254 errorlon=0;
255
256 for(i=0;i<ncoords;i++)
257 {
258 errorlat+=latitude[i];
259 errorlon+=longitude[i];
260 }
261
262 errorlat/=ncoords;
263 errorlon/=ncoords;
264 }
265 else
266 {
267 errorlat=NO_LATLONG;
268 errorlon=NO_LATLONG;
269 }
270 }
271
272 /* Write to file */
273
274 errorlogx.offset=offset;
275 errorlogx.length=errorlogobject.offset-offset;
276
277 errorlogx.latitude =errorlat;
278 errorlogx.longitude=errorlon;
279
280 WriteFileBuffered(newfd,&errorlogx,sizeof(ErrorLogX));
281
282 errorlogsx->number++;
283
284 offset=errorlogobject.offset;
285 nerrorlogobjects=0;
286
287 if(!(errorlogsx->number%10000))
288 printf_middle("Calculating Coordinates: Errors=%"Pindex_t,errorlogsx->number);
289 }
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 nodesx->fd=CloseFileUnbuffered(nodesx->fd);
307 #endif
308
309 waysx->fd=CloseFileBuffered(waysx->fd);
310 relationsx->rrfd=CloseFileBuffered(relationsx->rrfd);
311 relationsx->trfd=CloseFileBuffered(relationsx->trfd);
312
313 CloseFileBuffered(oldfd);
314 CloseFileBuffered(newfd);
315
316 /* Print the final message */
317
318 printf_last("Calculated Coordinates: Errors=%"Pindex_t,errorlogsx->number);
319 }
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 fd=ReOpenFileBuffered(nodesx->filename);
341
342 while(!ReadFileBuffered(fd,&nodex,sizeof(NodeX)))
343 {
344 nodesx->idata[index]=nodex.id;
345
346 index++;
347 }
348
349 CloseFileBuffered(fd);
350 }
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 FILESORT_VARINT waysize;
362 int fd;
363 off_t position=0;
364 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 fd=ReOpenFileBuffered(waysx->filename);
374
375 while(!ReadFileBuffered(fd,&waysize,FILESORT_VARSIZE))
376 {
377 WayX wayx;
378
379 ReadFileBuffered(fd,&wayx,sizeof(WayX));
380
381 waysx->idata[index]=wayx.id;
382 waysx->odata[index]=position+FILESORT_VARSIZE+sizeof(WayX);
383
384 index++;
385
386 SkipFileBuffered(fd,waysize-sizeof(WayX));
387
388 position+=waysize+FILESORT_VARSIZE;
389 }
390
391 CloseFileBuffered(fd);
392 }
393
394
395 /*++++++++++++++++++++++++++++++++++++++
396 Re-index the relations that were kept.
397
398 RelationsX *relationsx The set of relations to process (contains the filenames and numbers of relations).
399 ++++++++++++++++++++++++++++++++++++++*/
400
401 static void reindex_relations(RelationsX *relationsx)
402 {
403 FILESORT_VARINT relationsize;
404 int fd;
405 off_t position=0;
406 index_t index;
407 TurnRelX turnrelx;
408
409 /* Route relations */
410
411 relationsx->rrnumber=relationsx->rrknumber;
412
413 relationsx->rridata=(relation_t*)malloc(relationsx->rrnumber*sizeof(relation_t));
414 relationsx->rrodata=(off_t*)malloc(relationsx->rrnumber*sizeof(off_t));
415
416 /* Get the relation id and the offset for each relation in the file */
417
418 fd=ReOpenFileBuffered(relationsx->rrfilename);
419
420 index=0;
421
422 while(!ReadFileBuffered(fd,&relationsize,FILESORT_VARSIZE))
423 {
424 RouteRelX routerelx;
425
426 ReadFileBuffered(fd,&routerelx,sizeof(RouteRelX));
427
428 relationsx->rridata[index]=routerelx.id;
429 relationsx->rrodata[index]=position+FILESORT_VARSIZE+sizeof(RouteRelX);
430
431 index++;
432
433 SkipFileBuffered(fd,relationsize-sizeof(RouteRelX));
434
435 position+=relationsize+FILESORT_VARSIZE;
436 }
437
438 CloseFileBuffered(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=ReOpenFileBuffered(relationsx->trfilename);
450
451 index=0;
452
453 while(!ReadFileBuffered(fd,&turnrelx,sizeof(TurnRelX)))
454 {
455 relationsx->tridata[index]=turnrelx.id;
456
457 index++;
458 }
459
460 CloseFileBuffered(fd);
461 }
462
463
464 /*++++++++++++++++++++++++++++++++++++++
465 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 SeekFileBuffered(waysx->fd,offset);
528
529 /* Choose a random pair of adjacent nodes */
530
531 if(ReadFileBuffered(waysx->fd,&node1,sizeof(node_t)) || node1==NO_NODE_ID)
532 return 0;
533
534 if(ReadFileBuffered(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(!ReadFileBuffered(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 SeekFileBuffered(relationsx->trfd,index*sizeof(TurnRelX));
601 ReadFileBuffered(relationsx->trfd,&turnrelx,sizeof(TurnRelX));
602
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 int count;
618 off_t offset=relationsx->rrodata[index];
619 node_t node=NO_NODE_ID,tempnode;
620 way_t way=NO_WAY_ID,tempway;
621 relation_t relation=NO_RELATION_ID,temprelation;
622
623 SeekFileBuffered(relationsx->rrfd,offset);
624
625 /* Choose a random node */
626
627 count=0;
628
629 while(!ReadFileBuffered(relationsx->rrfd,&tempnode,sizeof(node_t)) && tempnode!=NO_NODE_ID)
630 {
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 /* Choose a random way */
641
642 count=0;
643
644 while(!ReadFileBuffered(relationsx->rrfd,&tempway,sizeof(way_t)) && tempway!=NO_WAY_ID)
645 {
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 count=0;
658
659 while(!ReadFileBuffered(relationsx->rrfd,&temprelation,sizeof(relation_t)) && temprelation!=NO_RELATION_ID)
660 {
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 Sort the error logs geographically.
674
675 ErrorLogsX *errorlogsx The set of error logs to sort.
676 ++++++++++++++++++++++++++++++++++++++*/
677
678 void SortErrorLogsGeographically(ErrorLogsX *errorlogsx)
679 {
680 int oldfd,newfd;
681 ll_bin_t lat_min_bin,lat_max_bin,lon_min_bin,lon_max_bin;
682
683 /* Print the start message */
684
685 printf_first("Sorting Errors Geographically");
686
687 /* 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 /* Re-open the file read-only and a new file writeable */
695
696 oldfd=ReOpenFileBuffered(errorbinfilename);
697
698 DeleteFile(errorbinfilename);
699
700 newfd=OpenFileBufferedNew(errorbinfilename);
701
702 /* Sort errors geographically */
703
704 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
708 /* Close the files */
709
710 CloseFileBuffered(oldfd);
711 CloseFileBuffered(newfd);
712
713 /* 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 /* Print the final message */
727
728 printf_last("Sorted Errors Geographically: Errors=%"Pindex_t,errorlogsx->number);
729 }
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 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 Save the binary error log.
812
813 ErrorLogsX *errorlogsx The set of error logs to write.
814
815 char *filename The name of the final file to write.
816 ++++++++++++++++++++++++++++++++++++++*/
817
818 void SaveErrorLogs(ErrorLogsX *errorlogsx,char *filename)
819 {
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 offsets=(index_t*)malloc((errorlogsx->latbins*errorlogsx->lonbins+1)*sizeof(index_t));
835
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 oldfd=ReOpenFileBuffered(errorbinfilename);
843
844 newfd=OpenFileBufferedNew(filename);
845
846 /* Write out the geographical errors */
847
848 SeekFileBuffered(newfd,sizeof(ErrorLogsFile)+(errorlogsx->latbins*errorlogsx->lonbins+1)*sizeof(index_t));
849
850 while(!ReadFileBuffered(oldfd,&errorlogx,sizeof(ErrorLogX)))
851 {
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 latbin=latlong_to_bin(errorlogx.latitude )-errorlogsx->latzero;
870 lonbin=latlong_to_bin(errorlogx.longitude)-errorlogsx->lonzero;
871 llbin=lonbin*errorlogsx->latbins+latbin;
872
873 for(;latlonbin<=llbin;latlonbin++)
874 offsets[latlonbin]=number_geo;
875
876 /* Write the data */
877
878 WriteFileBuffered(newfd,&errorlog,sizeof(ErrorLog));
879
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 SeekFileBuffered(oldfd,0);
890
891 while(!ReadFileBuffered(oldfd,&errorlogx,sizeof(ErrorLogX)))
892 {
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 WriteFileBuffered(newfd,&errorlog,sizeof(ErrorLog));
909
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 CloseFileBuffered(oldfd);
920
921 DeleteFile(errorbinfilename);
922
923 /* Append the text from the log file */
924
925 size=SizeFile(errorlogfilename);
926
927 oldfd=ReOpenFileBuffered(errorlogfilename);
928
929 while(size)
930 {
931 int i;
932 char buffer[4096];
933 off_t chunksize=(size>sizeof(buffer)?sizeof(buffer):size);
934
935 ReadFileBuffered(oldfd,buffer,chunksize);
936
937 for(i=0;i<chunksize;i++)
938 if(buffer[i]=='\n')
939 buffer[i]=0;
940
941 WriteFileBuffered(newfd,buffer,chunksize);
942
943 size-=chunksize;
944 }
945
946 CloseFileBuffered(oldfd);
947
948 /* Finish off the offset indexing and write them out */
949
950 maxlatlonbins=errorlogsx->latbins*errorlogsx->lonbins;
951
952 for(;latlonbin<=maxlatlonbins;latlonbin++)
953 offsets[latlonbin]=number_geo;
954
955 SeekFileBuffered(newfd,sizeof(ErrorLogsFile));
956 WriteFileBuffered(newfd,offsets,(errorlogsx->latbins*errorlogsx->lonbins+1)*sizeof(index_t));
957
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 errorlogsfile.latbins=errorlogsx->latbins;
967 errorlogsfile.lonbins=errorlogsx->lonbins;
968
969 errorlogsfile.latzero=errorlogsx->latzero;
970 errorlogsfile.lonzero=errorlogsx->lonzero;
971
972 SeekFileBuffered(newfd,0);
973 WriteFileBuffered(newfd,&errorlogsfile,sizeof(ErrorLogsFile));
974
975 CloseFileBuffered(newfd);
976
977 /* Print the final message */
978
979 printf_last("Wrote Errors: Geographical=%"Pindex_t" Non-geographical=%"Pindex_t,number_geo,number_nongeo);
980 }