diff options
Diffstat (limited to 'src/http')
| -rw-r--r-- | src/http/modules/proxy/ngx_http_proxy_cache.c | 37 | ||||
| -rw-r--r-- | src/http/modules/proxy/ngx_http_proxy_handler.c | 33 | ||||
| -rw-r--r-- | src/http/modules/proxy/ngx_http_proxy_handler.h | 3 | ||||
| -rw-r--r-- | src/http/modules/proxy/ngx_http_proxy_upstream.c | 126 | ||||
| -rw-r--r-- | src/http/ngx_http_busy_lock.c | 59 | ||||
| -rw-r--r-- | src/http/ngx_http_busy_lock.h | 16 | ||||
| -rw-r--r-- | src/http/ngx_http_cache.c | 8 |
7 files changed, 249 insertions, 33 deletions
diff --git a/src/http/modules/proxy/ngx_http_proxy_cache.c b/src/http/modules/proxy/ngx_http_proxy_cache.c index e8e3b5280..0bc7c6159 100644 --- a/src/http/modules/proxy/ngx_http_proxy_cache.c +++ b/src/http/modules/proxy/ngx_http_proxy_cache.c @@ -216,6 +216,30 @@ static int ngx_http_proxy_process_cached_header(ngx_http_proxy_ctx_t *p) } +#if 0 + +static void ngx_http_proxy_cache_busy_lock(ngx_http_proxy_ctx_t *p) +{ + rc = ngx_http_busy_lock(p->lcf->busy_lock, p->cache->ctx.md5); + + if (rc == NGX_OK) { + ngx_http_proxy_request_upstream(p); + } + + if (rc == NGX_AGAIN) { + if (p->busy_lock_time) { + ngx_add_timer(p->request->connection->read, 1000); + return; + } + } + + rc == NGX_ERROR + check waitn +} + +#endif + + int ngx_http_proxy_send_cached_response(ngx_http_proxy_ctx_t *p) { int rc, len, i; @@ -428,10 +452,21 @@ int ngx_http_proxy_is_cachable(ngx_http_proxy_ctx_t *p) int ngx_http_proxy_update_cache(ngx_http_proxy_ctx_t *p) { + ngx_event_pipe_t *ep; + if (p->cache == NULL) { return NGX_OK; } + ep = p->upstream->event_pipe; + + if (p->cache->ctx.length == -1) { + /* TODO: test rc */ + ngx_write_file(&ep->temp_file->file, + (char *) &ep->read_length, sizeof(off_t), + offsetof(ngx_http_cache_header_t, length)); + } + return ngx_http_cache_update_file(p->request, &p->cache->ctx, - &p->upstream->event_pipe->temp_file->file.name); + &ep->temp_file->file.name); } diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.c b/src/http/modules/proxy/ngx_http_proxy_handler.c index 860ba7ac7..a28495668 100644 --- a/src/http/modules/proxy/ngx_http_proxy_handler.c +++ b/src/http/modules/proxy/ngx_http_proxy_handler.c @@ -266,7 +266,9 @@ static int ngx_http_proxy_handler(ngx_http_request_t *r) ngx_memzero(p->state, sizeof(ngx_http_proxy_state_t)); - if (!p->lcf->cache) { + if (!p->lcf->cache + || (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD)) + { p->state->cache = NGX_HTTP_PROXY_CACHE_PASS; } else if (r->bypass_cache) { @@ -290,16 +292,16 @@ static int ngx_http_proxy_handler(ngx_http_request_t *r) rc = ngx_http_proxy_get_cached_response(p); + if (rc == NGX_DONE || rc == NGX_HTTP_INTERNAL_SERVER_ERROR) { + return rc; + } + p->valid_header_in = 1; if (rc == NGX_OK) { return ngx_http_proxy_send_cached_response(p); } - if (rc == NGX_HTTP_INTERNAL_SERVER_ERROR) { - return rc; - } - /* rc == NGX_DECLINED || NGX_HTTP_CACHE_STALE || NGX_HTTP_CACHE_AGED */ return ngx_http_proxy_request_upstream(p); @@ -312,8 +314,7 @@ void ngx_http_proxy_finalize_request(ngx_http_proxy_ctx_t *p, int rc) "finalize http proxy request"); if (p->upstream->peer.connection) { - ngx_http_proxy_close_connection(p->upstream->peer.connection); - p->upstream->peer.connection = NULL; + ngx_http_proxy_close_connection(p); } if (p->header_sent @@ -329,8 +330,17 @@ void ngx_http_proxy_finalize_request(ngx_http_proxy_ctx_t *p, int rc) } -void ngx_http_proxy_close_connection(ngx_connection_t *c) +void ngx_http_proxy_close_connection(ngx_http_proxy_ctx_t *p) { + ngx_connection_t *c; + + c = p->upstream->peer.connection; + p->upstream->peer.connection = NULL; + + if (p->lcf->busy_lock) { + p->lcf->busy_lock->conn_n--; + } + ngx_log_debug(c->log, "proxy close connection: %d" _ c->fd); if (c->fd == -1) { @@ -505,6 +515,13 @@ static char *ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, if (conf->busy_lock && conf->cache && conf->busy_lock->busy == NULL) { + /* ngx_alloc_shared() */ + conf->busy_lock->busy_mask = + ngx_palloc(cf->pool, (conf->busy_lock->max_conn + 7) / 8); + if (conf->busy_lock->busy_mask == NULL) { + return NGX_CONF_ERROR; + } + /* 16 bytes are 128 bits of the md5 */ /* ngx_alloc_shared() */ diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.h b/src/http/modules/proxy/ngx_http_proxy_handler.h index 6e4b08429..919a0afc3 100644 --- a/src/http/modules/proxy/ngx_http_proxy_handler.h +++ b/src/http/modules/proxy/ngx_http_proxy_handler.h @@ -140,6 +140,7 @@ struct ngx_http_proxy_ctx_s { ngx_hunk_t *header_in; + time_t busy_lock_time; unsigned accel:1; @@ -188,7 +189,7 @@ int ngx_http_proxy_update_cache(ngx_http_proxy_ctx_t *p); size_t ngx_http_proxy_log_error(void *data, char *buf, size_t len); void ngx_http_proxy_finalize_request(ngx_http_proxy_ctx_t *p, int rc); -void ngx_http_proxy_close_connection(ngx_connection_t *c); +void ngx_http_proxy_close_connection(ngx_http_proxy_ctx_t *p); int ngx_http_proxy_parse_status_line(ngx_http_proxy_ctx_t *p); int ngx_http_proxy_copy_header(ngx_http_proxy_ctx_t *p, diff --git a/src/http/modules/proxy/ngx_http_proxy_upstream.c b/src/http/modules/proxy/ngx_http_proxy_upstream.c index cee93ee65..c66c16418 100644 --- a/src/http/modules/proxy/ngx_http_proxy_upstream.c +++ b/src/http/modules/proxy/ngx_http_proxy_upstream.c @@ -11,6 +11,8 @@ static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_proxy_ctx_t *p); static void ngx_http_proxy_init_upstream(void *data); static void ngx_http_proxy_reinit_upstream(ngx_http_proxy_ctx_t *p); +static void ngx_http_proxy_upstream_busy_lock(ngx_http_proxy_ctx_t *p); +static void ngx_http_proxy_upstream_busy_lock_handler(ngx_event_t *rev); static void ngx_http_proxy_connect(ngx_http_proxy_ctx_t *p); static void ngx_http_proxy_send_request(ngx_http_proxy_ctx_t *p); static void ngx_http_proxy_send_request_handler(ngx_event_t *wev); @@ -264,7 +266,11 @@ ngx_log_debug(r->connection->log, "timer_set: %d" _ wctx->pool = r->pool; - ngx_http_proxy_connect(p); + if (p->lcf->busy_lock) { + ngx_http_proxy_upstream_busy_lock(p); + } else { + ngx_http_proxy_connect(p); + } } @@ -306,6 +312,109 @@ static void ngx_http_proxy_reinit_upstream(ngx_http_proxy_ctx_t *p) } +static void ngx_http_proxy_upstream_busy_lock(ngx_http_proxy_ctx_t *p) +{ + int ft_type; + + if (p->lcf->busy_lock->conn_n < p->lcf->busy_lock->max_conn) { + p->lcf->busy_lock->conn_n++; + + if (p->busy_lock_time) { + p->busy_lock_time = 0; + p->lcf->busy_lock->waiting_n--; + } + + ngx_http_proxy_connect(p); + return; + } + + if (p->busy_lock_time) { + if (p->busy_lock_time < p->lcf->busy_lock->timeout) { + ngx_add_timer(p->request->connection->read, 1000); + return; + } + + p->lcf->busy_lock->waiting_n--; + ft_type = NGX_HTTP_PROXY_FT_BUSY_LOCK; + + } else { + if (p->lcf->busy_lock->waiting_n < p->lcf->busy_lock->max_waiting) { + p->lcf->busy_lock->waiting_n++; + ngx_add_timer(p->request->connection->read, 1000); + p->request->connection->read->event_handler = + ngx_http_proxy_upstream_busy_lock_handler; + /* TODO: ngx_handle_level_read_event() */ + return; + } + + ft_type = NGX_HTTP_PROXY_FT_MAX_WAITING; + } + + if (p->stale && (p->lcf->use_stale & ft_type)) { + ngx_http_proxy_finalize_request(p, + ngx_http_proxy_send_cached_response(p)); + return; + } + + ngx_http_proxy_finalize_request(p, NGX_HTTP_SERVICE_UNAVAILABLE); + return; +} + + +static void ngx_http_proxy_upstream_busy_lock_handler(ngx_event_t *rev) +{ + ngx_connection_t *c; + ngx_http_request_t *r; + ngx_http_proxy_ctx_t *p; + + ngx_log_debug(rev->log, "busy lock"); + + c = rev->data; + r = c->data; + p = ngx_http_get_module_ctx(r, ngx_http_proxy_module); + p->action = "waiting upstream in busy lock"; + + if (rev->timedout) { + rev->timedout = 0; + p->busy_lock_time++; + ngx_http_proxy_upstream_busy_lock(p); + return; + } + + ngx_log_debug(rev->log, "client sent while busy lock"); + + /* + * TODO: kevent() notify about error, otherwise we need to + * call ngx_peek(): recv(MGS_PEEK) to get errno. THINK about aio + * if there's no error we need to disable event. + */ + +#if (HAVE_KQUEUE) + + if ((ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) && rev->kq_eof) { + p->lcf->busy_lock->waiting_n--; + + ngx_del_timer(rev); + + ngx_log_error(NGX_LOG_ERR, c->log, rev->kq_errno, + "client() closed connection"); + + if (ngx_del_event(rev, NGX_READ_EVENT, NGX_CLOSE_EVENT) == NGX_ERROR) { + ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + + /* we have not HTTP code for the case when a client cancels a request */ + + ngx_http_proxy_finalize_request(p, 0); + return; + } + +#endif + +} + + static void ngx_http_proxy_connect(ngx_http_proxy_ctx_t *p) { int rc; @@ -1011,8 +1120,7 @@ static void ngx_http_proxy_process_body(ngx_event_t *ev) } if (ep->upstream_done || ep->upstream_eof || ep->upstream_error) { - ngx_http_proxy_close_connection(p->upstream->peer.connection); - p->upstream->peer.connection = NULL; + ngx_http_proxy_close_connection(p); } } @@ -1024,8 +1132,7 @@ static void ngx_http_proxy_process_body(ngx_event_t *ev) if (ep->downstream_error) { if (!p->cachable && p->upstream->peer.connection) { - ngx_http_proxy_close_connection(p->upstream->peer.connection); - p->upstream->peer.connection = NULL; + ngx_http_proxy_close_connection(p); } if (p->upstream->peer.connection == NULL) { @@ -1080,8 +1187,7 @@ ngx_log_debug(p->request->connection->log, "next upstream: %d" _ ft_type); } if (p->upstream->peer.connection) { - ngx_http_proxy_close_connection(p->upstream->peer.connection); - p->upstream->peer.connection = NULL; + ngx_http_proxy_close_connection(p); } if (status) { @@ -1100,5 +1206,9 @@ ngx_log_debug(p->request->connection->log, "next upstream: %d" _ ft_type); } } - ngx_http_proxy_connect(p); + if (p->lcf->busy_lock) { + ngx_http_proxy_upstream_busy_lock(p); + } else { + ngx_http_proxy_connect(p); + } } diff --git a/src/http/ngx_http_busy_lock.c b/src/http/ngx_http_busy_lock.c index 8ebedfb16..9431a3876 100644 --- a/src/http/ngx_http_busy_lock.c +++ b/src/http/ngx_http_busy_lock.c @@ -4,6 +4,61 @@ #include <ngx_http.h> +int ngx_http_busy_lock(ngx_http_busy_lock_t *bl, u_char *md5) +{ + int i, b, busy, free; + u_int mask; + + b = 0; + busy = 0; + free = -1; + +#if (NGX_SUPPRESS_WARN) + mask = 0; +#endif + + for (i = 0; i < bl->max_conn; i++) { + + if ((b & 7) == 0) { + mask = bl->busy_mask[i / 8]; + } + + if (mask & 1) { + if (ngx_memcmp(&bl->busy[i * 16], md5, 16) == 0) { + return NGX_AGAIN; + } + busy++; + + } else if (free == -1) { + free = i; + } + + if (busy == bl->busy_n) { + if (busy < bl->max_conn) { + free = i + 1; + } + + break; + } + + mask >>= 1; + b++; + } + + if (free == -1) { + return NGX_ERROR; + } + + ngx_memcpy(&bl->busy[free * 16], md5, 16); + bl->busy_mask[free / 8] |= free % 8; + + bl->busy_n++; + bl->conn_n++; + + return NGX_OK; +} + + char *ngx_http_set_busy_lock_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { @@ -26,7 +81,7 @@ char *ngx_http_set_busy_lock_slot(ngx_conf_t *cf, ngx_command_t *cmd, value = (ngx_str_t *) cf->args->elts; - for (i = 1; i < 3; i++) { + for (i = 1; i < 4; i++) { if (value[i].len > 2 && ngx_strncasecmp(value[i].data, "c:", 2) == 0) { if (bl->max_conn) { @@ -68,7 +123,7 @@ char *ngx_http_set_busy_lock_slot(ngx_conf_t *cf, ngx_command_t *cmd, return NGX_CONF_ERROR; } - bl->timeout = ngx_parse_time(&value[1], 0); + bl->timeout = ngx_parse_time(&value[1], 1); if (bl->timeout == NGX_ERROR) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid timeout \"%s\"", value[i].data); diff --git a/src/http/ngx_http_busy_lock.h b/src/http/ngx_http_busy_lock.h index 40aa3d2b3..1ee95c93d 100644 --- a/src/http/ngx_http_busy_lock.h +++ b/src/http/ngx_http_busy_lock.h @@ -8,22 +8,24 @@ typedef struct { - char *busy; - int busy_n; + u_char *busy_mask; + char *busy; + int busy_n; - int waiting_n; - int max_waiting; + int waiting_n; + int max_waiting; - int conn_n; - int max_conn; + int conn_n; + int max_conn; - int timeout; + time_t timeout; /* ngx_mutex_t mutex; */ } ngx_http_busy_lock_t; +int ngx_http_busy_lock(ngx_http_busy_lock_t *bl, u_char *md5); char *ngx_http_set_busy_lock_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); diff --git a/src/http/ngx_http_cache.c b/src/http/ngx_http_cache.c index ffe7ad5aa..6ae779ad0 100644 --- a/src/http/ngx_http_cache.c +++ b/src/http/ngx_http_cache.c @@ -26,13 +26,8 @@ int ngx_http_cache_get_file(ngx_http_request_t *r, ngx_http_cache_ctx_t *ctx) 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, + ngx_md5_text(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); @@ -90,6 +85,7 @@ ngx_log_debug(r->connection->log, "FILE: %s" _ ctx->file.name.data); ctx->buf->last += n; if (ctx->expires < ngx_time()) { +ngx_log_debug(r->connection->log, "EXPIRED"); return NGX_HTTP_CACHE_STALE; } |
