doc cleanup
[external/binutils.git] / bfd / cache.c
1 /* BFD library -- caching of file descriptors.
2    Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
3    Hacked by Steve Chamberlain of Cygnus Support (steve@cygnus.com).
4
5 This file is part of BFD, the Binary File Descriptor library.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
20
21 /*
22 SECTION
23         File caching
24
25         The file caching mechanism is embedded within BFD and allows
26         the application to open as many BFDs as it wants without
27         regard to the underlying operating system's file descriptor
28         limit (often as low as 20 open files).  The module in
29         <<cache.c>> maintains a least recently used list of
30         <<BFD_CACHE_MAX_OPEN>> files, and exports the name
31         <<bfd_cache_lookup>>, which runs around and makes sure that
32         the required BFD is open. If not, then it chooses a file to
33         close, closes it and opens the one wanted, returning its file
34         handle. 
35
36 */
37
38 #include "bfd.h"
39 #include "sysdep.h"
40 #include "libbfd.h"
41
42 /*
43 INTERNAL_FUNCTION
44         BFD_CACHE_MAX_OPEN macro
45
46 DESCRIPTION
47         The maximum number of files which the cache will keep open at
48         one time.
49
50 .#define BFD_CACHE_MAX_OPEN 10
51
52 */
53
54
55 static boolean
56 bfd_cache_delete PARAMS ((bfd *));
57
58 /* Number of bfds on the chain.  All such bfds have their file open;
59    if it closed, they get snipd()d from the chain.  */
60
61 static int open_files;
62
63 static bfd *cache_sentinel;     /* Chain of BFDs with active fds we've
64                                    opened */
65
66 /*
67 INTERNAL_FUNCTION
68         bfd_last_cache
69
70 SYNOPSIS
71         extern bfd *bfd_last_cache;
72
73 DESCRIPTION
74         Zero, or a pointer to the topmost BFD on the chain.  This is
75         used by the <<bfd_cache_lookup>> macro in @file{libbfd.h} to
76         determine when it can avoid a function call.
77 */
78
79 bfd *bfd_last_cache;
80
81 /*
82   INTERNAL_FUNCTION
83         bfd_cache_lookup
84  
85   DESCRIPTION
86         Check to see if the required BFD is the same as the last one
87         looked up. If so, then it can use the stream in the BFD with
88         impunity, since it can't have changed since the last lookup;
89         otherwise, it has to perform the complicated lookup function.
90  
91   .#define bfd_cache_lookup(x) \
92   .    ((x)==bfd_last_cache? \
93   .      (FILE*)(bfd_last_cache->iostream): \
94   .       bfd_cache_lookup_worker(x))
95  
96  
97  */
98
99 static void
100 DEFUN_VOID(close_one)
101 {
102     bfd *kill = cache_sentinel;
103     if (kill == 0)              /* Nothing in the cache */
104         return ;
105
106     /* We can only close files that want to play this game.  */
107     while (!kill->cacheable) {
108         kill = kill->lru_prev;
109         if (kill == cache_sentinel) /* Nobody wants to play */
110            return ;
111     }
112
113     kill->where = ftell((FILE *)(kill->iostream));
114     (void) bfd_cache_delete(kill);
115 }
116
117 /* Cuts the BFD abfd out of the chain in the cache */
118 static void 
119 DEFUN(snip,(abfd),
120       bfd *abfd)
121 {
122   abfd->lru_prev->lru_next = abfd->lru_next;
123   abfd->lru_next->lru_prev = abfd->lru_prev; 
124   if (cache_sentinel == abfd) cache_sentinel = (bfd *)NULL;
125 }
126
127 static boolean
128 DEFUN(bfd_cache_delete,(abfd),
129       bfd *abfd)
130 {
131   boolean ret;
132
133   if (fclose ((FILE *)(abfd->iostream)) == 0)
134     ret = true;
135   else
136     {
137       ret = false;
138       bfd_error = system_call_error;
139     }
140   snip (abfd);
141   abfd->iostream = NULL;
142   open_files--;
143   bfd_last_cache = 0;
144   return ret;
145 }
146   
147 static bfd *
148 DEFUN(insert,(x,y),
149       bfd *x AND
150       bfd *y)
151 {
152   if (y) {
153     x->lru_next = y;
154     x->lru_prev = y->lru_prev;
155     y->lru_prev->lru_next = x;
156     y->lru_prev = x;
157
158   }
159   else {
160     x->lru_prev = x;
161     x->lru_next = x;
162   }
163   return x;
164 }
165 \f
166
167 /* Initialize a BFD by putting it on the cache LRU.  */
168
169 void
170 DEFUN(bfd_cache_init,(abfd),
171       bfd *abfd)
172 {
173   if (open_files >= BFD_CACHE_MAX_OPEN)
174     close_one ();
175   cache_sentinel = insert(abfd, cache_sentinel);
176   ++open_files;
177 }
178
179
180 /*
181 INTERNAL_FUNCTION
182         bfd_cache_close
183
184 SYNOPSIS
185         boolean bfd_cache_close (bfd *abfd);
186
187 DESCRIPTION
188         Remove the BFD @var{abfd} from the cache. If the attached file is open,
189         then close it too.
190
191 RETURNS
192         <<false>> is returned if closing the file fails, <<true>> is
193         returned if all is well.
194 */
195 boolean
196 DEFUN(bfd_cache_close,(abfd),
197       bfd *abfd)
198 {
199   /* If this file is open then remove from the chain */
200   if (abfd->iostream) 
201     {
202       return bfd_cache_delete(abfd);
203     }
204   else
205     {
206       return true;
207     }
208 }
209
210 /*
211 INTERNAL_FUNCTION
212         bfd_open_file
213
214 SYNOPSIS
215         FILE* bfd_open_file(bfd *abfd);
216
217 DESCRIPTION
218         Call the OS to open a file for @var{abfd}.  Return the <<FILE *>>
219         (possibly NULL) that results from this operation.  Set up the
220         BFD so that future accesses know the file is open. If the <<FILE *>>
221         returned is NULL, then it won't have been put in the
222         cache, so it won't have to be removed from it.
223 */
224
225 FILE *
226 DEFUN(bfd_open_file, (abfd),
227       bfd *abfd)
228 {
229   abfd->cacheable = true;       /* Allow it to be closed later. */
230
231   if(open_files >= BFD_CACHE_MAX_OPEN) {
232     close_one();
233   }
234
235   switch (abfd->direction) {
236   case read_direction:
237   case no_direction:
238     abfd->iostream = (char *) fopen(abfd->filename, FOPEN_RB);
239     break;
240   case both_direction:
241   case write_direction:
242     if (abfd->opened_once == true) {
243       abfd->iostream = (char *) fopen(abfd->filename, FOPEN_RUB);
244       if (!abfd->iostream) {
245         abfd->iostream = (char *) fopen(abfd->filename, FOPEN_WUB);
246       }
247     } else {
248       /*open for creat */
249       abfd->iostream = (char *) fopen(abfd->filename, FOPEN_WB);
250       abfd->opened_once = true;
251     }
252     break;
253   }
254
255   if (abfd->iostream) {
256     bfd_cache_init (abfd);
257   }
258
259   return (FILE *)(abfd->iostream);
260 }
261
262 /*
263 INTERNAL_FUNCTION
264         bfd_cache_lookup_worker
265
266 SYNOPSIS
267         FILE *bfd_cache_lookup_worker(bfd *abfd);
268
269 DESCRIPTION
270         Called when the macro <<bfd_cache_lookup>> fails to find a
271         quick answer.  Find a file descriptor for @var{abfd}.  If
272         necessary, it open it.  If there are already more than
273         <<BFD_CACHE_MAX_OPEN>> files open, it tries to close one first, to
274         avoid running out of file descriptors.  
275
276 */
277
278 FILE *
279 DEFUN(bfd_cache_lookup_worker,(abfd),
280       bfd *abfd)
281 {
282   if (abfd->my_archive) 
283       {
284         abfd = abfd->my_archive;
285       }
286   /* Is this file already open .. if so then quick exit */
287   if (abfd->iostream) 
288       {
289         if (abfd != cache_sentinel) {
290           /* Place onto head of lru chain */
291           snip (abfd);
292           cache_sentinel = insert(abfd, cache_sentinel);
293         }
294       }
295   /* This is a BFD without a stream -
296      so it must have been closed or never opened.
297      find an empty cache entry and use it.  */
298   else 
299       {
300
301         if (open_files >= BFD_CACHE_MAX_OPEN) 
302             {
303               close_one();
304             }
305
306         BFD_ASSERT(bfd_open_file (abfd) != (FILE *)NULL) ;
307         fseek((FILE *)(abfd->iostream), abfd->where, false);
308       }
309   bfd_last_cache = abfd;
310   return (FILE *)(abfd->iostream);
311 }