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