view 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 source


#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;
}