# HG changeset patch # User Dmitry Volyntsev # Date 1475666550 -10800 # Node ID ca709bca4b77fb4a5b3986e02f472b17e9fa9c6f # Parent 631753428ecb96b0afb1b2b25424f801ee921bc6 Cache: cache manager limits. The new parameters "manager_files", "manager_sleep" and "manager_threshold" were added to proxy_cache_path and friends. Note that ngx_path_manager_pt was changed to return ngx_msec_t instead of time_t (API change). diff --git a/src/core/ngx_file.h b/src/core/ngx_file.h --- a/src/core/ngx_file.h +++ b/src/core/ngx_file.h @@ -42,7 +42,7 @@ struct ngx_file_s { #define NGX_MAX_PATH_LEVEL 3 -typedef time_t (*ngx_path_manager_pt) (void *data); +typedef ngx_msec_t (*ngx_path_manager_pt) (void *data); typedef ngx_msec_t (*ngx_path_purger_pt) (void *data); typedef void (*ngx_path_loader_pt) (void *data); diff --git a/src/http/ngx_http_cache.h b/src/http/ngx_http_cache.h --- a/src/http/ngx_http_cache.h +++ b/src/http/ngx_http_cache.h @@ -166,6 +166,10 @@ struct ngx_http_file_cache_s { ngx_msec_t loader_sleep; ngx_msec_t loader_threshold; + ngx_uint_t manager_files; + ngx_msec_t manager_sleep; + ngx_msec_t manager_threshold; + ngx_shm_zone_t *shm_zone; }; diff --git a/src/http/ngx_http_file_cache.c b/src/http/ngx_http_file_cache.c --- a/src/http/ngx_http_file_cache.c +++ b/src/http/ngx_http_file_cache.c @@ -1759,6 +1759,7 @@ ngx_http_file_cache_expire(ngx_http_file size_t len; time_t now, wait; ngx_path_t *path; + ngx_msec_t elapsed; ngx_queue_t *q; ngx_http_file_cache_node_t *fcn; u_char key[2 * NGX_HTTP_CACHE_KEY_LEN]; @@ -1810,7 +1811,7 @@ ngx_http_file_cache_expire(ngx_http_file if (fcn->count == 0) { ngx_http_file_cache_delete(cache, q, name); - continue; + goto next; } if (fcn->deleting) { @@ -1836,6 +1837,22 @@ ngx_http_file_cache_expire(ngx_http_file ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, "ignore long locked inactive cache entry %*s, count:%d", (size_t) 2 * NGX_HTTP_CACHE_KEY_LEN, key, fcn->count); + +next: + + if (++cache->files >= cache->manager_files) { + wait = 0; + break; + } + + ngx_time_update(); + + elapsed = ngx_abs((ngx_msec_int_t) (ngx_current_msec - cache->last)); + + if (elapsed >= cache->manager_threshold) { + wait = 0; + break; + } } ngx_shmtx_unlock(&cache->shpool->mutex); @@ -1897,20 +1914,25 @@ ngx_http_file_cache_delete(ngx_http_file } -static time_t +static ngx_msec_t ngx_http_file_cache_manager(void *data) { ngx_http_file_cache_t *cache = data; off_t size; time_t next, wait; + ngx_msec_t elapsed; ngx_uint_t count, watermark; - next = ngx_http_file_cache_expire(cache); - cache->last = ngx_current_msec; cache->files = 0; + next = ngx_http_file_cache_expire(cache); + + if (next == 0) { + return cache->manager_sleep; + } + for ( ;; ) { ngx_shmtx_lock(&cache->shpool->mutex); @@ -1925,17 +1947,29 @@ ngx_http_file_cache_manager(void *data) size, count, (ngx_int_t) watermark); if (size < cache->max_size && count < watermark) { - return next; + return (ngx_msec_t) next * 1000; } wait = ngx_http_file_cache_forced_expire(cache); if (wait > 0) { - return wait; + return (ngx_msec_t) wait * 1000; } if (ngx_quit || ngx_terminate) { - return next; + return (ngx_msec_t) next * 1000; + } + + if (++cache->files >= cache->manager_files) { + return cache->manager_sleep; + } + + ngx_time_update(); + + elapsed = ngx_abs((ngx_msec_int_t) (ngx_current_msec - cache->last)); + + if (elapsed >= cache->manager_threshold) { + return cache->manager_sleep; } } } @@ -2211,8 +2245,9 @@ ngx_http_file_cache_set_slot(ngx_conf_t size_t len; ssize_t size; ngx_str_t s, name, *value; - ngx_int_t loader_files; - ngx_msec_t loader_sleep, loader_threshold; + ngx_int_t loader_files, manager_files; + ngx_msec_t loader_sleep, manager_sleep, loader_threshold, + manager_threshold; ngx_uint_t i, n, use_temp_path; ngx_array_t *caches; ngx_http_file_cache_t *cache, **ce; @@ -2230,10 +2265,15 @@ ngx_http_file_cache_set_slot(ngx_conf_t use_temp_path = 1; inactive = 600; + loader_files = 100; loader_sleep = 50; loader_threshold = 200; + manager_files = 100; + manager_sleep = 50; + manager_threshold = 200; + name.len = 0; size = 0; max_size = NGX_MAX_OFF_T_VALUE; @@ -2405,6 +2445,48 @@ ngx_http_file_cache_set_slot(ngx_conf_t continue; } + if (ngx_strncmp(value[i].data, "manager_files=", 14) == 0) { + + manager_files = ngx_atoi(value[i].data + 14, value[i].len - 14); + if (manager_files == NGX_ERROR) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid manager_files value \"%V\"", &value[i]); + return NGX_CONF_ERROR; + } + + continue; + } + + if (ngx_strncmp(value[i].data, "manager_sleep=", 14) == 0) { + + s.len = value[i].len - 14; + s.data = value[i].data + 14; + + manager_sleep = ngx_parse_time(&s, 0); + if (manager_sleep == (ngx_msec_t) NGX_ERROR) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid manager_sleep value \"%V\"", &value[i]); + return NGX_CONF_ERROR; + } + + continue; + } + + if (ngx_strncmp(value[i].data, "manager_threshold=", 18) == 0) { + + s.len = value[i].len - 18; + s.data = value[i].data + 18; + + manager_threshold = ngx_parse_time(&s, 0); + if (manager_threshold == (ngx_msec_t) NGX_ERROR) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid manager_threshold value \"%V\"", &value[i]); + return NGX_CONF_ERROR; + } + + continue; + } + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"", &value[i]); return NGX_CONF_ERROR; @@ -2425,6 +2507,9 @@ ngx_http_file_cache_set_slot(ngx_conf_t cache->loader_files = loader_files; cache->loader_sleep = loader_sleep; cache->loader_threshold = loader_threshold; + cache->manager_files = manager_files; + cache->manager_sleep = manager_sleep; + cache->manager_threshold = manager_threshold; if (ngx_add_path(cf, &cache->path) != NGX_OK) { return NGX_CONF_ERROR; diff --git a/src/os/unix/ngx_process_cycle.c b/src/os/unix/ngx_process_cycle.c --- a/src/os/unix/ngx_process_cycle.c +++ b/src/os/unix/ngx_process_cycle.c @@ -1148,11 +1148,11 @@ ngx_cache_manager_process_cycle(ngx_cycl static void ngx_cache_manager_process_handler(ngx_event_t *ev) { - time_t next, n; ngx_uint_t i; + ngx_msec_t next, n; ngx_path_t **path; - next = 60 * 60; + next = 60 * 60 * 1000; path = ngx_cycle->paths.elts; for (i = 0; i < ngx_cycle->paths.nelts; i++) { @@ -1170,7 +1170,7 @@ ngx_cache_manager_process_handler(ngx_ev next = 1; } - ngx_add_timer(ev, next * 1000); + ngx_add_timer(ev, next); } diff --git a/src/os/win32/ngx_process_cycle.c b/src/os/win32/ngx_process_cycle.c --- a/src/os/win32/ngx_process_cycle.c +++ b/src/os/win32/ngx_process_cycle.c @@ -921,11 +921,11 @@ static void ngx_cache_manager_process_handler(void) { u_long ev; - time_t next, n; ngx_uint_t i; + ngx_msec_t next, n; ngx_path_t **path; - next = 60 * 60; + next = 60 * 60 * 1000; path = ngx_cycle->paths.elts; for (i = 0; i < ngx_cycle->paths.nelts; i++) { @@ -943,7 +943,7 @@ ngx_cache_manager_process_handler(void) next = 1; } - ev = WaitForSingleObject(ngx_cache_manager_event, (u_long) next * 1000); + ev = WaitForSingleObject(ngx_cache_manager_event, (u_long) next); if (ev != WAIT_TIMEOUT) {