diff --git a/src/core/ngx_open_file_cache.c b/src/core/ngx_open_file_cache.c index a05bbcf27..5748f9e68 100644 --- a/src/core/ngx_open_file_cache.c +++ b/src/core/ngx_open_file_cache.c @@ -20,7 +20,7 @@ static void ngx_open_file_cache_cleanup(void *data); static void ngx_open_file_cleanup(void *data); static void ngx_close_cached_file(ngx_open_file_cache_t *cache, - ngx_cached_open_file_t *file, ngx_log_t *log); + ngx_cached_open_file_t *file, ngx_uint_t min_uses, ngx_log_t *log); static ngx_int_t ngx_open_and_stat_file(u_char *name, ngx_open_file_info_t *of, ngx_log_t *log); static void ngx_expire_old_cached_files(ngx_open_file_cache_t *cache, @@ -95,7 +95,7 @@ ngx_open_file_cache_cleanup(void *data) if (!file->err && !file->is_dir) { file->close = 1; file->count = 0; - ngx_close_cached_file(cache, file, ngx_cycle->log); + ngx_close_cached_file(cache, file, 0, ngx_cycle->log); } else { ngx_free(file->name); @@ -187,10 +187,29 @@ ngx_open_cached_file(ngx_open_file_cache_t *cache, ngx_str_t *name, if (rc == 0) { + file->uses++; + ngx_queue_remove(&file->queue); + if (file->fd == NGX_INVALID_FILE + && file->err == 0 + && !file->is_dir) + { + /* file was not used often enough to be open */ + + rc = ngx_open_and_stat_file(name->data, of, pool->log); + + if (rc != NGX_OK && (of->err == 0 || !of->errors)) { + goto failed; + } + + goto update; + } + if (file->event || now - file->created < of->valid) { + if (file->err == 0) { + of->fd = file->fd; of->uniq = file->uniq; of->mtime = file->mtime; @@ -338,6 +357,7 @@ create: cache->current++; file->count = 0; + file->uses = 1; update: @@ -412,9 +432,9 @@ found: ngx_queue_insert_head(&cache->expire_queue, &file->queue); - ngx_log_debug4(NGX_LOG_DEBUG_CORE, pool->log, 0, - "cached open file: %s, fd:%d, c:%d, e:%d", - file->name, file->fd, file->count, file->err); + ngx_log_debug5(NGX_LOG_DEBUG_CORE, pool->log, 0, + "cached open file: %s, fd:%d, c:%d, e:%d, u:%d", + file->name, file->fd, file->count, file->err, file->uses); if (of->err == 0) { @@ -424,6 +444,7 @@ found: ofcln->cache = cache; ofcln->file = file; + ofcln->min_uses = of->min_uses; ofcln->log = pool->log; } @@ -536,7 +557,7 @@ ngx_open_file_cleanup(void *data) c->file->count--; - ngx_close_cached_file(c->cache, c->file, c->log); + ngx_close_cached_file(c->cache, c->file, c->min_uses, c->log); /* drop one or two expired open files */ ngx_expire_old_cached_files(c->cache, 1, c->log); @@ -545,11 +566,11 @@ ngx_open_file_cleanup(void *data) static void ngx_close_cached_file(ngx_open_file_cache_t *cache, - ngx_cached_open_file_t *file, ngx_log_t *log) + ngx_cached_open_file_t *file, ngx_uint_t min_uses, ngx_log_t *log) { - ngx_log_debug4(NGX_LOG_DEBUG_CORE, log, 0, - "close cached open file: %s, fd:%d, c:%d, %d", - file->name, file->fd, file->count, file->close); + ngx_log_debug5(NGX_LOG_DEBUG_CORE, log, 0, + "close cached open file: %s, fd:%d, c:%d, u:%d, %d", + file->name, file->fd, file->count, file->uses, file->close); if (!file->close) { @@ -559,7 +580,9 @@ ngx_close_cached_file(ngx_open_file_cache_t *cache, ngx_queue_insert_head(&cache->expire_queue, &file->queue); - return; + if (file->uses >= min_uses || file->count) { + return; + } } if (file->event) { @@ -575,9 +598,18 @@ ngx_close_cached_file(ngx_open_file_cache_t *cache, return; } - if (ngx_close_file(file->fd) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, - ngx_close_file_n " \"%s\" failed", file->name); + if (file->fd != NGX_INVALID_FILE) { + + if (ngx_close_file(file->fd) == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, + ngx_close_file_n " \"%s\" failed", file->name); + } + + file->fd = NGX_INVALID_FILE; + } + + if (!file->close) { + return; } ngx_free(file->name); @@ -626,7 +658,7 @@ ngx_expire_old_cached_files(ngx_open_file_cache_t *cache, ngx_uint_t n, if (!file->err && !file->is_dir) { file->close = 1; - ngx_close_cached_file(cache, file, log); + ngx_close_cached_file(cache, file, 0, log); } else { ngx_free(file->name); @@ -697,7 +729,7 @@ ngx_open_file_cache_remove(ngx_event_t *ev) file->close = 1; - ngx_close_cached_file(fev->cache, file, ev->log); + ngx_close_cached_file(fev->cache, file, 0, ev->log); /* free memory only when fev->cache and fev->file are already not needed */ diff --git a/src/core/ngx_open_file_cache.h b/src/core/ngx_open_file_cache.h index 6865f684b..8ef4aeac8 100644 --- a/src/core/ngx_open_file_cache.h +++ b/src/core/ngx_open_file_cache.h @@ -21,6 +21,8 @@ typedef struct { time_t valid; + ngx_uint_t min_uses; + unsigned test_dir:1; unsigned errors:1; unsigned events:1; @@ -48,6 +50,8 @@ struct ngx_cached_open_file_s { off_t size; ngx_err_t err; + uint32_t uses; + unsigned count:24; unsigned close:1; @@ -74,6 +78,7 @@ typedef struct { typedef struct { ngx_open_file_cache_t *cache; ngx_cached_open_file_t *file; + ngx_uint_t min_uses; ngx_log_t *log; } ngx_open_file_cache_cleanup_t; diff --git a/src/http/modules/ngx_http_flv_module.c b/src/http/modules/ngx_http_flv_module.c index 2c14d29be..1e8f96faf 100644 --- a/src/http/modules/ngx_http_flv_module.c +++ b/src/http/modules/ngx_http_flv_module.c @@ -107,6 +107,7 @@ ngx_http_flv_handler(ngx_http_request_t *r) of.test_dir = 0; of.valid = clcf->open_file_cache_valid; + of.min_uses = clcf->open_file_cache_min_uses; of.errors = clcf->open_file_cache_errors; of.events = clcf->open_file_cache_events; diff --git a/src/http/modules/ngx_http_index_module.c b/src/http/modules/ngx_http_index_module.c index a82b31850..c9622835d 100644 --- a/src/http/modules/ngx_http_index_module.c +++ b/src/http/modules/ngx_http_index_module.c @@ -210,6 +210,7 @@ ngx_http_index_handler(ngx_http_request_t *r) of.test_dir = 0; of.valid = clcf->open_file_cache_valid; + of.min_uses = clcf->open_file_cache_min_uses; of.errors = clcf->open_file_cache_errors; of.events = clcf->open_file_cache_events; @@ -293,6 +294,7 @@ ngx_http_index_test_dir(ngx_http_request_t *r, ngx_http_core_loc_conf_t *clcf, of.test_dir = 1; of.valid = clcf->open_file_cache_valid; + of.min_uses = 0; of.errors = clcf->open_file_cache_errors; if (ngx_open_cached_file(clcf->open_file_cache, &dir, &of, r->pool) diff --git a/src/http/modules/ngx_http_static_module.c b/src/http/modules/ngx_http_static_module.c index e89b1cd81..cfc708916 100644 --- a/src/http/modules/ngx_http_static_module.c +++ b/src/http/modules/ngx_http_static_module.c @@ -98,6 +98,7 @@ ngx_http_static_handler(ngx_http_request_t *r) of.test_dir = 0; of.valid = clcf->open_file_cache_valid; + of.min_uses = clcf->open_file_cache_min_uses; of.errors = clcf->open_file_cache_errors; of.events = clcf->open_file_cache_events; diff --git a/src/http/modules/perl/nginx.xs b/src/http/modules/perl/nginx.xs index 771fd81c7..78455b951 100644 --- a/src/http/modules/perl/nginx.xs +++ b/src/http/modules/perl/nginx.xs @@ -644,6 +644,7 @@ sendfile(r, filename, offset = -1, bytes = 0) of.test_dir = 0; of.valid = clcf->open_file_cache_valid; + of.min_uses = clcf->open_file_cache_min_uses; of.errors = clcf->open_file_cache_errors; of.events = clcf->open_file_cache_events; diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index 066e1298b..a7da92a74 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -491,6 +491,13 @@ static ngx_command_t ngx_http_core_commands[] = { offsetof(ngx_http_core_loc_conf_t, open_file_cache_valid), &ngx_conf_deprecated_open_file_cache_retest }, + { ngx_string("open_file_cache_min_uses"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_core_loc_conf_t, open_file_cache_min_uses), + NULL }, + { ngx_string("open_file_cache_errors"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, ngx_conf_set_flag_slot, @@ -2429,6 +2436,7 @@ ngx_http_core_create_loc_conf(ngx_conf_t *cf) lcf->types_hash_bucket_size = NGX_CONF_UNSET_UINT; lcf->open_file_cache = NGX_CONF_UNSET_PTR; lcf->open_file_cache_valid = NGX_CONF_UNSET; + lcf->open_file_cache_min_uses = NGX_CONF_UNSET_UINT; lcf->open_file_cache_errors = NGX_CONF_UNSET; lcf->open_file_cache_events = NGX_CONF_UNSET; @@ -2634,6 +2642,9 @@ ngx_http_core_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_sec_value(conf->open_file_cache_valid, prev->open_file_cache_valid, 60); + ngx_conf_merge_uint_value(conf->open_file_cache_min_uses, + prev->open_file_cache_min_uses, 1); + ngx_conf_merge_sec_value(conf->open_file_cache_errors, prev->open_file_cache_errors, 0); diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h index d08e9b113..52eb94779 100644 --- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -296,6 +296,7 @@ struct ngx_http_core_loc_conf_s { ngx_open_file_cache_t *open_file_cache; time_t open_file_cache_valid; + ngx_uint_t open_file_cache_min_uses; ngx_flag_t open_file_cache_errors; ngx_flag_t open_file_cache_events; diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c index 0ae27aafe..e30fda254 100644 --- a/src/http/ngx_http_script.c +++ b/src/http/ngx_http_script.c @@ -977,6 +977,7 @@ ngx_http_script_file_code(ngx_http_script_engine_t *e) of.test_dir = 0; of.valid = clcf->open_file_cache_valid; + of.min_uses = clcf->open_file_cache_min_uses; of.errors = clcf->open_file_cache_errors; of.events = clcf->open_file_cache_events;