changeset 3092:4f28e63e42b4 stable-0.7

merge r2953, r2958, r3084: *) $upstream_cache_status *) clean cache updating state if a response has uncacheable code or cache prohibitive headers
author Igor Sysoev <igor@sysoev.ru>
date Mon, 07 Sep 2009 09:49:51 +0000
parents ecc8d537e9a9
children 5795b2710eef
files src/http/ngx_http_cache.h src/http/ngx_http_file_cache.c src/http/ngx_http_upstream.c src/http/ngx_http_upstream.h
diffstat 4 files changed, 100 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/src/http/ngx_http_cache.h
+++ b/src/http/ngx_http_cache.h
@@ -13,8 +13,11 @@
 #include <ngx_http.h>
 
 
-#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_ */
--- 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', ':', ' ' };
 
 
--- 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,14 @@ static ngx_http_variable_t  ngx_http_ups
       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
     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
             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 +644,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 +673,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 +1555,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);
             }
 
@@ -2007,6 +2044,10 @@ ngx_http_upstream_send_response(ngx_http
     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_
 
 #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
 
 #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_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)
 {
--- 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;