# HG changeset patch # User Igor Sysoev # Date 1068051821 0 # Node ID e92c2c647c57eb128a12135ba2a15900231ca2e9 # Parent ea464a6c05815727ce328e1ac0a2146185336ebe nginx-0.0.1-2003-11-05-20:03:41 import diff --git a/src/core/ngx_file.c b/src/core/ngx_file.c --- a/src/core/ngx_file.c +++ b/src/core/ngx_file.c @@ -119,7 +119,7 @@ void ngx_create_hashed_filename(ngx_file break; } - ngx_log_debug(file->log, "temp: %s" _ file->name.data); + ngx_log_debug(file->log, "hashed path: %s" _ file->name.data); name -= level; file->name.data[pos - 1] = '/'; @@ -127,7 +127,7 @@ void ngx_create_hashed_filename(ngx_file pos += level + 1; } - ngx_log_debug(file->log, "temp: %s" _ file->name.data); + ngx_log_debug(file->log, "hashed path: %s" _ file->name.data); } 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,12 +69,15 @@ int ngx_atoi(char *line, size_t n) } -void ngx_print_md5(char *text, u_char *md5) +void ngx_md5_text(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]); + /* STUB */ + + ngx_snprintf(text, 33, + "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", + 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]); } 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,7 +61,7 @@ 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); +void ngx_md5_text(char *text, u_char *md5); #define ngx_qsort qsort diff --git a/src/event/ngx_event.h b/src/event/ngx_event.h --- a/src/event/ngx_event.h +++ b/src/event/ngx_event.h @@ -371,7 +371,8 @@ ngx_inline static int ngx_handle_read_ev if (!rev->active && !rev->ready) { if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT) - == NGX_ERROR) { + == NGX_ERROR) + { return NGX_ERROR; } @@ -380,7 +381,8 @@ ngx_inline static int ngx_handle_read_ev if (rev->active && (rev->ready || close)) { if (ngx_del_event(rev, NGX_READ_EVENT, close ? NGX_CLOSE_EVENT : 0) - == NGX_ERROR) { + == NGX_ERROR) + { return NGX_ERROR; } @@ -399,7 +401,8 @@ ngx_inline static int ngx_handle_level_r if (ngx_event_flags & NGX_USE_LEVEL_EVENT) { if (!rev->active && !rev->ready) { if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT) - == NGX_ERROR) { + == NGX_ERROR) + { return NGX_ERROR; } diff --git a/src/event/ngx_event_pipe.c b/src/event/ngx_event_pipe.c --- a/src/event/ngx_event_pipe.c +++ b/src/event/ngx_event_pipe.c @@ -245,8 +245,10 @@ int ngx_event_pipe_read_upstream(ngx_eve p->upstream_eof = 1; break; } + } + p->read_length += n; cl = chain; while (cl && n > 0) { @@ -402,6 +404,18 @@ int ngx_event_pipe_write_to_downstream(n for (cl = p->free; cl; cl = cl->next) { + if (cl->hunk->type & NGX_HUNK_TEMP_FILE) { + if (p->cachable || !p->cyclic_temp_file) { + continue; + } + + /* reset p->temp_offset if all hunks had been sent */ + + if (cl->hunk->file_last == p->temp_file->offset) { + p->temp_file->offset = 0; + } + } + /* TODO: free hunk if p->free_bufs && upstream done */ /* add the free shadow raw hunk to p->free_raw_hunks */ @@ -416,6 +430,7 @@ int ngx_event_pipe_write_to_downstream(n } cl->hunk->shadow = NULL; +#if 0 if (p->cyclic_temp_file && (cl->hunk->type & NGX_HUNK_TEMP_FILE)) { /* reset p->temp_offset if all hunks had been sent */ @@ -424,6 +439,7 @@ int ngx_event_pipe_write_to_downstream(n p->temp_file->offset = 0; } } +#endif } } @@ -518,11 +534,15 @@ ngx_log_debug(p->log, "size: %d" _ size) p->temp_file->offset += h->last - h->pos; h->file_last = p->temp_file->offset; + h->type |= NGX_HUNK_FILE|NGX_HUNK_TEMP_FILE; + +#if 0 if (p->cachable) { h->type |= NGX_HUNK_FILE; } else { h->type |= NGX_HUNK_FILE|NGX_HUNK_TEMP_FILE; } +#endif ngx_chain_add_link(p->out, p->last_out, cl); diff --git a/src/event/ngx_event_pipe.h b/src/event/ngx_event_pipe.h --- a/src/event/ngx_event_pipe.h +++ b/src/event/ngx_event_pipe.h @@ -54,6 +54,8 @@ struct ngx_event_pipe_s { size_t busy_size; + off_t read_length; + off_t max_temp_file_size; int temp_file_write_size; diff --git a/src/event/ngx_event_timer.c b/src/event/ngx_event_timer.c --- a/src/event/ngx_event_timer.c +++ b/src/event/ngx_event_timer.c @@ -173,7 +173,6 @@ void ngx_event_expire_timers(ngx_msec_t delta -= ev->timer_delta; ngx_del_timer(ev); - ev->timer_set = 0; if (ev->delayed) { ev->delayed = 0; 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 @@ -216,6 +216,30 @@ static int ngx_http_proxy_process_cached } +#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_ 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 --- 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_ht 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_ht 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 "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 } -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_co 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 --- 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 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 --- 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 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_upstre } +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( } 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( 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->lo } 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->lo } } - 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 --- a/src/http/ngx_http_busy_lock.c +++ b/src/http/ngx_http_busy_lock.c @@ -4,6 +4,61 @@ #include +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_co 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_co 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 --- 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 --- 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_req 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: ctx->buf->last += n; if (ctx->expires < ngx_time()) { +ngx_log_debug(r->connection->log, "EXPIRED"); return NGX_HTTP_CACHE_STALE; }