2 /* BFD library -- caching of file descriptors.
3 Copyright (C) 1990-1991 Free Software Foundation, Inc.
6 This file is part of BFD, the Binary File Descriptor library.
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.
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.
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. */
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
47 BFD_CACHE_MAX_OPEN macro
50 The maxiumum number of files which the cache will keep open at
53 .#define BFD_CACHE_MAX_OPEN 10
58 static int open_files;
60 static bfd *cache_sentinel; /* Chain of BFDs with active fds we've
68 extern bfd *bfd_last_cache;
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.
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
88 * .#define bfd_cache_lookup(x) \
89 * . ((x)==bfd_last_cache? \
90 * . (FILE*)(bfd_last_cache->iostream): \
91 * . bfd_cache_lookup_worker(x))
96 static void bfd_cache_delete();
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 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),
131 fclose ((FILE *)(abfd->iostream));
133 abfd->iostream = NULL;
145 x->lru_prev = y->lru_prev;
146 y->lru_prev->lru_next = x;
163 void bfd_cache_init (bfd *);
166 Initialize a BFD by putting it on the cache LRU.
170 DEFUN(bfd_cache_init,(abfd),
173 cache_sentinel = insert(abfd, cache_sentinel);
182 Remove the BFD from the cache. If the attached file is open,
186 void bfd_cache_close (bfd *);
189 DEFUN(bfd_cache_close,(abfd),
192 /* If this file is open then remove from the chain */
195 bfd_cache_delete(abfd);
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.
211 FILE* bfd_open_file(bfd *);
215 DEFUN(bfd_open_file, (abfd),
218 abfd->cacheable = true; /* Allow it to be closed later. */
220 if(open_files >= BFD_CACHE_MAX_OPEN) {
224 switch (abfd->direction) {
227 abfd->iostream = (char *) fopen(abfd->filename, FOPEN_RB);
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);
238 abfd->iostream = (char *) fopen(abfd->filename, FOPEN_WB);
239 abfd->opened_once = true;
244 if (abfd->iostream) {
246 bfd_cache_init (abfd);
249 return (FILE *)(abfd->iostream);
254 bfd_cache_lookup_worker
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.
264 FILE *bfd_cache_lookup_worker(bfd *);
269 DEFUN(bfd_cache_lookup_worker,(abfd),
272 if (abfd->my_archive)
274 abfd = abfd->my_archive;
276 /* Is this file already open .. if so then quick exit */
279 if (abfd != cache_sentinel) {
280 /* Place onto head of lru chain */
282 cache_sentinel = insert(abfd, cache_sentinel);
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. */
291 if (open_files >= BFD_CACHE_MAX_OPEN)
296 BFD_ASSERT(bfd_open_file (abfd) != (FILE *)NULL) ;
297 fseek((FILE *)(abfd->iostream), abfd->where, false);
299 bfd_last_cache = abfd;
300 return (FILE *)(abfd->iostream);