diff options
author | nginx <nginx@nginx.org> | 2014-09-30 13:30:36 +0000 |
---|---|---|
committer | Jon Kolb <kolbyjack@gmail.com> | 2014-09-30 13:30:36 +0000 |
commit | 4aeefe1f3cef9d863cc04f7ee3fe2c730e6cfdf1 (patch) | |
tree | 40d86068ccd6d06c9866bd809af03830e89752cd | |
parent | bb8c0683da773566e09797ef8a4ee00ad1e0f956 (diff) | |
download | nginx-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-- | CHANGES | 14 | ||||
-rw-r--r-- | CHANGES.ru | 13 | ||||
-rw-r--r-- | src/core/nginx.h | 4 | ||||
-rw-r--r-- | src/core/ngx_buf.c | 46 | ||||
-rw-r--r-- | src/core/ngx_buf.h | 1 | ||||
-rw-r--r-- | src/core/ngx_syslog.c | 39 | ||||
-rw-r--r-- | src/core/ngx_syslog.h | 2 | ||||
-rw-r--r-- | src/http/modules/ngx_http_fastcgi_module.c | 1 | ||||
-rw-r--r-- | src/http/modules/ngx_http_limit_conn_module.c | 227 | ||||
-rw-r--r-- | src/http/modules/ngx_http_limit_req_module.c | 120 | ||||
-rw-r--r-- | src/http/modules/ngx_http_upstream_keepalive_module.c | 1 | ||||
-rw-r--r-- | src/http/ngx_http.c | 6 | ||||
-rw-r--r-- | src/http/ngx_http_upstream.c | 11 | ||||
-rw-r--r-- | src/os/unix/ngx_darwin_sendfile_chain.c | 65 | ||||
-rw-r--r-- | src/os/unix/ngx_freebsd_sendfile_chain.c | 63 | ||||
-rw-r--r-- | src/os/unix/ngx_linux_sendfile_chain.c | 57 | ||||
-rw-r--r-- | src/os/unix/ngx_os.h | 7 | ||||
-rw-r--r-- | src/os/unix/ngx_readv_chain.c | 119 | ||||
-rw-r--r-- | src/os/unix/ngx_solaris_sendfilev_chain.c | 53 | ||||
-rw-r--r-- | src/os/unix/ngx_writev_chain.c | 52 |
20 files changed, 297 insertions, 604 deletions
@@ -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; } } |