changeset 174:ea464a6c0581

nginx-0.0.1-2003-11-05-01:12:39 import
author Igor Sysoev <igor@sysoev.ru>
date Tue, 04 Nov 2003 22:12:39 +0000
parents 4fb2a2cff023
children e92c2c647c57
files src/core/ngx_string.c src/core/ngx_string.h src/http/modules/proxy/ngx_http_proxy_cache.c src/http/modules/proxy/ngx_http_proxy_handler.c src/http/modules/proxy/ngx_http_proxy_handler.h src/http/modules/proxy/ngx_http_proxy_upstream.c src/http/ngx_http.h src/http/ngx_http_busy_lock.c src/http/ngx_http_busy_lock.h src/http/ngx_http_cache.c src/http/ngx_http_cache.h
diffstat 11 files changed, 274 insertions(+), 55 deletions(-) [+]
line wrap: on
line diff
--- a/src/core/ngx_string.c
+++ b/src/core/ngx_string.c
@@ -69,6 +69,15 @@ int ngx_atoi(char *line, size_t n)
 }
 
 
+void ngx_print_md5(char *text, u_char *md5)
+{
+    ngx_snprintf(text, 33, "%0x%0x%0x%0x%0x%0x%0x%0x%0x%0x%0x%0x%0x%0x%0x%0x",
+                 md5[0], md5[1], md5[2], md5[3], md5[4], md5[5],
+                 md5[6], md5[7], md5[8], md5[9], md5[10], md5[11],
+                 md5[12], md5[13], md5[14], md5[15]);
+}
+
+
 #if 0
 char *ngx_psprintf(ngx_pool_t *p, const char *fmt, ...)
 {
--- a/src/core/ngx_string.h
+++ b/src/core/ngx_string.h
@@ -61,6 +61,9 @@ char *ngx_cpystrn(char *dst, char *src, 
 int ngx_rstrncmp(char *s1, char *s2, size_t n);
 int ngx_atoi(char *line, size_t n);
 
+void ngx_print_md5(char *text, u_char *md5);
+
+
 #define  ngx_qsort                qsort
 
 
--- a/src/http/modules/proxy/ngx_http_proxy_cache.c
+++ b/src/http/modules/proxy/ngx_http_proxy_cache.c
@@ -79,13 +79,15 @@ int ngx_http_proxy_get_cached_response(n
         || rc == NGX_HTTP_CACHE_STALE
         || rc == NGX_HTTP_CACHE_AGED)
     {
-        p->header_in->pos += c->ctx.header_size;
+        p->header_in->pos = p->header_in->start + c->ctx.header_size;
         if (ngx_http_proxy_process_cached_header(p) == NGX_ERROR) {
             return NGX_HTTP_INTERNAL_SERVER_ERROR;
         }
+        p->header_in->pos = p->header_in->start + c->ctx.header_size;
+        p->header_in->last = p->header_in->pos;
 
     } else if (rc == NGX_DECLINED) {
-        p->header_in->pos += c->ctx.header_size;
+        p->header_in->pos = p->header_in->start + c->ctx.header_size;
         p->header_in->last = p->header_in->pos;
     }
 
@@ -129,6 +131,11 @@ static int ngx_http_proxy_process_cached
         return NGX_ERROR;
     }
 
+    /* reset for the possible parsing the upstream header */
+
+    p->status = 0;
+    p->status_count = 0;
+
     ngx_cpystrn(c->status_line.data, p->status_start, c->status_line.len + 1);
 
     ngx_log_debug(r->connection->log, "http cache status %d '%s'" _ 
@@ -186,6 +193,8 @@ static int ngx_http_proxy_process_cached
 
             ngx_log_debug(r->connection->log, "HTTP header done");
 
+            c->ctx.file_start = p->header_in->pos - p->header_in->start;
+
             return NGX_OK;
 
         } else if (rc == NGX_HTTP_PARSE_INVALID_HEADER) {
@@ -209,9 +218,10 @@ static int ngx_http_proxy_process_cached
 
 int ngx_http_proxy_send_cached_response(ngx_http_proxy_ctx_t *p)
 {
-    int                  rc;
-    ngx_hunk_t          *h;
-    ngx_chain_t          out;
+    int                  rc, len, i;
+    off_t                rest;
+    ngx_hunk_t          *h0, *h1;
+    ngx_chain_t          out[2];
     ngx_http_request_t  *r;
 
     r = p->request;
@@ -231,12 +241,29 @@ int ngx_http_proxy_send_cached_response(
 
     /* we need to allocate all before the header would be sent */
 
-    if (!((h = ngx_calloc_hunk(r->pool)))) {
-        return NGX_HTTP_INTERNAL_SERVER_ERROR;
+    len = p->header_in->end - (p->header_in->start + p->cache->ctx.file_start);
+
+    h0 = NULL;
+    h1 = NULL;
+
+    if (len) {
+        if (!((h0 = ngx_calloc_hunk(r->pool)))) {
+            return NGX_HTTP_INTERNAL_SERVER_ERROR;
+        }
+
+        if (!((h0->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t))))) {
+            return NGX_HTTP_INTERNAL_SERVER_ERROR;
+        }
     }
 
-    if (!((h->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t))))) {
-        return NGX_HTTP_INTERNAL_SERVER_ERROR;
+    if (len < p->cache->ctx.length) {
+        if (!((h1 = ngx_calloc_hunk(r->pool)))) {
+            return NGX_HTTP_INTERNAL_SERVER_ERROR;
+        }
+
+        if (!((h1->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t))))) {
+            return NGX_HTTP_INTERNAL_SERVER_ERROR;
+        }
     }
 
     rc = ngx_http_send_header(r);
