2003-11-14 13:52:04 -03:00
|
|
|
|
|
|
|
#include <ngx_config.h>
|
|
|
|
#include <ngx_core.h>
|
2003-11-18 18:34:08 -03:00
|
|
|
#include <ngx_garbage_collector.h>
|
2003-11-14 13:52:04 -03:00
|
|
|
|
|
|
|
|
2003-11-18 18:34:08 -03:00
|
|
|
int ngx_garbage_collector_temp_handler(ngx_gc_t *ctx, ngx_str_t *name,
|
|
|
|
ngx_dir_t *dir);
|
2003-11-14 13:52:04 -03:00
|
|
|
|
|
|
|
|
|
|
|
static int ngx_collect_garbage(ngx_gc_t *ctx, ngx_str_t *dname, int level);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
|
|
|
{
|
|
|
|
ngx_test_null(cycle->timer_events,
|
|
|
|
ngx_alloc(sizeof(ngx_event_t) * TIMERS, cycle->log),
|
|
|
|
NGX_ERROR);
|
|
|
|
|
|
|
|
ngx_event_timer_init(cycle);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void garbage_collector()
|
|
|
|
{
|
|
|
|
ngx_msec_t timer;
|
|
|
|
struct timeval tv;
|
|
|
|
ngx_epoch_msec_t delta;
|
|
|
|
|
|
|
|
for ( ;; ) {
|
|
|
|
timer = ngx_event_find_timer();
|
|
|
|
|
|
|
|
ngx_gettimeofday(&tv);
|
|
|
|
delta = tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
|
|
|
|
|
|
|
msleep(timer);
|
|
|
|
|
|
|
|
ngx_gettimeofday(&tv);
|
|
|
|
|
|
|
|
ngx_cached_time = tv.tv_sec;
|
|
|
|
ngx_time_update();
|
|
|
|
|
|
|
|
delta = tv.tv_sec * 1000 + tv.tv_usec / 1000 - delta;
|
|
|
|
|
|
|
|
ngx_event_expire_timers((ngx_msec_t) delta);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2003-11-18 18:34:08 -03:00
|
|
|
void stub_init(ngx_cycle_t *cycle)
|
2003-11-14 13:52:04 -03:00
|
|
|
{
|
2003-11-18 18:34:08 -03:00
|
|
|
int i;
|
|
|
|
ngx_gc_t ctx;
|
|
|
|
ngx_path_t **path;
|
2003-11-14 13:52:04 -03:00
|
|
|
|
2003-11-18 18:34:08 -03:00
|
|
|
path = cycle->pathes.elts;
|
|
|
|
for (i = 0; i < cycle->pathes.nelts; i++) {
|
|
|
|
ctx.path = path[i];
|
|
|
|
ctx.log = cycle->log;
|
|
|
|
ctx.handler = path[i]->gc_handler;
|
2003-11-14 13:52:04 -03:00
|
|
|
|
2003-11-18 18:34:08 -03:00
|
|
|
ngx_collect_garbage(&ctx, &path[i]->name, 0);
|
|
|
|
}
|
2003-11-14 13:52:04 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int ngx_collect_garbage(ngx_gc_t *ctx, ngx_str_t *dname, int level)
|
|
|
|
{
|
2003-11-16 18:49:42 -03:00
|
|
|
int rc, len;
|
|
|
|
char *last;
|
|
|
|
ngx_err_t err;
|
|
|
|
ngx_str_t fname, buf;
|
|
|
|
ngx_dir_t dir;
|
2003-11-14 13:52:04 -03:00
|
|
|
|
2003-11-16 18:49:42 -03:00
|
|
|
buf.len = 0;
|
2003-11-14 13:52:04 -03:00
|
|
|
|
2003-11-16 18:49:42 -03:00
|
|
|
ngx_log_debug(ctx->log, "dir '%s':%d" _ dname->data _ dname->len);
|
2003-11-14 13:52:04 -03:00
|
|
|
|
2003-11-16 18:49:42 -03:00
|
|
|
if (ngx_open_dir(dname, &dir) == NGX_ERROR) {
|
|
|
|
ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno,
|
|
|
|
ngx_open_dir_n " \"%s\" failed", dname->data);
|
2003-11-14 13:52:04 -03:00
|
|
|
return NGX_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
for ( ;; ) {
|
2003-11-16 18:49:42 -03:00
|
|
|
ngx_set_errno(0);
|
|
|
|
if (ngx_read_dir(&dir) == NGX_ERROR) {
|
|
|
|
err = ngx_errno;
|
|
|
|
|
|
|
|
if (err != NGX_ENOMOREFILES) {
|
|
|
|
ngx_log_error(NGX_LOG_CRIT, ctx->log, err,
|
|
|
|
ngx_read_dir_n " \"%s\" failed", dname->data);
|
|
|
|
rc = NGX_ERROR;
|
2003-11-14 13:52:04 -03:00
|
|
|
|
2003-11-16 18:49:42 -03:00
|
|
|
} else {
|
|
|
|
rc = NGX_OK;
|
2003-11-14 13:52:04 -03:00
|
|
|
}
|
2003-11-16 18:49:42 -03:00
|
|
|
|
2003-11-14 13:52:04 -03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2003-11-16 18:49:42 -03:00
|
|
|
len = ngx_de_namelen(&dir);
|
2003-11-14 13:52:04 -03:00
|
|
|
|
2003-11-16 18:49:42 -03:00
|
|
|
ngx_log_debug(ctx->log, "name '%s':%d" _ ngx_de_name(&dir) _ len);
|
2003-11-14 13:52:04 -03:00
|
|
|
|
2003-11-16 18:49:42 -03:00
|
|
|
if (len == 1 && ngx_de_name(&dir)[0] == '.') {
|
2003-11-14 13:52:04 -03:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2003-11-16 18:49:42 -03:00
|
|
|
if (len == 2
|
|
|
|
&& ngx_de_name(&dir)[0] == '.'
|
|
|
|
&& ngx_de_name(&dir)[1] == '.')
|
|
|
|
{
|
2003-11-14 13:52:04 -03:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2003-11-16 18:49:42 -03:00
|
|
|
fname.len = dname->len + 1+ len;
|
|
|
|
|
|
|
|
if (fname.len + NGX_DIR_MASK_LEN > buf.len) {
|
|
|
|
|
|
|
|
if (buf.len) {
|
|
|
|
ngx_free(buf.data);
|
2003-11-14 13:52:04 -03:00
|
|
|
}
|
|
|
|
|
2003-11-16 18:49:42 -03:00
|
|
|
buf.len = dname->len + 1 + len + NGX_DIR_MASK_LEN;
|
2003-11-14 13:52:04 -03:00
|
|
|
|
2003-11-16 18:49:42 -03:00
|
|
|
if (!(buf.data = ngx_alloc(buf.len + 1, ctx->log))) {
|
2003-11-14 13:52:04 -03:00
|
|
|
return NGX_ABORT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-11-16 18:49:42 -03:00
|
|
|
last = ngx_cpymem(buf.data, dname->data, dname->len);
|
2003-11-14 13:52:04 -03:00
|
|
|
*last++ = '/';
|
2003-11-16 18:49:42 -03:00
|
|
|
ngx_memcpy(last, ngx_de_name(&dir), len + 1);
|
|
|
|
fname.data = buf.data;
|
2003-11-14 13:52:04 -03:00
|
|
|
|
2003-11-16 18:49:42 -03:00
|
|
|
ngx_log_debug(ctx->log, "path %s" _ fname.data);
|
2003-11-14 13:52:04 -03:00
|
|
|
|
2003-11-16 18:49:42 -03:00
|
|
|
if (!dir.info_valid) {
|
|
|
|
if (ngx_de_info(fname.data, &dir) == NGX_FILE_ERROR) {
|
|
|
|
ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno,
|
|
|
|
ngx_de_info_n " \"%s\" failed", fname.data);
|
|
|
|
continue;
|
|
|
|
}
|
2003-11-14 13:52:04 -03:00
|
|
|
}
|
|
|
|
|
2003-11-16 18:49:42 -03:00
|
|
|
if (ngx_de_is_dir(&dir)) {
|
2003-11-14 13:52:04 -03:00
|
|
|
|
|
|
|
ngx_log_debug(ctx->log, "enter %s" _ fname.data);
|
|
|
|
|
|
|
|
if (level == -1
|
|
|
|
/* there can not be directory on the last level */
|
|
|
|
|| level == NGX_MAX_PATH_LEVEL
|
|
|
|
/* an directory from the old path hierarchy */
|
2003-11-16 18:49:42 -03:00
|
|
|
|| len != ctx->path->level[level])
|
2003-11-14 13:52:04 -03:00
|
|
|
{
|
|
|
|
if (ngx_collect_garbage(ctx, &fname, -1) == NGX_ABORT) {
|
|
|
|
return NGX_ABORT;
|
|
|
|
}
|
|
|
|
|
2003-11-16 18:49:42 -03:00
|
|
|
fname.data[fname.len] = '\0';
|
|
|
|
|
2003-11-14 13:52:04 -03:00
|
|
|
ngx_log_error(NGX_LOG_NOTICE, ctx->log, 0,
|
|
|
|
"delete old hierachy directory \"%s\"",
|
|
|
|
fname.data);
|
|
|
|
|
|
|
|
if (ngx_delete_dir(fname.data) == NGX_FILE_ERROR) {
|
|
|
|
ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno,
|
|
|
|
ngx_delete_dir_n " \"%s\" failed",
|
|
|
|
fname.data);
|
|
|
|
} else {
|
|
|
|
ctx->deleted++;
|
2003-11-16 18:49:42 -03:00
|
|
|
ctx->freed += ngx_de_size(&dir);
|
2003-11-14 13:52:04 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ngx_collect_garbage(ctx, &fname, level + 1) == NGX_ABORT) {
|
|
|
|
return NGX_ABORT;
|
|
|
|
}
|
|
|
|
|
2003-11-16 18:49:42 -03:00
|
|
|
} else if (ngx_de_is_file(&dir)) {
|
|
|
|
|
|
|
|
ngx_log_debug(ctx->log, "file %s" _ fname.data);
|
2003-11-14 13:52:04 -03:00
|
|
|
|
|
|
|
if (level == -1
|
|
|
|
|| (level < NGX_MAX_PATH_LEVEL && ctx->path->level[level] != 0))
|
|
|
|
{
|
|
|
|
if (ngx_delete_file(fname.data) == NGX_FILE_ERROR) {
|
|
|
|
ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno,
|
|
|
|
ngx_delete_file_n " \"%s\" failed",
|
|
|
|
fname.data);
|
|
|
|
} else {
|
|
|
|
ctx->deleted++;
|
2003-11-16 18:49:42 -03:00
|
|
|
ctx->freed += ngx_de_size(&dir);
|
2003-11-14 13:52:04 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2003-11-16 18:49:42 -03:00
|
|
|
if (ctx->handler(ctx, &fname, &dir) == NGX_ABORT) {
|
2003-11-14 13:52:04 -03:00
|
|
|
return NGX_ABORT;
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno,
|
|
|
|
"\"%s\" has unknown file type, deleting", fname.data);
|
|
|
|
|
|
|
|
if (ngx_delete_file(fname.data) == NGX_FILE_ERROR) {
|
|
|
|
ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno,
|
|
|
|
ngx_delete_file_n " \"%s\" failed", fname.data);
|
|
|
|
} else {
|
|
|
|
ctx->deleted++;
|
2003-11-16 18:49:42 -03:00
|
|
|
ctx->freed += ngx_de_size(&dir);
|
2003-11-14 13:52:04 -03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-11-16 18:49:42 -03:00
|
|
|
if (buf.len) {
|
|
|
|
ngx_free(buf.data);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ngx_close_dir(&dir) == NGX_ERROR) {
|
|
|
|
ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno,
|
|
|
|
ngx_close_dir_n " \"%s\" failed", fname.data);
|
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
2003-11-14 13:52:04 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-11-18 18:34:08 -03:00
|
|
|
int ngx_garbage_collector_temp_handler(ngx_gc_t *ctx, ngx_str_t *name,
|
|
|
|
ngx_dir_t *dir)
|
2003-11-14 13:52:04 -03:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* we use mtime only and do not use atime because:
|
|
|
|
* on NTFS access time has a resolution of 1 hour,
|
|
|
|
* on NT FAT access time has a resolution of 1 day,
|
|
|
|
* Unices have mount option "noatime"
|
|
|
|
*/
|
|
|
|
|
2003-11-16 18:49:42 -03:00
|
|
|
if (ngx_cached_time - ngx_de_mtime(dir) < 3600) {
|
2003-11-14 13:52:04 -03:00
|
|
|
return NGX_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
ngx_log_error(NGX_LOG_NOTICE, ctx->log, 0,
|
|
|
|
"delete stale temporary \"%s\"", name->data);
|
|
|
|
|
|
|
|
if (ngx_delete_file(name->data) == NGX_FILE_ERROR) {
|
|
|
|
ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno,
|
|
|
|
ngx_delete_file_n " \"%s\" failed", name->data);
|
|
|
|
return NGX_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx->deleted++;
|
2003-11-16 18:49:42 -03:00
|
|
|
ctx->freed += ngx_de_size(dir);
|
2003-11-18 18:34:08 -03:00
|
|
|
|
2003-11-14 13:52:04 -03:00
|
|
|
return NGX_OK;
|
|
|
|
}
|