diff --git a/src/http/ngx_http_cache.h b/src/http/ngx_http_cache.h index cf909cc3d..1ee80751d 100644 --- 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_request_t *); 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 index 323358742..8e908a1dc 100644 --- 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_delete_file(ngx_tree_ctx_t *ctx, 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_upstream.c b/src/http/ngx_http_upstream.c index c04e643fb..a0e7f8206 100644 --- 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_request_t *r, 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,14 @@ static ngx_http_variable_t ngx_http_upstream_vars[] = { ngx_http_upstream_response_length_variable, 0, NGX_HTTP_VAR_NOHASH|NGX_HTTP_VAR_NOCACHEABLE, 0 }, +#if (NGX_HTTP_CACHE) + + { ngx_string("upstream_cache_status"), NULL, + ngx_http_upstream_cache_status, 0, + NGX_HTTP_VAR_NOHASH|NGX_HTTP_VAR_NOCACHEABLE, 0 }, + +#endif + { ngx_null_string, NULL, NULL, 0, 0, 0 } }; @@ -575,21 +585,34 @@ 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; + 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 +620,21 @@ ngx_http_upstream_cache(ngx_http_request_t *r, ngx_http_upstream_t *u) 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; + u->cache_status = NGX_HTTP_CACHE_EXPIRED; - } else if (rc == NGX_DECLINED) { + break; + + case NGX_DECLINED: if ((size_t) (u->buffer.end - u->buffer.start) < u->conf->buffer_size) { u->buffer.start = NULL; @@ -617,14 +644,20 @@ ngx_http_upstream_cache(ngx_http_request_t *r, ngx_http_upstream_t *u) 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 +673,7 @@ ngx_http_upstream_cache_send(ngx_http_request_t *r, ngx_http_upstream_t *u) ngx_int_t rc; ngx_http_cache_t *c; + r->cached = 1; c = r->cache; /* TODO: cache stack */ @@ -1521,12 +1555,15 @@ ngx_http_upstream_test_next(ngx_http_request_t *r, ngx_http_upstream_t *u) #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); } @@ -2007,6 +2044,10 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u) ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http cacheable: %d", u->cacheable); + if (u->cacheable == 0 && r->cache) { + ngx_http_file_cache_free(r, u->pipe->temp_file); + } + #endif p = u->pipe; @@ -2681,12 +2722,15 @@ ngx_http_upstream_next(ngx_http_request_t *r, ngx_http_upstream_t *u, #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); } @@ -3263,7 +3307,7 @@ ngx_http_upstream_copy_last_modified(ngx_http_request_t *r, ngx_table_elt_t *h, #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); @@ -3714,6 +3758,33 @@ ngx_http_upstream_header_variable(ngx_http_request_t *r, } +#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) { diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h index eb97d3989..fc777670e 100644 --- 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;