summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornginx <nginx@nginx.org>2014-09-30 13:30:36 +0000
committerJon Kolb <kolbyjack@gmail.com>2014-09-30 13:30:36 +0000
commit4aeefe1f3cef9d863cc04f7ee3fe2c730e6cfdf1 (patch)
tree40d86068ccd6d06c9866bd809af03830e89752cd
parentbb8c0683da773566e09797ef8a4ee00ad1e0f956 (diff)
downloadnginx-4aeefe1f3cef9d863cc04f7ee3fe2c730e6cfdf1.tar.gz
Changes with nginx 1.7.6 30 Sep 2014v1.7.6
*) Change: the deprecated "limit_zone" directive is not supported anymore. *) Feature: the "limit_conn_zone" and "limit_req_zone" directives now can be used with combinations of multiple variables. *) Bugfix: request body might be transmitted incorrectly when retrying a FastCGI request to the next upstream server. *) Bugfix: in logging to syslog.
-rw-r--r--CHANGES14
-rw-r--r--CHANGES.ru13
-rw-r--r--src/core/nginx.h4
-rw-r--r--src/core/ngx_buf.c46
-rw-r--r--src/core/ngx_buf.h1
-rw-r--r--src/core/ngx_syslog.c39
-rw-r--r--src/core/ngx_syslog.h2
-rw-r--r--src/http/modules/ngx_http_fastcgi_module.c1
-rw-r--r--src/http/modules/ngx_http_limit_conn_module.c227
-rw-r--r--src/http/modules/ngx_http_limit_req_module.c120
-rw-r--r--src/http/modules/ngx_http_upstream_keepalive_module.c1
-rw-r--r--src/http/ngx_http.c6
-rw-r--r--src/http/ngx_http_upstream.c11
-rw-r--r--src/os/unix/ngx_darwin_sendfile_chain.c65
-rw-r--r--src/os/unix/ngx_freebsd_sendfile_chain.c63
-rw-r--r--src/os/unix/ngx_linux_sendfile_chain.c57
-rw-r--r--src/os/unix/ngx_os.h7
-rw-r--r--src/os/unix/ngx_readv_chain.c119
-rw-r--r--src/os/unix/ngx_solaris_sendfilev_chain.c53
-rw-r--r--src/os/unix/ngx_writev_chain.c52
20 files changed, 297 insertions, 604 deletions
diff --git a/CHANGES b/CHANGES
index ac1fac018..ddfb80014 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,18 @@
+Changes with nginx 1.7.6 30 Sep 2014
+
+ *) Change: the deprecated "limit_zone" directive is not supported
+ anymore.
+
+ *) Feature: the "limit_conn_zone" and "limit_req_zone" directives now
+ can be used with combinations of multiple variables.
+
+ *) Bugfix: request body might be transmitted incorrectly when retrying a
+ FastCGI request to the next upstream server.
+
+ *) Bugfix: in logging to syslog.
+
+
Changes with nginx 1.7.5 16 Sep 2014
*) Security: it was possible to reuse SSL sessions in unrelated contexts
diff --git a/CHANGES.ru b/CHANGES.ru
index dcdab4e0a..4eff3ccf9 100644
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,17 @@
+Изменения в nginx 1.7.6 30.09.2014
+
+ *) Изменение: устаревшая директива limit_zone больше не поддерживается.
+
+ *) Добавление: в директивах limit_conn_zone и limit_req_zone теперь
+ можно использовать комбинации нескольких переменных.
+
+ *) Исправление: при повторной отправке FastCGI-запроса на бэкенд тело
+ запроса могло передаваться неправильно.
+
+ *) Исправление: в логгировании в syslog.
+
+
Изменения в nginx 1.7.5 16.09.2014
*) Безопасность: при использовании общего для нескольких блоков server
diff --git a/src/core/nginx.h b/src/core/nginx.h
index 4524e005e..3030b44b4 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -9,8 +9,8 @@
#define _NGINX_H_INCLUDED_
-#define nginx_version 1007005
-#define NGINX_VERSION "1.7.5"
+#define nginx_version 1007006
+#define NGINX_VERSION "1.7.6"
#define NGINX_VER "nginx/" NGINX_VERSION
#ifdef NGX_BUILD
diff --git a/src/core/ngx_buf.c b/src/core/ngx_buf.c
index 835c76ced..94a3d3f10 100644
--- a/src/core/ngx_buf.c
+++ b/src/core/ngx_buf.c
@@ -218,3 +218,49 @@ ngx_chain_update_chains(ngx_pool_t *p, ngx_chain_t **free, ngx_chain_t **busy,
*free = cl;
}
}
+
+
+ngx_chain_t *
+ngx_handle_sent_chain(ngx_chain_t *in, off_t sent)
+{
+ off_t size;
+
+ for ( /* void */ ; in; in = in->next) {
+
+ if (ngx_buf_special(in->buf)) {
+ continue;
+ }
+
+ if (sent == 0) {
+ break;
+ }
+
+ size = ngx_buf_size(in->buf);
+
+ if (sent >= size) {
+ sent -= size;
+
+ if (ngx_buf_in_memory(in->buf)) {
+ in->buf->pos = in->buf->last;
+ }
+
+ if (in->buf->in_file) {
+ in->buf->file_pos = in->buf->file_last;
+ }
+
+ continue;
+ }
+
+ if (ngx_buf_in_memory(in->buf)) {
+ in->buf->pos += (size_t) sent;
+ }
+
+ if (in->buf->in_file) {
+ in->buf->file_pos += sent;
+ }
+
+ break;
+ }
+
+ return in;
+}
diff --git a/src/core/ngx_buf.h b/src/core/ngx_buf.h
index ffc531094..cc28a3e15 100644
--- a/src/core/ngx_buf.h
+++ b/src/core/ngx_buf.h
@@ -158,5 +158,6 @@ ngx_chain_t *ngx_chain_get_free_buf(ngx_pool_t *p, ngx_chain_t **free);
void ngx_chain_update_chains(ngx_pool_t *p, ngx_chain_t **free,
ngx_chain_t **busy, ngx_chain_t **out, ngx_buf_tag_t tag);
+ngx_chain_t *ngx_handle_sent_chain(ngx_chain_t *in, off_t sent);
#endif /* _NGX_BUF_H_INCLUDED_ */
diff --git a/src/core/ngx_syslog.c b/src/core/ngx_syslog.c
index e6d40f48a..616fd712e 100644
--- a/src/core/ngx_syslog.c
+++ b/src/core/ngx_syslog.c
@@ -234,11 +234,11 @@ ngx_syslog_writer(ngx_log_t *log, ngx_uint_t level, u_char *buf,
peer = log->wdata;
- if (peer->processing) {
+ if (peer->busy) {
return;
}
- peer->processing = 1;
+ peer->busy = 1;
peer->severity = level - 1;
p = ngx_syslog_add_header(peer, msg);
@@ -254,26 +254,47 @@ ngx_syslog_writer(ngx_log_t *log, ngx_uint_t level, u_char *buf,
(void) ngx_syslog_send(peer, msg, p - msg);
- peer->processing = 0;
+ peer->busy = 0;
}
ssize_t
ngx_syslog_send(ngx_syslog_peer_t *peer, u_char *buf, size_t len)
{
+ ssize_t n;
+
if (peer->conn.fd == (ngx_socket_t) -1) {
if (ngx_syslog_init_peer(peer) != NGX_OK) {
return NGX_ERROR;
}
}
+ /* log syslog socket events with valid log */
+ peer->conn.log = ngx_cycle->log;
+
if (ngx_send) {
- return ngx_send(&peer->conn, buf, len);
+ n = ngx_send(&peer->conn, buf, len);
} else {
/* event module has not yet set ngx_io */
- return ngx_os_io.send(&peer->conn, buf, len);
+ n = ngx_os_io.send(&peer->conn, buf, len);
+ }
+
+#if (NGX_HAVE_UNIX_DOMAIN)
+
+ if (n == NGX_ERROR && peer->server.sockaddr->sa_family == AF_UNIX) {
+
+ if (ngx_close_socket(peer->conn.fd) == -1) {
+ ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_socket_errno,
+ ngx_close_socket_n " failed");
+ }
+
+ peer->conn.fd = (ngx_socket_t) -1;
}
+
+#endif
+
+ return n;
}
@@ -285,7 +306,6 @@ ngx_syslog_init_peer(ngx_syslog_peer_t *peer)
peer->conn.read = &ngx_syslog_dummy_event;
peer->conn.write = &ngx_syslog_dummy_event;
- peer->conn.log = &ngx_syslog_dummy_log;
ngx_syslog_dummy_event.log = &ngx_syslog_dummy_log;
@@ -339,6 +359,13 @@ ngx_syslog_cleanup(void *data)
{
ngx_syslog_peer_t *peer = data;
+ /* prevents further use of this peer */
+ peer->busy = 1;
+
+ if (peer->conn.fd == (ngx_socket_t) -1) {
+ return;
+ }
+
if (ngx_close_socket(peer->conn.fd) == -1) {
ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_socket_errno,
ngx_close_socket_n " failed");
diff --git a/src/core/ngx_syslog.h b/src/core/ngx_syslog.h
index 92d47d5f5..a9150516f 100644
--- a/src/core/ngx_syslog.h
+++ b/src/core/ngx_syslog.h
@@ -16,7 +16,7 @@ typedef struct {
ngx_addr_t server;
ngx_connection_t conn;
- ngx_uint_t processing; /* unsigned processing:1; */
+ ngx_uint_t busy; /* unsigned busy:1; */
} ngx_syslog_peer_t;
diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c
index 9847ec170..a49c93ca2 100644
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -1129,6 +1129,7 @@ ngx_http_fastcgi_create_request(ngx_http_request_t *r)
} else {
b->pos = pos;
+ b->start = pos;
pos += 32 * 1024;
if (pos >= body->buf->last) {
diff --git a/src/http/modules/ngx_http_limit_conn_module.c b/src/http/modules/ngx_http_limit_conn_module.c
index 7f0eea7ab..4379311ca 100644
--- a/src/http/modules/ngx_http_limit_conn_module.c
+++ b/src/http/modules/ngx_http_limit_conn_module.c
@@ -11,41 +11,40 @@
typedef struct {
- u_char color;
- u_char len;
- u_short conn;
- u_char data[1];
+ u_char color;
+ u_char len;
+ u_short conn;
+ u_char data[1];
} ngx_http_limit_conn_node_t;
typedef struct {
- ngx_shm_zone_t *shm_zone;
- ngx_rbtree_node_t *node;
+ ngx_shm_zone_t *shm_zone;
+ ngx_rbtree_node_t *node;
} ngx_http_limit_conn_cleanup_t;
typedef struct {
- ngx_rbtree_t *rbtree;
- ngx_int_t index;
- ngx_str_t var;
+ ngx_rbtree_t *rbtree;
+ ngx_http_complex_value_t key;
} ngx_http_limit_conn_ctx_t;
typedef struct {
- ngx_shm_zone_t *shm_zone;
- ngx_uint_t conn;
+ ngx_shm_zone_t *shm_zone;
+ ngx_uint_t conn;
} ngx_http_limit_conn_limit_t;
typedef struct {
- ngx_array_t limits;
- ngx_uint_t log_level;
- ngx_uint_t status_code;
+ ngx_array_t limits;
+ ngx_uint_t log_level;
+ ngx_uint_t status_code;
} ngx_http_limit_conn_conf_t;
static ngx_rbtree_node_t *ngx_http_limit_conn_lookup(ngx_rbtree_t *rbtree,
- ngx_http_variable_value_t *vv, uint32_t hash);
+ ngx_str_t *key, uint32_t hash);
static void ngx_http_limit_conn_cleanup(void *data);
static ngx_inline void ngx_http_limit_conn_cleanup_all(ngx_pool_t *pool);
@@ -54,18 +53,11 @@ static char *ngx_http_limit_conn_merge_conf(ngx_conf_t *cf, void *parent,
void *child);
static char *ngx_http_limit_conn_zone(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
-static char *ngx_http_limit_zone(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
static char *ngx_http_limit_conn(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static ngx_int_t ngx_http_limit_conn_init(ngx_conf_t *cf);
-static ngx_conf_deprecated_t ngx_conf_deprecated_limit_zone = {
- ngx_conf_deprecated, "limit_zone", "limit_conn_zone"
-};
-
-
static ngx_conf_enum_t ngx_http_limit_conn_log_levels[] = {
{ ngx_string("info"), NGX_LOG_INFO },
{ ngx_string("notice"), NGX_LOG_NOTICE },
@@ -89,13 +81,6 @@ static ngx_command_t ngx_http_limit_conn_commands[] = {
0,
NULL },
- { ngx_string("limit_zone"),
- NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE3,
- ngx_http_limit_zone,
- 0,
- 0,
- NULL },
-
{ ngx_string("limit_conn"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
ngx_http_limit_conn,
@@ -155,13 +140,13 @@ ngx_module_t ngx_http_limit_conn_module = {
static ngx_int_t
ngx_http_limit_conn_handler(ngx_http_request_t *r)
{
- size_t len, n;
+ size_t n;
uint32_t hash;
+ ngx_str_t key;
ngx_uint_t i;
ngx_slab_pool_t *shpool;
ngx_rbtree_node_t *node;
ngx_pool_cleanup_t *cln;
- ngx_http_variable_value_t *vv;
ngx_http_limit_conn_ctx_t *ctx;
ngx_http_limit_conn_node_t *lc;
ngx_http_limit_conn_conf_t *lccf;
@@ -178,41 +163,37 @@ ngx_http_limit_conn_handler(ngx_http_request_t *r)
for (i = 0; i < lccf->limits.nelts; i++) {
ctx = limits[i].shm_zone->data;
- vv = ngx_http_get_indexed_variable(r, ctx->index);
-
- if (vv == NULL || vv->not_found) {
- continue;
+ if (ngx_http_complex_value(r, &ctx->key, &key) != NGX_OK) {
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
- len = vv->len;
-
- if (len == 0) {
+ if (key.len == 0) {
continue;
}
- if (len > 255) {
+ if (key.len > 255) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "the value of the \"%V\" variable "
- "is more than 255 bytes: \"%v\"",
- &ctx->var, vv);
+ "the value of the \"%V\" key "
+ "is more than 255 bytes: \"%V\"",
+ &ctx->key.value, &key);
continue;
}
r->main->limit_conn_set = 1;
- hash = ngx_crc32_short(vv->data, len);
+ hash = ngx_crc32_short(key.data, key.len);
shpool = (ngx_slab_pool_t *) limits[i].shm_zone->shm.addr;
ngx_shmtx_lock(&shpool->mutex);
- node = ngx_http_limit_conn_lookup(ctx->rbtree, vv, hash);
+ node = ngx_http_limit_conn_lookup(ctx->rbtree, &key, hash);
if (node == NULL) {
n = offsetof(ngx_rbtree_node_t, color)
+ offsetof(ngx_http_limit_conn_node_t, data)
- + len;
+ + key.len;
node = ngx_slab_alloc_locked(shpool, n);
@@ -225,9 +206,9 @@ ngx_http_limit_conn_handler(ngx_http_request_t *r)
lc = (ngx_http_limit_conn_node_t *) &node->color;
node->key = hash;
- lc->len = (u_char) len;
+ lc->len = (u_char) key.len;
lc->conn = 1;
- ngx_memcpy(lc->data, vv->data, len);
+ ngx_memcpy(lc->data, key.data, key.len);
ngx_rbtree_insert(ctx->rbtree, node);
@@ -314,8 +295,7 @@ ngx_http_limit_conn_rbtree_insert_value(ngx_rbtree_node_t *temp,
static ngx_rbtree_node_t *
-ngx_http_limit_conn_lookup(ngx_rbtree_t *rbtree, ngx_http_variable_value_t *vv,
- uint32_t hash)
+ngx_http_limit_conn_lookup(ngx_rbtree_t *rbtree, ngx_str_t *key, uint32_t hash)
{
ngx_int_t rc;
ngx_rbtree_node_t *node, *sentinel;
@@ -340,8 +320,8 @@ ngx_http_limit_conn_lookup(ngx_rbtree_t *rbtree, ngx_http_variable_value_t *vv,
lcn = (ngx_http_limit_conn_node_t *) &node->color;
- rc = ngx_memn2cmp(vv->data, lcn->data,
- (size_t) vv->len, (size_t) lcn->len);
+ rc = ngx_memn2cmp(key->data, lcn->data, key->len, (size_t) lcn->len);
+
if (rc == 0) {
return node;
}
@@ -413,11 +393,16 @@ ngx_http_limit_conn_init_zone(ngx_shm_zone_t *shm_zone, void *data)
ctx = shm_zone->data;
if (octx) {
- if (ngx_strcmp(ctx->var.data, octx->var.data) != 0) {
+ if (ctx->key.value.len != octx->key.value.len
+ || ngx_strncmp(ctx->key.value.data, octx->key.value.data,
+ ctx->key.value.len)
+ != 0)
+ {
ngx_log_error(NGX_LOG_EMERG, shm_zone->shm.log, 0,
- "limit_conn_zone \"%V\" uses the \"%V\" variable "
- "while previously it used the \"%V\" variable",
- &shm_zone->shm.name, &ctx->var, &octx->var);
+ "limit_conn_zone \"%V\" uses the \"%V\" key "
+ "while previously it used the \"%V\" key",
+ &shm_zone->shm.name, &ctx->key.value,
+ &octx->key.value);
return NGX_ERROR;
}
@@ -507,20 +492,35 @@ ngx_http_limit_conn_merge_conf(ngx_conf_t *cf, void *parent, void *child)
static char *
ngx_http_limit_conn_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
- u_char *p;
- ssize_t size;
- ngx_str_t *value, name, s;
- ngx_uint_t i;
- ngx_shm_zone_t *shm_zone;
- ngx_http_limit_conn_ctx_t *ctx;
+ u_char *p;
+ ssize_t size;
+ ngx_str_t *value, name, s;
+ ngx_uint_t i;
+ ngx_shm_zone_t *shm_zone;
+ ngx_http_limit_conn_ctx_t *ctx;
+ ngx_http_compile_complex_value_t ccv;
value = cf->args->elts;
- ctx = NULL;
+ ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_limit_conn_ctx_t));
+ if (ctx == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
+
+ ccv.cf = cf;
+ ccv.value = &value[1];
+ ccv.complex_value = &ctx->key;
+
+ if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+
size = 0;
name.len = 0;
- for (i = 1; i < cf->args->nelts; i++) {
+ for (i = 2; i < cf->args->nelts; i++) {
if (ngx_strncmp(value[i].data, "zone=", 5) == 0) {
@@ -556,26 +556,6 @@ ngx_http_limit_conn_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
continue;
}
- if (value[i].data[0] == '$') {
-
- value[i].len--;
- value[i].data++;
-
- ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_limit_conn_ctx_t));
- if (ctx == NULL) {
- return NGX_CONF_ERROR;
- }
-
- ctx->index = ngx_http_get_variable_index(cf, &value[i]);
- if (ctx->index == NGX_ERROR) {
- return NGX_CONF_ERROR;
- }
-
- ctx->var = value[i];
-
- continue;
- }
-
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid parameter \"%V\"", &value[i]);
return NGX_CONF_ERROR;
@@ -588,13 +568,6 @@ ngx_http_limit_conn_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_ERROR;
}
- if (ctx == NULL) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "no variable is defined for %V \"%V\"",
- &cmd->name, &name);
- return NGX_CONF_ERROR;
- }
-
shm_zone = ngx_shared_memory_add(cf, &name, size,
&ngx_http_limit_conn_module);
if (shm_zone == NULL) {
@@ -605,78 +578,8 @@ ngx_http_limit_conn_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ctx = shm_zone->data;
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "%V \"%V\" is already bound to variable \"%V\"",
- &cmd->name, &name, &ctx->var);
- return NGX_CONF_ERROR;
- }
-
- shm_zone->init = ngx_http_limit_conn_init_zone;
- shm_zone->data = ctx;
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_limit_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ssize_t n;
- ngx_str_t *value;
- ngx_shm_zone_t *shm_zone;
- ngx_http_limit_conn_ctx_t *ctx;
-
- ngx_conf_deprecated(cf, &ngx_conf_deprecated_limit_zone, NULL);
-
- value = cf->args->elts;
-
- if (value[2].data[0] != '$') {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid variable name \"%V\"", &value[2]);
- return NGX_CONF_ERROR;
- }
-
- value[2].len--;
- value[2].data++;
-
- ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_limit_conn_ctx_t));
- if (ctx == NULL) {
- return NGX_CONF_ERROR;
- }
-
- ctx->index = ngx_http_get_variable_index(cf, &value[2]);
- if (ctx->index == NGX_ERROR) {
- return NGX_CONF_ERROR;
- }
-
- ctx->var = value[2];
-
- n = ngx_parse_size(&value[3]);
-
- if (n == NGX_ERROR) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid size of limit_zone \"%V\"", &value[3]);
- return NGX_CONF_ERROR;
- }
-
- if (n < (ngx_int_t) (8 * ngx_pagesize)) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "limit_zone \"%V\" is too small", &value[1]);
- return NGX_CONF_ERROR;
- }
-
-
- shm_zone = ngx_shared_memory_add(cf, &value[1], n,
- &ngx_http_limit_conn_module);
- if (shm_zone == NULL) {
- return NGX_CONF_ERROR;
- }
-
- if (shm_zone->data) {
- ctx = shm_zone->data;
-
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "limit_zone \"%V\" is already bound to variable \"%V\"",
- &value[1], &ctx->var);
+ "%V \"%V\" is already bound to key \"%V\"",
+ &cmd->name, &name, &ctx->key.value);
return NGX_CONF_ERROR;
}
diff --git a/src/http/modules/ngx_http_limit_req_module.c b/src/http/modules/ngx_http_limit_req_module.c
index 74f7fdaa7..5d5cbe944 100644
--- a/src/http/modules/ngx_http_limit_req_module.c
+++ b/src/http/modules/ngx_http_limit_req_module.c
@@ -35,8 +35,7 @@ typedef struct {
ngx_slab_pool_t *shpool;
/* integer value, 1 corresponds to 0.001 r/s */
ngx_uint_t rate;
- ngx_int_t index;
- ngx_str_t var;
+ ngx_http_complex_value_t key;
ngx_http_limit_req_node_t *node;
} ngx_http_limit_req_ctx_t;
@@ -59,8 +58,7 @@ typedef struct {
static void ngx_http_limit_req_delay(ngx_http_request_t *r);
static ngx_int_t ngx_http_limit_req_lookup(ngx_http_limit_req_limit_t *limit,
- ngx_uint_t hash, u_char *data, size_t len, ngx_uint_t *ep,
- ngx_uint_t account);
+ ngx_uint_t hash, ngx_str_t *key, ngx_uint_t *ep, ngx_uint_t account);
static ngx_msec_t ngx_http_limit_req_account(ngx_http_limit_req_limit_t *limits,
ngx_uint_t n, ngx_uint_t *ep, ngx_http_limit_req_limit_t **limit);
static void ngx_http_limit_req_expire(ngx_http_limit_req_ctx_t *ctx,
@@ -158,12 +156,11 @@ ngx_module_t ngx_http_limit_req_module = {
static ngx_int_t
ngx_http_limit_req_handler(ngx_http_request_t *r)
{
- size_t len;
uint32_t hash;
+ ngx_str_t key;
ngx_int_t rc;
ngx_uint_t n, excess;
ngx_msec_t delay;
- ngx_http_variable_value_t *vv;
ngx_http_limit_req_ctx_t *ctx;
ngx_http_limit_req_conf_t *lrcf;
ngx_http_limit_req_limit_t *limit, *limits;
@@ -189,31 +186,27 @@ ngx_http_limit_req_handler(ngx_http_request_t *r)
ctx = limit->shm_zone->data;
- vv = ngx_http_get_indexed_variable(r, ctx->index);
-
- if (vv == NULL || vv->not_found) {
- continue;
+ if (ngx_http_complex_value(r, &ctx->key, &key) != NGX_OK) {
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
- len = vv->len;
-
- if (len == 0) {
+ if (key.len == 0) {
continue;
}
- if (len > 65535) {
+ if (key.len > 65535) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "the value of the \"%V\" variable "
- "is more than 65535 bytes: \"%v\"",
- &ctx->var, vv);
+ "the value of the \"%V\" key "
+ "is more than 65535 bytes: \"%V\"",
+ &ctx->key.value, &key);
continue;
}
- hash = ngx_crc32_short(vv->data, len);
+ hash = ngx_crc32_short(key.data, key.len);
ngx_shmtx_lock(&ctx->shpool->mutex);
- rc = ngx_http_limit_req_lookup(limit, hash, vv->data, len, &excess,
+ rc = ngx_http_limit_req_lookup(limit, hash, &key, &excess,
(n == lrcf->limits.nelts - 1));
ngx_shmtx_unlock(&ctx->shpool->mutex);
@@ -365,7 +358,7 @@ ngx_http_limit_req_rbtree_insert_value(ngx_rbtree_node_t *temp,
static ngx_int_t
ngx_http_limit_req_lookup(ngx_http_limit_req_limit_t *limit, ngx_uint_t hash,
- u_char *data, size_t len, ngx_uint_t *ep, ngx_uint_t account)
+ ngx_str_t *key, ngx_uint_t *ep, ngx_uint_t account)
{
size_t size;
ngx_int_t rc, excess;
@@ -400,7 +393,7 @@ ngx_http_limit_req_lookup(ngx_http_limit_req_limit_t *limit, ngx_uint_t hash,
lr = (ngx_http_limit_req_node_t *) &node->color;
- rc = ngx_memn2cmp(data, lr->data, len, (size_t) lr->len);
+ rc = ngx_memn2cmp(key->data, lr->data, key->len, (size_t) lr->len);
if (rc == 0) {
ngx_queue_remove(&lr->queue);
@@ -440,7 +433,7 @@ ngx_http_limit_req_lookup(ngx_http_limit_req_limit_t *limit, ngx_uint_t hash,
size = offsetof(ngx_rbtree_node_t, color)
+ offsetof(ngx_http_limit_req_node_t, data)
- + len;
+ + key->len;
ngx_http_limit_req_expire(ctx, 1);
@@ -461,10 +454,10 @@ ngx_http_limit_req_lookup(ngx_http_limit_req_limit_t *limit, ngx_uint_t hash,
lr = (ngx_http_limit_req_node_t *) &node->color;
- lr->len = (u_char) len;
+ lr->len = (u_short) key->len;
lr->excess = 0;
- ngx_memcpy(lr->data, data, len);
+ ngx_memcpy(lr->data, key->data, key->len);
ngx_rbtree_insert(&ctx->sh->rbtree, node);
@@ -632,11 +625,16 @@ ngx_http_limit_req_init_zone(ngx_shm_zone_t *shm_zone, void *data)
ctx = shm_zone->data;
if (octx) {
- if (ngx_strcmp(ctx->var.data, octx->var.data) != 0) {
+ if (ctx->key.value.len != octx->key.value.len
+ || ngx_strncmp(ctx->key.value.data, octx->key.value.data,
+ ctx->key.value.len)
+ != 0)
+ {
ngx_log_error(NGX_LOG_EMERG, shm_zone->shm.log, 0,
- "limit_req \"%V\" uses the \"%V\" variable "
- "while previously it used the \"%V\" variable",
- &shm_zone->shm.name, &ctx->var, &octx->var);
+ "limit_req \"%V\" uses the \"%V\" key "
+ "while previously it used the \"%V\" key",
+ &shm_zone->shm.name, &ctx->key.value,
+ &octx->key.value);
return NGX_ERROR;
}
@@ -731,24 +729,39 @@ ngx_http_limit_req_merge_conf(ngx_conf_t *cf, void *parent, void *child)
static char *
ngx_http_limit_req_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
- u_char *p;
- size_t len;
- ssize_t size;
- ngx_str_t *value, name, s;
- ngx_int_t rate, scale;
- ngx_uint_t i;
- ngx_shm_zone_t *shm_zone;
- ngx_http_limit_req_ctx_t *ctx;
+ u_char *p;
+ size_t len;
+ ssize_t size;
+ ngx_str_t *value, name, s;
+ ngx_int_t rate, scale;
+ ngx_uint_t i;
+ ngx_shm_zone_t *shm_zone;
+ ngx_http_limit_req_ctx_t *ctx;
+ ngx_http_compile_complex_value_t ccv;
value = cf->args->elts;
- ctx = NULL;
+ ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_limit_req_ctx_t));
+ if (ctx == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
+
+ ccv.cf = cf;
+ ccv.value = &value[1];
+ ccv.complex_value = &ctx->key;
+
+ if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+
size = 0;
rate = 1;
scale = 1;
name.len = 0;
- for (i = 1; i < cf->args->nelts; i++) {
+ for (i = 2; i < cf->args->nelts; i++) {
if (ngx_strncmp(value[i].data, "zone=", 5) == 0) {
@@ -808,26 +821,6 @@ ngx_http_limit_req_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
continue;
}
- if (value[i].data[0] == '$') {
-
- value[i].len--;
- value[i].data++;
-
- ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_limit_req_ctx_t));
- if (ctx == NULL) {
- return NGX_CONF_ERROR;
- }
-
- ctx->index = ngx_http_get_variable_index(cf, &value[i]);
- if (ctx->index == NGX_ERROR) {
- return NGX_CONF_ERROR;
- }
-
- ctx->var = value[i];
-
- continue;
- }
-
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid parameter \"%V\"", &value[i]);
return NGX_CONF_ERROR;
@@ -840,13 +833,6 @@ ngx_http_limit_req_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_ERROR;
}
- if (ctx == NULL) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "no variable is defined for %V \"%V\"",
- &cmd->name, &name);
- return NGX_CONF_ERROR;
- }
-
ctx->rate = rate * 1000 / scale;
shm_zone = ngx_shared_memory_add(cf, &name, size,
@@ -859,8 +845,8 @@ ngx_http_limit_req_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ctx = shm_zone->data;
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "%V \"%V\" is already bound to variable \"%V\"",
- &cmd->name, &name, &ctx->var);
+ "%V \"%V\" is already bound to key \"%V\"",
+ &cmd->name, &name, &ctx->key.value);
return NGX_CONF_ERROR;
}
diff --git a/src/http/modules/ngx_http_upstream_keepalive_module.c b/src/http/modules/ngx_http_upstream_keepalive_module.c
index c1c1c70d6..f738f0cc1 100644
--- a/src/http/modules/ngx_http_upstream_keepalive_module.c
+++ b/src/http/modules/ngx_http_upstream_keepalive_module.c
@@ -248,6 +248,7 @@ ngx_http_upstream_get_keepalive_peer(ngx_peer_connection_t *pc, void *data)
"get keepalive peer: using connection %p", c);
c->idle = 0;
+ c->sent = 0;
c->log = pc->log;
c->read->log = pc->log;
c->write->log = pc->log;
diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c
index 31577f9a2..9c8d6cba4 100644
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -2005,7 +2005,7 @@ ngx_http_types_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
if (ngx_strcmp(value[i].data, type[n].key.data) == 0) {
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
"duplicate MIME type \"%V\"", &value[i]);
- continue;
+ goto next;
}
}
@@ -2017,6 +2017,10 @@ ngx_http_types_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
type->key = value[i];
type->key_hash = hash;
type->value = (void *) 4;
+
+ next:
+
+ continue;
}
return NGX_CONF_OK;
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index 000c6de69..d547ca74e 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -1570,6 +1570,7 @@ done:
static ngx_int_t
ngx_http_upstream_reinit(ngx_http_request_t *r, ngx_http_upstream_t *u)
{
+ off_t file_pos;
ngx_chain_t *cl;
if (u->reinit_request(r) != NGX_OK) {
@@ -1591,9 +1592,17 @@ ngx_http_upstream_reinit(ngx_http_request_t *r, ngx_http_upstream_t *u)
/* reinit the request chain */
+ file_pos = 0;
+
for (cl = u->request_bufs; cl; cl = cl->next) {
cl->buf->pos = cl->buf->start;
- cl->buf->file_pos = 0;
+
+ /* there is at most one file */
+
+ if (cl->buf->in_file) {
+ cl->buf->file_pos = file_pos;
+ file_pos = cl->buf->file_last;
+ }
}
/* reinit the subrequest's ngx_output_chain() context */
diff --git a/src/os/unix/ngx_darwin_sendfile_chain.c b/src/os/unix/ngx_darwin_sendfile_chain.c
index ee44e1d58..dd574e5ac 100644
--- a/src/os/unix/ngx_darwin_sendfile_chain.c
+++ b/src/os/unix/ngx_darwin_sendfile_chain.c
@@ -27,15 +27,6 @@
*/
-#if (IOV_MAX > 64)
-#define NGX_HEADERS 64
-#define NGX_TRAILERS 64
-#else
-#define NGX_HEADERS IOV_MAX
-#define NGX_TRAILERS IOV_MAX
-#endif
-
-
ngx_chain_t *
ngx_darwin_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
{
@@ -43,14 +34,16 @@ ngx_darwin_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
u_char *prev;
off_t size, send, prev_send, aligned, sent, fprev;
off_t header_size, file_size;
- ngx_uint_t eintr, complete;
+ ngx_uint_t eintr;
ngx_err_t err;
ngx_buf_t *file;
ngx_array_t header, trailer;
ngx_event_t *wev;
ngx_chain_t *cl;
struct sf_hdtr hdtr;
- struct iovec *iov, headers[NGX_HEADERS], trailers[NGX_TRAILERS];
+ struct iovec *iov;
+ struct iovec headers[NGX_IOVS_PREALLOCATE];
+ struct iovec trailers[NGX_IOVS_PREALLOCATE];
wev = c->write;
@@ -79,12 +72,12 @@ ngx_darwin_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
header.elts = headers;
header.size = sizeof(struct iovec);
- header.nalloc = NGX_HEADERS;
+ header.nalloc = NGX_IOVS_PREALLOCATE;
header.pool = c->pool;
trailer.elts = trailers;
trailer.size = sizeof(struct iovec);
- trailer.nalloc = NGX_TRAILERS;
+ trailer.nalloc = NGX_IOVS_PREALLOCATE;
trailer.pool = c->pool;
for ( ;; ) {
@@ -92,7 +85,6 @@ ngx_darwin_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
file_size = 0;
header_size = 0;
eintr = 0;
- complete = 0;
prev_send = send;
header.nelts = 0;
@@ -285,7 +277,7 @@ ngx_darwin_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
rc = writev(c->fd, header.elts, header.nelts);
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
- "writev: %d of %uz", rc, send);
+ "writev: %d of %O", rc, header_size);
if (rc == -1) {
err = ngx_errno;
@@ -311,54 +303,15 @@ ngx_darwin_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
sent = rc > 0 ? rc : 0;
}
- if (send - prev_send == sent) {
- complete = 1;
- }
-
c->sent += sent;
- for ( /* void */ ; in; in = in->next) {
-
- if (ngx_buf_special(in->buf)) {
- continue;
- }
-
- if (sent == 0) {
- break;
- }
-
- size = ngx_buf_size(in->buf);
-
- if (sent >= size) {
- sent -= size;
-
- if (ngx_buf_in_memory(in->buf)) {
- in->buf->pos = in->buf->last;
- }
-
- if (in->buf->in_file) {
- in->buf->file_pos = in->buf->file_last;
- }
-
- continue;
- }
-
- if (ngx_buf_in_memory(in->buf)) {
- in->buf->pos += (size_t) sent;
- }
-
- if (in->buf->in_file) {
- in->buf->file_pos += sent;
- }
-
- break;
- }
+ in = ngx_handle_sent_chain(in, sent);
if (eintr) {
continue;
}
- if (!complete) {
+ if (send - prev_send != sent) {
wev->ready = 0;
return in;
}
diff --git a/src/os/unix/ngx_freebsd_sendfile_chain.c b/src/os/unix/ngx_freebsd_sendfile_chain.c
index 6491e928f..f5d0f3a8a 100644
--- a/src/os/unix/ngx_freebsd_sendfile_chain.c
+++ b/src/os/unix/ngx_freebsd_sendfile_chain.c
@@ -29,15 +29,6 @@
*/
-#if (IOV_MAX > 64)
-#define NGX_HEADERS 64
-#define NGX_TRAILERS 64
-#else
-#define NGX_HEADERS IOV_MAX
-#define NGX_TRAILERS IOV_MAX
-#endif
-
-
ngx_chain_t *
ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
{
@@ -45,14 +36,16 @@ ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
u_char *prev;
off_t size, send, prev_send, aligned, sent, fprev;
size_t header_size, file_size;
- ngx_uint_t eintr, eagain, complete;
+ ngx_uint_t eintr, eagain;
ngx_err_t err;
ngx_buf_t *file;
ngx_array_t header, trailer;
ngx_event_t *wev;
ngx_chain_t *cl;
struct sf_hdtr hdtr;
- struct iovec *iov, headers[NGX_HEADERS], trailers[NGX_TRAILERS];
+ struct iovec *iov;
+ struct iovec headers[NGX_IOVS_PREALLOCATE];
+ struct iovec trailers[NGX_IOVS_PREALLOCATE];
wev = c->write;
@@ -83,12 +76,12 @@ ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
header.elts = headers;
header.size = sizeof(struct iovec);
- header.nalloc = NGX_HEADERS;
+ header.nalloc = NGX_IOVS_PREALLOCATE;
header.pool = c->pool;
trailer.elts = trailers;
trailer.size = sizeof(struct iovec);
- trailer.nalloc = NGX_TRAILERS;
+ trailer.nalloc = NGX_IOVS_PREALLOCATE;
trailer.pool = c->pool;
for ( ;; ) {
@@ -96,7 +89,6 @@ ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
file_size = 0;
header_size = 0;
eintr = 0;
- complete = 0;
prev_send = send;
header.nelts = 0;
@@ -362,48 +354,9 @@ ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
sent = rc > 0 ? rc : 0;
}
- if (send - prev_send == sent) {
- complete = 1;
- }
-
c->sent += sent;
- for ( /* void */ ; in; in = in->next) {
-
- if (ngx_buf_special(in->buf)) {
- continue;
- }
-
- if (sent == 0) {
- break;
- }
-
- size = ngx_buf_size(in->buf);
-
- if (sent >= size) {
- sent -= size;
-
- if (ngx_buf_in_memory(in->buf)) {
- in->buf->pos = in->buf->last;
- }
-
- if (in->buf->in_file) {
- in->buf->file_pos = in->buf->file_last;
- }
-
- continue;
- }
-
- if (ngx_buf_in_memory(in->buf)) {
- in->buf->pos += (size_t) sent;
- }
-
- if (in->buf->in_file) {
- in->buf->file_pos += sent;
- }
-
- break;
- }
+ in = ngx_handle_sent_chain(in, sent);
#if (NGX_HAVE_AIO_SENDFILE)
if (c->busy_sendfile) {
@@ -428,7 +381,7 @@ ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
continue;
}
- if (!complete) {
+ if (send - prev_send != sent) {
wev->ready = 0;
return in;
}
diff --git a/src/os/unix/ngx_linux_sendfile_chain.c b/src/os/unix/ngx_linux_sendfile_chain.c
index 16395f943..1060852a0 100644
--- a/src/os/unix/ngx_linux_sendfile_chain.c
+++ b/src/os/unix/ngx_linux_sendfile_chain.c
@@ -27,13 +27,6 @@
#define NGX_SENDFILE_MAXSIZE 2147483647L
-#if (IOV_MAX > 64)
-#define NGX_HEADERS 64
-#else
-#define NGX_HEADERS IOV_MAX
-#endif
-
-
ngx_chain_t *
ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
{
@@ -43,11 +36,11 @@ ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
size_t file_size;
ngx_err_t err;
ngx_buf_t *file;
- ngx_uint_t eintr, complete;
+ ngx_uint_t eintr;
ngx_array_t header;
ngx_event_t *wev;
ngx_chain_t *cl;
- struct iovec *iov, headers[NGX_HEADERS];
+ struct iovec *iov, headers[NGX_IOVS_PREALLOCATE];
#if (NGX_HAVE_SENDFILE64)
off_t offset;
#else
@@ -72,14 +65,13 @@ ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
header.elts = headers;
header.size = sizeof(struct iovec);
- header.nalloc = NGX_HEADERS;
+ header.nalloc = NGX_IOVS_PREALLOCATE;
header.pool = c->pool;
for ( ;; ) {
file = NULL;
file_size = 0;
eintr = 0;
- complete = 0;
prev_send = send;
header.nelts = 0;
@@ -319,54 +311,15 @@ ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "writev: %O", sent);
}
- if (send - prev_send == sent) {
- complete = 1;
- }
-
c->sent += sent;
- for ( /* void */ ; in; in = in->next) {
-
- if (ngx_buf_special(in->buf)) {
- continue;
- }
-
- if (sent == 0) {
- break;
- }
-
- size = ngx_buf_size(in->buf);
-
- if (sent >= size) {
- sent -= size;
-
- if (ngx_buf_in_memory(in->buf)) {
- in->buf->pos = in->buf->last;
- }
-
- if (in->buf->in_file) {
- in->buf->file_pos = in->buf->file_last;
- }
-
- continue;
- }
-
- if (ngx_buf_in_memory(in->buf)) {
- in->buf->pos += (size_t) sent;
- }
-
- if (in->buf->in_file) {
- in->buf->file_pos += sent;
- }
-
- break;
- }
+ in = ngx_handle_sent_chain(in, sent);
if (eintr) {
continue;
}
- if (!complete) {
+ if (send - prev_send != sent) {
wev->ready = 0;
return in;
}
diff --git a/src/os/unix/ngx_os.h b/src/os/unix/ngx_os.h
index c646e2aa5..1033d8825 100644
--- a/src/os/unix/ngx_os.h
+++ b/src/os/unix/ngx_os.h
@@ -56,6 +56,13 @@ ngx_chain_t *ngx_aio_write_chain(ngx_connection_t *c, ngx_chain_t *in,
#endif
+#if (IOV_MAX > 64)
+#define NGX_IOVS_PREALLOCATE 64
+#else
+#define NGX_IOVS_PREALLOCATE IOV_MAX
+#endif
+
+
extern ngx_os_io_t ngx_os_io;
extern ngx_int_t ngx_ncpu;
extern ngx_int_t ngx_max_sockets;
diff --git a/src/os/unix/ngx_readv_chain.c b/src/os/unix/ngx_readv_chain.c
index e4eb5ff32..3cba80ccc 100644
--- a/src/os/unix/ngx_readv_chain.c
+++ b/src/os/unix/ngx_readv_chain.c
@@ -10,15 +10,6 @@
#include <ngx_event.h>
-#if (IOV_MAX > 64)
-#define NGX_IOVS 64
-#else
-#define NGX_IOVS IOV_MAX
-#endif
-
-
-#if (NGX_HAVE_KQUEUE)
-
ssize_t
ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain)
{
@@ -27,10 +18,12 @@ ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain)
ngx_err_t err;
ngx_array_t vec;
ngx_event_t *rev;
- struct iovec *iov, iovs[NGX_IOVS];
+ struct iovec *iov, iovs[NGX_IOVS_PREALLOCATE];
rev = c->read;
+#if (NGX_HAVE_KQUEUE)
+
if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
"readv: eof:%d, avail:%d, err:%d",
@@ -58,6 +51,8 @@ ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain)
}
}
+#endif
+
prev = NULL;
iov = NULL;
size = 0;
@@ -65,7 +60,7 @@ ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain)
vec.elts = iovs;
vec.nelts = 0;
vec.size = sizeof(struct iovec);
- vec.nalloc = NGX_IOVS;
+ vec.nalloc = NGX_IOVS_PREALLOCATE;
vec.pool = c->pool;
/* coalesce the neighbouring bufs */
@@ -96,12 +91,13 @@ ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain)
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
"readv: %d, last:%d", vec.nelts, iov->iov_len);
- rev = c->read;
-
do {
n = readv(c->fd, (struct iovec *) vec.elts, vec.nelts);
if (n >= 0) {
+
+#if (NGX_HAVE_KQUEUE)
+
if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
rev->available -= n;
@@ -141,6 +137,8 @@ ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain)
return n;
}
+#endif /* NGX_HAVE_KQUEUE */
+
if (n < size && !(ngx_event_flags & NGX_USE_GREEDY_EVENT)) {
rev->ready = 0;
}
@@ -174,98 +172,3 @@ ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain)
return n;
}
-
-#else /* ! NGX_HAVE_KQUEUE */
-
-ssize_t
-ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain)
-{
- u_char *prev;
- ssize_t n, size;
- ngx_err_t err;
- ngx_array_t vec;
- ngx_event_t *rev;
- struct iovec *iov, iovs[NGX_IOVS];
-
- prev = NULL;
- iov = NULL;
- size = 0;
-
- vec.elts = iovs;
- vec.nelts = 0;
- vec.size = sizeof(struct iovec);
- vec.nalloc = NGX_IOVS;
- vec.pool = c->pool;
-
- /* coalesce the neighbouring bufs */
-
- while (chain) {
- if (prev == chain->buf->last) {
- iov->iov_len += chain->buf->end - chain->buf->last;
-
- } else {
- if (vec.nelts >= IOV_MAX) {
- break;
- }
-
- iov = ngx_array_push(&vec);
- if (iov == NULL) {
- return NGX_ERROR;
- }
-
- iov->iov_base = (void *) chain->buf->last;
- iov->iov_len = chain->buf->end - chain->buf->last;
- }
-
- size += chain->buf->end - chain->buf->last;
- prev = chain->buf->end;
- chain = chain->next;
- }
-
- ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
- "readv: %d:%d", vec.nelts, iov->iov_len);
-
- rev = c->read;
-
- do {
- n = readv(c->fd, (struct iovec *) vec.elts, vec.nelts);
-
- if (n == 0) {
- rev->ready = 0;
- rev->eof = 1;
-
- return n;
-
- } else if (n > 0) {
-
- if (n < size && !(ngx_event_flags & NGX_USE_GREEDY_EVENT)) {
- rev->ready = 0;
- }
-
- return n;
- }
-
- err = ngx_socket_errno;
-
- if (err == NGX_EAGAIN || err == NGX_EINTR) {
- ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
- "readv() not ready");
- n = NGX_AGAIN;
-
- } else {
- n = ngx_connection_error(c, err, "readv() failed");
- break;
- }
-
- } while (err == NGX_EINTR);
-
- rev->ready = 0;
-
- if (n == NGX_ERROR) {
- c->read->error = 1;
- }
-
- return n;
-}
-
-#endif /* NGX_HAVE_KQUEUE */
diff --git a/src/os/unix/ngx_solaris_sendfilev_chain.c b/src/os/unix/ngx_solaris_sendfilev_chain.c
index 37bb09d96..ba328c810 100644
--- a/src/os/unix/ngx_solaris_sendfilev_chain.c
+++ b/src/os/unix/ngx_solaris_sendfilev_chain.c
@@ -35,12 +35,7 @@ ngx_chain_t *ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in,
#endif
-#if (IOV_MAX > 64)
-#define NGX_SENDFILEVECS 64
-#else
-#define NGX_SENDFILEVECS IOV_MAX
-#endif
-
+#define NGX_SENDFILEVECS NGX_IOVS_PREALLOCATE
ngx_chain_t *
@@ -51,7 +46,7 @@ ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
off_t size, send, prev_send, aligned, fprev;
size_t sent;
ssize_t n;
- ngx_int_t eintr, complete;
+ ngx_int_t eintr;
ngx_err_t err;
sendfilevec_t *sfv, sfvs[NGX_SENDFILEVECS];
ngx_array_t vec;
@@ -89,7 +84,6 @@ ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
fprev = 0;
sfv = NULL;
eintr = 0;
- complete = 0;
sent = 0;
prev_send = send;
@@ -201,54 +195,15 @@ ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
"sendfilev: %z %z", n, sent);
- if (send - prev_send == (off_t) sent) {
- complete = 1;
- }
-
c->sent += sent;
- for ( /* void */ ; in; in = in->next) {
-
- if (ngx_buf_special(in->buf)) {
- continue;
- }
-
- if (sent == 0) {
- break;
- }
-
- size = ngx_buf_size(in->buf);
-
- if ((off_t) sent >= size) {
- sent = (size_t) ((off_t) sent - size);
-
- if (ngx_buf_in_memory(in->buf)) {
- in->buf->pos = in->buf->last;
- }
-
- if (in->buf->in_file) {
- in->buf->file_pos = in->buf->file_last;
- }
-
- continue;
- }
-
- if (ngx_buf_in_memory(in->buf)) {
- in->buf->pos += sent;
- }
-
- if (in->buf->in_file) {
- in->buf->file_pos += sent;
- }
-
- break;
- }
+ in = ngx_handle_sent_chain(in, sent);
if (eintr) {
continue;
}
- if (!complete) {
+ if (send - prev_send != (off_t) sent) {
wev->ready = 0;
return in;
}
diff --git a/src/os/unix/ngx_writev_chain.c b/src/os/unix/ngx_writev_chain.c
index 805982d65..95af2da7a 100644
--- a/src/os/unix/ngx_writev_chain.c
+++ b/src/os/unix/ngx_writev_chain.c
@@ -10,25 +10,18 @@
#include <ngx_event.h>
-#if (IOV_MAX > 64)
-#define NGX_IOVS 64
-#else
-#define NGX_IOVS IOV_MAX
-#endif
-
-
ngx_chain_t *
ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
{
u_char *prev;
ssize_t n, size, sent;
off_t send, prev_send;
- ngx_uint_t eintr, complete;
+ ngx_uint_t eintr;
ngx_err_t err;
ngx_array_t vec;
ngx_chain_t *cl;
ngx_event_t *wev;
- struct iovec *iov, iovs[NGX_IOVS];
+ struct iovec *iov, iovs[NGX_IOVS_PREALLOCATE];
wev = c->write;
@@ -57,14 +50,13 @@ ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
vec.elts = iovs;
vec.size = sizeof(struct iovec);
- vec.nalloc = NGX_IOVS;
+ vec.nalloc = NGX_IOVS_PREALLOCATE;
vec.pool = c->pool;
for ( ;; ) {
prev = NULL;
iov = NULL;
eintr = 0;
- complete = 0;
prev_send = send;
vec.nelts = 0;
@@ -137,49 +129,21 @@ ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "writev: %z", sent);
- if (send - prev_send == sent) {
- complete = 1;
- }
-
c->sent += sent;
- for (cl = in; cl; cl = cl->next) {
-
- if (ngx_buf_special(cl->buf)) {
- continue;
- }
-
- if (sent == 0) {
- break;
- }
-
- size = cl->buf->last - cl->buf->pos;
-
- if (sent >= size) {
- sent -= size;
- cl->buf->pos = cl->buf->last;
-
- continue;
- }
-
- cl->buf->pos += sent;
-
- break;
- }
+ in = ngx_handle_sent_chain(in, sent);
if (eintr) {
continue;
}
- if (!complete) {
+ if (send - prev_send != sent) {
wev->ready = 0;
- return cl;
+ return in;
}
- if (send >= limit || cl == NULL) {
- return cl;
+ if (send >= limit || in == NULL) {
+ return in;
}
-
- in = cl;
}
}