diff options
Diffstat (limited to 'src/http')
-rw-r--r-- | src/http/ngx_http_cache.h | 1 | ||||
-rw-r--r-- | src/http/ngx_http_copy_filter_module.c | 53 | ||||
-rw-r--r-- | src/http/ngx_http_core_module.c | 17 | ||||
-rw-r--r-- | src/http/ngx_http_core_module.h | 3 | ||||
-rw-r--r-- | src/http/ngx_http_file_cache.c | 109 | ||||
-rw-r--r-- | src/http/ngx_http_request.c | 28 | ||||
-rw-r--r-- | src/http/ngx_http_request.h | 9 | ||||
-rw-r--r-- | src/http/ngx_http_upstream.c | 74 |
8 files changed, 238 insertions, 56 deletions
diff --git a/src/http/ngx_http_cache.h b/src/http/ngx_http_cache.h index 6ac6fd876..e04eba3a4 100644 --- a/src/http/ngx_http_cache.h +++ b/src/http/ngx_http_cache.h @@ -18,6 +18,7 @@ #define NGX_HTTP_CACHE_STALE 3 #define NGX_HTTP_CACHE_UPDATING 4 #define NGX_HTTP_CACHE_HIT 5 +#define NGX_HTTP_CACHE_SCARCE 6 #define NGX_HTTP_CACHE_KEY_LEN 16 diff --git a/src/http/ngx_http_copy_filter_module.c b/src/http/ngx_http_copy_filter_module.c index 688677f50..411e731f3 100644 --- a/src/http/ngx_http_copy_filter_module.c +++ b/src/http/ngx_http_copy_filter_module.c @@ -14,6 +14,12 @@ typedef struct { } ngx_http_copy_filter_conf_t; +#if (NGX_HAVE_FILE_AIO) +static void ngx_http_copy_aio_handler(ngx_output_chain_ctx_t *ctx, + ngx_file_t *file); +static void ngx_http_copy_aio_event_handler(ngx_event_t *ev); +#endif + static void *ngx_http_copy_filter_create_conf(ngx_conf_t *cf); static char *ngx_http_copy_filter_merge_conf(ngx_conf_t *cf, void *parent, void *child); @@ -73,10 +79,15 @@ ngx_http_copy_filter(ngx_http_request_t *r, ngx_chain_t *in) ngx_int_t rc; ngx_connection_t *c; ngx_output_chain_ctx_t *ctx; + ngx_http_core_loc_conf_t *clcf; ngx_http_copy_filter_conf_t *conf; c = r->connection; + if (r->aio) { + return NGX_AGAIN; + } + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "copy filter: \"%V?%V\"", &r->uri, &r->args); @@ -104,6 +115,13 @@ ngx_http_copy_filter(ngx_http_request_t *r, ngx_chain_t *in) ctx->output_filter = (ngx_output_chain_filter_pt) ngx_http_next_filter; ctx->filter_ctx = r; +#if (NGX_HAVE_FILE_AIO) + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + if (clcf->aio) { + ctx->aio = ngx_http_copy_aio_handler; + } +#endif + r->request_output = 1; } @@ -123,6 +141,41 @@ ngx_http_copy_filter(ngx_http_request_t *r, ngx_chain_t *in) } +#if (NGX_HAVE_FILE_AIO) + +static void +ngx_http_copy_aio_handler(ngx_output_chain_ctx_t *ctx, ngx_file_t *file) +{ + ngx_http_request_t *r; + + r = ctx->filter_ctx; + + file->aio->data = r; + file->aio->handler = ngx_http_copy_aio_event_handler; + + r->main->blocked++; + r->aio = 1; +} + + +static void +ngx_http_copy_aio_event_handler(ngx_event_t *ev) +{ + ngx_event_aio_t *aio; + ngx_http_request_t *r; + + aio = ev->data; + r = aio->data; + + r->main->blocked--; + r->aio = 0; + + r->connection->write->handler(r->connection->write); +} + +#endif + + static void * ngx_http_copy_filter_create_conf(ngx_conf_t *cf) { diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index 7b47fbb61..da91ee66a 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -383,6 +383,17 @@ static ngx_command_t ngx_http_core_commands[] = { offsetof(ngx_http_core_loc_conf_t, sendfile_max_chunk), NULL }, +#if (NGX_HAVE_FILE_AIO) + + { ngx_string("aio"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_core_loc_conf_t, aio), + NULL }, + +#endif + { ngx_string("directio"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_http_core_directio, @@ -2916,6 +2927,9 @@ ngx_http_core_create_loc_conf(ngx_conf_t *cf) lcf->internal = NGX_CONF_UNSET; lcf->sendfile = NGX_CONF_UNSET; lcf->sendfile_max_chunk = NGX_CONF_UNSET_SIZE; +#if (NGX_HAVE_FILE_AIO) + lcf->aio = NGX_CONF_UNSET; +#endif lcf->directio = NGX_CONF_UNSET; lcf->tcp_nopush = NGX_CONF_UNSET; lcf->tcp_nodelay = NGX_CONF_UNSET; @@ -3113,6 +3127,9 @@ ngx_http_core_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_value(conf->sendfile, prev->sendfile, 0); ngx_conf_merge_size_value(conf->sendfile_max_chunk, prev->sendfile_max_chunk, 0); +#if (NGX_HAVE_FILE_AIO) + ngx_conf_merge_value(conf->aio, prev->aio, 0); +#endif ngx_conf_merge_off_value(conf->directio, prev->directio, NGX_MAX_OFF_T_VALUE); ngx_conf_merge_value(conf->tcp_nopush, prev->tcp_nopush, 0); diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h index 71d5b953c..522509b41 100644 --- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -347,6 +347,9 @@ struct ngx_http_core_loc_conf_s { /* client_body_in_singe_buffer */ ngx_flag_t internal; /* internal */ ngx_flag_t sendfile; /* sendfile */ +#if (NGX_HAVE_FILE_AIO) + ngx_flag_t aio; /* aio */ +#endif ngx_flag_t tcp_nopush; /* tcp_nopush */ ngx_flag_t tcp_nodelay; /* tcp_nodelay */ ngx_flag_t reset_timedout_connection; /* reset_timedout_connection */ diff --git a/src/http/ngx_http_file_cache.c b/src/http/ngx_http_file_cache.c index 8972f47dc..a6271a8e9 100644 --- a/src/http/ngx_http_file_cache.c +++ b/src/http/ngx_http_file_cache.c @@ -10,6 +10,11 @@ #include <ngx_md5.h> +static ngx_int_t ngx_http_file_cache_read(ngx_http_request_t *r, + ngx_http_cache_t *c); +#if (NGX_HAVE_FILE_AIO) +static void ngx_http_cache_aio_event_handler(ngx_event_t *ev); +#endif static ngx_int_t ngx_http_file_cache_exists(ngx_http_file_cache_t *cache, ngx_http_cache_t *c); static ngx_http_file_cache_node_t * @@ -173,20 +178,22 @@ ngx_http_file_cache_create_key(ngx_http_request_t *r) ngx_int_t ngx_http_file_cache_open(ngx_http_request_t *r) { - u_char *p; - time_t now; - ssize_t n; - ngx_int_t rc, rv; - ngx_uint_t cold, test; - ngx_path_t *path; - ngx_http_cache_t *c; - ngx_pool_cleanup_t *cln; - ngx_open_file_info_t of; - ngx_http_file_cache_t *cache; - ngx_http_core_loc_conf_t *clcf; - ngx_http_file_cache_header_t *h; + u_char *p; + ngx_int_t rc, rv; + ngx_uint_t cold, test; + ngx_path_t *path; + ngx_http_cache_t *c; + ngx_pool_cleanup_t *cln; + ngx_open_file_info_t of; + ngx_http_file_cache_t *cache; + ngx_http_core_loc_conf_t *clcf; c = r->cache; + + if (c->buf) { + return ngx_http_file_cache_read(r, c); + } + cache = c->file_cache; cln = ngx_pool_cleanup_add(r->pool, 0); @@ -207,7 +214,7 @@ ngx_http_file_cache_open(ngx_http_request_t *r) cln->data = c; if (rc == NGX_AGAIN) { - return rc; + return NGX_HTTP_CACHE_SCARCE; } cold = cache->sh->cold; @@ -227,11 +234,11 @@ ngx_http_file_cache_open(ngx_http_request_t *r) if (c->min_uses > 1) { if (!cold) { - return NGX_AGAIN; + return NGX_HTTP_CACHE_SCARCE; } test = 1; - rv = NGX_AGAIN; + rv = NGX_HTTP_CACHE_SCARCE; } else { c->temp_file = 1; @@ -299,14 +306,58 @@ ngx_http_file_cache_open(ngx_http_request_t *r) c->file.fd = of.fd; c->file.log = r->connection->log; + c->uniq = of.uniq; + c->length = of.size; c->buf = ngx_create_temp_buf(r->pool, c->body_start); if (c->buf == NULL) { return NGX_ERROR; } + return ngx_http_file_cache_read(r, c); +} + + +static ngx_int_t +ngx_http_file_cache_read(ngx_http_request_t *r, ngx_http_cache_t *c) +{ + time_t now; + ssize_t n; + ngx_int_t rc; + ngx_http_file_cache_t *cache; + ngx_http_file_cache_header_t *h; + + c = r->cache; + +#if (NGX_HAVE_FILE_AIO) + { + ngx_http_core_loc_conf_t *clcf; + + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + if (clcf->aio) { + n = ngx_file_aio_read(&c->file, c->buf->pos, c->body_start, 0, r->pool); + + if (n == NGX_AGAIN) { + c->file.aio->data = r; + c->file.aio->handler = ngx_http_cache_aio_event_handler; + + r->main->blocked++; + r->aio = 1; + + return NGX_AGAIN; + } + + } else { + n = ngx_read_file(&c->file, c->buf->pos, c->body_start, 0); + } + } +#else + n = ngx_read_file(&c->file, c->buf->pos, c->body_start, 0); +#endif + if (n == NGX_ERROR) { return n; } @@ -331,12 +382,13 @@ ngx_http_file_cache_open(ngx_http_request_t *r) c->last_modified = h->last_modified; c->date = h->date; c->valid_msec = h->valid_msec; - c->length = of.size; c->body_start = h->body_start; r->cached = 1; - if (cold) { + cache = c->file_cache; + + if (cache->sh->cold) { ngx_shmtx_lock(&cache->shpool->mutex); @@ -344,7 +396,7 @@ ngx_http_file_cache_open(ngx_http_request_t *r) c->node->uses = 1; c->node->body_start = c->body_start; c->node->exists = 1; - c->node->uniq = of.uniq; + c->node->uniq = c->uniq; cache->sh->size += (c->length + cache->bsize - 1) / cache->bsize; } @@ -379,6 +431,27 @@ ngx_http_file_cache_open(ngx_http_request_t *r) } +#if (NGX_HAVE_FILE_AIO) + + +static void +ngx_http_cache_aio_event_handler(ngx_event_t *ev) +{ + ngx_event_aio_t *aio; + ngx_http_request_t *r; + + aio = ev->data; + r = aio->data; + + r->main->blocked--; + r->aio = 0; + + r->connection->write->handler(r->connection->write); +} + +#endif + + static ngx_int_t ngx_http_file_cache_exists(ngx_http_file_cache_t *cache, ngx_http_cache_t *c) { diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c index ea8843bfc..5f46e61cc 100644 --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -1868,6 +1868,10 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc) return; } + if (r->main->blocked) { + r->write_event_handler = ngx_http_request_finalizer; + } + ngx_http_terminate_request(r, rc); return; } @@ -1969,7 +1973,7 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc) return; } - if (r->buffered || c->buffered || r->postponed) { + if (r->buffered || c->buffered || r->postponed || r->blocked) { if (ngx_http_set_write_handler(r) != NGX_OK) { ngx_http_terminate_request(r, 0); @@ -2022,7 +2026,7 @@ ngx_http_terminate_request(ngx_http_request_t *r, ngx_int_t rc) mr = r->main; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http terminate request count: %d", mr->count); + "http terminate request count:%d", mr->count); cln = mr->cleanup; mr->cleanup = NULL; @@ -2035,10 +2039,16 @@ ngx_http_terminate_request(ngx_http_request_t *r, ngx_int_t rc) cln = cln->next; } - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http terminate cleanup count: %d", mr->count); + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http terminate cleanup count:%d blk:%d", + mr->count, mr->blocked); if (mr->write_event_handler) { + + if (mr->blocked) { + return; + } + mr->posted_requests = NULL; mr->write_event_handler = ngx_http_terminate_handler; (void) ngx_http_post_request(mr); @@ -2053,7 +2063,7 @@ static void ngx_http_terminate_handler(ngx_http_request_t *r) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http terminate handler count: %d", r->count); + "http terminate handler count:%d", r->count); r->count = 1; @@ -2161,7 +2171,7 @@ ngx_http_writer(ngx_http_request_t *r) } } else { - if (wev->delayed) { + if (wev->delayed || r->aio) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0, "http writer delayed"); @@ -2830,8 +2840,8 @@ ngx_http_close_request(ngx_http_request_t *r, ngx_int_t rc) r = r->main; c = r->connection; - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, - "http request count: %d", r->count); + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http request count:%d blk:%d", r->count, r->blocked); if (r->count == 0) { ngx_log_error(NGX_LOG_ALERT, c->log, 0, "http request count is zero"); @@ -2839,7 +2849,7 @@ ngx_http_close_request(ngx_http_request_t *r, ngx_int_t rc) r->count--; - if (r->count) { + if (r->count || r->blocked) { return; } diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h index 7b984fb27..52ac90c23 100644 --- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -416,6 +416,12 @@ struct ngx_http_request_s { ngx_http_cleanup_t *cleanup; + unsigned subrequests:8; + unsigned count:8; + unsigned blocked:8; + + unsigned aio:1; + unsigned http_state:4; /* URI with "/." and on Win32 with "//" */ @@ -501,9 +507,6 @@ struct ngx_http_request_s { unsigned stat_writing:1; #endif - unsigned subrequests:8; - unsigned count:8; - /* used to parse HTTP headers */ ngx_uint_t state; diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c index f552d2e76..a864fb16d 100644 --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -18,6 +18,7 @@ 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_init_request(ngx_http_request_t *r); static void ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t *ctx); static void ngx_http_upstream_rd_check_broken_connection(ngx_http_request_t *r); static void ngx_http_upstream_wr_check_broken_connection(ngx_http_request_t *r); @@ -386,15 +387,7 @@ ngx_http_upstream_create(ngx_http_request_t *r) void ngx_http_upstream_init(ngx_http_request_t *r) { - ngx_str_t *host; - ngx_uint_t i; - ngx_connection_t *c; - ngx_resolver_ctx_t *ctx, temp; - ngx_http_cleanup_t *cln; - ngx_http_upstream_t *u; - ngx_http_core_loc_conf_t *clcf; - ngx_http_upstream_srv_conf_t *uscf, **uscfp; - ngx_http_upstream_main_conf_t *umcf; + ngx_connection_t *c; c = r->connection; @@ -405,15 +398,6 @@ ngx_http_upstream_init(ngx_http_request_t *r) ngx_del_timer(c->read); } - u = r->upstream; - - u->store = (u->conf->store || u->conf->store_lengths); - - if (!u->store && !r->post_action && !u->conf->ignore_client_abort) { - r->read_event_handler = ngx_http_upstream_rd_check_broken_connection; - r->write_event_handler = ngx_http_upstream_wr_check_broken_connection; - } - if (ngx_event_flags & NGX_USE_CLEAR_EVENT) { if (!c->write->active) { @@ -426,10 +410,28 @@ ngx_http_upstream_init(ngx_http_request_t *r) } } - if (r->request_body) { - u->request_bufs = r->request_body->bufs; + ngx_http_upstream_init_request(r); +} + + +static void +ngx_http_upstream_init_request(ngx_http_request_t *r) +{ + ngx_str_t *host; + ngx_uint_t i; + ngx_resolver_ctx_t *ctx, temp; + ngx_http_cleanup_t *cln; + ngx_http_upstream_t *u; + ngx_http_core_loc_conf_t *clcf; + ngx_http_upstream_srv_conf_t *uscf, **uscfp; + ngx_http_upstream_main_conf_t *umcf; + + if (r->aio) { + return; } + u = r->upstream; + #if (NGX_HTTP_CACHE) if (u->conf->cache) { @@ -437,6 +439,11 @@ ngx_http_upstream_init(ngx_http_request_t *r) rc = ngx_http_upstream_cache(r, u); + if (rc == NGX_AGAIN) { + r->write_event_handler = ngx_http_upstream_init_request; + return; + } + if (rc == NGX_DONE) { return; } @@ -449,6 +456,17 @@ ngx_http_upstream_init(ngx_http_request_t *r) #endif + u->store = (u->conf->store || u->conf->store_lengths); + + if (!u->store && !r->post_action && !u->conf->ignore_client_abort) { + r->read_event_handler = ngx_http_upstream_rd_check_broken_connection; + r->write_event_handler = ngx_http_upstream_wr_check_broken_connection; + } + + if (r->request_body) { + u->request_bufs = r->request_body->bufs; + } + if (u->create_request(r) != NGX_OK) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return; @@ -543,7 +561,7 @@ ngx_http_upstream_init(ngx_http_request_t *r) } if (ctx == NGX_NO_RESOLVER) { - ngx_log_error(NGX_LOG_ERR, c->log, 0, + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "no resolver defined to resolve %V", host); ngx_http_finalize_request(r, NGX_HTTP_BAD_GATEWAY); @@ -657,10 +675,6 @@ ngx_http_upstream_cache(ngx_http_request_t *r, ngx_http_upstream_t *u) break; - case NGX_ERROR: - - return NGX_ERROR; - case NGX_HTTP_CACHE_STALE: c->valid_sec = 0; @@ -681,12 +695,20 @@ ngx_http_upstream_cache(ngx_http_request_t *r, ngx_http_upstream_t *u) break; - case NGX_AGAIN: + case NGX_HTTP_CACHE_SCARCE: u->cacheable = 0; break; + case NGX_AGAIN: + + return NGX_AGAIN; + + case NGX_ERROR: + + return NGX_ERROR; + default: /* cached NGX_HTTP_BAD_GATEWAY, NGX_HTTP_GATEWAY_TIME_OUT, etc. */ |