1 /* BFD library -- caching of file descriptors.
2 Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
5 This file is part of BFD, the Binary File Descriptor library.
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.
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.
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. */
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
44 BFD_CACHE_MAX_OPEN macro
47 The maximum number of files which the cache will keep open at
50 .#define BFD_CACHE_MAX_OPEN 10
56 bfd_cache_delete PARAMS ((bfd *));
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. */
61 static int open_files;
63 static bfd *cache_sentinel = 0; /* Chain of BFDs with active fds we've
71 extern bfd *bfd_last_cache;
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.
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.
91 .#define bfd_cache_lookup(x) \
92 . ((x)==bfd_last_cache? \
93 . (FILE*)(bfd_last_cache->iostream): \
94 . bfd_cache_lookup_worker(x))
100 DEFUN_VOID(close_one)
102 bfd *kill = cache_sentinel;
103 if (kill == 0) /* Nothing in the cache */
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 */
113 kill->where = ftell((FILE *)(kill->iostream));
114 (void) bfd_cache_delete(kill);
117 /* Cuts the BFD abfd out of the chain in the cache */
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;
128 DEFUN(bfd_cache_delete,(abfd),
133 if (fclose ((FILE *)(abfd->iostream)) == 0)
138 bfd_set_error (bfd_error_system_call);
141 abfd->iostream = NULL;
154 x->lru_prev = y->lru_prev;
155 y->lru_prev->lru_next = x;
167 /* Initialize a BFD by putting it on the cache LRU. */
170 DEFUN(bfd_cache_init,(abfd),
173 if (open_files >= BFD_CACHE_MAX_OPEN)
175 cache_sentinel = insert(abfd, cache_sentinel);
185 boolean bfd_cache_close (bfd *abfd);
188 Remove the BFD @var{abfd} from the cache. If the attached file is open,
192 <<false>> is returned if closing the file fails, <<true>> is
193 returned if all is well.
196 DEFUN(bfd_cache_close,(abfd),
199 /* If this file is open then remove from the chain */
202 return bfd_cache_delete(abfd);
215 FILE* bfd_open_file(bfd *abfd);
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.
226 DEFUN(bfd_open_file, (abfd),
229 abfd->cacheable = true; /* Allow it to be closed later. */
231 if(open_files >= BFD_CACHE_MAX_OPEN) {
235 switch (abfd->direction) {
238 abfd->iostream = (char *) fopen(abfd->filename, FOPEN_RB);
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);
249 abfd->iostream = (char *) fopen(abfd->filename, FOPEN_WB);
250 abfd->opened_once = true;
255 if (abfd->iostream) {
256 bfd_cache_init (abfd);
259 return (FILE *)(abfd->iostream);
264 bfd_cache_lookup_worker
267 FILE *bfd_cache_lookup_worker(bfd *abfd);
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.
279 DEFUN(bfd_cache_lookup_worker,(abfd),
282 if (abfd->my_archive)
284 abfd = abfd->my_archive;
286 /* Is this file already open .. if so then quick exit */
289 if (abfd != cache_sentinel) {
290 /* Place onto head of lru chain */
292 cache_sentinel = insert(abfd, cache_sentinel);
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. */
301 if (open_files >= BFD_CACHE_MAX_OPEN)
306 BFD_ASSERT(bfd_open_file (abfd) != (FILE *)NULL) ;
307 fseek((FILE *)(abfd->iostream), abfd->where, false);
309 bfd_last_cache = abfd;
310 return (FILE *)(abfd->iostream);