4
4
#include "fscache.h"
5
5
#include "../../dir.h"
6
6
#include "config.h"
7
+ #include "../../mem-pool.h"
7
8
8
9
static volatile long initialized ;
9
10
static DWORD dwTlsIndex ;
@@ -18,6 +19,7 @@ static CRITICAL_SECTION mutex;
18
19
struct fscache {
19
20
volatile long enabled ;
20
21
struct hashmap map ;
22
+ struct mem_pool mem_pool ;
21
23
unsigned int lstat_requests ;
22
24
unsigned int opendir_requests ;
23
25
unsigned int fscache_requests ;
@@ -122,11 +124,12 @@ static void fsentry_init(struct fsentry *fse, struct fsentry *list,
122
124
/*
123
125
* Allocate an fsentry structure on the heap.
124
126
*/
125
- static struct fsentry * fsentry_alloc (struct fsentry * list , const char * name ,
127
+ static struct fsentry * fsentry_alloc (struct fscache * cache , struct fsentry * list , const char * name ,
126
128
size_t len )
127
129
{
128
130
/* overallocate fsentry and copy the name to the end */
129
- struct fsentry * fse = xmalloc (sizeof (struct fsentry ) + len + 1 );
131
+ struct fsentry * fse =
132
+ mem_pool_alloc (& cache -> mem_pool , sizeof (* fse ) + len + 1 );
130
133
/* init the rest of the structure */
131
134
fsentry_init (fse , list , name , len );
132
135
fse -> next = NULL ;
@@ -146,35 +149,29 @@ inline static void fsentry_addref(struct fsentry *fse)
146
149
}
147
150
148
151
/*
149
- * Release the reference to an fsentry, frees the memory if its the last ref .
152
+ * Release the reference to an fsentry.
150
153
*/
151
154
static void fsentry_release (struct fsentry * fse )
152
155
{
153
156
if (fse -> list )
154
157
fse = fse -> list ;
155
158
156
- if (InterlockedDecrement (& (fse -> u .refcnt )))
157
- return ;
158
-
159
- while (fse ) {
160
- struct fsentry * next = fse -> next ;
161
- free (fse );
162
- fse = next ;
163
- }
159
+ InterlockedDecrement (& (fse -> u .refcnt ));
164
160
}
165
161
166
162
/*
167
163
* Allocate and initialize an fsentry from a WIN32_FIND_DATA structure.
168
164
*/
169
- static struct fsentry * fseentry_create_entry (struct fsentry * list ,
165
+ static struct fsentry * fseentry_create_entry (struct fscache * cache ,
166
+ struct fsentry * list ,
170
167
const WIN32_FIND_DATAW * fdata )
171
168
{
172
169
char buf [MAX_PATH * 3 ];
173
170
int len ;
174
171
struct fsentry * fse ;
175
172
len = xwcstoutf (buf , fdata -> cFileName , ARRAY_SIZE (buf ));
176
173
177
- fse = fsentry_alloc (list , buf , len );
174
+ fse = fsentry_alloc (cache , list , buf , len );
178
175
179
176
fse -> st_mode = file_attr_to_st_mode (fdata -> dwFileAttributes );
180
177
fse -> dirent .d_type = S_ISDIR (fse -> st_mode ) ? DT_DIR : DT_REG ;
@@ -192,7 +189,7 @@ static struct fsentry *fseentry_create_entry(struct fsentry *list,
192
189
* Dir should not contain trailing '/'. Use an empty string for the current
193
190
* directory (not "."!).
194
191
*/
195
- static struct fsentry * fsentry_create_list (const struct fsentry * dir ,
192
+ static struct fsentry * fsentry_create_list (struct fscache * cache , const struct fsentry * dir ,
196
193
int * dir_not_found )
197
194
{
198
195
wchar_t pattern [MAX_PATH + 2 ]; /* + 2 for '/' '*' */
@@ -231,14 +228,14 @@ static struct fsentry *fsentry_create_list(const struct fsentry *dir,
231
228
}
232
229
233
230
/* allocate object to hold directory listing */
234
- list = fsentry_alloc (NULL , dir -> dirent .d_name , dir -> len );
231
+ list = fsentry_alloc (cache , NULL , dir -> dirent .d_name , dir -> len );
235
232
list -> st_mode = S_IFDIR ;
236
233
list -> dirent .d_type = DT_DIR ;
237
234
238
235
/* walk directory and build linked list of fsentry structures */
239
236
phead = & list -> next ;
240
237
do {
241
- * phead = fseentry_create_entry (list , & fdata );
238
+ * phead = fseentry_create_entry (cache , list , & fdata );
242
239
phead = & (* phead )-> next ;
243
240
} while (FindNextFileW (h , & fdata ));
244
241
@@ -250,7 +247,7 @@ static struct fsentry *fsentry_create_list(const struct fsentry *dir,
250
247
if (err == ERROR_NO_MORE_FILES )
251
248
return list ;
252
249
253
- /* otherwise free the list and return error */
250
+ /* otherwise release the list and return error */
254
251
fsentry_release (list );
255
252
errno = err_win_to_posix (err );
256
253
return NULL ;
@@ -273,7 +270,9 @@ static void fscache_add(struct fscache *cache, struct fsentry *fse)
273
270
*/
274
271
static void fscache_clear (struct fscache * cache )
275
272
{
276
- hashmap_clear_and_free (& cache -> map , struct fsentry , ent );
273
+ mem_pool_discard (& cache -> mem_pool , 0 );
274
+ mem_pool_init (& cache -> mem_pool , 0 );
275
+ hashmap_clear (& cache -> map );
277
276
hashmap_init (& cache -> map , (hashmap_cmp_fn )fsentry_cmp , NULL , 0 );
278
277
cache -> lstat_requests = cache -> opendir_requests = 0 ;
279
278
cache -> fscache_misses = cache -> fscache_requests = 0 ;
@@ -326,7 +325,7 @@ static struct fsentry *fscache_get(struct fscache *cache, struct fsentry *key)
326
325
}
327
326
328
327
/* create the directory listing */
329
- fse = fsentry_create_list (key -> list ? key -> list : key , & dir_not_found );
328
+ fse = fsentry_create_list (cache , key -> list ? key -> list : key , & dir_not_found );
330
329
331
330
/* leave on error (errno set by fsentry_create_list) */
332
331
if (!fse ) {
@@ -336,7 +335,7 @@ static struct fsentry *fscache_get(struct fscache *cache, struct fsentry *key)
336
335
* empty, which for all practical matters is the same
337
336
* thing as far as fscache is concerned).
338
337
*/
339
- fse = fsentry_alloc (key -> list -> list ,
338
+ fse = fsentry_alloc (cache , key -> list -> list ,
340
339
key -> list -> dirent .d_name ,
341
340
key -> list -> len );
342
341
fse -> st_mode = 0 ;
@@ -415,6 +414,7 @@ int fscache_enable(size_t initial_size)
415
414
* '4' was determined empirically by testing several repos
416
415
*/
417
416
hashmap_init (& cache -> map , (hashmap_cmp_fn )fsentry_cmp , NULL , initial_size * 4 );
417
+ mem_pool_init (& cache -> mem_pool , 0 );
418
418
if (!TlsSetValue (dwTlsIndex , cache ))
419
419
BUG ("TlsSetValue error" );
420
420
}
@@ -446,7 +446,8 @@ void fscache_disable(void)
446
446
"total requests/misses %u/%u\n" ,
447
447
cache -> lstat_requests , cache -> opendir_requests ,
448
448
cache -> fscache_requests , cache -> fscache_misses );
449
- fscache_clear (cache );
449
+ mem_pool_discard (& cache -> mem_pool , 0 );
450
+ hashmap_clear (& cache -> map );
450
451
free (cache );
451
452
}
452
453
@@ -631,6 +632,8 @@ void fscache_merge(struct fscache *dest)
631
632
while ((e = hashmap_iter_next (& iter )))
632
633
hashmap_add (& dest -> map , e );
633
634
635
+ mem_pool_combine (& dest -> mem_pool , & cache -> mem_pool );
636
+
634
637
dest -> lstat_requests += cache -> lstat_requests ;
635
638
dest -> opendir_requests += cache -> opendir_requests ;
636
639
dest -> fscache_requests += cache -> fscache_requests ;
0 commit comments