Mercurial > hg > nginx-vendor-1-0
diff src/core/ngx_garbage_collector.c @ 0:f0b350454894 NGINX_0_1_0
nginx 0.1.0
*) The first public version.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Mon, 04 Oct 2004 00:00:00 +0400 |
parents | |
children | 80ba094c6b3e |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/src/core/ngx_garbage_collector.c @@ -0,0 +1,279 @@ + +/* + * Copyright (C) Igor Sysoev + */ + + +#include <ngx_config.h> +#include <ngx_core.h> +#include <ngx_garbage_collector.h> + + +int ngx_garbage_collector_temp_handler(ngx_gc_t *ctx, ngx_str_t *name, + ngx_dir_t *dir); + + +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 + + +void stub_init(ngx_cycle_t *cycle) +{ + ngx_uint_t i; + ngx_gc_t ctx; + ngx_path_t **path; + + 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; + + ngx_collect_garbage(&ctx, &path[i]->name, 0); + } +} + + +static int ngx_collect_garbage(ngx_gc_t *ctx, ngx_str_t *dname, int level) +{ + int rc; + u_char *last; + size_t len; + ngx_err_t err; + ngx_str_t fname, buf; + ngx_dir_t dir; + + buf.len = 0; +#if (NGX_SUPPRESS_WARN) + buf.data = NULL; + fname.data = NULL; +#endif + + ngx_log_debug2(NGX_LOG_DEBUG_CORE, ctx->log, 0, + "gc dir \"%s\":%d", dname->data, dname->len); + + 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); + return NGX_ERROR; + } + + for ( ;; ) { + 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; + + } else { + rc = NGX_OK; + } + + break; + } + + len = ngx_de_namelen(&dir); + + ngx_log_debug2(NGX_LOG_DEBUG_CORE, ctx->log, 0, + "gc name \"%s\":%d", ngx_de_name(&dir), len); + + if (len == 1 && ngx_de_name(&dir)[0] == '.') { + continue; + } + + if (len == 2 + && ngx_de_name(&dir)[0] == '.' + && ngx_de_name(&dir)[1] == '.') + { + continue; + } + + fname.len = dname->len + 1+ len; + + if (fname.len + NGX_DIR_MASK_LEN > buf.len) { + + if (buf.len) { + ngx_free(buf.data); + } + + buf.len = dname->len + 1 + len + NGX_DIR_MASK_LEN; + + if (!(buf.data = ngx_alloc(buf.len + 1, ctx->log))) { + return NGX_ABORT; + } + } + + last = ngx_cpymem(buf.data, dname->data, dname->len); + *last++ = '/'; + ngx_memcpy(last, ngx_de_name(&dir), len + 1); + fname.data = buf.data; + + ngx_log_debug1(NGX_LOG_DEBUG_CORE, ctx->log, 0, + "gc path: \"%s\"", fname.data); + + 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; + } + } + + if (ngx_de_is_dir(&dir)) { + + ngx_log_debug1(NGX_LOG_DEBUG_CORE, ctx->log, 0, + "gc enter dir \"%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 */ + || len != ctx->path->level[level]) + { + if (ngx_collect_garbage(ctx, &fname, -1) == NGX_ABORT) { + return NGX_ABORT; + } + + fname.data[fname.len] = '\0'; + + 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++; + ctx->freed += ngx_de_size(&dir); + } + + continue; + } + + if (ngx_collect_garbage(ctx, &fname, level + 1) == NGX_ABORT) { + return NGX_ABORT; + } + + } else if (ngx_de_is_file(&dir)) { + + ngx_log_debug1(NGX_LOG_DEBUG_CORE, ctx->log, 0, + "gc file \"%s\"", fname.data); + + 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++; + ctx->freed += ngx_de_size(&dir); + } + + continue; + } + + if (ctx->handler(ctx, &fname, &dir) == NGX_ABORT) { + 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++; + ctx->freed += ngx_de_size(&dir); + } + } + } + + 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; +} + + +int ngx_garbage_collector_temp_handler(ngx_gc_t *ctx, ngx_str_t *name, + ngx_dir_t *dir) +{ + /* + * 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 the mount option "noatime". + */ + + if (ngx_time() - ngx_de_mtime(dir) < 3600) { + 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++; + ctx->freed += ngx_de_size(dir); + + return NGX_OK; +}