aboutsummaryrefslogtreecommitdiff
path: root/src/core/ngx_garbage_collector.c
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2003-11-14 16:52:04 +0000
committerIgor Sysoev <igor@sysoev.ru>2003-11-14 16:52:04 +0000
commit297c0487518d4b974a548dfd3d5d2f10c250177c (patch)
tree16667b611d5e4f4e88abd7d920fe20e0a7066b65 /src/core/ngx_garbage_collector.c
parent7f9d894e1069306f7361201a77efbe7b866024ff (diff)
downloadnginx-297c0487518d4b974a548dfd3d5d2f10c250177c.tar.gz
nginx-297c0487518d4b974a548dfd3d5d2f10c250177c.zip
nginx-0.0.1-2003-11-14-19:52:04 import
Diffstat (limited to 'src/core/ngx_garbage_collector.c')
-rw-r--r--src/core/ngx_garbage_collector.c256
1 files changed, 256 insertions, 0 deletions
diff --git a/src/core/ngx_garbage_collector.c b/src/core/ngx_garbage_collector.c
new file mode 100644
index 000000000..ae6fab420
--- /dev/null
+++ b/src/core/ngx_garbage_collector.c
@@ -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;
+}