@@ -247,20 +274,62 @@ int ngx_http_proxy_send_cached_response(
         return rc;
     }
 
-    /* TODO: part in p->header_in */
+    rest = p->cache->ctx.length;
+
+    if (len) {
+        if (p->valid_header_in) {
+            h0->pos = p->header_in->start + p->cache->ctx.file_start;
+
+            if (len > p->cache->ctx.length) {
+                h0->last = h0->pos + p->cache->ctx.length;
+
+            } else {
+                h0->last = p->header_in->end;
+            }
 
-    h->type = r->main ? NGX_HUNK_FILE : NGX_HUNK_FILE|NGX_HUNK_LAST;
+            h0->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_TEMP;
+        }
+
+        h0->type |= NGX_HUNK_FILE;
+        h0->file_pos = p->cache->ctx.file_start;
 
-    h->file_pos = p->header_in->pos - p->header_in->start;
-    h->file_last = h->file_pos + p->cache->ctx.header.length;
+        h0->file->fd = p->cache->ctx.file.fd;
+        h0->file->log = r->connection->log;
+
+        if (len > p->cache->ctx.length) {
+            h0->file_last = h0->file_pos + p->cache->ctx.length;
+            rest = 0;
 
-    h->file->fd = p->cache->ctx.file.fd;
-    h->file->log = r->connection->log;
-    
-    out.hunk = h;
-    out.next = NULL;
+        } else {
+            h0->file_last = h0->file_pos + len;
+            rest -= len;
+        }
+
+        out[0].hunk = h0;
+        out[0].next = &out[1];
+        i = 0;
+
+    } else {
+        i = -1;
+    }
 
-    return ngx_http_output_filter(r, &out);
+    if (rest) {
+        h1->file_pos = p->cache->ctx.file_start + len;
+        h1->file_last = h1->file_pos + rest;
+        h1->type = NGX_HUNK_FILE;
+
+        h1->file->fd = p->cache->ctx.file.fd;
+        h1->file->log = r->connection->log;
+
+        out[++i].hunk = h1;
+    }
+
+    out[i].next = NULL;
+    if (!r->main) {
+        out[i].hunk->type |= NGX_HUNK_LAST;
+    }
+
+    return ngx_http_output_filter(r, out);
 }
 
 
