Mercurial > hg > nginx
comparison src/core/ngx_garbage_collector.c @ 185:d5f50cefc322
nginx-0.0.1-2003-11-14-19:52:04 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Fri, 14 Nov 2003 16:52:04 +0000 |
parents | |
children | c1f3a3c7c5db |
comparison
equal
deleted
inserted
replaced
184:1bf718ce0dde | 185:d5f50cefc322 |
---|---|
1 | |
2 #include <ngx_config.h> | |
3 #include <ngx_core.h> | |
4 | |
5 | |
6 typedef struct ngx_gc_s ngx_gc_t; | |
7 | |
8 typedef int (*ngx_gc_handler_pt) (ngx_gc_t *ctx, ngx_str_t *name, | |
9 ngx_file_info_t *fi); | |
10 | |
11 struct ngx_gc_s { | |
12 ngx_path_t *path; | |
13 u_int deleted; | |
14 off_t freed; | |
15 ngx_gc_handler_pt handler; | |
16 ngx_log_t *log; | |
17 }; | |
18 | |
19 | |
20 static int ngx_collect_garbage(ngx_gc_t *ctx, ngx_str_t *dname, int level); | |
21 | |
22 | |
23 | |
24 #if 0 | |
25 | |
26 { | |
27 ngx_test_null(cycle->timer_events, | |
28 ngx_alloc(sizeof(ngx_event_t) * TIMERS, cycle->log), | |
29 NGX_ERROR); | |
30 | |
31 ngx_event_timer_init(cycle); | |
32 } | |
33 | |
34 | |
35 void garbage_collector() | |
36 { | |
37 ngx_msec_t timer; | |
38 struct timeval tv; | |
39 ngx_epoch_msec_t delta; | |
40 | |
41 for ( ;; ) { | |
42 timer = ngx_event_find_timer(); | |
43 | |
44 ngx_gettimeofday(&tv); | |
45 delta = tv.tv_sec * 1000 + tv.tv_usec / 1000; | |
46 | |
47 msleep(timer); | |
48 | |
49 ngx_gettimeofday(&tv); | |
50 | |
51 ngx_cached_time = tv.tv_sec; | |
52 ngx_time_update(); | |
53 | |
54 delta = tv.tv_sec * 1000 + tv.tv_usec / 1000 - delta; | |
55 | |
56 ngx_event_expire_timers((ngx_msec_t) delta); | |
57 } | |
58 } | |
59 | |
60 #endif | |
61 | |
62 | |
63 void stub_init(ngx_log_t *log) | |
64 { | |
65 ngx_gc_t *ctx; | |
66 ngx_path_t path; | |
67 | |
68 if (!(ctx = ngx_alloc(sizeof(ngx_gc_t), log))) { | |
69 return; | |
70 } | |
71 | |
72 path.name.len = 4; | |
73 path.name.data = "temp"; | |
74 path.len = 5; | |
75 path.level[0] = 1; | |
76 path.level[1] = 2; | |
77 path.level[2] = 0; | |
78 | |
79 ctx->path = &path; | |
80 ctx->log = log; | |
81 | |
82 ngx_collect_garbage(ctx, &path.name, 0); | |
83 } | |
84 | |
85 | |
86 static int ngx_collect_garbage(ngx_gc_t *ctx, ngx_str_t *dname, int level) | |
87 { | |
88 int nlen; | |
89 char *last; | |
90 ngx_str_t fname; | |
91 ngx_dir_t *dir; | |
92 ngx_dirent_t *de; | |
93 ngx_file_info_t fi; | |
94 | |
95 fname.len = 0; | |
96 | |
97 ngx_log_debug(ctx->log, "dir %s" _ dname->data); | |
98 | |
99 dir = ngx_open_dir(dname->data); | |
100 | |
101 if (dir == NULL) { | |
102 ngx_log_error(NGX_LOG_ERR, ctx->log, ngx_errno, | |
103 ngx_open_dir_n " \"%s\" failed", dname->data); | |
104 return NGX_ERROR; | |
105 } | |
106 | |
107 for ( ;; ) { | |
108 de = ngx_read_dir(dir); | |
109 | |
110 if (de == NULL) { | |
111 if (fname.len) { | |
112 ngx_free(fname.data); | |
113 } | |
114 break; | |
115 } | |
116 | |
117 ngx_log_debug(ctx->log, "file %s" _ de->d_name); | |
118 | |
119 #ifdef __FreeBSD__ | |
120 nlen = de->d_namlen; | |
121 #else | |
122 nlen = ngx_strlen(de->d_name); | |
123 #endif | |
124 | |
125 if (nlen == 1 && de->d_name[0] == '.') { | |
126 continue; | |
127 } | |
128 | |
129 if (nlen == 2 && de->d_name[0] == '.' && de->d_name[1] == '.') { | |
130 continue; | |
131 } | |
132 | |
133 if (dname->len + 1 + nlen > fname.len) { | |
134 if (fname.len) { | |
135 ngx_free(fname.data); | |
136 } | |
137 | |
138 fname.len = dname->len + 1 + nlen; | |
139 | |
140 if (!(fname.data = ngx_alloc(fname.len + 1, ctx->log))) { | |
141 return NGX_ABORT; | |
142 } | |
143 } | |
144 | |
145 last = ngx_cpymem(fname.data, dname->data, dname->len); | |
146 *last++ = '/'; | |
147 ngx_memcpy(last, de->d_name, nlen + 1); | |
148 | |
149 ngx_log_debug(ctx->log, "de %s" _ fname.data); | |
150 | |
151 if (ngx_file_type(fname.data, &fi) == NGX_FILE_ERROR) { | |
152 ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno, | |
153 ngx_file_type_n " \"%s\" failed", fname.data); | |
154 continue; | |
155 } | |
156 | |
157 if (ngx_is_dir((&fi))) { | |
158 | |
159 ngx_log_debug(ctx->log, "enter %s" _ fname.data); | |
160 | |
161 if (level == -1 | |
162 /* there can not be directory on the last level */ | |
163 || level == NGX_MAX_PATH_LEVEL | |
164 /* an directory from the old path hierarchy */ | |
165 || nlen != ctx->path->level[level]) | |
166 { | |
167 if (ngx_collect_garbage(ctx, &fname, -1) == NGX_ABORT) { | |
168 return NGX_ABORT; | |
169 } | |
170 | |
171 ngx_log_error(NGX_LOG_NOTICE, ctx->log, 0, | |
172 "delete old hierachy directory \"%s\"", | |
173 fname.data); | |
174 | |
175 if (ngx_delete_dir(fname.data) == NGX_FILE_ERROR) { | |
176 ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno, | |
177 ngx_delete_dir_n " \"%s\" failed", | |
178 fname.data); | |
179 } else { | |
180 ctx->deleted++; | |
181 ctx->freed += ngx_file_size((&fi)); | |
182 } | |
183 | |
184 continue; | |
185 } | |
186 | |
187 if (ngx_collect_garbage(ctx, &fname, level + 1) == NGX_ABORT) { | |
188 return NGX_ABORT; | |
189 } | |
190 | |
191 } else if (ngx_is_file((&fi))) { | |
192 | |
193 if (level == -1 | |
194 || (level < NGX_MAX_PATH_LEVEL && ctx->path->level[level] != 0)) | |
195 { | |
196 if (ngx_delete_file(fname.data) == NGX_FILE_ERROR) { | |
197 ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno, | |
198 ngx_delete_file_n " \"%s\" failed", | |
199 fname.data); | |
200 } else { | |
201 ctx->deleted++; | |
202 ctx->freed += ngx_file_size((&fi)); | |
203 } | |
204 | |
205 continue; | |
206 } | |
207 | |
208 if (ctx->handler(ctx, &fname, &fi) == NGX_ABORT) { | |
209 return NGX_ABORT; | |
210 } | |
211 | |
212 } else { | |
213 ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno, | |
214 "\"%s\" has unknown file type, deleting", fname.data); | |
215 | |
216 if (ngx_delete_file(fname.data) == NGX_FILE_ERROR) { | |
217 ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno, | |
218 ngx_delete_file_n " \"%s\" failed", fname.data); | |
219 } else { | |
220 ctx->deleted++; | |
221 ctx->freed += ngx_file_size((&fi)); | |
222 } | |
223 } | |
224 } | |
225 | |
226 return NGX_OK; | |
227 } | |
228 | |
229 | |
230 int ngx_garbage_collector_temp_handler(ngx_gc_t *ctx, ngx_str_t *name, | |
231 ngx_file_info_t *fi) | |
232 { | |
233 /* | |
234 * we use mtime only and do not use atime because: | |
235 * on NTFS access time has a resolution of 1 hour, | |
236 * on NT FAT access time has a resolution of 1 day, | |
237 * Unices have mount option "noatime" | |
238 */ | |
239 | |
240 if (ngx_cached_time - ngx_file_mtime(fi) < 3600) { | |
241 return NGX_OK; | |
242 } | |
243 | |
244 ngx_log_error(NGX_LOG_NOTICE, ctx->log, 0, | |
245 "delete stale temporary \"%s\"", name->data); | |
246 | |
247 if (ngx_delete_file(name->data) == NGX_FILE_ERROR) { | |
248 ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno, | |
249 ngx_delete_file_n " \"%s\" failed", name->data); | |
250 return NGX_ERROR; | |
251 } | |
252 | |
253 ctx->deleted++; | |
254 ctx->freed += ngx_file_size(fi); | |
255 return NGX_OK; | |
256 } |