Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino
Contents of /trunk/src/relationsx.c
Parent Directory
|
Revision Log
Revision 496 -
(show annotations)
(download)
(as text)
Fri Sep 17 17:42:45 2010 UTC (14 years, 6 months ago) by amb
File MIME type: text/x-csrc
File size: 8395 byte(s)
Fri Sep 17 17:42:45 2010 UTC (14 years, 6 months ago) by amb
File MIME type: text/x-csrc
File size: 8395 byte(s)
Initial revision
1 | /*************************************** |
2 | $Header: /home/amb/CVS/routino/src/relationsx.c,v 1.1 2010-09-17 17:42:45 amb Exp $ |
3 | |
4 | Extended Relation data type functions. |
5 | |
6 | Part of the Routino routing software. |
7 | ******************/ /****************** |
8 | This file Copyright 2010 Andrew M. Bishop |
9 | |
10 | This program is free software: you can redistribute it and/or modify |
11 | it under the terms of the GNU Affero General Public License as published by |
12 | the Free Software Foundation, either version 3 of the License, or |
13 | (at your option) any later version. |
14 | |
15 | This program is distributed in the hope that it will be useful, |
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
18 | GNU Affero General Public License for more details. |
19 | |
20 | You should have received a copy of the GNU Affero General Public License |
21 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
22 | ***************************************/ |
23 | |
24 | |
25 | #include <assert.h> |
26 | #include <stdlib.h> |
27 | #include <stdio.h> |
28 | #include <string.h> |
29 | #include <sys/stat.h> |
30 | |
31 | #include "waysx.h" |
32 | #include "relationsx.h" |
33 | |
34 | #include "files.h" |
35 | #include "functions.h" |
36 | |
37 | |
38 | /* Variables */ |
39 | |
40 | /*+ The command line '--tmpdir' option or its default value. +*/ |
41 | extern char *option_tmpdirname; |
42 | |
43 | /*+ A temporary file-local variable for use by the sort functions. +*/ |
44 | static RelationsX *sortrelationsx; |
45 | |
46 | /* Functions */ |
47 | |
48 | static int sort_by_id(RouteRelX *a,RouteRelX *b); |
49 | static int deduplicate_by_id(RouteRelX *relationx,index_t index); |
50 | |
51 | |
52 | /*++++++++++++++++++++++++++++++++++++++ |
53 | Allocate a new relation list (create a new file or open an existing one). |
54 | |
55 | RelationsX *NewRelationList Returns the relation list. |
56 | |
57 | int append Set to 1 if the file is to be opened for appending (now or later). |
58 | ++++++++++++++++++++++++++++++++++++++*/ |
59 | |
60 | RelationsX *NewRelationList(int append) |
61 | { |
62 | RelationsX *relationsx; |
63 | |
64 | relationsx=(RelationsX*)calloc(1,sizeof(RelationsX)); |
65 | |
66 | assert(relationsx); /* Check calloc() worked */ |
67 | |
68 | relationsx->rfilename=(char*)malloc(strlen(option_tmpdirname)+32); |
69 | |
70 | if(append) |
71 | sprintf(relationsx->rfilename,"%s/relationsx.route.input.tmp",option_tmpdirname); |
72 | else |
73 | sprintf(relationsx->rfilename,"%s/relationsx.route.%p.tmp",option_tmpdirname,relationsx); |
74 | |
75 | if(append) |
76 | { |
77 | off_t size,position=0; |
78 | |
79 | relationsx->rfd=AppendFile(relationsx->rfilename); |
80 | |
81 | size=SizeFile(relationsx->rfilename); |
82 | |
83 | while(position<size) |
84 | { |
85 | FILESORT_VARINT relationsize; |
86 | |
87 | SeekFile(relationsx->rfd,position); |
88 | ReadFile(relationsx->rfd,&relationsize,FILESORT_VARSIZE); |
89 | |
90 | relationsx->rxnumber++; |
91 | position+=relationsize+FILESORT_VARSIZE; |
92 | } |
93 | |
94 | SeekFile(relationsx->rfd,size); |
95 | } |
96 | else |
97 | relationsx->rfd=OpenFile(relationsx->rfilename); |
98 | |
99 | return(relationsx); |
100 | } |
101 | |
102 | |
103 | /*++++++++++++++++++++++++++++++++++++++ |
104 | Free a relation list. |
105 | |
106 | RelationsX *relationsx The list to be freed. |
107 | |
108 | int keep Set to 1 if the file is to be kept. |
109 | ++++++++++++++++++++++++++++++++++++++*/ |
110 | |
111 | void FreeRelationList(RelationsX *relationsx,int keep) |
112 | { |
113 | if(!keep) |
114 | DeleteFile(relationsx->rfilename); |
115 | |
116 | free(relationsx->rfilename); |
117 | |
118 | free(relationsx); |
119 | } |
120 | |
121 | |
122 | /*++++++++++++++++++++++++++++++++++++++ |
123 | Append a single relation to an unsorted route relation list. |
124 | |
125 | RelationsX* relationsx The set of relations to process. |
126 | |
127 | relation_t id The ID of the relation. |
128 | |
129 | allow_t routes The types of routes that this relation is for. |
130 | |
131 | way_t *ways The array of ways that are members of the relation. |
132 | |
133 | int nways The number of ways that are members of the relation. |
134 | |
135 | relation_t *relations The array of relations that are members of the relation. |
136 | |
137 | int nrelations The number of relations that are members of the relation. |
138 | ++++++++++++++++++++++++++++++++++++++*/ |
139 | |
140 | void AppendRouteRelation(RelationsX* relationsx,relation_t id,allow_t routes, |
141 | way_t *ways,int nways, |
142 | relation_t *relations,int nrelations) |
143 | { |
144 | RouteRelX relationx; |
145 | FILESORT_VARINT size,padsize; |
146 | way_t zeroway=0; |
147 | relation_t zerorelation=0; |
148 | void *zeropointer=NULL; |
149 | |
150 | relationx.id=id; |
151 | relationx.routes=routes; |
152 | |
153 | size=sizeof(RouteRelX)+(nways+1)*sizeof(way_t)+(nrelations+1)*sizeof(relation_t); |
154 | padsize=sizeof(RouteRelX*)*((size+sizeof(RouteRelX*)-1)/sizeof(RouteRelX*)); |
155 | |
156 | WriteFile(relationsx->rfd,&padsize,FILESORT_VARSIZE); |
157 | WriteFile(relationsx->rfd,&relationx,sizeof(RouteRelX)); |
158 | |
159 | WriteFile(relationsx->rfd,ways ,nways*sizeof(way_t)); |
160 | WriteFile(relationsx->rfd,&zeroway, sizeof(way_t)); |
161 | |
162 | WriteFile(relationsx->rfd,relations ,nrelations*sizeof(relation_t)); |
163 | WriteFile(relationsx->rfd,&zerorelation, sizeof(relation_t)); |
164 | |
165 | WriteFile(relationsx->rfd,&zeropointer,padsize-size); |
166 | |
167 | relationsx->rxnumber++; |
168 | |
169 | assert(!(relationsx->rxnumber==0)); /* Zero marks the high-water mark for relations. */ |
170 | } |
171 | |
172 | |
173 | /*++++++++++++++++++++++++++++++++++++++ |
174 | Sort the list of relations. |
175 | |
176 | RelationsX* relationsx The set of relations to process. |
177 | ++++++++++++++++++++++++++++++++++++++*/ |
178 | |
179 | void SortRelationList(RelationsX* relationsx) |
180 | { |
181 | int rfd; |
182 | |
183 | /* Print the start message */ |
184 | |
185 | printf("Sorting Relations"); |
186 | fflush(stdout); |
187 | |
188 | /* Close the file and re-open it (finished appending) */ |
189 | |
190 | CloseFile(relationsx->rfd); |
191 | relationsx->rfd=ReOpenFile(relationsx->rfilename); |
192 | |
193 | DeleteFile(relationsx->rfilename); |
194 | |
195 | rfd=OpenFile(relationsx->rfilename); |
196 | |
197 | /* Sort the relations to allow removing duplicates */ |
198 | |
199 | sortrelationsx=relationsx; |
200 | |
201 | filesort_vary(relationsx->rfd,rfd,(int (*)(const void*,const void*))sort_by_id,(int (*)(void*,index_t))deduplicate_by_id); |
202 | |
203 | /* Close the files */ |
204 | |
205 | CloseFile(relationsx->rfd); |
206 | CloseFile(rfd); |
207 | |
208 | /* Print the final message */ |
209 | |
210 | printf("\rSorted Relations: Relations=%d Duplicates=%d\n",relationsx->rxnumber,relationsx->rxnumber-relationsx->rnumber); |
211 | fflush(stdout); |
212 | } |
213 | |
214 | |
215 | /*++++++++++++++++++++++++++++++++++++++ |
216 | Sort the relations into id order. |
217 | |
218 | int sort_by_id Returns the comparison of the id fields. |
219 | |
220 | RouteRelX *a The first extended relation. |
221 | |
222 | RouteRelX *b The second extended relation. |
223 | ++++++++++++++++++++++++++++++++++++++*/ |
224 | |
225 | static int sort_by_id(RouteRelX *a,RouteRelX *b) |
226 | { |
227 | relation_t a_id=a->id; |
228 | relation_t b_id=b->id; |
229 | |
230 | if(a_id<b_id) |
231 | return(-1); |
232 | else if(a_id>b_id) |
233 | return(1); |
234 | else |
235 | return(0); |
236 | } |
237 | |
238 | |
239 | /*++++++++++++++++++++++++++++++++++++++ |
240 | Deduplicate the extended relations using the id after sorting. |
241 | |
242 | int deduplicate_by_id Return 1 if the value is to be kept, otherwise zero. |
243 | |
244 | RouteRelX *relationx The extended relation. |
245 | |
246 | index_t index The index of this relation in the total. |
247 | ++++++++++++++++++++++++++++++++++++++*/ |
248 | |
249 | static int deduplicate_by_id(RouteRelX *relationx,index_t index) |
250 | { |
251 | static relation_t previd; |
252 | |
253 | if(index==0 || relationx->id!=previd) |
254 | { |
255 | previd=relationx->id; |
256 | |
257 | sortrelationsx->rnumber++; |
258 | |
259 | return(1); |
260 | } |
261 | |
262 | return(0); |
263 | } |
264 | |
265 | |
266 | /*++++++++++++++++++++++++++++++++++++++ |
267 | Process the route relations and apply the information to the ways. |
268 | |
269 | RelationsX *relationsx The set of relations to process. |
270 | |
271 | WaysX *waysx The set of ways to update. |
272 | ++++++++++++++++++++++++++++++++++++++*/ |
273 | |
274 | void ProcessRouteRelations(RelationsX *relationsx,WaysX *waysx) |
275 | { |
276 | int i; |
277 | |
278 | /* Print the start message */ |
279 | |
280 | printf("Processing Route Relations: Relations=0"); |
281 | fflush(stdout); |
282 | |
283 | /* Open the file and read through it */ |
284 | |
285 | relationsx->rfd=ReOpenFile(relationsx->rfilename); |
286 | |
287 | for(i=0;i<relationsx->rnumber;i++) |
288 | { |
289 | FILESORT_VARINT padsize,size; |
290 | RouteRelX relationx; |
291 | way_t way; |
292 | relation_t relation; |
293 | void *pointer; |
294 | |
295 | ReadFile(relationsx->rfd,&padsize,FILESORT_VARSIZE); |
296 | ReadFile(relationsx->rfd,&relationx,sizeof(RouteRelX)); |
297 | |
298 | size=FILESORT_VARSIZE+sizeof(RouteRelX); |
299 | |
300 | do |
301 | { |
302 | ReadFile(relationsx->rfd,&way,sizeof(way_t)); |
303 | |
304 | // if(way) |
305 | // printf("Relation %d includes way %d\n",relationx.id,way); |
306 | |
307 | size+=sizeof(way_t); |
308 | } |
309 | while(way); |
310 | |
311 | do |
312 | { |
313 | ReadFile(relationsx->rfd,&relation,sizeof(relation_t)); |
314 | |
315 | // if(relation) |
316 | // printf("Relation %d includes relation %d\n",relationx.id,relation); |
317 | |
318 | size+=sizeof(relation_t); |
319 | } |
320 | while(relation); |
321 | |
322 | ReadFile(relationsx->rfd,&pointer,padsize-size); |
323 | } |
324 | |
325 | CloseFile(relationsx->rfd); |
326 | |
327 | /* Print the final message */ |
328 | |
329 | printf("\rProcessed Route Relations: Relations=%d \n",relationsx->rnumber); |
330 | fflush(stdout); |
331 | } |