@@ -293,13 +362,13 @@ int ngx_http_proxy_is_cachable(ngx_http_
     if (date == NGX_ERROR) {
         date = ngx_time();
     }
-    p->cache->ctx.header.date = date;
+    p->cache->ctx.date = date;
 
     last_modified = NGX_ERROR;
     if (h->last_modified) {
         last_modified = ngx_http_parse_time(h->last_modified->value.data,
                                             h->last_modified->value.len);
-        p->cache->ctx.header.last_modified = last_modified;
+        p->cache->ctx.last_modified = last_modified;
     }
 
     if (h->x_accel_expires) {
@@ -307,7 +376,7 @@ int ngx_http_proxy_is_cachable(ngx_http_
                            h->x_accel_expires->value.len);
         if (expires != NGX_ERROR) {
             p->state->reason = NGX_HTTP_PROXY_CACHE_XAE;
-            p->cache->ctx.header.expires = date + expires;
+            p->cache->ctx.expires = date + expires;
             return (expires > 0);
         }
     }
@@ -321,7 +390,7 @@ int ngx_http_proxy_is_cachable(ngx_http_
                                           h->expires->value.len);
             if (expires != NGX_ERROR) {
                 p->state->reason = NGX_HTTP_PROXY_CACHE_EXP;
-                p->cache->ctx.header.expires = expires;
+                p->cache->ctx.expires = expires;
                 return (date < expires);
             }
         }
