/[hydra]/hydra/src/mmap_cache.c
ViewVC logotype

Annotation of /hydra/src/mmap_cache.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.14 - (hide annotations)
Sun Jan 26 11:25:39 2003 UTC (21 years, 2 months ago) by nmav
Branch: MAIN
CVS Tags: hydra_0_1_6_without_hic, hydra_0_1_7, hydra_0_1_6, hydra_0_1_4, hydra_0_1_8, HEAD
Changes since 1.13: +3 -3 lines
File MIME type: text/plain
Better large file support (now uses the included autoconf macros).
(++some indentation)

1 nmav 1.1 /*
2 nmav 1.9 * Hydra, an http server
3 nmav 1.1 * Copyright (C) 1999 Larry Doolittle <ldoolitt@boa.org>
4 nmav 1.2 * Portions Copyright (C) 2002 Nikos Mavroyanopoulos <nmav@gnutls.org>
5 nmav 1.1 *
6     * This program is free software; you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation; either version 1, or (at your option)
9     * any later version.
10     *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with this program; if not, write to the Free Software
18     * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19     *
20     */
21    
22 nmav 1.14 /* $Id: mmap_cache.c,v 1.13 2002/10/27 10:46:19 nmav Exp $*/
23 nmav 1.1
24     #include "boa.h"
25 nmav 1.2
26 nmav 1.1 #ifdef ENABLE_SMP
27     pthread_mutex_t mmap_lock = PTHREAD_MUTEX_INITIALIZER;
28     #endif
29    
30     int mmap_list_entries_used = 0;
31     int mmap_list_total_requests = 0;
32     int mmap_list_hash_bounces = 0;
33    
34 nmav 1.2 #ifdef USE_MMAP_LIST
35    
36 nmav 1.7 static int previous_max_files_cache = 0;
37    
38 nmav 1.1 /* define local table variable */
39 nmav 1.7 static struct mmap_entry* mmap_list;
40    
41 nmav 1.1
42 nmav 1.14 struct mmap_entry *find_mmap(int data_fd, struct stat *s)
43 nmav 1.1 {
44     char *m;
45     int i, start;
46    
47 nmav 1.7 if ( max_files_cache == 0) return NULL;
48    
49 nmav 1.1 #ifdef ENABLE_SMP
50     pthread_mutex_lock(&mmap_lock);
51     #endif
52     mmap_list_total_requests++;
53     i = start = MMAP_LIST_HASH(s->st_dev, s->st_ino, s->st_size);
54    
55 nmav 1.5 for (;mmap_list[i].available;) {
56 nmav 1.1 if (mmap_list[i].dev == s->st_dev && mmap_list[i].ino == s->st_ino
57     && mmap_list[i].len == s->st_size) {
58     mmap_list[i].use_count++;
59 nmav 1.2 mmap_list[i].times_used++;
60 nmav 1.1
61 nmav 1.4 #ifdef DEBUG0
62 nmav 1.1 fprintf(stderr,
63     "Old mmap_list entry %d use_count now %d (hash was %d)\n",
64     i, mmap_list[i].use_count, start);
65     #endif
66     #ifdef ENABLE_SMP
67     pthread_mutex_unlock(&mmap_lock);
68     #endif
69     return &mmap_list[i];
70     }
71     mmap_list_hash_bounces++;
72     i = MMAP_LIST_NEXT(i);
73 nmav 1.3
74 nmav 1.1 if (i == start) {
75 nmav 1.12 i = cleanup_mmap_list(0);
76 nmav 1.3 if (i != -1) break; /* if we found an empty index */
77     /* otherwise no space could be cleaned. So say bye!!
78     */
79 nmav 1.1 #ifdef ENABLE_SMP
80     pthread_mutex_unlock(&mmap_lock);
81     #endif
82     return NULL;
83     }
84    
85     }
86    
87     /* didn't find an entry that matches our dev/inode/size.
88     There might be an entry that matches later in the table,
89     but that _should_ be rare. The worst case is that we
90     needlessly mmap() a file that is already mmap'd, but we
91     did that all the time before this code was written,
92     so it shouldn't be _too_ bad.
93     */
94    
95     m = mmap(0, s->st_size, PROT_READ, MAP_OPTIONS, data_fd, 0);
96    
97 nmav 1.3 if ( m == MAP_FAILED) {
98 nmav 1.1 /* boa_perror(req,"mmap"); */
99     return NULL;
100     }
101 nmav 1.4 #ifdef DEBUG0
102 nmav 1.1 fprintf(stderr,
103     "New mmap_list entry %d (hash was %d) [ino: %u size: %u]\n", i,
104     start, s->st_ino, s->st_size);
105     #endif
106     mmap_list_entries_used++;
107     mmap_list[i].dev = s->st_dev;
108     mmap_list[i].ino = s->st_ino;
109     mmap_list[i].len = s->st_size;
110     mmap_list[i].mmap = m;
111     mmap_list[i].use_count = 1;
112     mmap_list[i].available = 1;
113 nmav 1.2 mmap_list[i].times_used = 1;
114 nmav 1.1
115     #ifdef ENABLE_SMP
116     pthread_mutex_unlock(&mmap_lock);
117     #endif
118     return &mmap_list[i];
119     }
120    
121     /* Removes all entries in the mmap list that are not used and
122 nmav 1.3 * have been used less times than the average of all.
123 nmav 1.2 * No locking here. The caller has to do the proper locking.
124 nmav 1.3 *
125     * Return values:
126     * -1 failed. Could not make any space on the list
127     * >=0 an index number, of an empty element in the list.
128     *
129 nmav 1.1 */
130 nmav 1.12 int cleanup_mmap_list(int all)
131 nmav 1.1 {
132 nmav 1.3 int i, avg = 0;
133     int ret = -1;
134 nmav 1.4 #ifdef DEBUG
135     int count = 0;
136    
137     fprintf(stderr, "Cleaning up mmap_list. Entries: %d.\n", mmap_list_entries_used);
138     #endif
139 nmav 1.2
140 nmav 1.12 if (all != 0) goto remove_all_unused;
141    
142 nmav 1.2 /* The algorithm here is:
143 nmav 1.4 * 1. Calculate the average of all times used
144     * 2. Remove all entries that have been used less than
145 nmav 1.5 * 'average' times. Also remove entries that their hash does not
146     * equal their index. This is to avoid duplicate entries.
147 nmav 1.2 */
148 nmav 1.7 for (i = 0; i < max_files_cache; i++) {
149 nmav 1.2 if (mmap_list[i].available) {
150 nmav 1.12 avg += mmap_list[i].times_used;
151 nmav 1.2 }
152     }
153 nmav 1.1
154 nmav 1.3 avg /= i;
155 nmav 1.1
156 nmav 1.7 for (i = 0; i < max_files_cache; i++) {
157 nmav 1.2 if (mmap_list[i].available && (mmap_list[i].use_count == 0) &&
158 nmav 1.5 (mmap_list[i].times_used < avg || MMAP_LIST_HASH(mmap_list[i].dev,
159     mmap_list[i].ino, mmap_list[i].len) != i)) {
160 nmav 1.3
161     ret = i;
162 nmav 1.1 munmap(mmap_list[i].mmap, mmap_list[i].len);
163     mmap_list[i].available = 0;
164     mmap_list_entries_used--;
165 nmav 1.2 #ifdef DEBUG
166 nmav 1.4 count++;
167 nmav 1.2 #endif
168 nmav 1.6 } else mmap_list[i].times_used = 0; /* zero all counters. */
169 nmav 1.2 }
170 nmav 1.4 #ifdef DEBUG
171     fprintf(stderr, "Removed %d entries from the mmap_hashtable (clean stage1)\n", count);
172     count = 0;
173     #endif
174 nmav 1.2
175     /* If no list elements were removed, then remove all that
176     * are not used. This is our last resort! We shouldn't have
177     * come here.
178     */
179 nmav 1.7 if (mmap_list_entries_used >= max_files_cache) {
180 nmav 1.12 remove_all_unused:
181 nmav 1.7 for (i = 0; i < max_files_cache; i++) {
182 nmav 1.2 if (mmap_list[i].available && mmap_list[i].use_count == 0) {
183    
184 nmav 1.3 ret = i;
185 nmav 1.2 munmap(mmap_list[i].mmap, mmap_list[i].len);
186     mmap_list[i].available = 0;
187     mmap_list_entries_used--;
188     #ifdef DEBUG
189 nmav 1.4 count++;
190 nmav 1.2 #endif
191     }
192 nmav 1.1 }
193 nmav 1.4 #ifdef DEBUG
194     fprintf(stderr, "Removed %d entries from the mmap_hashtable (clean stage2)\n", count);
195     #endif
196 nmav 1.1
197     }
198 nmav 1.2
199     /* If we have come here and we didn't remove any list entries,
200     * then all list entries are used or there is a bug above.
201     */
202 nmav 1.4
203     #ifdef DEBUG
204     fprintf(stderr, "Cleaned up mmap_list. Entries: %d.\n", mmap_list_entries_used);
205     #endif
206 nmav 1.3
207     return ret;
208 nmav 1.1 }
209    
210     void release_mmap(struct mmap_entry *e)
211     {
212     if (!e)
213     return;
214    
215     #ifdef ENABLE_SMP
216     pthread_mutex_lock(&mmap_lock);
217     #endif
218    
219     if (!e->use_count) {
220     #ifdef DEBUG
221     fprintf(stderr, "mmap_list(%p)->use_count already zero!\n", e);
222     #endif
223     goto finish;
224     }
225    
226     e->use_count--;
227    
228    
229     finish:
230     #ifdef ENABLE_SMP
231     pthread_mutex_unlock(&mmap_lock);
232     #endif
233     return;
234     }
235    
236     struct mmap_entry *find_named_mmap(char *fname)
237     {
238     int data_fd;
239 nmav 1.14 struct stat statbuf;
240 nmav 1.1 struct mmap_entry *e;
241     data_fd = open(fname, O_RDONLY);
242     if (data_fd == -1) {
243     perror(fname);
244     return NULL;
245     }
246     fstat(data_fd, &statbuf);
247     if (S_ISDIR(statbuf.st_mode)) {
248     #ifdef DEBUG
249     fprintf(stderr, "%s is a directory\n", fname);
250     #endif
251     return NULL;
252     }
253    
254     e = find_mmap(data_fd, &statbuf);
255     close(data_fd);
256     return e;
257     }
258    
259 nmav 1.7 void mmap_reinit()
260     {
261    
262     if (max_files_cache > previous_max_files_cache) {
263     mmap_list = realloc( mmap_list, sizeof(struct mmap_entry)*max_files_cache);
264     if (mmap_list == NULL) {
265     log_error_time();
266     fprintf(stderr, "Could not allocate mmap list\n");
267     exit(1);
268     }
269     memset( &mmap_list[previous_max_files_cache], 0, sizeof(struct mmap_entry)*
270     (max_files_cache-previous_max_files_cache));
271     } else {
272     /* we cannot make the max file cache less than
273     * the previous one, or we risk having some stray mmaped
274     * stuff, in memory we cannot access.
275     */
276 nmav 1.10 if (max_files_cache < previous_max_files_cache) {
277     log_error_time();
278     fprintf(stderr, "Cannot not decrease the maximum files cache value, on runtime.\n");
279     }
280    
281 nmav 1.7 max_files_cache = previous_max_files_cache;
282     }
283     previous_max_files_cache = max_files_cache;
284    
285     }
286 nmav 1.1
287 nmav 1.7 void initialize_mmap()
288     {
289     /* initialize the list array */
290     mmap_list = calloc( 1, sizeof(struct mmap_entry)*max_files_cache);
291     if (mmap_list == NULL) {
292     log_error_time();
293     fprintf(stderr, "Could not allocate mmap list\n");
294     exit(1);
295     }
296    
297     previous_max_files_cache = max_files_cache;
298     return;
299     }
300 nmav 1.2
301     #endif /* USE_MMAP_LIST */

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26