# HG changeset patch # User Igor Sysoev # Date 1245355200 -14400 # Node ID f0cac61857ae53b080bb44fa899762c901079dee # Parent 531b6bbae52966e6c59105213920c2c30ccbbe1d nginx 0.8.3 *) Feature: the $upstream_cache_status variable. *) Bugfix: nginx could not be built on MacOSX 10.6. the bug had appeared in 0.8.2. *) Bugfix: nginx could not be built --without-http-cache; the bug had appeared in 0.8.2. *) Bugfix: a segmentation fault occurred in worker process, if a backend 401 error was intercepted and the backend did not set the "WWW-Authenticate" response header line. Thanks to Eugene Mychlo. diff --git a/CHANGES b/CHANGES --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,20 @@ +Changes with nginx 0.8.2 19 Jun 2009 + + *) Feature: the $upstream_cache_status variable. + + *) Bugfix: nginx could not be built on MacOSX 10.6. the bug had + appeared in 0.8.2. + + *) Bugfix: nginx could not be built --without-http-cache; the bug had + appeared in 0.8.2. + + *) Bugfix: a segmentation fault occurred in worker process, if a + backend 401 error was intercepted and the backend did not set the + "WWW-Authenticate" response header line. + Thanks to Eugene Mychlo. + + Changes with nginx 0.8.2 15 Jun 2009 *) Bugfix: in open_file_cache and proxy/fastcgi cache interaction on diff --git a/CHANGES.ru b/CHANGES.ru --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,19 @@ +Изменения в nginx 0.8.2 19.06.2009 + + *) Добавление: переменная $upstream_cache_status. + + *) Исправление: nginx не собирался на MacOSX 10.6. + + *) Исправление: nginx не собирался с параметром --without-http-cache; + ошибка появилась в 0.8.2. + + *) Исправление: если было использовался перехват 401 ошибки от бэкенда + и бэкенд не возвращал строку "WWW-Authenticate" в заголовке ответа, + то в рабочем процессе происходил segmentation fault. + Спасибо Евгению Мычло. + + Изменения в nginx 0.8.2 15.06.2009 *) Исправление: во взаимодействии open_file_cache и proxy/fastcgi кэша diff --git a/auto/lib/md5/conf b/auto/lib/md5/conf --- a/auto/lib/md5/conf +++ b/auto/lib/md5/conf @@ -100,9 +100,9 @@ cat << END $0: error: the HTTP cache module requires md5 functions from OpenSSL library. You can either disable the module by using ---without-http_cache option, or install the OpenSSL library into the system, +--without-http-cache option, or install the OpenSSL library into the system, or build the OpenSSL library statically from the source with nginx by using ---with-openssl= option. +--with-http_ssl_module --with-openssl= options. END exit 1 diff --git a/src/core/nginx.h b/src/core/nginx.h --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -8,8 +8,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 8002 -#define NGINX_VERSION "0.8.2" +#define nginx_version 8003 +#define NGINX_VERSION "0.8.3" #define NGINX_VER "nginx/" NGINX_VERSION #define NGINX_VAR "NGINX" diff --git a/src/event/ngx_event_accept.c b/src/event/ngx_event_accept.c --- a/src/event/ngx_event_accept.c +++ b/src/event/ngx_event_accept.c @@ -75,7 +75,7 @@ ngx_event_accept(ngx_event_t *ev) } #if (NGX_STAT_STUB) - ngx_atomic_fetch_add(ngx_stat_accepted, 1); + (void) ngx_atomic_fetch_add(ngx_stat_accepted, 1); #endif ngx_accept_disabled = ngx_cycle->connection_n / 8 @@ -93,7 +93,7 @@ ngx_event_accept(ngx_event_t *ev) } #if (NGX_STAT_STUB) - ngx_atomic_fetch_add(ngx_stat_active, 1); + (void) ngx_atomic_fetch_add(ngx_stat_active, 1); #endif c->pool = ngx_create_pool(ls->pool_size, ev->log); @@ -188,7 +188,7 @@ ngx_event_accept(ngx_event_t *ev) c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1); #if (NGX_STAT_STUB) - ngx_atomic_fetch_add(ngx_stat_handled, 1); + (void) ngx_atomic_fetch_add(ngx_stat_handled, 1); #endif #if (NGX_THREADS) @@ -379,7 +379,7 @@ ngx_close_accepted_connection(ngx_connec } #if (NGX_STAT_STUB) - ngx_atomic_fetch_add(ngx_stat_active, -1); + (void) ngx_atomic_fetch_add(ngx_stat_active, -1); #endif } 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 @@ -2343,7 +2343,10 @@ ngx_http_proxy_merge_headers(ngx_conf_t } if (conf->headers_set_hash.buckets - && ((conf->upstream.cache == NULL) == (prev->upstream.cache == NULL))) +#if (NGX_HTTP_CACHE) + && ((conf->upstream.cache == NULL) == (prev->upstream.cache == NULL)) +#endif + ) { return NGX_OK; } 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.8.2'; +our $VERSION = '0.8.3'; require XSLoader; XSLoader::load('nginx', $VERSION); 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 @@ -13,8 +13,11 @@ #include -#define NGX_HTTP_CACHE_STALE 1 -#define NGX_HTTP_CACHE_UPDATING 2 +#define NGX_HTTP_CACHE_MISS 1 +#define NGX_HTTP_CACHE_EXPIRED 2 +#define NGX_HTTP_CACHE_STALE 3 +#define NGX_HTTP_CACHE_UPDATING 4 +#define NGX_HTTP_CACHE_HIT 5 #define NGX_HTTP_CACHE_KEY_LEN 16 @@ -124,11 +127,12 @@ ngx_int_t ngx_http_cache_send(ngx_http_r void ngx_http_file_cache_free(ngx_http_request_t *r, ngx_temp_file_t *tf); time_t ngx_http_file_cache_valid(ngx_array_t *cache_valid, ngx_uint_t status); - char *ngx_http_file_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); char *ngx_http_file_cache_valid_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +extern ngx_str_t ngx_http_cache_status[]; + #endif /* _NGX_HTTP_CACHE_H_INCLUDED_ */ 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 @@ -35,6 +35,15 @@ static ngx_int_t ngx_http_file_cache_del ngx_str_t *path); +ngx_str_t ngx_http_cache_status[] = { + ngx_string("MISS"), + ngx_string("EXPIRED"), + ngx_string("STALE"), + ngx_string("UPDATING"), + ngx_string("HIT") +}; + + static u_char ngx_http_file_cache_key[] = { LF, 'K', 'E', 'Y', ':', ' ' }; diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -198,7 +198,7 @@ ngx_http_init_connection(ngx_connection_ c->write->handler = ngx_http_empty_handler; #if (NGX_STAT_STUB) - ngx_atomic_fetch_add(ngx_stat_reading, 1); + (void) ngx_atomic_fetch_add(ngx_stat_reading, 1); #endif if (rev->ready) { @@ -217,7 +217,7 @@ ngx_http_init_connection(ngx_connection_ if (ngx_handle_read_event(rev, 0) != NGX_OK) { #if (NGX_STAT_STUB) - ngx_atomic_fetch_add(ngx_stat_reading, -1); + (void) ngx_atomic_fetch_add(ngx_stat_reading, -1); #endif ngx_http_close_connection(c); return; @@ -247,7 +247,7 @@ ngx_http_init_request(ngx_event_t *rev) #endif #if (NGX_STAT_STUB) - ngx_atomic_fetch_add(ngx_stat_reading, -1); + (void) ngx_atomic_fetch_add(ngx_stat_reading, -1); #endif c = rev->data; @@ -500,9 +500,9 @@ ngx_http_init_request(ngx_event_t *rev) r->log_handler = ngx_http_log_error_handler; #if (NGX_STAT_STUB) - ngx_atomic_fetch_add(ngx_stat_reading, 1); + (void) ngx_atomic_fetch_add(ngx_stat_reading, 1); r->stat_reading = 1; - ngx_atomic_fetch_add(ngx_stat_requests, 1); + (void) ngx_atomic_fetch_add(ngx_stat_requests, 1); #endif rev->handler(rev); @@ -1547,9 +1547,9 @@ ngx_http_process_request(ngx_http_reques } #if (NGX_STAT_STUB) - ngx_atomic_fetch_add(ngx_stat_reading, -1); + (void) ngx_atomic_fetch_add(ngx_stat_reading, -1); r->stat_reading = 0; - ngx_atomic_fetch_add(ngx_stat_writing, 1); + (void) ngx_atomic_fetch_add(ngx_stat_writing, 1); r->stat_writing = 1; #endif @@ -2319,7 +2319,7 @@ ngx_http_set_keepalive(ngx_http_request_ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "pipelined request"); #if (NGX_STAT_STUB) - ngx_atomic_fetch_add(ngx_stat_reading, 1); + (void) ngx_atomic_fetch_add(ngx_stat_reading, 1); #endif hc->pipeline = 1; @@ -2549,7 +2549,7 @@ ngx_http_keepalive_handler(ngx_event_t * b->last += n; #if (NGX_STAT_STUB) - ngx_atomic_fetch_add(ngx_stat_reading, 1); + (void) ngx_atomic_fetch_add(ngx_stat_reading, 1); #endif c->log->handler = ngx_http_log_error; @@ -2778,11 +2778,11 @@ ngx_http_request_done(ngx_http_request_t #if (NGX_STAT_STUB) if (r->stat_reading) { - ngx_atomic_fetch_add(ngx_stat_reading, -1); + (void) ngx_atomic_fetch_add(ngx_stat_reading, -1); } if (r->stat_writing) { - ngx_atomic_fetch_add(ngx_stat_writing, -1); + (void) ngx_atomic_fetch_add(ngx_stat_writing, -1); } #endif @@ -2863,7 +2863,7 @@ ngx_http_close_connection(ngx_connection #endif #if (NGX_STAT_STUB) - ngx_atomic_fetch_add(ngx_stat_active, -1); + (void) ngx_atomic_fetch_add(ngx_stat_active, -1); #endif c->destroyed = 1; diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -14,6 +14,8 @@ static ngx_int_t ngx_http_upstream_cache ngx_http_upstream_t *u); static ngx_int_t ngx_http_upstream_cache_send(ngx_http_request_t *r, ngx_http_upstream_t *u); +static ngx_int_t ngx_http_upstream_cache_status(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); #endif static void ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t *ctx); @@ -316,6 +318,10 @@ static ngx_http_variable_t ngx_http_ups ngx_http_upstream_response_length_variable, 0, NGX_HTTP_VAR_NOHASH|NGX_HTTP_VAR_NOCACHEABLE, 0 }, + { ngx_string("upstream_cache_status"), NULL, + ngx_http_upstream_cache_status, 0, + NGX_HTTP_VAR_NOHASH|NGX_HTTP_VAR_NOCACHEABLE, 0 }, + { ngx_null_string, NULL, NULL, 0, 0, 0 } }; @@ -575,21 +581,34 @@ ngx_http_upstream_cache(ngx_http_request c->body_start = u->conf->buffer_size; c->file_cache = u->conf->cache->data; + u->cache_status = NGX_HTTP_CACHE_MISS; + rc = ngx_http_file_cache_open(r); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http upstream cache: %i", rc); - if (rc == NGX_HTTP_CACHE_UPDATING) { + switch (rc) { + + case NGX_HTTP_CACHE_UPDATING: + if (u->conf->cache_use_stale & NGX_HTTP_UPSTREAM_FT_UPDATING) { + u->cache_status = rc; rc = NGX_OK; } else { rc = NGX_HTTP_CACHE_STALE; } + + break; + + case NGX_OK: + u->cache_status = NGX_HTTP_CACHE_HIT; } - if (rc == NGX_OK) { + switch (rc) { + + case NGX_OK: rc = ngx_http_upstream_cache_send(r, u); @@ -597,17 +616,21 @@ ngx_http_upstream_cache(ngx_http_request return rc; } - } else if (rc == NGX_ERROR) { + break; + + case NGX_ERROR: return NGX_ERROR; - } else if (rc == NGX_HTTP_CACHE_STALE) { + case NGX_HTTP_CACHE_STALE: c->valid_sec = 0; - u->stale_cache = 1; u->buffer.start = NULL; - - } else if (rc == NGX_DECLINED) { + u->cache_status = NGX_HTTP_CACHE_EXPIRED; + + break; + + case NGX_DECLINED: if ((size_t) (u->buffer.end - u->buffer.start) < u->conf->buffer_size) { u->buffer.start = NULL; @@ -617,14 +640,20 @@ ngx_http_upstream_cache(ngx_http_request u->buffer.last = u->buffer.pos; } - } else if (rc == NGX_AGAIN) { + break; + + case NGX_AGAIN: u->cacheable = 0; - } else { + break; + + default: /* cached NGX_HTTP_BAD_GATEWAY, NGX_HTTP_GATEWAY_TIME_OUT, etc. */ + u->cache_status = NGX_HTTP_CACHE_HIT; + return rc; } @@ -640,6 +669,7 @@ ngx_http_upstream_cache_send(ngx_http_re ngx_int_t rc; ngx_http_cache_t *c; + r->cached = 1; c = r->cache; /* TODO: cache stack */ @@ -1521,12 +1551,15 @@ ngx_http_upstream_test_next(ngx_http_req #if (NGX_HTTP_CACHE) - if (u->stale_cache && (u->conf->cache_use_stale & un->mask)) { + if (u->cache_status == NGX_HTTP_CACHE_EXPIRED + && (u->conf->cache_use_stale & un->mask)) + { ngx_int_t rc; rc = u->reinit_request(r); if (rc == NGX_OK) { + u->cache_status = NGX_HTTP_CACHE_STALE; rc = ngx_http_upstream_cache_send(r, u); } @@ -1573,8 +1606,9 @@ ngx_http_upstream_intercept_errors(ngx_h if (err_page[i].status == status) { - if (status == NGX_HTTP_UNAUTHORIZED) { - + if (status == NGX_HTTP_UNAUTHORIZED + && u->headers_in.www_authenticate) + { h = ngx_list_push(&r->headers_out.headers); if (h == NULL) { @@ -2680,12 +2714,15 @@ ngx_http_upstream_next(ngx_http_request_ #if (NGX_HTTP_CACHE) - if (u->stale_cache && (u->conf->cache_use_stale & ft_type)) { + if (u->cache_status == NGX_HTTP_CACHE_EXPIRED + && (u->conf->cache_use_stale & ft_type)) + { ngx_int_t rc; rc = u->reinit_request(r); if (rc == NGX_OK) { + u->cache_status = NGX_HTTP_CACHE_STALE; rc = ngx_http_upstream_cache_send(r, u); } @@ -3262,7 +3299,7 @@ ngx_http_upstream_copy_last_modified(ngx #if (NGX_HTTP_CACHE) - if (r->cached || r->upstream->cacheable) { + if (r->upstream->cacheable) { r->headers_out.last_modified = ho; r->headers_out.last_modified_time = ngx_http_parse_time(h->value.data, h->value.len); @@ -3713,6 +3750,33 @@ ngx_http_upstream_header_variable(ngx_ht } +#if (NGX_HTTP_CACHE) + +ngx_int_t +ngx_http_upstream_cache_status(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + ngx_uint_t n; + + if (r->upstream == NULL || r->upstream->cache_status == 0) { + v->not_found = 1; + return NGX_OK; + } + + n = r->upstream->cache_status - 1; + + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->len = ngx_http_cache_status[n].len; + v->data = ngx_http_cache_status[n].data; + + return NGX_OK; +} + +#endif + + static char * ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) { @@ -4086,7 +4150,10 @@ ngx_http_upstream_hide_headers_hash(ngx_ conf->hide_headers_hash = prev->hide_headers_hash; if (conf->hide_headers_hash.buckets - && ((conf->cache == NULL) == (prev->cache == NULL))) +#if (NGX_HTTP_CACHE) + && ((conf->cache == NULL) == (prev->cache == NULL)) +#endif + ) { return NGX_OK; } diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h --- a/src/http/ngx_http_upstream.h +++ b/src/http/ngx_http_upstream.h @@ -298,7 +298,7 @@ struct ngx_http_upstream_s { unsigned accel:1; unsigned ssl:1; #if (NGX_HTTP_CACHE) - unsigned stale_cache:1; + unsigned cache_status:3; #endif unsigned buffering:1; diff --git a/src/mail/ngx_mail_handler.c b/src/mail/ngx_mail_handler.c --- a/src/mail/ngx_mail_handler.c +++ b/src/mail/ngx_mail_handler.c @@ -710,7 +710,7 @@ ngx_mail_close_connection(ngx_connection #endif #if (NGX_STAT_STUB) - ngx_atomic_fetch_add(ngx_stat_active, -1); + (void) ngx_atomic_fetch_add(ngx_stat_active, -1); #endif c->destroyed = 1;