# HG changeset patch # User Igor Sysoev # Date 1067983959 0 # Node ID ea464a6c05815727ce328e1ac0a2146185336ebe # Parent 4fb2a2cff023675c6e1207803f6244560e7f33b1 nginx-0.0.1-2003-11-05-01:12:39 import diff --git a/src/core/ngx_string.c b/src/core/ngx_string.c --- 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, ...) { diff --git a/src/core/ngx_string.h b/src/core/ngx_string.h --- 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 diff --git a/src/http/modules/proxy/ngx_http_proxy_cache.c b/src/http/modules/proxy/ngx_http_proxy_cache.c --- 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; } diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.c b/src/http/modules/proxy/ngx_http_proxy_handler.c --- 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); diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.h b/src/http/modules/proxy/ngx_http_proxy_handler.h --- 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; diff --git a/src/http/modules/proxy/ngx_http_proxy_upstream.c b/src/http/modules/proxy/ngx_http_proxy_upstream.c --- 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; diff --git a/src/http/ngx_http.h b/src/http/ngx_http.h --- a/src/http/ngx_http.h +++ b/src/http/ngx_http.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include diff --git a/src/http/ngx_http_busy_lock.c b/src/http/ngx_http_busy_lock.c new file mode 100644 --- /dev/null +++ b/src/http/ngx_http_busy_lock.c @@ -0,0 +1,80 @@ + +#include +#include +#include + + +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; +} diff --git a/src/http/ngx_http_busy_lock.h b/src/http/ngx_http_busy_lock.h --- 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_ */ diff --git a/src/http/ngx_http_cache.c b/src/http/ngx_http_cache.c --- 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; } 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 @@ -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;