33#include  "../win32.h" 
44#include  "fscache.h" 
55#include  "config.h" 
6+ #include  "../../mem-pool.h" 
67
78static  volatile  long  initialized ;
89static  DWORD  dwTlsIndex ;
@@ -17,6 +18,7 @@ static CRITICAL_SECTION mutex;
1718struct  fscache  {
1819	volatile  long  enabled ;
1920	struct  hashmap  map ;
21+ 	struct  mem_pool  mem_pool ;
2022	unsigned int   lstat_requests ;
2123	unsigned int   opendir_requests ;
2224	unsigned int   fscache_requests ;
@@ -116,11 +118,12 @@ static void fsentry_init(struct fsentry *fse, struct fsentry *list,
116118/* 
117119 * Allocate an fsentry structure on the heap. 
118120 */ 
119- static  struct  fsentry  * fsentry_alloc (struct  fsentry  * list , const  char  * name ,
121+ static  struct  fsentry  * fsentry_alloc (struct  fscache   * cache ,  struct   fsentry  * list , const  char  * name ,
120122		size_t  len )
121123{
122124	/* overallocate fsentry and copy the name to the end */ 
123- 	struct  fsentry  * fse  =  xmalloc (sizeof (struct  fsentry ) +  len  +  1 );
125+ 	struct  fsentry  * fse  = 
126+ 		mem_pool_alloc (& cache -> mem_pool , sizeof (* fse ) +  len  +  1 );
124127	/* init the rest of the structure */ 
125128	fsentry_init (fse , list , name , len );
126129	fse -> next  =  NULL ;
@@ -140,35 +143,29 @@ inline static void fsentry_addref(struct fsentry *fse)
140143}
141144
142145/* 
143-  * Release the reference to an fsentry, frees the memory if its the last ref . 
146+  * Release the reference to an fsentry. 
144147 */ 
145148static  void  fsentry_release (struct  fsentry  * fse )
146149{
147150	if  (fse -> list )
148151		fse  =  fse -> list ;
149152
150- 	if  (InterlockedDecrement (& (fse -> u .refcnt )))
151- 		return ;
152- 
153- 	while  (fse ) {
154- 		struct  fsentry  * next  =  fse -> next ;
155- 		free (fse );
156- 		fse  =  next ;
157- 	}
153+ 	InterlockedDecrement (& (fse -> u .refcnt ));
158154}
159155
160156/* 
161157 * Allocate and initialize an fsentry from a WIN32_FIND_DATA structure. 
162158 */ 
163- static  struct  fsentry  * fseentry_create_entry (struct  fsentry  * list ,
159+ static  struct  fsentry  * fseentry_create_entry (struct  fscache  * cache ,
160+ 					     struct  fsentry  * list ,
164161					     const  WIN32_FIND_DATAW  * fdata )
165162{
166163	char  buf [MAX_PATH  *  3 ];
167164	int  len ;
168165	struct  fsentry  * fse ;
169166	len  =  xwcstoutf (buf , fdata -> cFileName , ARRAY_SIZE (buf ));
170167
171- 	fse  =  fsentry_alloc (list , buf , len );
168+ 	fse  =  fsentry_alloc (cache ,  list , buf , len );
172169
173170	fse -> st_mode  =  file_attr_to_st_mode (fdata -> dwFileAttributes );
174171	fse -> dirent .d_type  =  S_ISDIR (fse -> st_mode ) ? DT_DIR  : DT_REG ;
@@ -186,7 +183,7 @@ static struct fsentry *fseentry_create_entry(struct fsentry *list,
186183 * Dir should not contain trailing '/'. Use an empty string for the current 
187184 * directory (not "."!). 
188185 */ 
189- static  struct  fsentry  * fsentry_create_list (const  struct  fsentry  * dir ,
186+ static  struct  fsentry  * fsentry_create_list (struct   fscache   * cache ,  const  struct  fsentry  * dir ,
190187					   int  * dir_not_found )
191188{
192189	wchar_t  pattern [MAX_PATH  +  2 ]; /* + 2 for '/' '*' */ 
@@ -225,14 +222,14 @@ static struct fsentry *fsentry_create_list(const struct fsentry *dir,
225222	}
226223
227224	/* allocate object to hold directory listing */ 
228- 	list  =  fsentry_alloc (NULL , dir -> dirent .d_name , dir -> len );
225+ 	list  =  fsentry_alloc (cache ,  NULL , dir -> dirent .d_name , dir -> len );
229226	list -> st_mode  =  S_IFDIR ;
230227	list -> dirent .d_type  =  DT_DIR ;
231228
232229	/* walk directory and build linked list of fsentry structures */ 
233230	phead  =  & list -> next ;
234231	do  {
235- 		* phead  =  fseentry_create_entry (list , & fdata );
232+ 		* phead  =  fseentry_create_entry (cache ,  list , & fdata );
236233		phead  =  & (* phead )-> next ;
237234	} while  (FindNextFileW (h , & fdata ));
238235
@@ -244,7 +241,7 @@ static struct fsentry *fsentry_create_list(const struct fsentry *dir,
244241	if  (err  ==  ERROR_NO_MORE_FILES )
245242		return  list ;
246243
247- 	/* otherwise free  the list and return error */ 
244+ 	/* otherwise release  the list and return error */ 
248245	fsentry_release (list );
249246	errno  =  err_win_to_posix (err );
250247	return  NULL ;
@@ -267,7 +264,9 @@ static void fscache_add(struct fscache *cache, struct fsentry *fse)
267264 */ 
268265static  void  fscache_clear (struct  fscache  * cache )
269266{
270- 	hashmap_free_entries (& cache -> map , struct  fsentry , ent );
267+ 	mem_pool_discard (& cache -> mem_pool , 0 );
268+ 	mem_pool_init (& cache -> mem_pool , 0 );
269+ 	hashmap_free (& cache -> map );
271270	hashmap_init (& cache -> map , (hashmap_cmp_fn )fsentry_cmp , NULL , 0 );
272271	cache -> lstat_requests  =  cache -> opendir_requests  =  0 ;
273272	cache -> fscache_misses  =  cache -> fscache_requests  =  0 ;
@@ -320,7 +319,7 @@ static struct fsentry *fscache_get(struct fscache *cache, struct fsentry *key)
320319	}
321320
322321	/* create the directory listing */ 
323- 	fse  =  fsentry_create_list (key -> list  ? key -> list  : key , & dir_not_found );
322+ 	fse  =  fsentry_create_list (cache ,  key -> list  ? key -> list  : key , & dir_not_found );
324323
325324	/* leave on error (errno set by fsentry_create_list) */ 
326325	if  (!fse ) {
@@ -330,7 +329,7 @@ static struct fsentry *fscache_get(struct fscache *cache, struct fsentry *key)
330329			 * empty, which for all practical matters is the same 
331330			 * thing as far as fscache is concerned). 
332331			 */ 
333- 			fse  =  fsentry_alloc (key -> list -> list ,
332+ 			fse  =  fsentry_alloc (cache ,  key -> list -> list ,
334333					    key -> list -> dirent .d_name ,
335334					    key -> list -> len );
336335			fse -> st_mode  =  0 ;
@@ -409,6 +408,7 @@ int fscache_enable(size_t initial_size)
409408		 * '4' was determined empirically by testing several repos 
410409		 */ 
411410		hashmap_init (& cache -> map , (hashmap_cmp_fn )fsentry_cmp , NULL , initial_size  *  4 );
411+ 		mem_pool_init (& cache -> mem_pool , 0 );
412412		if  (!TlsSetValue (dwTlsIndex , cache ))
413413			BUG ("TlsSetValue error" );
414414	}
@@ -440,7 +440,8 @@ void fscache_disable(void)
440440			"total requests/misses %u/%u\n" ,
441441			cache -> lstat_requests , cache -> opendir_requests ,
442442			cache -> fscache_requests , cache -> fscache_misses );
443- 		fscache_clear (cache );
443+ 		mem_pool_discard (& cache -> mem_pool , 0 );
444+ 		hashmap_free (& cache -> map );
444445		free (cache );
445446	}
446447
@@ -623,6 +624,8 @@ void fscache_merge(struct fscache *dest)
623624	while  ((e  =  hashmap_iter_next (& iter )))
624625		hashmap_add (& dest -> map , e );
625626
627+ 	mem_pool_combine (& dest -> mem_pool , & cache -> mem_pool );
628+ 
626629	dest -> lstat_requests  +=  cache -> lstat_requests ;
627630	dest -> opendir_requests  +=  cache -> opendir_requests ;
628631	dest -> fscache_requests  +=  cache -> fscache_requests ;
0 commit comments