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 }