Mercurial > hg > nginx
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/ngx_garbage_collector.c Fri Nov 14 16:52:04 2003 +0000 @@ -0,0 +1,256 @@ + +#include <ngx_config.h> +#include <ngx_core.h> + + +typedef struct ngx_gc_s ngx_gc_t; + +typedef int (*ngx_gc_handler_pt) (ngx_gc_t *ctx, ngx_str_t *name, + ngx_file_info_t *fi); + +struct ngx_gc_s { + ngx_path_t *path; + u_int deleted; + off_t freed; + ngx_gc_handler_pt handler; + ngx_log_t *log; +}; + + +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_log_t *log) +{ + ngx_gc_t *ctx; + ngx_path_t path; + + if (!(ctx = ngx_alloc(sizeof(ngx_gc_t), log))) { + return; + } + + path.name.len = 4; + path.name.data = "temp"; + path.len = 5; + path.level[0] = 1; + path.level[1] = 2; + path.level[2] = 0; + + ctx->path = &path; + ctx->log = log; + + ngx_collect_garbage(ctx, &path.name, 0); +} + + +static int ngx_collect_garbage(ngx_gc_t *ctx, ngx_str_t *dname, int level) +{ + int nlen; + char *last; + ngx_str_t fname; + ngx_dir_t *dir; + ngx_dirent_t *de; + ngx_file_info_t fi; + + fname.len = 0; + +ngx_log_debug(ctx->log, "dir %s" _ dname->data); + + dir = ngx_open_dir(dname->data); + + if (dir == NULL) { + ngx_log_error(NGX_LOG_ERR, ctx->log, ngx_errno, + ngx_open_dir_n " \"%s\" failed", dname->data); + return NGX_ERROR; + } + + for ( ;; ) { + de = ngx_read_dir(dir); + + if (de == NULL) { + if (fname.len) { + ngx_free(fname.data); + } + break; + } + +ngx_log_debug(ctx->log, "file %s" _ de->d_name); + +#ifdef __FreeBSD__ + nlen = de->d_namlen; +#else + nlen = ngx_strlen(de->d_name); +#endif + + if (nlen == 1 && de->d_name[0] == '.') { + continue; + } + + if (nlen == 2 && de->d_name[0] == '.' && de->d_name[1] == '.') { + continue; + } + + if (dname->len + 1 + nlen > fname.len) { + if (fname.len) { + ngx_free(fname.data); + } + + fname.len = dname->len + 1 + nlen; + + if (!(fname.data = ngx_alloc(fname.len + 1, ctx->log))) { + return NGX_ABORT; + } + } + + last = ngx_cpymem(fname.data, dname->data, dname->len); + *last++ = '/'; + ngx_memcpy(last, de->d_name, nlen + 1); + +ngx_log_debug(ctx->log, "de %s" _ fname.data); + + if (ngx_file_type(fname.data, &fi) == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno, + ngx_file_type_n " \"%s\" failed", fname.data); + continue; + } + + if (ngx_is_dir((&fi))) { + +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 */ + || nlen != ctx->path->level[level]) + { + if (ngx_collect_garbage(ctx, &fname, -1) == NGX_ABORT) { + return NGX_ABORT; + } + + 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_file_size((&fi)); + } + + continue; + } + + if (ngx_collect_garbage(ctx, &fname, level + 1) == NGX_ABORT) { + return NGX_ABORT; + } + + } else if (ngx_is_file((&fi))) { + + 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_file_size((&fi)); + } + + continue; + } + + if (ctx->handler(ctx, &fname, &fi) == 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_file_size((&fi)); + } + } + } + + return NGX_OK; +} + + +int ngx_garbage_collector_temp_handler(ngx_gc_t *ctx, ngx_str_t *name, + ngx_file_info_t *fi) +{ + /* + * 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" + */ + + if (ngx_cached_time - ngx_file_mtime(fi) < 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_file_size(fi); + return NGX_OK; +}