Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino
Contents of /trunk/src/errorlogx.c
Parent Directory
|
Revision Log
Revision 1414 -
(show 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)
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 | /*************************************** |
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=SlimMapFile(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=SlimUnmapFile(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 | } |