@@ -329,7 +398,7 @@ int ngx_http_proxy_is_cachable(ngx_http_
 
     if (p->upstream->status == NGX_HTTP_MOVED_PERMANENTLY) {
         p->state->reason = NGX_HTTP_PROXY_CACHE_MVD;
-        p->cache->ctx.header.expires = /* STUB: 1 hour */ 60 * 60;
+        p->cache->ctx.expires = /* STUB: 1 hour */ 60 * 60;
         return 1;
     }
 
@@ -339,17 +408,17 @@ int ngx_http_proxy_is_cachable(ngx_http_
 
     if (last_modified != NGX_ERROR && p->lcf->lm_factor > 0) {
 
-        /* FIXME: time_t == int_64_t */ 
+        /* FIXME: time_t == int_64_t, we can use fpu */ 
 
         p->state->reason = NGX_HTTP_PROXY_CACHE_LMF;
-        p->cache->ctx.header.expires = ngx_time()
+        p->cache->ctx.expires = ngx_time()
               + (((int64_t) (date - last_modified)) * p->lcf->lm_factor) / 100;
         return 1;
     }
 
     if (p->lcf->default_expires > 0) {
         p->state->reason = NGX_HTTP_PROXY_CACHE_PDE;
-        p->cache->ctx.header.expires = p->lcf->default_expires;
+        p->cache->ctx.expires = p->lcf->default_expires;
         return 1;
     }
 
--- a/src/http/modules/proxy/ngx_http_proxy_handler.c
+++ b/src/http/modules/proxy/ngx_http_proxy_handler.c
@@ -131,6 +131,14 @@ static ngx_command_t  ngx_http_proxy_com
       NULL },
 
 
+    { ngx_string("proxy_busy_lock"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE3,
+      ngx_http_set_busy_lock_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_proxy_loc_conf_t, busy_lock),
+      NULL },
+
+
     { ngx_string("proxy_pass_server"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
       ngx_conf_set_flag_slot,
@@ -255,6 +263,8 @@ static int ngx_http_proxy_handler(ngx_ht
         return NGX_HTTP_INTERNAL_SERVER_ERROR;
     }
 
+    ngx_memzero(p->state, sizeof(ngx_http_proxy_state_t));
+
 
     if (!p->lcf->cache) {
         p->state->cache = NGX_HTTP_PROXY_CACHE_PASS;
@@ -280,6 +290,8 @@ static int ngx_http_proxy_handler(ngx_ht
 
     rc = ngx_http_proxy_get_cached_response(p);
 
+    p->valid_header_in = 1;
+
     if (rc == NGX_OK) {
         return ngx_http_proxy_send_cached_response(p);
     }
@@ -406,6 +418,8 @@ static void *ngx_http_proxy_create_loc_c
     conf->cache_path = NULL;
     conf->temp_path = NULL;
 
+    conf->busy_lock = NULL;
+
     */
 
     conf->request_buffer_size = NGX_CONF_UNSET;
@@ -482,6 +496,26 @@ static char *ngx_http_proxy_merge_loc_co
 
     ngx_conf_merge_value(conf->cache, prev->cache, 0);
 
+
+    /* conf->cache must be merged */
+
+    if (conf->busy_lock == NULL) {
+        conf->busy_lock = prev->busy_lock;
+    }
+
+    if (conf->busy_lock && conf->cache && conf->busy_lock->busy == NULL) {
+
+        /* 16 bytes are 128 bits of the md5 */
+
+        /* ngx_alloc_shared() */
+        conf->busy_lock->busy = ngx_palloc(cf->pool,
+                                           16 * conf->busy_lock->max_conn);
+        if (conf->busy_lock->busy == NULL) {
+            return NGX_CONF_ERROR;
+        }
+    }
+
+
     ngx_conf_merge_value(conf->pass_server, prev->pass_server, 0);
     ngx_conf_merge_value(conf->pass_x_accel_expires,
                          prev->pass_x_accel_expires, 0);
--- a/src/http/modules/proxy/ngx_http_proxy_handler.h
+++ b/src/http/modules/proxy/ngx_http_proxy_handler.h
@@ -73,6 +73,8 @@ typedef struct {
     ngx_path_t                      *cache_path;
     ngx_path_t                      *temp_path;
 
+    ngx_http_busy_lock_t            *busy_lock;
+
     ngx_http_proxy_upstream_conf_t  *upstream;
     ngx_peers_t                     *peers;
 } ngx_http_proxy_loc_conf_t;
@@ -143,6 +145,7 @@ struct ngx_http_proxy_ctx_s {
 
     unsigned                      cachable:1;
     unsigned                      stale:1;
+    unsigned                      valid_header_in:1;
 
     unsigned                      request_sent:1;
     unsigned                      header_sent:1;
--- a/src/http/modules/proxy/ngx_http_proxy_upstream.c
+++ b/src/http/modules/proxy/ngx_http_proxy_upstream.c
@@ -300,6 +300,9 @@ static void ngx_http_proxy_reinit_upstre
             p->header_in->last = p->header_in->start;
         }
     }
+
+    p->status = 0;
+    p->status_count = 0;
 }
 
 
@@ -557,6 +560,8 @@ static void ngx_http_proxy_process_upstr
         return;
     }
 
+    p->valid_header_in = 0;
+
     p->upstream->peer.cached = 0;
 
     rc = ngx_http_proxy_parse_status_line(p);
@@ -811,7 +816,7 @@ static void ngx_http_proxy_send_response
     int                           rc;
     ngx_event_pipe_t             *ep;
     ngx_http_request_t           *r;
-    ngx_http_cache_file_t        *header;
+    ngx_http_cache_header_t      *header;
     ngx_http_core_loc_conf_t     *clcf;
 
     r = p->request;
@@ -836,14 +841,15 @@ static void ngx_http_proxy_send_response
 
     p->header_sent = 1;
 
-    if (p->cache) {
-        header = (ngx_http_cache_file_t *) p->header_in->start;
+    if (p->cachable) {
+        header = (ngx_http_cache_header_t *) p->header_in->start;
 
-        /* STUB */
-        header->header.expires = 0;
-        header->header.last_modified = 0;
+        header->expires = p->cache->ctx.expires;
+        header->last_modified = p->cache->ctx.last_modified;
+        header->date = p->cache->ctx.date;
+        /* TODO: r->headers_out.content_length_n == -1 */
+        header->length = r->headers_out.content_length_n;
 
-        header->header.length = r->headers_out.content_length_n;
         header->key_len = p->cache->ctx.key.len;
         ngx_memcpy(&header->key, p->cache->ctx.key.data, header->key_len);
         header->key[header->key_len] = LF;
--- a/src/http/ngx_http.h
+++ b/src/http/ngx_http.h
@@ -7,6 +7,7 @@
 #include <ngx_http_request.h>
 #include <ngx_http_config.h>
 #include <ngx_http_cache.h>
+#include <ngx_http_busy_lock.h>
 #include <ngx_http_filter.h>
 #include <ngx_http_core_module.h>
 
new file mode 100644
--- /dev/null
+++ b/src/http/ngx_http_busy_lock.c
@@ -0,0 +1,80 @@
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_http.h>
+
+
+char *ngx_http_set_busy_lock_slot(ngx_conf_t *cf, ngx_command_t *cmd,
+                                  void *conf)
+{
+    char  *p = conf;
+
+    int                    i;
+    ngx_str_t             *value;
+    ngx_http_busy_lock_t  *bl, **blp;
+
+    blp = (ngx_http_busy_lock_t **) (p + cmd->offset);
+    if (*blp) {
+        return "is duplicate";
+    }
+
+    /* ngx_calloc_shared() */
+    if (!(bl = ngx_pcalloc(cf->pool, sizeof(ngx_http_busy_lock_t)))) {
+        return NGX_CONF_ERROR;
+    }
+    *blp = bl;
+
+    value = (ngx_str_t *) cf->args->elts;
+
+    for (i = 1; i < 3; i++) {
+
+        if (value[i].len > 2 && ngx_strncasecmp(value[i].data, "c:", 2) == 0) {
+            if (bl->max_conn) {
+                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                               "duplicate \"%s\"", value[i].data);
+                return NGX_CONF_ERROR;
+            }
+
+            bl->max_conn = ngx_atoi(value[i].data + 2, value[i].len - 2);
+            if (bl->max_conn == NGX_ERROR) {
+                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                               "invalid value \"%s\"", value[i].data);
+                return NGX_CONF_ERROR;
+            }
+
+            continue;
+        }
+
+        if (value[i].len > 2 && ngx_strncasecmp(value[i].data, "w:", 2) == 0) {
+            if (bl->max_waiting) {
+                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                               "duplicate \"%s\"", value[i].data);
+                return NGX_CONF_ERROR;
+            }
+
+            bl->max_waiting = ngx_atoi(value[i].data + 2, value[i].len - 2);
+            if (bl->max_waiting == NGX_ERROR) {
+                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                               "invalid value \"%s\"", value[i].data);
+                return NGX_CONF_ERROR;
+            }
+
+            continue;
+        }
+
+        if (bl->timeout) {
+            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                               "duplicate timeout \"%s\"", value[i].data);
+            return NGX_CONF_ERROR;
+        }
+
+        bl->timeout = ngx_parse_time(&value[1], 0);
+        if (bl->timeout == NGX_ERROR) {
+            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                               "invalid timeout \"%s\"", value[i].data);
+            return NGX_CONF_ERROR;
+        }
+    }
+
+    return NGX_CONF_OK;
+}
--- a/src/http/ngx_http_busy_lock.h
+++ b/src/http/ngx_http_busy_lock.h
@@ -24,4 +24,8 @@ typedef struct {
 } ngx_http_busy_lock_t;
 
 
