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