Imported Upstream version 1.5.1
[routino] / src / relationsx.c
1 /***************************************
2  $Header: /home/amb/routino/src/RCS/relationsx.c,v 1.10 2010/11/13 14:57:30 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 "logging.h"
36 #include "functions.h"
37
38
39 /* Variables */
40
41 /*+ The command line '--tmpdir' option or its default value. +*/
42 extern char *option_tmpdirname;
43
44
45 /*++++++++++++++++++++++++++++++++++++++
46   Allocate a new relation list (create a new file or open an existing one).
47
48   RelationsX *NewRelationList Returns the relation list.
49
50   int append Set to 1 if the file is to be opened for appending (now or later).
51   ++++++++++++++++++++++++++++++++++++++*/
52
53 RelationsX *NewRelationList(int append)
54 {
55  RelationsX *relationsx;
56
57  relationsx=(RelationsX*)calloc(1,sizeof(RelationsX));
58
59  assert(relationsx); /* Check calloc() worked */
60
61  relationsx->rfilename=(char*)malloc(strlen(option_tmpdirname)+32);
62
63  if(append)
64     sprintf(relationsx->rfilename,"%s/relationsx.route.input.tmp",option_tmpdirname);
65  else
66     sprintf(relationsx->rfilename,"%s/relationsx.route.%p.tmp",option_tmpdirname,relationsx);
67
68  if(append)
69    {
70     off_t size,position=0;
71
72     relationsx->rfd=OpenFileAppend(relationsx->rfilename);
73
74     size=SizeFile(relationsx->rfilename);
75
76     while(position<size)
77       {
78        FILESORT_VARINT relationsize;
79
80        SeekFile(relationsx->rfd,position);
81        ReadFile(relationsx->rfd,&relationsize,FILESORT_VARSIZE);
82
83        relationsx->rxnumber++;
84        position+=relationsize+FILESORT_VARSIZE;
85       }
86
87     SeekFile(relationsx->rfd,size);
88    }
89  else
90     relationsx->rfd=OpenFileNew(relationsx->rfilename);
91
92  return(relationsx);
93 }
94
95
96 /*++++++++++++++++++++++++++++++++++++++
97   Free a relation list.
98
99   RelationsX *relationsx The list to be freed.
100
101   int keep Set to 1 if the file is to be kept.
102   ++++++++++++++++++++++++++++++++++++++*/
103
104 void FreeRelationList(RelationsX *relationsx,int keep)
105 {
106  if(!keep)
107     DeleteFile(relationsx->rfilename);
108
109  free(relationsx->rfilename);
110
111  free(relationsx);
112 }
113
114
115 /*++++++++++++++++++++++++++++++++++++++
116   Append a single relation to an unsorted route relation list.
117
118   RelationsX* relationsx The set of relations to process.
119
120   relation_t id The ID of the relation.
121
122   allow_t routes The types of routes that this relation is for.
123
124   way_t *ways The array of ways that are members of the relation.
125
126   int nways The number of ways that are members of the relation.
127
128   relation_t *relations The array of relations that are members of the relation.
129
130   int nrelations The number of relations that are members of the relation.
131   ++++++++++++++++++++++++++++++++++++++*/
132
133 void AppendRouteRelation(RelationsX* relationsx,relation_t id,allow_t routes,
134                          way_t *ways,int nways,
135                          relation_t *relations,int nrelations)
136 {
137  RouteRelX relationx;
138  FILESORT_VARINT size;
139  way_t zeroway=0;
140  relation_t zerorelation=0;
141
142  relationx.id=id;
143  relationx.routes=routes;
144
145  size=sizeof(RouteRelX)+(nways+1)*sizeof(way_t)+(nrelations+1)*sizeof(relation_t);
146
147  WriteFile(relationsx->rfd,&size,FILESORT_VARSIZE);
148  WriteFile(relationsx->rfd,&relationx,sizeof(RouteRelX));
149
150  WriteFile(relationsx->rfd,ways    ,nways*sizeof(way_t));
151  WriteFile(relationsx->rfd,&zeroway,      sizeof(way_t));
152
153  WriteFile(relationsx->rfd,relations    ,nrelations*sizeof(relation_t));
154  WriteFile(relationsx->rfd,&zerorelation,           sizeof(relation_t));
155
156  relationsx->rxnumber++;
157
158  assert(!(relationsx->rxnumber==0)); /* Zero marks the high-water mark for relations. */
159 }
160
161
162 /*++++++++++++++++++++++++++++++++++++++
163   Sort the list of relations.
164
165   RelationsX* relationsx The set of relations to process.
166   ++++++++++++++++++++++++++++++++++++++*/
167
168 void SortRelationList(RelationsX* relationsx)
169 {
170  /* Don't need to sort route relations */
171 }
172
173
174 /*++++++++++++++++++++++++++++++++++++++
175   Process the route relations and apply the information to the ways.
176
177   RelationsX *relationsx The set of relations to process.
178
179   WaysX *waysx The set of ways to update.
180   ++++++++++++++++++++++++++++++++++++++*/
181
182 void ProcessRouteRelations(RelationsX *relationsx,WaysX *waysx)
183 {
184  RouteRelX *unmatched=NULL,*lastunmatched=NULL;
185  int nunmatched=0,lastnunmatched=0,iteration=0;
186
187  if(waysx->number==0)
188     return;
189
190  /* Map into memory */
191
192 #if !SLIM
193  waysx->xdata=MapFileWriteable(waysx->filename);
194 #endif
195
196  /* Re-open the ways file read/write */
197
198 #if SLIM
199  CloseFile(waysx->fd);
200  waysx->fd=ReOpenFileWriteable(waysx->filename);
201 #endif
202
203  /* Open the file and read through it */
204
205  relationsx->rfd=ReOpenFile(relationsx->rfilename);
206
207  do
208    {
209     int ways=0,relations=0;
210     int i;
211
212     SeekFile(relationsx->rfd,0);
213
214     /* Print the start message */
215
216     printf_first("Processing Route Relations: Iteration=%d Relations=0 Modified Ways=0",iteration);
217
218     for(i=0;i<relationsx->rxnumber;i++)
219       {
220        FILESORT_VARINT size;
221        RouteRelX relationx;
222        way_t wayid;
223        relation_t relationid;
224        allow_t routes=Allow_None;
225
226        /* Read each route relation */
227
228        ReadFile(relationsx->rfd,&size,FILESORT_VARSIZE);
229        ReadFile(relationsx->rfd,&relationx,sizeof(RouteRelX));
230
231        /* Decide what type of route it is */
232
233        if(iteration==0)
234          {
235           relations++;
236           routes=relationx.routes;
237          }
238        else
239          {
240           int j;
241
242           for(j=0;j<lastnunmatched;j++)
243              if(lastunmatched[j].id==relationx.id)
244                {
245                 relations++;
246
247                 if((lastunmatched[j].routes|relationx.routes)==relationx.routes)
248                    routes=0; /* Nothing new to add */
249                 else
250                    routes=lastunmatched[j].routes;
251                 break;
252                }
253          }
254
255        /* Loop through the ways */
256
257        do
258          {
259           ReadFile(relationsx->rfd,&wayid,sizeof(way_t));
260
261           /* Update the ways that are listed for the relation */
262
263           if(wayid && routes)
264             {
265              index_t way=IndexWayX(waysx,wayid);
266
267              if(way!=NO_WAY)
268                {
269                 WayX *wayx=LookupWayX(waysx,way,1);
270
271                 if(routes&Allow_Foot)
272                    wayx->way.props|=Properties_FootRoute;
273
274                 if(routes&Allow_Bicycle)
275                    wayx->way.props|=Properties_BicycleRoute;
276
277 #if SLIM
278                 PutBackWayX(waysx,way,1);
279 #endif
280
281                 ways++;
282                }
283             }
284          }
285        while(wayid);
286
287        /* Loop through the relations */
288
289        do
290          {
291           ReadFile(relationsx->rfd,&relationid,sizeof(relation_t));
292
293           /* Add the relations that are listed for this relation to the list for next time */
294
295           if(relationid && routes && relationid!=relationx.id)
296             {
297              if(nunmatched%256==0)
298                 unmatched=(RouteRelX*)realloc((void*)unmatched,(nunmatched+256)*sizeof(RouteRelX));
299
300              unmatched[nunmatched].id=relationid;
301              unmatched[nunmatched].routes=routes;
302
303              nunmatched++;
304             }
305          }
306        while(relationid);
307
308        if(!((i+1)%10000))
309           printf_middle("Processing Route Relations: Iteration=%d Relations=%d Modified Ways=%d",iteration,relations,ways);
310       }
311
312     if(lastunmatched)
313        free(lastunmatched);
314
315     lastunmatched=unmatched;
316     lastnunmatched=nunmatched;
317
318     unmatched=NULL;
319     nunmatched=0;
320
321     /* Print the final message */
322
323     printf_last("Processed Route Relations: Iteration=%d Relations=%d Modified Ways=%d",iteration,relations,ways);
324    }
325  while(lastnunmatched && ++iteration<5);
326
327  if(lastunmatched)
328     free(lastunmatched);
329
330  CloseFile(relationsx->rfd);
331
332  /* Unmap from memory */
333
334 #if !SLIM
335  waysx->xdata=UnmapFile(waysx->filename);
336 #endif
337
338  /* Re-open the ways file read only */
339
340 #if SLIM
341  CloseFile(waysx->fd);
342  waysx->fd=ReOpenFile(waysx->filename);
343 #endif
344 }