+char *ngx_http_set_busy_lock_slot(ngx_conf_t *cf, ngx_command_t *cmd,
+                                  void *conf);
+
+
 #endif /* _NGX_HTTP_BUSY_LOCK_H_INCLUDED_ */
--- a/src/http/ngx_http_cache.c
+++ b/src/http/ngx_http_cache.c
@@ -8,12 +8,12 @@
 
 int ngx_http_cache_get_file(ngx_http_request_t *r, ngx_http_cache_ctx_t *ctx)
 {
-    ssize_t                 n;
-    MD5_CTX                 md5;
-    ngx_err_t               err;
-    ngx_http_cache_file_t  *h;
+    ssize_t                   n;
+    MD5_CTX                   md5;
+    ngx_err_t                 err;
+    ngx_http_cache_header_t  *h;
 
-    ctx->header_size = sizeof(ngx_http_cache_file_t) + ctx->key.len + 1;
+    ctx->header_size = sizeof(ngx_http_cache_header_t) + ctx->key.len + 1;
 
     ctx->file.name.len = ctx->path->name.len + 1 + ctx->path->len + 32;
     if (!(ctx->file.name.data = ngx_palloc(r->pool, ctx->file.name.len + 1))) {
@@ -24,8 +24,15 @@ int ngx_http_cache_get_file(ngx_http_req
 
     MD5Init(&md5);
     MD5Update(&md5, (u_char *) ctx->key.data, ctx->key.len);
+    MD5Final(ctx->md5, &md5);
+
+    ngx_print_md5(
+                 ctx->file.name.data + ctx->path->name.len + 1 + ctx->path->len,
+                 ctx->md5);
+#if 0
     MD5End(&md5,
            ctx->file.name.data + ctx->path->name.len + 1 + ctx->path->len);
+#endif
 
 ngx_log_debug(r->connection->log, "URL: %s, md5: %s" _ ctx->key.data _
               ctx->file.name.data + ctx->path->name.len + 1 + ctx->path->len);
@@ -64,8 +71,11 @@ ngx_log_debug(r->connection->log, "FILE:
         return NGX_ERROR;
     }
 
-    h = (ngx_http_cache_file_t *) ctx->buf->pos;
-    ctx->header = h->header;
+    h = (ngx_http_cache_header_t *) ctx->buf->pos;
+    ctx->expires = h->expires;
+    ctx->last_modified= h->last_modified;
+    ctx->date = h->date;
+    ctx->length = h->length;
 
     if (h->key_len != ctx->key.len
         || ngx_strncmp(h->key, ctx->key.data, h->key_len) != 0)
@@ -79,7 +89,7 @@ ngx_log_debug(r->connection->log, "FILE:
 
     ctx->buf->last += n;
 
-    if (ctx->header.expires < ngx_time()) {
+    if (ctx->expires < ngx_time()) {
         return NGX_HTTP_CACHE_STALE;
     }
 
--- a/src/http/ngx_http_cache.h
+++ b/src/http/ngx_http_cache.h
@@ -12,17 +12,12 @@ typedef struct {
     time_t       last_modified;
     time_t       date;
     off_t        length;
+    size_t       key_len;
+    char         key[0];
 } ngx_http_cache_header_t;
 
 
 typedef struct {
-    ngx_http_cache_header_t  header;
-    size_t                   key_len;
-    char                     key[0];
-} ngx_http_cache_file_t;
-
-
-typedef struct {
     u_int32_t    crc;
     ngx_str_t    key;
     ngx_fd_t     fd;
@@ -37,12 +32,17 @@ typedef struct {
 
 
 typedef struct {
-    ngx_file_t                file;
-    ngx_str_t                 key;
-    ngx_path_t               *path;
-    ngx_hunk_t               *buf;
-    ngx_http_cache_header_t   header;
-    ssize_t                   header_size;
+    ngx_file_t   file;
+    ngx_str_t    key;
+    u_char       md5[16];
+    ngx_path_t  *path;
+    ngx_hunk_t  *buf;
+    time_t       expires;
+    time_t       last_modified;
+    time_t       date;
+    off_t        length;
+    ssize_t      header_size;
+    size_t       file_start;
 } ngx_http_cache_ctx_t;