summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES55
-rw-r--r--CHANGES.ru41
-rw-r--r--auto/install2
-rw-r--r--auto/lib/pcre/conf23
-rw-r--r--auto/lib/pcre/make2
-rw-r--r--auto/modules6
-rw-r--r--auto/options4
-rw-r--r--auto/sources1
-rw-r--r--conf/fastcgi.conf1
-rw-r--r--src/core/nginx.h2
-rw-r--r--src/core/ngx_regex.c215
-rw-r--r--src/core/ngx_regex.h8
-rw-r--r--src/http/modules/ngx_http_fastcgi_module.c22
-rw-r--r--src/http/modules/ngx_http_limit_conn_module.c2
-rw-r--r--src/http/modules/ngx_http_limit_req_module.c2
-rw-r--r--src/http/modules/ngx_http_mp4_module.c2
-rw-r--r--src/http/modules/ngx_http_proxy_module.c31
-rw-r--r--src/http/modules/ngx_http_scgi_module.c38
-rw-r--r--src/http/modules/ngx_http_ssi_filter_module.c191
-rw-r--r--src/http/modules/ngx_http_ssi_filter_module.h6
-rw-r--r--src/http/modules/ngx_http_uwsgi_module.c22
-rw-r--r--src/http/modules/perl/nginx.pm2
-rw-r--r--src/http/ngx_http_cache.h8
-rw-r--r--src/http/ngx_http_core_module.c1
-rw-r--r--src/http/ngx_http_file_cache.c159
-rw-r--r--src/http/ngx_http_upstream.c5
-rw-r--r--src/http/ngx_http_upstream.h3
-rw-r--r--src/http/ngx_http_write_filter_module.c20
28 files changed, 767 insertions, 107 deletions
diff --git a/CHANGES b/CHANGES
index 9a6450a2a..e9457a840 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,44 @@
+Changes with nginx 1.1.12 26 Dec 2011
+
+ *) Change: a "proxy_pass" directive without URI part now uses changed
+ URI after redirection with the "error_page" directive;
+ Thanks to Lanshun Zhou.
+
+ *) Feature: the "proxy/fastcgi/scgi/uwsgi_cache_lock",
+ "proxy/fastcgi/scgi/uwsgi_cache_lock_timeout" directives.
+
+ *) Feature: the "pcre_jit" directive.
+
+ *) Feature: the "if" SSI command supports captures in regular
+ expressions.
+
+ *) Bugfix: the "if" SSI command did not work inside the "block" command.
+
+ *) Bugfix: the "limit_conn_log_level" and "limit_req_log_level"
+ directives might not work.
+
+ *) Bugfix: the "limit_rate" directive did not allow to use full
+ throughput, even if limit value was very high.
+
+ *) Bugfix: the "sendfile_max_chunk" directive did not work, if the
+ "limit_rate" directive was used.
+
+ *) Bugfix: a "proxy_pass" directive without URI part always used
+ original request URI if variables were used.
+
+ *) Bugfix: a "proxy_pass" directive without URI part might use original
+ request after redirection with the "try_files" directive;
+ Thanks to Lanshun Zhou.
+
+ *) Bugfix: in the ngx_http_scgi_module.
+
+ *) Bugfix: in the ngx_http_mp4_module.
+
+ *) Bugfix: nginx could not be built on Solaris; the bug had appeared in
+ 1.1.9.
+
+
Changes with nginx 1.1.11 12 Dec 2011
*) Feature: the "so_keepalive" parameter of the "listen" directive.
@@ -4564,8 +4604,8 @@ Changes with nginx 0.3.6 24 Oct 2005
*) Bugfix: if at least in one server was no the "listen" directive, then
nginx did not listen on the 80 port; the bug had appeared in 0.3.3.
- *) Bugfix: if the URI part is omitted in "proxy_pass" directive, the the
- 80 port was always used.
+ *) Bugfix: if the URI part is omitted in "proxy_pass" directive, the 80
+ port was always used.
Changes with nginx 0.3.5 21 Oct 2005
@@ -4810,7 +4850,7 @@ Changes with nginx 0.1.43 30 Aug 2005
*) Bugfix: the segmentation fault occurred or the worker process may got
caught in an endless loop if the proxied or FastCGI server sent the
"Cache-Control" header line and the "expires" directive was used; in
- the proxied mode the the bug had appeared in 0.1.29.
+ the proxied mode the bug had appeared in 0.1.29.
Changes with nginx 0.1.42 23 Aug 2005
@@ -4885,8 +4925,8 @@ Changes with nginx 0.1.39 14 Jul 2005
Changes with nginx 0.1.38 08 Jul 2005
- *) Feature: the "limit_rate" directive is supported in in proxy and
- FastCGI mode.
+ *) Feature: the "limit_rate" directive is supported in proxy and FastCGI
+ mode.
*) Feature: the "X-Accel-Limit-Rate" response header line is supported
in proxy and FastCGI mode.
@@ -5038,8 +5078,7 @@ Changes with nginx 0.1.30 14 May 2005
*) Bugfix: if the length of the response part received at once from
proxied or FastCGI server was equal to 500, then nginx returns the
- 500 response code; in proxy mode the the bug had appeared in 0.1.29
- only.
+ 500 response code; in proxy mode the bug had appeared in 0.1.29 only.
*) Bugfix: nginx did not consider the directives with 8 or 9 parameters
as invalid.
@@ -5282,7 +5321,7 @@ Changes with nginx 0.1.19 16 Feb 2005
*) Bugfix: nginx could not be built on NetBSD 2.0.
- *) Bugfix: the timeout may occur while reading of the the client request
+ *) Bugfix: the timeout may occur while reading of the client request
body via SSL connections.
diff --git a/CHANGES.ru b/CHANGES.ru
index 6b559ed99..750fc81c1 100644
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,45 @@
+Изменения в nginx 1.1.12 26.12.2011
+
+ *) Изменение: после перенаправления запроса с помощью директивы
+ error_page директива proxy_pass без URI теперь использует изменённый
+ URI;
+ Спасибо Lanshun Zhou.
+
+ *) Добавление: директивы proxy/fastcgi/scgi/uwsgi_cache_lock,
+ proxy/fastcgi/scgi/uwsgi_cache_lock_timeout.
+
+ *) Добавление: директива pcre_jit.
+
+ *) Добавление: SSI команда if поддерживает выделения в регулярных
+ выражениях.
+
+ *) Исправление: SSI команда if не работала внутри команды block.
+
+ *) Исправление: директивы limit_conn_log_level и limit_req_log_level
+ могли не работать.
+
+ *) Исправление: директива limit_rate не позволяла передавать на полной
+ скорости, даже если был указан очень большой лимит.
+
+ *) Исправление: директива sendfile_max_chunk не работала, если
+ использовалась директива limit_rate.
+
+ *) Исправление: если в директиве proxy_pass использовались переменные и
+ не был указан URI, всегда использовался URI исходного запроса.
+
+ *) Исправление: после перенаправления запроса с помощью директивы
+ try_files директива proxy_pass без URI могла использовать URI
+ исходного запроса;
+ Спасибо Lanshun Zhou.
+
+ *) Исправление: в модуле ngx_http_scgi_module.
+
+ *) Исправление: в модуле ngx_http_mp4_module.
+
+ *) Исправление: nginx не собирался на Solaris; ошибка появилась в 1.1.9.
+
+
Изменения в nginx 1.1.11 12.12.2011
*) Добавление: параметр so_keepalive в директиве listen.
diff --git a/auto/install b/auto/install
index d56be27ef..2b1002472 100644
--- a/auto/install
+++ b/auto/install
@@ -72,7 +72,7 @@ case ".$NGX_HTTP_LOG_PATH" in
esac
-if test -e man/nginx.8 ; then
+if test -f man/nginx.8 ; then
NGX_MAN=man/nginx.8
else
NGX_MAN=docs/man/nginx.8
diff --git a/auto/lib/pcre/conf b/auto/lib/pcre/conf
index 3008f5892..e90d02307 100644
--- a/auto/lib/pcre/conf
+++ b/auto/lib/pcre/conf
@@ -4,8 +4,6 @@
if [ $PCRE != NONE ]; then
CORE_INCS="$CORE_INCS $PCRE"
- CORE_DEPS="$CORE_DEPS $REGEX_DEPS"
- CORE_SRCS="$CORE_SRCS $REGEX_SRCS"
case "$NGX_CC_NAME" in
@@ -81,6 +79,12 @@ if [ $PCRE != NONE ]; then
esac
+
+ if [ $PCRE_JIT = YES ]; then
+ have=NGX_HAVE_PCRE_JIT . auto/have
+ PCRE_CONF_OPT="$PCRE_CONF_OPT --enable-jit"
+ fi
+
else
if [ "$NGX_PLATFORM" != win32 ]; then
@@ -156,12 +160,23 @@ else
fi
if [ $ngx_found = yes ]; then
- CORE_DEPS="$CORE_DEPS $REGEX_DEPS"
- CORE_SRCS="$CORE_SRCS $REGEX_SRCS"
CORE_INCS="$CORE_INCS $ngx_feature_path"
CORE_LIBS="$CORE_LIBS $ngx_feature_libs"
PCRE=YES
fi
+
+ if [ $PCRE == YES ]; then
+ ngx_feature="PCRE JIT support"
+ ngx_feature_name="NGX_HAVE_PCRE_JIT"
+ ngx_feature_test="int jit = 0;
+ pcre_config(PCRE_CONFIG_JIT, &jit);
+ if (jit != 1) return 1;"
+ . auto/feature
+
+ if [ $ngx_found = yes ]; then
+ PCRE_JIT=YES
+ fi
+ fi
fi
if [ $PCRE != YES ]; then
diff --git a/auto/lib/pcre/make b/auto/lib/pcre/make
index 9f2c658bf..a9be75e36 100644
--- a/auto/lib/pcre/make
+++ b/auto/lib/pcre/make
@@ -50,7 +50,7 @@ $PCRE/Makefile: $NGX_MAKEFILE
cd $PCRE \\
&& if [ -f Makefile ]; then \$(MAKE) distclean; fi \\
&& CC="\$(CC)" CFLAGS="$PCRE_OPT" \\
- ./configure --disable-shared
+ ./configure --disable-shared $PCRE_CONF_OPT
$PCRE/.libs/libpcre.a: $PCRE/Makefile
cd $PCRE \\
diff --git a/auto/modules b/auto/modules
index a8607eefc..93e0de995 100644
--- a/auto/modules
+++ b/auto/modules
@@ -396,6 +396,12 @@ if [ $USE_OPENSSL = YES ]; then
CORE_SRCS="$CORE_SRCS $OPENSSL_SRCS"
fi
+if [ $USE_PCRE = YES ]; then
+ modules="$modules $REGEX_MODULE"
+ CORE_DEPS="$CORE_DEPS $REGEX_DEPS"
+ CORE_SRCS="$CORE_SRCS $REGEX_SRCS"
+fi
+
if [ $HTTP = YES ]; then
modules="$modules $HTTP_MODULES $HTTP_FILTER_MODULES \
$HTTP_HEADERS_FILTER_MODULE \
diff --git a/auto/options b/auto/options
index e8de4ff45..2b040238e 100644
--- a/auto/options
+++ b/auto/options
@@ -111,6 +111,8 @@ NGX_ADDONS=
USE_PCRE=NO
PCRE=NONE
PCRE_OPT=
+PCRE_CONF_OPT=
+PCRE_JIT=NO
USE_OPENSSL=NO
OPENSSL=NONE
@@ -274,6 +276,7 @@ use the \"--without-http_limit_conn_module\" option instead"
--with-pcre) USE_PCRE=YES ;;
--with-pcre=*) PCRE="$value" ;;
--with-pcre-opt=*) PCRE_OPT="$value" ;;
+ --with-pcre-jit) PCRE_JIT=YES ;;
--with-openssl=*) OPENSSL="$value" ;;
--with-openssl-opt=*) OPENSSL_OPT="$value" ;;
@@ -421,6 +424,7 @@ cat << END
--with-pcre force PCRE library usage
--with-pcre=DIR set path to PCRE library sources
--with-pcre-opt=OPTIONS set additional build options for PCRE
+ --with-pcre-jit build PCRE with JIT compilation support
--with-md5=DIR set path to md5 library sources
--with-md5-opt=OPTIONS set additional build options for md5
diff --git a/auto/sources b/auto/sources
index 24fa3b89f..38b3f40af 100644
--- a/auto/sources
+++ b/auto/sources
@@ -69,6 +69,7 @@ CORE_SRCS="src/core/nginx.c \
src/core/ngx_crypt.c"
+REGEX_MODULE=ngx_regex_module
REGEX_DEPS=src/core/ngx_regex.h
REGEX_SRCS=src/core/ngx_regex.c
diff --git a/conf/fastcgi.conf b/conf/fastcgi.conf
index fab09eb24..ac9ff9204 100644
--- a/conf/fastcgi.conf
+++ b/conf/fastcgi.conf
@@ -10,6 +10,7 @@ fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;
+fastcgi_param HTTPS $https if_not_empty;
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
diff --git a/src/core/nginx.h b/src/core/nginx.h
index 965a7f2bf..a781b5ef9 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -9,7 +9,7 @@
#define nginx_version 1001011
-#define NGINX_VERSION "1.1.11"
+#define NGINX_VERSION "1.1.12"
#define NGINX_VER "nginx/" NGINX_VERSION
#define NGINX_VAR "NGINX"
diff --git a/src/core/ngx_regex.c b/src/core/ngx_regex.c
index af00f8319..fc5296ac1 100644
--- a/src/core/ngx_regex.c
+++ b/src/core/ngx_regex.c
@@ -8,11 +8,61 @@
#include <ngx_core.h>
+typedef struct {
+ ngx_flag_t pcre_jit;
+} ngx_regex_conf_t;
+
+
static void * ngx_libc_cdecl ngx_regex_malloc(size_t size);
static void ngx_libc_cdecl ngx_regex_free(void *p);
+static ngx_int_t ngx_regex_module_init(ngx_cycle_t *cycle);
+
+static void *ngx_regex_create_conf(ngx_cycle_t *cycle);
+static char *ngx_regex_init_conf(ngx_cycle_t *cycle, void *conf);
+
+static char *ngx_regex_pcre_jit(ngx_conf_t *cf, void *post, void *data);
+static ngx_conf_post_t ngx_regex_pcre_jit_post = { ngx_regex_pcre_jit };
+
+
+static ngx_command_t ngx_regex_commands[] = {
+
+ { ngx_string("pcre_jit"),
+ NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_flag_slot,
+ 0,
+ offsetof(ngx_regex_conf_t, pcre_jit),
+ &ngx_regex_pcre_jit_post },
+
+ ngx_null_command
+};
+
+
+static ngx_core_module_t ngx_regex_module_ctx = {
+ ngx_string("regex"),
+ ngx_regex_create_conf,
+ ngx_regex_init_conf
+};
+
+
+ngx_module_t ngx_regex_module = {
+ NGX_MODULE_V1,
+ &ngx_regex_module_ctx, /* module context */
+ ngx_regex_commands, /* module directives */
+ NGX_CORE_MODULE, /* module type */
+ NULL, /* init master */
+ ngx_regex_module_init, /* init module */
+ NULL, /* init process */
+ NULL, /* init thread */
+ NULL, /* exit thread */
+ NULL, /* exit process */
+ NULL, /* exit master */
+ NGX_MODULE_V1_PADDING
+};
+
static ngx_pool_t *ngx_pcre_pool;
+static ngx_list_t *ngx_pcre_studies;
void
@@ -62,10 +112,11 @@ ngx_regex_malloc_done(void)
ngx_int_t
ngx_regex_compile(ngx_regex_compile_t *rc)
{
- int n, erroff;
- char *p;
- const char *errstr;
- ngx_regex_t *re;
+ int n, erroff;
+ char *p;
+ pcre *re;
+ const char *errstr;
+ ngx_regex_elt_t *elt;
ngx_regex_malloc_init(rc->pool);
@@ -92,7 +143,24 @@ ngx_regex_compile(ngx_regex_compile_t *rc)
return NGX_ERROR;
}
- rc->regex = re;
+ rc->regex = ngx_pcalloc(rc->pool, sizeof(ngx_regex_t));
+ if (rc->regex == NULL) {
+ return NGX_ERROR;
+ }
+
+ rc->regex->pcre = re;
+
+ /* do not study at runtime */
+
+ if (ngx_pcre_studies != NULL) {
+ elt = ngx_list_push(ngx_pcre_studies);
+ if (elt == NULL) {
+ return NGX_ERROR;
+ }
+
+ elt->regex = rc->regex;
+ elt->name = rc->pattern.data;
+ }
n = pcre_fullinfo(re, NULL, PCRE_INFO_CAPTURECOUNT, &rc->captures);
if (n < 0) {
@@ -203,3 +271,140 @@ ngx_regex_free(void *p)
{
return;
}
+
+
+static ngx_int_t
+ngx_regex_module_init(ngx_cycle_t *cycle)
+{
+ int opt;
+ const char *errstr;
+ ngx_uint_t i;
+ ngx_list_part_t *part;
+ ngx_regex_elt_t *elts;
+
+ opt = 0;
+
+#if (NGX_HAVE_PCRE_JIT)
+ {
+ ngx_regex_conf_t *rcf;
+
+ rcf = (ngx_regex_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_regex_module);
+
+ if (rcf->pcre_jit) {
+ opt = PCRE_STUDY_JIT_COMPILE;
+ }
+ }
+#endif
+
+ ngx_regex_malloc_init(cycle->pool);
+
+ part = &ngx_pcre_studies->part;
+ elts = part->elts;
+
+ for (i = 0 ; /* void */ ; i++) {
+
+ if (i >= part->nelts) {
+ if (part->next == NULL) {
+ break;
+ }
+
+ part = part->next;
+ elts = part->elts;
+ i = 0;
+ }
+
+ elts[i].regex->extra = pcre_study(elts[i].regex->pcre, opt, &errstr);
+
+ if (errstr != NULL) {
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
+ "pcre_study() failed: %s in \"%s\"",
+ errstr, elts[i].name);
+ }
+
+#if (NGX_HAVE_PCRE_JIT)
+ if (opt & PCRE_STUDY_JIT_COMPILE) {
+ int jit, n;
+
+ jit = 0;
+ n = pcre_fullinfo(elts[i].regex->pcre, elts[i].regex->extra,
+ PCRE_INFO_JIT, &jit);
+
+ if (n != 0 || jit != 1) {
+ ngx_log_error(NGX_LOG_INFO, cycle->log, 0,
+ "JIT compiler does not support pattern: \"%s\"",
+ elts[i].name);
+ }
+ }
+#endif
+ }
+
+ ngx_regex_malloc_done();
+
+ ngx_pcre_studies = NULL;
+
+ return NGX_OK;
+}
+
+
+static void *
+ngx_regex_create_conf(ngx_cycle_t *cycle)
+{
+ ngx_regex_conf_t *rcf;
+
+ rcf = ngx_pcalloc(cycle->pool, sizeof(ngx_regex_conf_t));
+ if (rcf == NULL) {
+ return NULL;
+ }
+
+ rcf->pcre_jit = NGX_CONF_UNSET;
+
+ ngx_pcre_studies = ngx_list_create(cycle->pool, 8, sizeof(ngx_regex_elt_t));
+ if (ngx_pcre_studies == NULL) {
+ return NULL;
+ }
+
+ return rcf;
+}
+
+
+static char *
+ngx_regex_init_conf(ngx_cycle_t *cycle, void *conf)
+{
+ ngx_regex_conf_t *rcf = conf;
+
+ ngx_conf_init_value(rcf->pcre_jit, 0);
+
+ return NGX_CONF_OK;
+}
+
+
+static char *
+ngx_regex_pcre_jit(ngx_conf_t *cf, void *post, void *data)
+{
+ ngx_flag_t *fp = data;
+
+ if (*fp == 0) {
+ return NGX_CONF_OK;
+ }
+
+#if (NGX_HAVE_PCRE_JIT)
+ {
+ int jit, r;
+
+ jit = 0;
+ r = pcre_config(PCRE_CONFIG_JIT, &jit);
+
+ if (r != 0 || jit != 1) {
+ ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
+ "PCRE library does not support JIT");
+ *fp = 0;
+ }
+ }
+#else
+ ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
+ "nginx was build without PCRE JIT support");
+ *fp = 0;
+#endif
+
+ return NGX_CONF_OK;
+}
diff --git a/src/core/ngx_regex.h b/src/core/ngx_regex.h
index fc35059b3..52d059e5c 100644
--- a/src/core/ngx_regex.h
+++ b/src/core/ngx_regex.h
@@ -18,7 +18,11 @@
#define NGX_REGEX_CASELESS PCRE_CASELESS
-typedef pcre ngx_regex_t;
+
+typedef struct {
+ pcre *pcre;
+ pcre_extra *extra;
+} ngx_regex_t;
typedef struct {
@@ -45,7 +49,7 @@ void ngx_regex_init(void);
ngx_int_t ngx_regex_compile(ngx_regex_compile_t *rc);
#define ngx_regex_exec(re, s, captures, size) \
- pcre_exec(re, NULL, (const char *) (s)->data, (s)->len, 0, 0, \
+ pcre_exec(re->pcre, re->extra, (const char *) (s)->data, (s)->len, 0, 0, \
captures, size)
#define ngx_regex_exec_n "pcre_exec()"
diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c
index 599edc77c..f976b7aea 100644
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -380,6 +380,20 @@ static ngx_command_t ngx_http_fastcgi_commands[] = {
offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_methods),
&ngx_http_upstream_cache_method_mask },
+ { ngx_string("fastcgi_cache_lock"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+ ngx_conf_set_flag_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_lock),
+ NULL },
+
+ { ngx_string("fastcgi_cache_lock_timeout"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_msec_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_lock_timeout),
+ NULL },
+
#endif
{ ngx_string("fastcgi_temp_path"),
@@ -2086,6 +2100,8 @@ ngx_http_fastcgi_create_loc_conf(ngx_conf_t *cf)
conf->upstream.cache_bypass = NGX_CONF_UNSET_PTR;
conf->upstream.no_cache = NGX_CONF_UNSET_PTR;
conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
+ conf->upstream.cache_lock = NGX_CONF_UNSET;
+ conf->upstream.cache_lock_timeout = NGX_CONF_UNSET_MSEC;
#endif
conf->upstream.hide_headers = NGX_CONF_UNSET_PTR;
@@ -2323,6 +2339,12 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
conf->cache_key = prev->cache_key;
}
+ ngx_conf_merge_value(conf->upstream.cache_lock,
+ prev->upstream.cache_lock, 0);
+
+ ngx_conf_merge_msec_value(conf->upstream.cache_lock_timeout,
+ prev->upstream.cache_lock_timeout, 5000);
+
#endif
ngx_conf_merge_value(conf->upstream.pass_request_headers,
diff --git a/src/http/modules/ngx_http_limit_conn_module.c b/src/http/modules/ngx_http_limit_conn_module.c
index a84d54d7e..40f05a22e 100644
--- a/src/http/modules/ngx_http_limit_conn_module.c
+++ b/src/http/modules/ngx_http_limit_conn_module.c
@@ -483,7 +483,7 @@ ngx_http_limit_conn_merge_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_http_limit_conn_conf_t *conf = child;
if (conf->limits.elts == NULL) {
- *conf = *prev;
+ conf->limits = prev->limits;
}
ngx_conf_merge_uint_value(conf->log_level, prev->log_level, NGX_LOG_ERR);
diff --git a/src/http/modules/ngx_http_limit_req_module.c b/src/http/modules/ngx_http_limit_req_module.c
index 718fae8e2..865f7666d 100644
--- a/src/http/modules/ngx_http_limit_req_module.c
+++ b/src/http/modules/ngx_http_limit_req_module.c
@@ -569,7 +569,7 @@ ngx_http_limit_req_merge_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_http_limit_req_conf_t *conf = child;
if (conf->shm_zone == NULL) {
- *conf = *prev;
+ conf->shm_zone = prev->shm_zone;
}
ngx_conf_merge_uint_value(conf->limit_log_level, prev->limit_log_level,
diff --git a/src/http/modules/ngx_http_mp4_module.c b/src/http/modules/ngx_http_mp4_module.c
index 3c9f88cfc..7bfb3db66 100644
--- a/src/http/modules/ngx_http_mp4_module.c
+++ b/src/http/modules/ngx_http_mp4_module.c
@@ -2382,6 +2382,8 @@ found:
data->pos = (u_char *) entry;
atom_size = sizeof(ngx_mp4_stsc_atom_t) + (data->last - data->pos);
+ ngx_mp4_set_32value(entry->chunk, 1);
+
if (trak->chunk_samples) {
first = &trak->stsc_chunk_entry;
diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c
index 5ce875f62..b65093b72 100644
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -402,6 +402,20 @@ static ngx_command_t ngx_http_proxy_commands[] = {
offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_methods),
&ngx_http_upstream_cache_method_mask },
+ { ngx_string("proxy_cache_lock"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+ ngx_conf_set_flag_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_lock),
+ NULL },
+
+ { ngx_string("proxy_cache_lock_timeout"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_msec_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_lock_timeout),
+ NULL },
+
#endif
{ ngx_string("proxy_temp_path"),
@@ -736,9 +750,6 @@ ngx_http_proxy_eval(ngx_http_request_t *r, ngx_http_proxy_ctx_t *ctx,
url.uri.len++;
url.uri.data = p - 1;
}
-
- } else {
- url.uri = r->unparsed_uri;
}
ctx->vars.key_start = u->schema;
@@ -806,7 +817,7 @@ ngx_http_proxy_create_key(ngx_http_request_t *r)
return NGX_ERROR;
}
- if (plcf->proxy_lengths) {
+ if (plcf->proxy_lengths && ctx->vars.uri.len) {
*key = ctx->vars.uri;
u->uri = ctx->vars.uri;
@@ -916,7 +927,7 @@ ngx_http_proxy_create_request(ngx_http_request_t *r)
loc_len = 0;
unparsed_uri = 0;
- if (plcf->proxy_lengths) {
+ if (plcf->proxy_lengths && ctx->vars.uri.len) {
uri_len = ctx->vars.uri.len;
} else if (ctx->vars.uri.len == 0 && r->valid_unparsed_uri && r == r->main)
@@ -1022,7 +1033,7 @@ ngx_http_proxy_create_request(ngx_http_request_t *r)
u->uri.data = b->last;
- if (plcf->proxy_lengths) {
+ if (plcf->proxy_lengths && ctx->vars.uri.len) {
b->last = ngx_copy(b->last, ctx->vars.uri.data, ctx->vars.uri.len);
} else if (unparsed_uri) {
@@ -2438,6 +2449,8 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
conf->upstream.cache_bypass = NGX_CONF_UNSET_PTR;
conf->upstream.no_cache = NGX_CONF_UNSET_PTR;
conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
+ conf->upstream.cache_lock = NGX_CONF_UNSET;
+ conf->upstream.cache_lock_timeout = NGX_CONF_UNSET_MSEC;
#endif
conf->upstream.hide_headers = NGX_CONF_UNSET_PTR;
@@ -2684,6 +2697,12 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
conf->cache_key = prev->cache_key;
}
+ ngx_conf_merge_value(conf->upstream.cache_lock,
+ prev->upstream.cache_lock, 0);
+
+ ngx_conf_merge_msec_value(conf->upstream.cache_lock_timeout,
+ prev->upstream.cache_lock_timeout, 5000);
+
#endif
if (conf->method.len == 0) {
diff --git a/src/http/modules/ngx_http_scgi_module.c b/src/http/modules/ngx_http_scgi_module.c
index 41cf23bc6..9fd60147e 100644
--- a/src/http/modules/ngx_http_scgi_module.c
+++ b/src/http/modules/ngx_http_scgi_module.c
@@ -36,7 +36,6 @@ static ngx_int_t ngx_http_scgi_create_request(ngx_http_request_t *r);
static ngx_int_t ngx_http_scgi_reinit_request(ngx_http_request_t *r);
static ngx_int_t ngx_http_scgi_process_status_line(ngx_http_request_t *r);
static ngx_int_t ngx_http_scgi_process_header(ngx_http_request_t *r);
-static ngx_int_t ngx_http_scgi_process_header(ngx_http_request_t *r);
static void ngx_http_scgi_abort_request(ngx_http_request_t *r);
static void ngx_http_scgi_finalize_request(ngx_http_request_t *r, ngx_int_t rc);
@@ -247,6 +246,20 @@ static ngx_command_t ngx_http_scgi_commands[] = {
offsetof(ngx_http_scgi_loc_conf_t, upstream.cache_methods),
&ngx_http_upstream_cache_method_mask },
+ { ngx_string("scgi_cache_lock"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+ ngx_conf_set_flag_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_scgi_loc_conf_t, upstream.cache_lock),
+ NULL },
+
+ { ngx_string("scgi_cache_lock_timeout"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_msec_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_scgi_loc_conf_t, upstream.cache_lock_timeout),
+ NULL },
+
#endif
{ ngx_string("scgi_temp_path"),
@@ -857,11 +870,7 @@ ngx_http_scgi_process_status_line(ngx_http_request_t *r)
}
if (rc == NGX_ERROR) {
-
- r->http_version = NGX_HTTP_VERSION_9;
-
u->process_header = ngx_http_scgi_process_header;
-
return ngx_http_scgi_process_header(r);
}
@@ -961,12 +970,12 @@ ngx_http_scgi_process_header(ngx_http_request_t *r)
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http scgi header done");
- if (r->http_version > NGX_HTTP_VERSION_9) {
+ u = r->upstream;
+
+ if (u->headers_in.status_n) {
return NGX_OK;
}
- u = r->upstream;
-
if (u->headers_in.status) {
status_line = &u->headers_in.status->value;
@@ -978,20 +987,15 @@ ngx_http_scgi_process_header(ngx_http_request_t *r)
return NGX_HTTP_UPSTREAM_INVALID_HEADER;
}
- r->http_version = NGX_HTTP_VERSION_10;
u->headers_in.status_n = status;
u->headers_in.status_line = *status_line;
} else if (u->headers_in.location) {
- r->http_version = NGX_HTTP_VERSION_10;
u->headers_in.status_n = 302;
ngx_str_set(&u->headers_in.status_line,
"302 Moved Temporarily");
} else {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent neither valid HTTP/1.0 header "
- "nor \"Status\" header line");
u->headers_in.status_n = 200;
ngx_str_set(&u->headers_in.status_line, "200 OK");
}
@@ -1072,6 +1076,8 @@ ngx_http_scgi_create_loc_conf(ngx_conf_t *cf)
conf->upstream.cache_bypass = NGX_CONF_UNSET_PTR;
conf->upstream.no_cache = NGX_CONF_UNSET_PTR;
conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
+ conf->upstream.cache_lock = NGX_CONF_UNSET;
+ conf->upstream.cache_lock_timeout = NGX_CONF_UNSET_MSEC;
#endif
conf->upstream.hide_headers = NGX_CONF_UNSET_PTR;
@@ -1299,6 +1305,12 @@ ngx_http_scgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
conf->cache_key = prev->cache_key;
}
+ ngx_conf_merge_value(conf->upstream.cache_lock,
+ prev->upstream.cache_lock, 0);
+
+ ngx_conf_merge_msec_value(conf->upstream.cache_lock_timeout,
+ prev->upstream.cache_lock_timeout, 5000);
+
#endif
ngx_conf_merge_value(conf->upstream.pass_request_headers,
diff --git a/src/http/modules/ngx_http_ssi_filter_module.c b/src/http/modules/ngx_http_ssi_filter_module.c
index 0b8bc9bf8..e33782166 100644
--- a/src/http/modules/ngx_http_ssi_filter_module.c
+++ b/src/http/modules/ngx_http_ssi_filter_module.c
@@ -78,6 +78,8 @@ static ngx_str_t *ngx_http_ssi_get_variable(ngx_http_request_t *r,
ngx_str_t *name, ngx_uint_t key);
static ngx_int_t ngx_http_ssi_evaluate_string(ngx_http_request_t *r,
ngx_http_ssi_ctx_t *ctx, ngx_str_t *text, ngx_uint_t flags);
+static ngx_int_t ngx_http_ssi_regex_match(ngx_http_request_t *r,
+ ngx_str_t *pattern, ngx_str_t *str);
static ngx_int_t ngx_http_ssi_include(ngx_http_request_t *r,
ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
@@ -624,16 +626,6 @@ ngx_http_ssi_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
continue;
}
- if (cmd->conditional
- && (ctx->conditional == 0
- || ctx->conditional > cmd->conditional))
- {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "invalid context of SSI command: \"%V\"",
- &ctx->command);
- goto ssi_error;
- }
-
if (!ctx->output && !cmd->block) {
if (ctx->block) {
@@ -709,6 +701,16 @@ ngx_http_ssi_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
}
}
+ if (cmd->conditional
+ && (ctx->conditional == 0
+ || ctx->conditional > cmd->conditional))
+ {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "invalid context of SSI command: \"%V\"",
+ &ctx->command);
+ goto ssi_error;
+ }
+
if (ctx->params.nelts > NGX_HTTP_SSI_MAX_PARAMS) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"too many SSI command paramters: \"%V\"",
@@ -1531,6 +1533,30 @@ ngx_http_ssi_get_variable(ngx_http_request_t *r, ngx_str_t *name,
ctx = ngx_http_get_module_ctx(r->main, ngx_http_ssi_filter_module);
+#if (NGX_PCRE)
+ {
+ ngx_str_t *value;
+
+ if (key >= '0' && key <= '9') {
+ i = key - '0';
+
+ if (i < ctx->ncaptures) {
+ value = ngx_palloc(r->pool, sizeof(ngx_str_t));
+ if (value == NULL) {
+ return NULL;
+ }
+
+ i *= 2;
+
+ value->data = ctx->captures_data + ctx->captures[i];
+ value->len = ctx->captures[i + 1] - ctx->captures[i];
+
+ return value;
+ }
+ }
+ }
+#endif
+
if (ctx->variables == NULL) {
return NULL;
}
@@ -1820,6 +1846,115 @@ invalid_variable:
static ngx_int_t
+ngx_http_ssi_regex_match(ngx_http_request_t *r, ngx_str_t *pattern,
+ ngx_str_t *str)
+{
+#if (NGX_PCRE)
+ int rc, *captures;
+ u_char *p, errstr[NGX_MAX_CONF_ERRSTR];
+ size_t size;
+ ngx_int_t key;
+ ngx_str_t *vv, name, value;
+ ngx_uint_t i, n;
+ ngx_http_ssi_ctx_t *ctx;
+ ngx_http_ssi_var_t *var;
+ ngx_regex_compile_t rgc;
+
+ ngx_memzero(&rgc, sizeof(ngx_regex_compile_t));
+
+ rgc.pattern = *pattern;
+ rgc.pool = r->pool;
+ rgc.err.len = NGX_MAX_CONF_ERRSTR;
+ rgc.err.data = errstr;
+
+ if (ngx_regex_compile(&rgc) != NGX_OK) {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%V", &rgc.err);
+ return NGX_HTTP_SSI_ERROR;
+ }
+
+ n = (rgc.captures + 1) * 3;
+
+ captures = ngx_palloc(r->pool, n * sizeof(int));
+ if (captures == NULL) {
+ return NGX_ERROR;
+ }
+
+ rc = ngx_regex_exec(rgc.regex, str, captures, n);
+
+ if (rc < NGX_REGEX_NO_MATCHED) {
+ ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+ ngx_regex_exec_n " failed: %i on \"%V\" using \"%V\"",
+ rc, str, pattern);
+ return NGX_HTTP_SSI_ERROR;
+ }
+
+ if (rc == NGX_REGEX_NO_MATCHED) {
+ return NGX_DECLINED;
+ }
+
+ ctx = ngx_http_get_module_ctx(r->main, ngx_http_ssi_filter_module);
+
+ ctx->ncaptures = rc;
+ ctx->captures = captures;
+ ctx->captures_data = str->data;
+
+ if (rgc.named_captures > 0) {
+
+ if (ctx->variables == NULL) {
+ ctx->variables = ngx_list_create(r->pool, 4,
+ sizeof(ngx_http_ssi_var_t));
+ if (ctx->variables == NULL) {
+ return NGX_ERROR;
+ }
+ }
+
+ size = rgc.name_size;
+ p = rgc.names;
+
+ for (i = 0; i < (ngx_uint_t) rgc.named_captures; i++, p += size) {
+
+ name.data = &p[2];
+ name.len = ngx_strlen(name.data);
+
+ n = 2 * ((p[0] << 8) + p[1]);
+
+ value.data = &str->data[captures[n]];
+ value.len = captures[n + 1] - captures[n];
+
+ key = ngx_hash_strlow(name.data, name.data, name.len);
+
+ vv = ngx_http_ssi_get_variable(r, &name, key);
+
+ if (vv) {
+ *vv = value;
+ continue;
+ }
+
+ var = ngx_list_push(ctx->variables);
+ if (var == NULL) {
+ return NGX_ERROR;
+ }
+
+ var->name = name;
+ var->key = key;
+ var->value = value;
+ }
+ }
+
+ return NGX_OK;
+
+#else
+
+ ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+ "the using of the regex \"%V\" in SSI requires PCRE library",
+ pattern);
+ return NGX_HTTP_SSI_ERROR;
+
+#endif
+}
+
+
+static ngx_int_t
ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
ngx_str_t **params)
{
@@ -2451,39 +2586,17 @@ ngx_http_ssi_if(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
}
} else {
-#if (NGX_PCRE)
- ngx_regex_compile_t rgc;
- u_char errstr[NGX_MAX_CONF_ERRSTR];
-
right.data[right.len] = '\0';
- ngx_memzero(&rgc, sizeof(ngx_regex_compile_t));
-
- rgc.pattern = right;
- rgc.pool = r->pool;
- rgc.err.len = NGX_MAX_CONF_ERRSTR;
- rgc.err.data = errstr;
-
- if (ngx_regex_compile(&rgc) != NGX_OK) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%V", &rgc.err);
- return NGX_HTTP_SSI_ERROR;
- }
+ rc = ngx_http_ssi_regex_match(r, &right, &left);
- rc = ngx_regex_exec(rgc.regex, &left, NULL, 0);
-
- if (rc < NGX_REGEX_NO_MATCHED) {
- ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
- ngx_regex_exec_n " failed: %i on \"%V\" using \"%V\"",
- rc, &left, &right);
- return NGX_HTTP_SSI_ERROR;
+ if (rc == NGX_OK) {
+ rc = 0;
+ } else if (rc == NGX_DECLINED) {
+ rc = -1;
+ } else {
+ return rc;
}
-#else
- ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
- "the using of the regex \"%V\" in SSI "
- "requires PCRE library", &right);
-
- return NGX_HTTP_SSI_ERROR;
-#endif
}
if ((rc == 0 && !negative) || (rc != 0 && negative)) {
diff --git a/src/http/modules/ngx_http_ssi_filter_module.h b/src/http/modules/ngx_http_ssi_filter_module.h
index 6ab18841c..2b0018662 100644
--- a/src/http/modules/ngx_http_ssi_filter_module.h
+++ b/src/http/modules/ngx_http_ssi_filter_module.h
@@ -64,6 +64,12 @@ typedef struct {
ngx_list_t *variables;
ngx_array_t *blocks;
+#if (NGX_PCRE)
+ ngx_uint_t ncaptures;
+ int *captures;
+ u_char *captures_data;
+#endif
+
unsigned conditional:2;
unsigned encoding:2;
unsigned block:1;
diff --git a/src/http/modules/ngx_http_uwsgi_module.c b/src/http/modules/ngx_http_uwsgi_module.c
index 2916a5916..86959b3e3 100644
--- a/src/http/modules/ngx_http_uwsgi_module.c
+++ b/src/http/modules/ngx_http_uwsgi_module.c
@@ -274,6 +274,20 @@ static ngx_command_t ngx_http_uwsgi_commands[] = {
offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_methods),
&ngx_http_upstream_cache_method_mask },
+ { ngx_string("uwsgi_cache_lock"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+ ngx_conf_set_flag_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_lock),
+ NULL },
+
+ { ngx_string("uwsgi_cache_lock_timeout"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_msec_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_lock_timeout),
+ NULL },
+
#endif
{ ngx_string("uwsgi_temp_path"),
@@ -1114,6 +1128,8 @@ ngx_http_uwsgi_create_loc_conf(ngx_conf_t *cf)
conf->upstream.cache_bypass = NGX_CONF_UNSET_PTR;
conf->upstream.no_cache = NGX_CONF_UNSET_PTR;
conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
+ conf->upstream.cache_lock = NGX_CONF_UNSET;
+ conf->upstream.cache_lock_timeout = NGX_CONF_UNSET_MSEC;
#endif
conf->upstream.hide_headers = NGX_CONF_UNSET_PTR;
@@ -1341,6 +1357,12 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
conf->cache_key = prev->cache_key;
}
+ ngx_conf_merge_value(conf->upstream.cache_lock,
+ prev->upstream.cache_lock, 0);
+
+ ngx_conf_merge_msec_value(conf->upstream.cache_lock_timeout,
+ prev->upstream.cache_lock_timeout, 5000);
+
#endif
ngx_conf_merge_value(conf->upstream.pass_request_headers,
diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm
index ec49d7bad..8cd3b7469 100644
--- a/src/http/modules/perl/nginx.pm
+++ b/src/http/modules/perl/nginx.pm
@@ -48,7 +48,7 @@ our @EXPORT = qw(
HTTP_INSUFFICIENT_STORAGE
);
-our $VERSION = '1.1.11';
+our $VERSION = '1.1.12';
require XSLoader;
XSLoader::load('nginx', $VERSION);
diff --git a/src/http/ngx_http_cache.h b/src/http/ngx_http_cache.h
index bd02100da..ae8b8c376 100644
--- a/src/http/ngx_http_cache.h
+++ b/src/http/ngx_http_cache.h
@@ -79,6 +79,14 @@ struct ngx_http_cache_s {
ngx_http_file_cache_t *file_cache;
ngx_http_file_cache_node_t *node;
+ ngx_msec_t lock_timeout;
+ ngx_msec_t wait_time;
+
+ ngx_event_t wait_event;
+
+ unsigned lock:1;
+ unsigned waiting:1;
+
unsigned updated:1;
unsigned updating:1;
unsigned exists:1;
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index 3c5711748..1d5ee5dc6 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -2506,6 +2506,7 @@ ngx_http_internal_redirect(ngx_http_request_t *r,
#endif
r->internal = 1;
+ r->valid_unparsed_uri = 0;
r->add_uri_to_alias = 0;
r->main->count++;
diff --git a/src/http/ngx_http_file_cache.c b/src/http/ngx_http_file_cache.c
index 050f356f1..dccbbac68 100644
--- a/src/http/ngx_http_file_cache.c
+++ b/src/http/ngx_http_file_cache.c
@@ -10,6 +10,9 @@
#include <ngx_md5.h>
+static ngx_int_t ngx_http_file_cache_lock(ngx_http_request_t *r,
+ ngx_http_cache_t *c);
+static void ngx_http_file_cache_lock_wait_handler(ngx_event_t *ev);
static ngx_int_t ngx_http_file_cache_read(ngx_http_request_t *r,
ngx_http_cache_t *c);
static ssize_t ngx_http_file_cache_aio_read(ngx_http_request_t *r,
@@ -181,13 +184,13 @@ ngx_http_file_cache_create(ngx_http_request_t *r)
return NGX_ERROR;
}
+ cln->handler = ngx_http_file_cache_cleanup;
+ cln->data = c;
+
if (ngx_http_file_cache_exists(cache, c) == NGX_ERROR) {
return NGX_ERROR;
}
- cln->handler = ngx_http_file_cache_cleanup;
- cln->data = c;
-
if (ngx_http_file_cache_name(r, cache->path) != NGX_OK) {
return NGX_ERROR;
}
@@ -244,15 +247,24 @@ ngx_http_file_cache_open(ngx_http_request_t *r)
c = r->cache;
+ if (c->waiting) {
+ return NGX_AGAIN;
+ }
+
if (c->buf) {
return ngx_http_file_cache_read(r, c);
}
cache = c->file_cache;
- cln = ngx_pool_cleanup_add(r->pool, 0);
- if (cln == NULL) {
- return NGX_ERROR;
+ if (c->node == NULL) {
+ cln = ngx_pool_cleanup_add(r->pool, 0);
+ if (cln == NULL) {
+ return NGX_ERROR;
+ }
+
+ cln->handler = ngx_http_file_cache_cleanup;
+ cln->data = c;
}
rc = ngx_http_file_cache_exists(cache, c);
@@ -264,9 +276,6 @@ ngx_http_file_cache_open(ngx_http_request_t *r)
return rc;
}
- cln->handler = ngx_http_file_cache_cleanup;
- cln->data = c;
-
if (rc == NGX_AGAIN) {
return NGX_HTTP_CACHE_SCARCE;
}
@@ -306,7 +315,7 @@ ngx_http_file_cache_open(ngx_http_request_t *r)
}
if (!test) {
- return NGX_DECLINED;
+ goto done;
}
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
@@ -330,7 +339,7 @@ ngx_http_file_cache_open(ngx_http_request_t *r)
case NGX_ENOENT:
case NGX_ENOTDIR:
- return rv;
+ goto done;
default:
ngx_log_error(NGX_LOG_CRIT, r->connection->log, of.err,
@@ -354,6 +363,114 @@ ngx_http_file_cache_open(ngx_http_request_t *r)
}
return ngx_http_file_cache_read(r, c);
+
+done:
+
+ if (rv == NGX_DECLINED) {
+ return ngx_http_file_cache_lock(r, c);
+ }
+
+ return rv;
+}
+
+
+static ngx_int_t
+ngx_http_file_cache_lock(ngx_http_request_t *r, ngx_http_cache_t *c)
+{
+ ngx_msec_t now, timer;
+ ngx_http_file_cache_t *cache;
+
+ if (!c->lock) {
+ return NGX_DECLINED;
+ }
+
+ cache = c->file_cache;
+
+ ngx_shmtx_lock(&cache->shpool->mutex);
+
+ if (!c->node->updating) {
+ c->node->updating = 1;
+ c->updating = 1;
+ }
+
+ ngx_shmtx_unlock(&cache->shpool->mutex);
+
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http file cache lock u:%d wt:%M",
+ c->updating, c->wait_time);
+
+ if (c->updating) {
+ return NGX_DECLINED;
+ }
+
+ c->waiting = 1;
+
+ now = ngx_current_msec;
+
+ if (c->wait_time == 0) {
+ c->wait_time = now + c->lock_timeout;
+
+ c->wait_event.handler = ngx_http_file_cache_lock_wait_handler;
+ c->wait_event.data = r;
+ c->wait_event.log = r->connection->log;
+ }
+
+ timer = c->wait_time - now;
+
+ ngx_add_timer(&c->wait_event, (timer > 500) ? 500 : timer);
+
+ r->main->blocked++;
+
+ return NGX_AGAIN;
+}
+
+
+static void
+ngx_http_file_cache_lock_wait_handler(ngx_event_t *ev)
+{
+ ngx_uint_t wait;
+ ngx_msec_t timer;
+ ngx_http_cache_t *c;
+ ngx_http_request_t *r;
+ ngx_http_file_cache_t *cache;
+
+ r = ev->data;
+ c = r->cache;
+
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, ev->log, 0,
+ "http file cache wait handler wt:%M cur:%M",
+ c->wait_time, ngx_current_msec);
+
+ timer = c->wait_time - ngx_current_msec;
+
+ if ((ngx_msec_int_t) timer <= 0) {
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ev->log, 0,
+ "http file cache lock timeout");
+ c->lock = 0;
+ goto wakeup;
+ }
+
+ cache = c->file_cache;
+ wait = 0;
+
+ ngx_shmtx_lock(&cache->shpool->mutex);
+
+ if (c->node->updating) {
+ wait = 1;
+ }
+
+ ngx_shmtx_unlock(&cache->shpool->mutex);
+
+ if (wait) {
+ ngx_add_timer(ev, (timer > 500) ? 500 : timer);
+ return;
+ }
+
+wakeup:
+
+ c->waiting = 0;
+ r->main->blocked--;
+ r->connection->write->handler(r->connection->write);
}
@@ -518,13 +635,19 @@ ngx_http_file_cache_exists(ngx_http_file_cache_t *cache, ngx_http_cache_t *c)
ngx_shmtx_lock(&cache->shpool->mutex);
- fcn = ngx_http_file_cache_lookup(cache, c->key);
+ fcn = c->node;
+
+ if (fcn == NULL) {
+ fcn = ngx_http_file_cache_lookup(cache, c->key);
+ }
if (fcn) {
ngx_queue_remove(&fcn->queue);
- fcn->uses++;
- fcn->count++;
+ if (c->node == NULL) {
+ fcn->uses++;
+ fcn->count++;
+ }
if (fcn->error) {
@@ -621,6 +744,10 @@ ngx_http_file_cache_name(ngx_http_request_t *r, ngx_path_t *path)
c = r->cache;
+ if (c->file.name.len) {
+ return NGX_OK;
+ }
+
c->file.name.len = path->name.len + 1 + path->len
+ 2 * NGX_HTTP_CACHE_KEY_LEN;
@@ -957,6 +1084,10 @@ ngx_http_file_cache_free(ngx_http_cache_t *c, ngx_temp_file_t *tf)
}
}
}
+
+ if (c->wait_event.timer_set) {
+ ngx_del_timer(&c->wait_event);
+ }
}
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index 9f0ff3a54..781ef1f96 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -707,6 +707,9 @@ ngx_http_upstream_cache(ngx_http_request_t *r, ngx_http_upstream_t *u)
c->body_start = u->conf->buffer_size;
c->file_cache = u->conf->cache->data;
+ c->lock = u->conf->cache_lock;
+ c->lock_timeout = u->conf->cache_lock_timeout;
+
u->cache_status = NGX_HTTP_CACHE_MISS;
}
@@ -1895,8 +1898,6 @@ ngx_http_upstream_process_headers(ngx_http_request_t *r, ngx_http_upstream_t *u)
r->method = NGX_HTTP_GET;
}
- r->valid_unparsed_uri = 0;
-
ngx_http_internal_redirect(r, uri, &args);
ngx_http_finalize_request(r, NGX_DONE);
return NGX_DONE;
diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h
index fa93be69f..62cbf533e 100644
--- a/src/http/ngx_http_upstream.h
+++ b/src/http/ngx_http_upstream.h
@@ -165,6 +165,9 @@ typedef struct {
ngx_uint_t cache_use_stale;
ngx_uint_t cache_methods;
+ ngx_flag_t cache_lock;
+ ngx_msec_t cache_lock_timeout;
+
ngx_array_t *cache_valid;
ngx_array_t *cache_bypass;
ngx_array_t *no_cache;
diff --git a/src/http/ngx_http_write_filter_module.c b/src/http/ngx_http_write_filter_module.c
index 46351349c..a9660ee1f 100644
--- a/src/http/ngx_http_write_filter_module.c
+++ b/src/http/ngx_http_write_filter_module.c
@@ -223,11 +223,14 @@ ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
return NGX_AGAIN;
}
- } else if (clcf->sendfile_max_chunk) {
- limit = clcf->sendfile_max_chunk;
+ if (clcf->sendfile_max_chunk
+ && (off_t) clcf->sendfile_max_chunk < limit)
+ {
+ limit = clcf->sendfile_max_chunk;
+ }
} else {
- limit = 0;
+ limit = clcf->sendfile_max_chunk;
}
sent = c->sent;
@@ -262,17 +265,18 @@ ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
}
}
- delay = (ngx_msec_t) ((nsent - sent) * 1000 / r->limit_rate + 1);
+ delay = (ngx_msec_t) ((nsent - sent) * 1000 / r->limit_rate);
if (delay > 0) {
+ limit = 0;
c->write->delayed = 1;
ngx_add_timer(c->write, delay);
}
+ }
- } else if (c->write->ready
- && clcf->sendfile_max_chunk
- && (size_t) (c->sent - sent)
- >= clcf->sendfile_max_chunk - 2 * ngx_pagesize)
+ if (limit
+ && c->write->ready
+ && c->sent - sent >= limit - (off_t) (2 * ngx_pagesize))
{
c->write->delayed = 1;
ngx_add_timer(c->write, 1);