# HG changeset patch # User Igor Sysoev # Date 1238356800 -14400 # Node ID 9eda3153223b42932fec477da26be67a8a33b781 # Parent 29602be4685054cd10e55f343cb0c1a2aa44b2d6 nginx 0.7.45 *) Change: now the "proxy_cache" and the "proxy_cache_valid" can be set on different levels. *) Change: the "clean_time" parameter of the "proxy_cache_path" directive is canceled. *) Feature: the "max_size" parameter of the "proxy_cache_path" directive. *) Feature: the ngx_http_fastcgi_module preliminary cache support. *) Feature: now on shared memory allocation errors directive and zone names are logged. *) Bugfix: the directive "add_header last-modified ''" did not delete a "Last-Modified" response header line; the bug had appeared in 0.7.44. *) Bugfix: a relative path in the "auth_basic_user_file" directive given without variables did not work; the bug had appeared in 0.7.44. Thanks to Jerome Loyet. *) Bugfix: in an "alias" directive given using variables without references to captures of regular expressions; the bug had appeared in 0.7.42. diff --git a/auto/os/features b/auto/os/features --- a/auto/os/features +++ b/auto/os/features @@ -98,7 +98,7 @@ if test -z "$NGX_KQUEUE_CHECKED"; then ngx_feature_name="NGX_HAVE_TIMER_EVENT" ngx_feature_run=yes ngx_feature_incs="#include -#include " + #include " ngx_feature_path= ngx_feature_libs= ngx_feature_test="int kq; diff --git a/auto/os/linux b/auto/os/linux --- a/auto/os/linux +++ b/auto/os/linux @@ -11,7 +11,8 @@ CORE_SRCS="$UNIX_SRCS $LINUX_SRCS" ngx_spacer=' ' -CC_AUX_FLAGS="$CC_AUX_FLAGS -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64" +cc_aux_flags="$CC_AUX_FLAGS" +CC_AUX_FLAGS="$cc_aux_flags -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64" # Linux kernel version @@ -60,12 +61,12 @@ fi # sendfile() -CC_AUX_FLAGS="$CC_AUX_FLAGS -D_GNU_SOURCE" +CC_AUX_FLAGS="$cc_aux_flags -D_GNU_SOURCE" ngx_feature="sendfile()" ngx_feature_name="NGX_HAVE_SENDFILE" ngx_feature_run=yes ngx_feature_incs="#include -#include " + #include " ngx_feature_path= ngx_feature_libs= ngx_feature_test="int s = 0, fd = 1; @@ -81,12 +82,12 @@ fi # sendfile64() -CC_AUX_FLAGS="$CC_AUX_FLAGS -D_FILE_OFFSET_BITS=64" +CC_AUX_FLAGS="$cc_aux_flags -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64" ngx_feature="sendfile64()" ngx_feature_name="NGX_HAVE_SENDFILE64" ngx_feature_run=yes ngx_feature_incs="#include -#include " + #include " ngx_feature_path= ngx_feature_libs= ngx_feature_test="int s = 0, fd = 1; @@ -121,3 +122,6 @@ ngx_feature_libs= ngx_feature_test="long mask = 0; sched_setaffinity(0, 32, (cpu_set_t *) &mask)" . auto/feature + + +CC_AUX_FLAGS=$cc_aux_flags diff --git a/auto/unix b/auto/unix --- a/auto/unix +++ b/auto/unix @@ -190,8 +190,8 @@ ngx_feature='mmap("/dev/zero", MAP_SHARE ngx_feature_name="NGX_HAVE_MAP_DEVZERO" ngx_feature_run=yes ngx_feature_incs="#include -#include -#include " + #include + #include " ngx_feature_path= ngx_feature_libs= ngx_feature_test='void *p; int fd; @@ -205,7 +205,7 @@ ngx_feature="System V shared memory" ngx_feature_name="NGX_HAVE_SYSVSHM" ngx_feature_run=yes ngx_feature_incs="#include -#include " + #include " ngx_feature_path= ngx_feature_libs= ngx_feature_test="int id; @@ -229,7 +229,7 @@ ngx_feature="ioctl(FIONBIO)" ngx_feature_name="NGX_HAVE_FIONBIO" ngx_feature_run=no ngx_feature_incs="#include -$NGX_INCLUDE_SYS_FILIO_H" + $NGX_INCLUDE_SYS_FILIO_H" ngx_feature_path= ngx_feature_libs= ngx_feature_test="int i; i = FIONBIO" diff --git a/src/core/nginx.h b/src/core/nginx.h --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -8,7 +8,7 @@ #define _NGINX_H_INCLUDED_ -#define NGINX_VERSION "0.7.44" +#define NGINX_VERSION "0.7.45" #define NGINX_VER "nginx/" NGINX_VERSION #define NGINX_VAR "NGINX" diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c --- a/src/http/modules/ngx_http_fastcgi_module.c +++ b/src/http/modules/ngx_http_fastcgi_module.c @@ -23,6 +23,10 @@ typedef struct { ngx_array_t *fastcgi_lengths; ngx_array_t *fastcgi_values; +#if (NGX_HTTP_CACHE) + ngx_http_complex_value_t cache_key; +#endif + #if (NGX_PCRE) ngx_regex_t *split_regex; ngx_str_t split_name; @@ -116,6 +120,9 @@ typedef struct { static ngx_int_t ngx_http_fastcgi_eval(ngx_http_request_t *r, ngx_http_fastcgi_loc_conf_t *flcf); +#if (NGX_HTTP_CACHE) +static ngx_int_t ngx_http_fastcgi_create_key(ngx_http_request_t *r); +#endif static ngx_int_t ngx_http_fastcgi_create_request(ngx_http_request_t *r); static ngx_int_t ngx_http_fastcgi_reinit_request(ngx_http_request_t *r); static ngx_int_t ngx_http_fastcgi_process_header(ngx_http_request_t *r); @@ -144,6 +151,13 @@ static char *ngx_http_fastcgi_split_path ngx_command_t *cmd, void *conf); static char *ngx_http_fastcgi_store(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +#if (NGX_HTTP_CACHE) +static char *ngx_http_fastcgi_cache(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); +static char *ngx_http_fastcgi_cache_key(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); +#endif + static char *ngx_http_fastcgi_lowat_check(ngx_conf_t *cf, void *post, void *data); @@ -169,6 +183,9 @@ static ngx_conf_bitmask_t ngx_http_fast }; +ngx_module_t ngx_http_fastcgi_module; + + static ngx_command_t ngx_http_fastcgi_commands[] = { { ngx_string("fastcgi_pass"), @@ -283,6 +300,52 @@ static ngx_command_t ngx_http_fastcgi_c offsetof(ngx_http_fastcgi_loc_conf_t, upstream.busy_buffers_size_conf), NULL }, +#if (NGX_HTTP_CACHE) + + { ngx_string("fastcgi_cache"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, + ngx_http_fastcgi_cache, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + NULL }, + + { ngx_string("fastcgi_cache_key"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, + ngx_http_fastcgi_cache_key, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + NULL }, + + { ngx_string("fastcgi_cache_path"), + NGX_HTTP_MAIN_CONF|NGX_CONF_2MORE, + ngx_http_file_cache_set_slot, + 0, + 0, + &ngx_http_fastcgi_module }, + + { ngx_string("fastcgi_cache_valid"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, + ngx_http_file_cache_valid_set_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_valid), + NULL }, + + { ngx_string("proxy_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_fastcgi_loc_conf_t, upstream.cache_min_uses), + NULL }, + + { ngx_string("fastcgi_cache_use_stale"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, + ngx_conf_set_bitmask_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_use_stale), + &ngx_http_fastcgi_next_upstream_masks }, + +#endif + { ngx_string("fastcgi_temp_path"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234, ngx_conf_set_path_slot, @@ -491,6 +554,9 @@ ngx_http_fastcgi_handler(ngx_http_reques u->conf = &flcf->upstream; +#if (NGX_HTTP_CACHE) + u->create_key = ngx_http_fastcgi_create_key; +#endif u->create_request = ngx_http_fastcgi_create_request; u->reinit_request = ngx_http_fastcgi_reinit_request; u->process_header = ngx_http_fastcgi_process_header; @@ -544,7 +610,7 @@ ngx_http_fastcgi_eval(ngx_http_request_t if (u.no_port) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "no port in upstream \"%V\"", &u.url); + "no port in upstream \"%V\"", &u.url); return NGX_ERROR; } @@ -569,6 +635,31 @@ ngx_http_fastcgi_eval(ngx_http_request_t } +#if (NGX_HTTP_CACHE) + +static ngx_int_t +ngx_http_fastcgi_create_key(ngx_http_request_t *r) +{ + ngx_str_t *key; + ngx_http_fastcgi_loc_conf_t *flcf; + + key = ngx_array_push(&r->cache->keys); + if (key == NULL) { + return NGX_ERROR; + } + + flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module); + + if (ngx_http_complex_value(r, &flcf->cache_key, key) != NGX_OK) { + return NGX_ERROR; + } + + return NGX_OK; +} + +#endif + + static ngx_int_t ngx_http_fastcgi_create_request(ngx_http_request_t *r) { @@ -1276,12 +1367,9 @@ ngx_http_fastcgi_process_header(ngx_http u->headers_in.status_line.data = (u_char *) "200 OK"; } - u->state->status = u->headers_in.status_n; -#if 0 - if (u->cacheable) { - u->cacheable = ngx_http_upstream_is_cacheable(r); + if (u->state) { + u->state->status = u->headers_in.status_n; } -#endif break; } @@ -1730,6 +1818,7 @@ ngx_http_fastcgi_create_loc_conf(ngx_con * * conf->upstream.bufs.num = 0; * conf->upstream.next_upstream = 0; + * conf->upstream.use_stale_cache = 0; * conf->upstream.temp_path = NULL; * conf->upstream.hide_headers_hash = { NULL, 0 }; * conf->upstream.uri = { 0, NULL }; @@ -1760,6 +1849,12 @@ ngx_http_fastcgi_create_loc_conf(ngx_con conf->upstream.pass_request_headers = NGX_CONF_UNSET; conf->upstream.pass_request_body = NGX_CONF_UNSET; +#if (NGX_HTTP_CACHE) + conf->upstream.cache = NGX_CONF_UNSET_PTR; + conf->upstream.cache_min_uses = NGX_CONF_UNSET_UINT; + conf->upstream.cache_valid = NGX_CONF_UNSET_PTR; +#endif + conf->upstream.hide_headers = NGX_CONF_UNSET_PTR; conf->upstream.pass_headers = NGX_CONF_UNSET_PTR; @@ -1936,6 +2031,41 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf return NGX_CONF_ERROR; } +#if (NGX_HTTP_CACHE) + + ngx_conf_merge_ptr_value(conf->upstream.cache, + prev->upstream.cache, NULL); + + if (conf->upstream.cache && conf->upstream.cache->data == NULL) { + ngx_shm_zone_t *shm_zone; + + shm_zone = conf->upstream.cache; + + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "\"fastcgi_cache\" zone \"%V\" is unknown", + &shm_zone->name); + + return NGX_CONF_ERROR; + } + + ngx_conf_merge_uint_value(conf->upstream.cache_min_uses, + prev->upstream.cache_min_uses, 1); + + ngx_conf_merge_bitmask_value(conf->upstream.cache_use_stale, + prev->upstream.cache_use_stale, + (NGX_CONF_BITMASK_SET + |NGX_HTTP_UPSTREAM_FT_OFF)); + + if (conf->upstream.cache_use_stale & NGX_HTTP_UPSTREAM_FT_OFF) { + conf->upstream.cache_use_stale = NGX_CONF_BITMASK_SET + |NGX_HTTP_UPSTREAM_FT_OFF; + } + + ngx_conf_merge_ptr_value(conf->upstream.cache_valid, + prev->upstream.cache_valid, NULL); + +#endif + ngx_conf_merge_value(conf->upstream.pass_request_headers, prev->upstream.pass_request_headers, 1); ngx_conf_merge_value(conf->upstream.pass_request_body, @@ -2409,6 +2539,66 @@ ngx_http_fastcgi_store(ngx_conf_t *cf, n } +#if (NGX_HTTP_CACHE) + +static char * +ngx_http_fastcgi_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_http_fastcgi_loc_conf_t *flcf = conf; + + ngx_str_t *value; + + value = cf->args->elts; + + if (flcf->upstream.cache != NGX_CONF_UNSET_PTR) { + return "is duplicate"; + } + + if (ngx_strcmp(value[1].data, "off") == 0) { + flcf->upstream.cache = NULL; + return NGX_CONF_OK; + } + + flcf->upstream.cache = ngx_shared_memory_add(cf, &value[1], 0, + &ngx_http_fastcgi_module); + if (flcf->upstream.cache == NULL) { + return NGX_CONF_ERROR; + } + + return NGX_CONF_OK; +} + + +static char * +ngx_http_fastcgi_cache_key(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_http_fastcgi_loc_conf_t *flcf = conf; + + ngx_str_t *value; + ngx_http_compile_complex_value_t ccv; + + value = cf->args->elts; + + if (flcf->cache_key.value.len) { + return "is duplicate"; + } + + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &value[1]; + ccv.complex_value = &flcf->cache_key; + + if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + + return NGX_CONF_OK; +} + +#endif + + static char * ngx_http_fastcgi_lowat_check(ngx_conf_t *cf, void *post, void *data) { diff --git a/src/http/modules/ngx_http_headers_filter_module.c b/src/http/modules/ngx_http_headers_filter_module.c --- a/src/http/modules/ngx_http_headers_filter_module.c +++ b/src/http/modules/ngx_http_headers_filter_module.c @@ -608,6 +608,11 @@ ngx_http_headers_add(ngx_conf_t *cf, ngx break; } + if (value[2].len == 0) { + ngx_memzero(&hv->value, sizeof(ngx_http_complex_value_t)); + return NGX_CONF_OK; + } + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); ccv.cf = cf; diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -324,7 +324,7 @@ static ngx_command_t ngx_http_proxy_com NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, ngx_http_proxy_cache, NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_proxy_loc_conf_t, upstream.cache), + 0, NULL }, { ngx_string("proxy_cache_path"), @@ -2068,10 +2068,6 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t ngx_conf_merge_ptr_value(conf->upstream.cache_valid, prev->upstream.cache_valid, NULL); - if (conf->upstream.cache_valid == NULL) { - conf->upstream.cache = NULL; - } - #endif if (conf->method.len == 0) { diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm --- a/src/http/modules/perl/nginx.pm +++ b/src/http/modules/perl/nginx.pm @@ -47,7 +47,7 @@ our @EXPORT = qw( HTTP_INSUFFICIENT_STORAGE ); -our $VERSION = '0.7.44'; +our $VERSION = '0.7.45'; require XSLoader; XSLoader::load('nginx', $VERSION); 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 @@ -251,6 +251,7 @@ ngx_http_file_cache_open(ngx_http_reques "http file cache fd: %d", of.fd); c->file.fd = of.fd; + c->file.log = r->connection->log; c->buf = ngx_create_temp_buf(r->pool, c->body_start); if (c->buf == NULL) { @@ -355,10 +356,7 @@ ngx_http_file_cache_exists(ngx_http_requ if (fcn->uses >= r->cache->min_uses) { r->cache->exists = fcn->exists; - - if (fcn->body_start) { - r->cache->body_start = fcn->body_start; - } + r->cache->body_start = fcn->body_start; rc = NGX_OK; @@ -816,8 +814,8 @@ ngx_http_file_cache_expire(ngx_http_file ngx_rbtree_delete(cache->rbtree, &fcn->node); ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, - "ignore long locked inactive cache entry %*s", - NGX_HTTP_CACHE_KEY_LEN, key); + "ignore long locked inactive cache entry %*s, count:%d", + 2 * NGX_HTTP_CACHE_KEY_LEN, key, fcn->count); } if (tries++ < 10) { @@ -895,8 +893,9 @@ ngx_http_file_cache_cleaner(void *data) now = ngx_time(); - if (now >= cache->next_clean_time) { - + if (now >= cache->next_clean_time + && now >= cache->created + cache->inactive) + { ngx_log_error(NGX_LOG_NOTICE, ngx_cycle->log, 0, "clean unused cache files");