Mercurial > mm7
comparison lib/swig/swigwin-2.0.11/CCache/cleanup.c @ 1899:b3009adc0e2f
Adding swig, gitignore, hgignore
author | Nomad |
---|---|
date | Mon, 21 Oct 2013 10:42:27 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
1867:eb580660bbbb | 1899:b3009adc0e2f |
---|---|
1 /* | |
2 Copyright (C) Andrew Tridgell 2002 | |
3 | |
4 This program is free software; you can redistribute it and/or modify | |
5 it under the terms of the GNU General Public License as published by | |
6 the Free Software Foundation; either version 2 of the License, or | |
7 (at your option) any later version. | |
8 | |
9 This program is distributed in the hope that it will be useful, | |
10 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 GNU General Public License for more details. | |
13 | |
14 You should have received a copy of the GNU General Public License | |
15 along with this program; if not, write to the Free Software | |
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
17 */ | |
18 /* | |
19 functions to cleanup the cache directory when it gets too large | |
20 */ | |
21 | |
22 #include "ccache.h" | |
23 | |
24 static struct files { | |
25 char *fname; | |
26 time_t mtime; | |
27 size_t size; | |
28 } **files; | |
29 static unsigned allocated; | |
30 static unsigned num_files; | |
31 static size_t total_size; | |
32 static size_t total_files; | |
33 static size_t size_threshold; | |
34 static size_t files_threshold; | |
35 | |
36 /* file comparison function to try to delete the oldest files first */ | |
37 static int files_compare(struct files **f1, struct files **f2) | |
38 { | |
39 if ((*f2)->mtime == (*f1)->mtime) { | |
40 return strcmp((*f2)->fname, (*f1)->fname); | |
41 } | |
42 if ((*f2)->mtime > (*f1)->mtime) { | |
43 return -1; | |
44 } | |
45 return 1; | |
46 } | |
47 | |
48 /* this builds the list of files in the cache */ | |
49 static void traverse_fn(const char *fname, struct stat *st) | |
50 { | |
51 char *p; | |
52 | |
53 if (!S_ISREG(st->st_mode)) return; | |
54 | |
55 p = str_basename(fname); | |
56 if (strcmp(p, "stats") == 0) { | |
57 free(p); | |
58 return; | |
59 } | |
60 free(p); | |
61 | |
62 if (num_files == allocated) { | |
63 allocated = 10000 + num_files*2; | |
64 files = (struct files **)x_realloc(files, | |
65 sizeof(struct files *)*allocated); | |
66 } | |
67 | |
68 files[num_files] = (struct files *)x_malloc(sizeof(struct files)); | |
69 files[num_files]->fname = x_strdup(fname); | |
70 files[num_files]->mtime = st->st_mtime; | |
71 files[num_files]->size = file_size(st) / 1024; | |
72 total_size += files[num_files]->size; | |
73 num_files++; | |
74 } | |
75 | |
76 /* sort the files we've found and delete the oldest ones until we are | |
77 below the thresholds */ | |
78 static void sort_and_clean(size_t minfiles) | |
79 { | |
80 unsigned i; | |
81 size_t adjusted_minfiles = minfiles; | |
82 | |
83 if (num_files > 1) { | |
84 /* sort in ascending data order */ | |
85 qsort(files, num_files, sizeof(struct files *), | |
86 (COMPAR_FN_T)files_compare); | |
87 } | |
88 /* ensure newly cached files (minfiles) are kept - instead of matching | |
89 the filenames of those newly cached, a faster and simpler approach | |
90 assumes these are the most recent in the cache and if any other | |
91 cached files have an identical time stamp, they will also be kept - | |
92 this approach would not be needed if the cleanup was done at exit. */ | |
93 if (minfiles != 0 && minfiles < num_files) { | |
94 unsigned minfiles_index = num_files - minfiles; | |
95 time_t minfiles_time = files[minfiles_index]->mtime; | |
96 for (i=1; i<=minfiles_index; i++) { | |
97 if (files[minfiles_index-i]->mtime == minfiles_time) | |
98 adjusted_minfiles++; | |
99 else | |
100 break; | |
101 } | |
102 } | |
103 | |
104 /* delete enough files to bring us below the threshold */ | |
105 for (i=0;i<num_files; i++) { | |
106 if ((size_threshold==0 || total_size < size_threshold) && | |
107 (files_threshold==0 || (num_files-i) < files_threshold)) break; | |
108 | |
109 if (adjusted_minfiles != 0 && num_files-i <= adjusted_minfiles) | |
110 break; | |
111 | |
112 if (unlink(files[i]->fname) != 0 && errno != ENOENT) { | |
113 fprintf(stderr, "unlink %s - %s\n", | |
114 files[i]->fname, strerror(errno)); | |
115 continue; | |
116 } | |
117 | |
118 total_size -= files[i]->size; | |
119 } | |
120 | |
121 total_files = num_files - i; | |
122 } | |
123 | |
124 /* cleanup in one cache subdir */ | |
125 void cleanup_dir(const char *dir, size_t maxfiles, size_t maxsize, size_t minfiles) | |
126 { | |
127 unsigned i; | |
128 | |
129 size_threshold = maxsize * LIMIT_MULTIPLE; | |
130 files_threshold = maxfiles * LIMIT_MULTIPLE; | |
131 | |
132 num_files = 0; | |
133 total_size = 0; | |
134 | |
135 /* build a list of files */ | |
136 traverse(dir, traverse_fn); | |
137 | |
138 /* clean the cache */ | |
139 sort_and_clean(minfiles); | |
140 | |
141 stats_set_sizes(dir, total_files, total_size); | |
142 | |
143 /* free it up */ | |
144 for (i=0;i<num_files;i++) { | |
145 free(files[i]->fname); | |
146 free(files[i]); | |
147 files[i] = NULL; | |
148 } | |
149 if (files) free(files); | |
150 allocated = 0; | |
151 files = NULL; | |
152 | |
153 num_files = 0; | |
154 total_size = 0; | |
155 } | |
156 | |
157 /* cleanup in all cache subdirs */ | |
158 void cleanup_all(const char *dir) | |
159 { | |
160 unsigned counters[STATS_END]; | |
161 char *dname, *sfile; | |
162 int i; | |
163 | |
164 for (i=0;i<=0xF;i++) { | |
165 x_asprintf(&dname, "%s/%1x", dir, i); | |
166 x_asprintf(&sfile, "%s/%1x/stats", dir, i); | |
167 | |
168 memset(counters, 0, sizeof(counters)); | |
169 stats_read(sfile, counters); | |
170 | |
171 cleanup_dir(dname, | |
172 counters[STATS_MAXFILES], | |
173 counters[STATS_MAXSIZE], | |
174 0); | |
175 free(dname); | |
176 free(sfile); | |
177 } | |
178 } | |
179 | |
180 | |
181 /* traverse function for wiping files */ | |
182 static void wipe_fn(const char *fname, struct stat *st) | |
183 { | |
184 char *p; | |
185 | |
186 if (!S_ISREG(st->st_mode)) return; | |
187 | |
188 p = str_basename(fname); | |
189 if (strcmp(p, "stats") == 0) { | |
190 free(p); | |
191 return; | |
192 } | |
193 free(p); | |
194 | |
195 unlink(fname); | |
196 } | |
197 | |
198 | |
199 /* wipe all cached files in all subdirs */ | |
200 void wipe_all(const char *dir) | |
201 { | |
202 char *dname; | |
203 int i; | |
204 | |
205 for (i=0;i<=0xF;i++) { | |
206 x_asprintf(&dname, "%s/%1x", dir, i); | |
207 traverse(dir, wipe_fn); | |
208 free(dname); | |
209 } | |
210 | |
211 /* and fix the counters */ | |
212 cleanup_all(dir); | |
213 } |