aboutsummaryrefslogtreecommitdiff
path: root/src/http
diff options
context:
space:
mode:
Diffstat (limited to 'src/http')
-rw-r--r--src/http/ngx_http_cache.h1
-rw-r--r--src/http/ngx_http_copy_filter_module.c53
-rw-r--r--src/http/ngx_http_core_module.c17
-rw-r--r--src/http/ngx_http_core_module.h3
-rw-r--r--src/http/ngx_http_file_cache.c109
-rw-r--r--src/http/ngx_http_request.c28
-rw-r--r--src/http/ngx_http_request.h9
-rw-r--r--src/http/ngx_http_upstream.c74
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. */