a prelimiary proxy cache support
diff --git a/src/core/ngx_file.c b/src/core/ngx_file.c
index 1bb4182..fed19e6 100644
--- a/src/core/ngx_file.c
+++ b/src/core/ngx_file.c
@@ -264,7 +264,7 @@
     }
 
     path->len = 0;
-    path->cleaner = (ngx_gc_handler_pt) cmd->post;
+    path->cleaner = (ngx_path_cleaner_pt) cmd->post;
     path->conf_file = cf->conf_file->file.name.data;
     path->line = cf->conf_file->line;
 
@@ -293,6 +293,49 @@
 
 
 char *
+ngx_conf_merge_path_value(ngx_conf_t *cf, ngx_path_t **path, ngx_path_t *prev,
+    ngx_path_init_t *init)
+{
+    if (*path) {
+        return NGX_CONF_OK;
+    }
+
+    if (prev) {
+        *path = prev;
+        return NGX_CONF_OK;
+    }
+
+    *path = ngx_palloc(cf->pool, sizeof(ngx_path_t));
+    if (*path == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    (*path)->name = init->name;
+
+    if (ngx_conf_full_name(cf->cycle, &(*path)->name, 0) != NGX_OK) {
+        return NGX_CONF_ERROR;
+    }
+
+    (*path)->level[0] = init->level[0];
+    (*path)->level[1] = init->level[1];
+    (*path)->level[2] = init->level[2];
+
+    (*path)->len = init->level[0] + (init->level[0] ? 1 : 0)
+                   + init->level[1] + (init->level[1] ? 1 : 0)
+                   + init->level[2] + (init->level[2] ? 1 : 0);
+
+    (*path)->cleaner = NULL;
+    (*path)->conf_file = NULL;
+
+    if (ngx_add_path(cf, path) != NGX_OK) {
+        return NGX_CONF_ERROR;
+    }
+
+    return NGX_CONF_OK;
+}
+
+
+char *
 ngx_conf_set_access_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
     char  *confp = conf;
diff --git a/src/core/ngx_file.h b/src/core/ngx_file.h
index 344da09..7890c48 100644
--- a/src/core/ngx_file.h
+++ b/src/core/ngx_file.h
@@ -11,65 +11,73 @@
 #include <ngx_config.h>
 #include <ngx_core.h>
 
-typedef struct ngx_path_s  ngx_path_t;
-
-#include <ngx_garbage_collector.h>
-
 
 struct ngx_file_s {
-    ngx_fd_t            fd;
-    ngx_str_t           name;
-    ngx_file_info_t     info;
+    ngx_fd_t                   fd;
+    ngx_str_t                  name;
+    ngx_file_info_t            info;
 
-    off_t               offset;
-    off_t               sys_offset;
+    off_t                      offset;
+    off_t                      sys_offset;
 
-    ngx_log_t          *log;
+    ngx_log_t                 *log;
 
-    unsigned            valid_info:1;
-    unsigned            directio:1;
+    unsigned                   valid_info:1;
+    unsigned                   directio:1;
 };
 
 #define NGX_MAX_PATH_LEVEL  3
 
-struct ngx_path_s {
-    ngx_str_t           name;
-    size_t              len;
-    size_t              level[3];
-    ngx_gc_handler_pt   cleaner;
 
-    u_char             *conf_file;
-    ngx_uint_t          line;
-};
+typedef time_t (*ngx_path_cleaner_pt) (void *data);
 
 
 typedef struct {
-    ngx_file_t          file;
-    off_t               offset;
-    ngx_path_t         *path;
-    ngx_pool_t         *pool;
-    char               *warn;
+    ngx_str_t                  name;
+    size_t                     len;
+    size_t                     level[3];
 
-    ngx_uint_t          access;
+    ngx_path_cleaner_pt        cleaner;
+    void                      *data;
 
-    unsigned            log_level:8;
-    unsigned            persistent:1;
-    unsigned            clean:1;
+    u_char                    *conf_file;
+    ngx_uint_t                 line;
+} ngx_path_t;
+
+
+typedef struct {
+    ngx_str_t                  name;
+    size_t                     level[3];
+} ngx_path_init_t;
+
+
+typedef struct {
+    ngx_file_t                 file;
+    off_t                      offset;
+    ngx_path_t                *path;
+    ngx_pool_t                *pool;
+    char                      *warn;
+
+    ngx_uint_t                 access;
+
+    unsigned                   log_level:8;
+    unsigned                   persistent:1;
+    unsigned                   clean:1;
 } ngx_temp_file_t;
 
 
 typedef struct {
-    ngx_uint_t          access;
-    ngx_uint_t          path_access;
-    time_t              time;
-    ngx_fd_t            fd;
-    ngx_err_t           rename_error;
+    ngx_uint_t                 access;
+    ngx_uint_t                 path_access;
+    time_t                     time;
+    ngx_fd_t                   fd;
+    ngx_err_t                  rename_error;
 
-    unsigned            create_path:1;
-    unsigned            delete_file:1;
-    unsigned            log_rename_error:1;
+    unsigned                   create_path:1;
+    unsigned                   delete_file:1;
+    unsigned                   log_rename_error:1;
 
-    ngx_log_t          *log;
+    ngx_log_t                 *log;
 } ngx_ext_rename_file_t;
 
 
@@ -113,40 +121,9 @@
 ngx_atomic_uint_t ngx_next_temp_number(ngx_uint_t collision);
 
 char *ngx_conf_set_path_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
+char *ngx_conf_merge_path_value(ngx_conf_t *cf, ngx_path_t **path,
+    ngx_path_t *prev, ngx_path_init_t *init);
 char *ngx_conf_set_access_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
 
 
-#define ngx_conf_merge_path_value(curr, prev, path, l1, l2, l3, clean, cf)    \
-    if (curr == NULL) {                                                       \
-        if (prev == NULL) {                                                   \
-            curr = ngx_palloc(cf->pool, sizeof(ngx_path_t));                  \
-            if (curr == NULL) {                                               \
-                return NGX_CONF_ERROR;                                        \
-            }                                                                 \
-                                                                              \
-            curr->name.len = sizeof(path) - 1;                                \
-            curr->name.data = (u_char *) path;                                \
-                                                                              \
-            if (ngx_conf_full_name(cf->cycle, &curr->name, 0) == NGX_ERROR) { \
-                return NGX_CONF_ERROR;                                        \
-            }                                                                 \
-                                                                              \
-            curr->level[0] = l1;                                              \
-            curr->level[1] = l2;                                              \
-            curr->level[2] = l3;                                              \
-            curr->len = l1 + l2 + l3 + (l1 ? 1:0) + (l2 ? 1:0) + (l3 ? 1:0);  \
-            curr->cleaner = clean;                                            \
-            curr->conf_file = NULL;                                           \
-                                                                              \
-            if (ngx_add_path(cf, &curr) == NGX_ERROR) {                       \
-                return NGX_CONF_ERROR;                                        \
-            }                                                                 \
-                                                                              \
-        } else {                                                              \
-            curr = prev;                                                      \
-        }                                                                     \
-    }
-
-
-
 #endif /* _NGX_FILE_H_INCLUDED_ */
diff --git a/src/core/ngx_garbage_collector.c b/src/core/ngx_garbage_collector.c
deleted file mode 100644
index 4eeaeb9..0000000
--- a/src/core/ngx_garbage_collector.c
+++ /dev/null
@@ -1,217 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-
-
-
-ngx_int_t ngx_collect_garbage(ngx_gc_t *ctx, ngx_str_t *dname, ngx_int_t 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;
-
-            buf.data = ngx_alloc(buf.len + 1, ctx->log);
-            if (buf.data == NULL) {
-                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.valid_info) {
-            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,
-                          "the file \"%s\" has unknown 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;
-}
-
-
-ngx_int_t 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 the stale temporary file \"%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;
-}
diff --git a/src/core/ngx_garbage_collector.h b/src/core/ngx_garbage_collector.h
deleted file mode 100644
index 4b0a734..0000000
--- a/src/core/ngx_garbage_collector.h
+++ /dev/null
@@ -1,31 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- */
-
-
-#ifndef _NGX_GARBAGE_COLLECTOR_H_INCLUDED_
-#define _NGX_GARBAGE_COLLECTOR_H_INCLUDED_
-
-
-typedef struct ngx_gc_s  ngx_gc_t;
-
-typedef ngx_int_t (*ngx_gc_handler_pt) (ngx_gc_t *ctx, ngx_str_t *name,
-    ngx_dir_t *dir);
-
-
-struct ngx_gc_s {
-    ngx_path_t         *path;
-    u_int               deleted;
-    off_t               freed;
-    ngx_gc_handler_pt   handler;
-    ngx_log_t          *log;
-};
-
-
-ngx_int_t ngx_collect_garbage(ngx_gc_t *ctx, ngx_str_t *dname, ngx_int_t level);
-ngx_int_t ngx_garbage_collector_temp_handler(ngx_gc_t *ctx, ngx_str_t *name,
-    ngx_dir_t *dir);
-
-
-#endif /* _NGX_GARBAGE_COLLECTOR_H_INCLUDED_ */
diff --git a/src/core/ngx_palloc.c b/src/core/ngx_palloc.c
index 7c89fda..3e1c9f2 100644
--- a/src/core/ngx_palloc.c
+++ b/src/core/ngx_palloc.c
@@ -326,6 +326,27 @@
 
 
 void
+ngx_pool_run_cleanup_file(ngx_pool_t *p, ngx_fd_t fd)
+{
+    ngx_pool_cleanup_t       *c;
+    ngx_pool_cleanup_file_t  *cf;
+
+    for (c = p->cleanup; c; c = c->next) {
+        if (c->handler == ngx_pool_cleanup_file) {
+
+            cf = c->data;
+
+            if (cf->fd == fd) {
+                c->handler(cf);
+                c->handler = NULL;
+                return;
+            }
+        }
+    }
+}
+
+
+void
 ngx_pool_cleanup_file(void *data)
 {
     ngx_pool_cleanup_file_t  *c = data;
diff --git a/src/core/ngx_palloc.h b/src/core/ngx_palloc.h
index c31db93..f9d5216 100644
--- a/src/core/ngx_palloc.h
+++ b/src/core/ngx_palloc.h
@@ -82,6 +82,7 @@
 
 
 ngx_pool_cleanup_t *ngx_pool_cleanup_add(ngx_pool_t *p, size_t size);
+void ngx_pool_run_cleanup_file(ngx_pool_t *p, ngx_fd_t fd);
 void ngx_pool_cleanup_file(void *data);
 void ngx_pool_delete_file(void *data);