mirror of
https://github.com/nginx/nginx.git
synced 2025-06-07 17:52:38 +08:00
nginx-0.0.7-2004-06-21-19:59:32 import
This commit is contained in:
parent
73a73b5a60
commit
ef06648615
@ -127,6 +127,7 @@ typedef struct {
|
|||||||
ngx_chain_t **last;
|
ngx_chain_t **last;
|
||||||
ngx_connection_t *connection;
|
ngx_connection_t *connection;
|
||||||
ngx_pool_t *pool;
|
ngx_pool_t *pool;
|
||||||
|
off_t limit;
|
||||||
} ngx_chain_writer_ctx_t;
|
} ngx_chain_writer_ctx_t;
|
||||||
|
|
||||||
|
|
||||||
|
@ -274,7 +274,7 @@ ngx_int_t ngx_chain_writer(void *data, ngx_chain_t *in)
|
|||||||
ngx_log_debug1(NGX_LOG_DEBUG_CORE, ctx->connection->log, 0,
|
ngx_log_debug1(NGX_LOG_DEBUG_CORE, ctx->connection->log, 0,
|
||||||
"WRITER0: %X", ctx->out);
|
"WRITER0: %X", ctx->out);
|
||||||
|
|
||||||
ctx->out = ngx_write_chain(ctx->connection, ctx->out);
|
ctx->out = ngx_write_chain(ctx->connection, ctx->out, ctx->limit);
|
||||||
|
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_CORE, ctx->connection->log, 0,
|
ngx_log_debug1(NGX_LOG_DEBUG_CORE, ctx->connection->log, 0,
|
||||||
"WRITER1: %X", ctx->out);
|
"WRITER1: %X", ctx->out);
|
||||||
|
@ -91,6 +91,8 @@ struct ngx_event_s {
|
|||||||
unsigned short timedout:1;
|
unsigned short timedout:1;
|
||||||
unsigned short timer_set:1;
|
unsigned short timer_set:1;
|
||||||
|
|
||||||
|
unsigned short delayed:1;
|
||||||
|
|
||||||
unsigned short read_discarded:1;
|
unsigned short read_discarded:1;
|
||||||
|
|
||||||
unsigned short unexpected_eof:1;
|
unsigned short unexpected_eof:1;
|
||||||
|
@ -605,6 +605,7 @@ static void ngx_http_proxy_connect(ngx_http_proxy_ctx_t *p)
|
|||||||
writer->out = NULL;
|
writer->out = NULL;
|
||||||
writer->last = &writer->out;
|
writer->last = &writer->out;
|
||||||
writer->connection = c;
|
writer->connection = c;
|
||||||
|
writer->limit = OFF_T_MAX_VALUE;
|
||||||
|
|
||||||
if (p->upstream->peer.tries > 1 && p->request_sent) {
|
if (p->upstream->peer.tries > 1 && p->request_sent) {
|
||||||
ngx_http_proxy_reinit_upstream(p);
|
ngx_http_proxy_reinit_upstream(p);
|
||||||
|
@ -125,9 +125,9 @@ typedef struct {
|
|||||||
ngx_str_t default_type;
|
ngx_str_t default_type;
|
||||||
|
|
||||||
size_t client_max_body_size; /* client_max_body_size */
|
size_t client_max_body_size; /* client_max_body_size */
|
||||||
size_t send_lowat; /* send_lowat */
|
|
||||||
size_t discarded_buffer_size; /* discarded_buffer_size */
|
size_t discarded_buffer_size; /* discarded_buffer_size */
|
||||||
size_t client_body_buffer_size; /* client_body_buffer_size */
|
size_t client_body_buffer_size; /* client_body_buffer_size */
|
||||||
|
size_t send_lowat; /* send_lowat */
|
||||||
|
|
||||||
ngx_msec_t client_body_timeout; /* client_body_timeout */
|
ngx_msec_t client_body_timeout; /* client_body_timeout */
|
||||||
ngx_msec_t send_timeout; /* send_timeout */
|
ngx_msec_t send_timeout; /* send_timeout */
|
||||||
|
@ -1050,13 +1050,13 @@ static void ngx_http_set_write_handler(ngx_http_request_t *r)
|
|||||||
wev = r->connection->write;
|
wev = r->connection->write;
|
||||||
wev->event_handler = ngx_http_writer;
|
wev->event_handler = ngx_http_writer;
|
||||||
|
|
||||||
if (wev->ready && r->delayed) {
|
if (wev->ready && wev->delayed) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
|
clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
|
||||||
ngx_http_core_module);
|
ngx_http_core_module);
|
||||||
if (!r->delayed) {
|
if (!wev->delayed) {
|
||||||
ngx_add_timer(wev, clcf->send_timeout);
|
ngx_add_timer(wev, clcf->send_timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1083,13 +1083,13 @@ void ngx_http_writer(ngx_event_t *wev)
|
|||||||
r = c->data;
|
r = c->data;
|
||||||
|
|
||||||
if (wev->timedout) {
|
if (wev->timedout) {
|
||||||
if (!r->delayed) {
|
if (!wev->delayed) {
|
||||||
ngx_http_client_error(r, 0, NGX_HTTP_REQUEST_TIME_OUT);
|
ngx_http_client_error(r, 0, NGX_HTTP_REQUEST_TIME_OUT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
wev->timedout = 0;
|
wev->timedout = 0;
|
||||||
r->delayed = 0;
|
wev->delayed = 0;
|
||||||
|
|
||||||
if (!wev->ready) {
|
if (!wev->ready) {
|
||||||
clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
|
clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
|
||||||
@ -1107,9 +1107,19 @@ void ngx_http_writer(ngx_event_t *wev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (r->delayed) {
|
if (wev->delayed) {
|
||||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0,
|
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0,
|
||||||
"http writer delayed");
|
"http writer delayed");
|
||||||
|
|
||||||
|
clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
|
||||||
|
ngx_http_core_module);
|
||||||
|
wev->available = clcf->send_lowat;
|
||||||
|
|
||||||
|
if (ngx_handle_write_event(wev, NGX_LOWAT_EVENT) == NGX_ERROR) {
|
||||||
|
ngx_http_close_request(r, 0);
|
||||||
|
ngx_http_close_connection(r->connection);
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1122,7 +1132,7 @@ void ngx_http_writer(ngx_event_t *wev)
|
|||||||
if (rc == NGX_AGAIN) {
|
if (rc == NGX_AGAIN) {
|
||||||
clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
|
clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
|
||||||
ngx_http_core_module);
|
ngx_http_core_module);
|
||||||
if (!wev->ready && !r->delayed) {
|
if (!wev->ready && !wev->delayed) {
|
||||||
ngx_add_timer(wev, clcf->send_timeout);
|
ngx_add_timer(wev, clcf->send_timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,7 +284,6 @@ struct ngx_http_request_s {
|
|||||||
/* can we use sendfile ? */
|
/* can we use sendfile ? */
|
||||||
unsigned sendfile:1;
|
unsigned sendfile:1;
|
||||||
|
|
||||||
unsigned delayed:1;
|
|
||||||
unsigned chunked:1;
|
unsigned chunked:1;
|
||||||
unsigned header_only:1;
|
unsigned header_only:1;
|
||||||
unsigned keepalive:1;
|
unsigned keepalive:1;
|
||||||
|
@ -6,7 +6,8 @@
|
|||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
size_t postpone_output;
|
size_t postpone_output; /* postpone_output */
|
||||||
|
size_t limit_rate; /* limit_rate */
|
||||||
} ngx_http_write_filter_conf_t;
|
} ngx_http_write_filter_conf_t;
|
||||||
|
|
||||||
|
|
||||||
@ -23,19 +24,18 @@ static ngx_int_t ngx_http_write_filter_init(ngx_cycle_t *cycle);
|
|||||||
|
|
||||||
static ngx_command_t ngx_http_write_filter_commands[] = {
|
static ngx_command_t ngx_http_write_filter_commands[] = {
|
||||||
|
|
||||||
/* STUB */
|
{ ngx_string("postpone_output"),
|
||||||
{ ngx_string("buffer_output"),
|
|
||||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
|
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
|
||||||
ngx_conf_set_size_slot,
|
ngx_conf_set_size_slot,
|
||||||
NGX_HTTP_LOC_CONF_OFFSET,
|
NGX_HTTP_LOC_CONF_OFFSET,
|
||||||
offsetof(ngx_http_write_filter_conf_t, postpone_output),
|
offsetof(ngx_http_write_filter_conf_t, postpone_output),
|
||||||
NULL },
|
NULL },
|
||||||
|
|
||||||
{ ngx_string("postpone_output"),
|
{ ngx_string("limit_rate"),
|
||||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
|
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
|
||||||
ngx_conf_set_size_slot,
|
ngx_conf_set_size_slot,
|
||||||
NGX_HTTP_LOC_CONF_OFFSET,
|
NGX_HTTP_LOC_CONF_OFFSET,
|
||||||
offsetof(ngx_http_write_filter_conf_t, postpone_output),
|
offsetof(ngx_http_write_filter_conf_t, limit_rate),
|
||||||
NULL },
|
NULL },
|
||||||
|
|
||||||
ngx_null_command
|
ngx_null_command
|
||||||
@ -138,7 +138,7 @@ ngx_int_t ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
|||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r->delayed) {
|
if (r->connection->write->delayed) {
|
||||||
return NGX_AGAIN;
|
return NGX_AGAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,16 +152,18 @@ ngx_int_t ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
|||||||
|
|
||||||
sent = r->connection->sent;
|
sent = r->connection->sent;
|
||||||
|
|
||||||
chain = ngx_write_chain(r->connection, ctx->out);
|
chain = ngx_write_chain(r->connection, ctx->out,
|
||||||
|
conf->limit_rate ? conf->limit_rate:
|
||||||
|
OFF_T_MAX_VALUE);
|
||||||
|
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||||
"http write filter %X", chain);
|
"http write filter %X", chain);
|
||||||
|
|
||||||
#if 1
|
if (conf->limit_rate) {
|
||||||
sent = r->connection->sent - sent;
|
sent = r->connection->sent - sent;
|
||||||
r->delayed = 1;
|
r->connection->write->delayed = 1;
|
||||||
ngx_add_timer(r->connection->write, sent * 1000 / (4 * 1024));
|
ngx_add_timer(r->connection->write, sent * 1000 / conf->limit_rate);
|
||||||
#endif
|
}
|
||||||
|
|
||||||
if (chain == NGX_CHAIN_ERROR) {
|
if (chain == NGX_CHAIN_ERROR) {
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
@ -186,6 +188,7 @@ static void *ngx_http_write_filter_create_conf(ngx_conf_t *cf)
|
|||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
conf->postpone_output = NGX_CONF_UNSET_SIZE;
|
conf->postpone_output = NGX_CONF_UNSET_SIZE;
|
||||||
|
conf->limit_rate = NGX_CONF_UNSET_SIZE;
|
||||||
|
|
||||||
return conf;
|
return conf;
|
||||||
}
|
}
|
||||||
@ -200,6 +203,8 @@ static char *ngx_http_write_filter_merge_conf(ngx_conf_t *cf,
|
|||||||
ngx_conf_merge_size_value(conf->postpone_output, prev->postpone_output,
|
ngx_conf_merge_size_value(conf->postpone_output, prev->postpone_output,
|
||||||
1460);
|
1460);
|
||||||
|
|
||||||
|
ngx_conf_merge_size_value(conf->limit_rate, prev->limit_rate, 0);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,8 @@
|
|||||||
ssize_t ngx_aio_read(ngx_connection_t *c, u_char *buf, size_t size);
|
ssize_t ngx_aio_read(ngx_connection_t *c, u_char *buf, size_t size);
|
||||||
ssize_t ngx_aio_read_chain(ngx_connection_t *c, ngx_chain_t *cl);
|
ssize_t ngx_aio_read_chain(ngx_connection_t *c, ngx_chain_t *cl);
|
||||||
ssize_t ngx_aio_write(ngx_connection_t *c, u_char *buf, size_t size);
|
ssize_t ngx_aio_write(ngx_connection_t *c, u_char *buf, size_t size);
|
||||||
ngx_chain_t *ngx_aio_write_chain(ngx_connection_t *c, ngx_chain_t *in);
|
ngx_chain_t *ngx_aio_write_chain(ngx_connection_t *c, ngx_chain_t *in,
|
||||||
|
off_t limit);
|
||||||
|
|
||||||
|
|
||||||
#endif /* _NGX_AIO_H_INCLUDED_ */
|
#endif /* _NGX_AIO_H_INCLUDED_ */
|
||||||
|
@ -5,21 +5,24 @@
|
|||||||
#include <ngx_aio.h>
|
#include <ngx_aio.h>
|
||||||
|
|
||||||
|
|
||||||
ngx_chain_t *ngx_aio_write_chain(ngx_connection_t *c, ngx_chain_t *in)
|
ngx_chain_t *ngx_aio_write_chain(ngx_connection_t *c, ngx_chain_t *in,
|
||||||
|
off_t limit)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
u_char *buf, *prev;
|
u_char *buf, *prev;
|
||||||
off_t sent;
|
off_t send, sent;
|
||||||
size_t size;
|
size_t len;
|
||||||
|
ssize_t size;
|
||||||
ngx_err_t err;
|
ngx_err_t err;
|
||||||
ngx_chain_t *cl;
|
ngx_chain_t *cl;
|
||||||
|
|
||||||
|
send = 0;
|
||||||
sent = 0;
|
sent = 0;
|
||||||
cl = in;
|
cl = in;
|
||||||
|
|
||||||
while (cl) {
|
while (cl) {
|
||||||
|
|
||||||
if (cl->buf->last - cl->buf->pos == 0) {
|
if (cl->buf->pos == cl->buf->last) {
|
||||||
cl = cl->next;
|
cl = cl->next;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -32,17 +35,28 @@ ngx_chain_t *ngx_aio_write_chain(ngx_connection_t *c, ngx_chain_t *in)
|
|||||||
|
|
||||||
buf = cl->buf->pos;
|
buf = cl->buf->pos;
|
||||||
prev = buf;
|
prev = buf;
|
||||||
size = 0;
|
len = 0;
|
||||||
|
|
||||||
/* coalesce the neighbouring bufs */
|
/* coalesce the neighbouring bufs */
|
||||||
|
|
||||||
while (cl && prev == cl->buf->pos) {
|
while (cl && prev == cl->buf->pos && send < limit) {
|
||||||
size += cl->buf->last - cl->buf->pos;
|
if (ngx_buf_special(cl->buf)) {
|
||||||
prev = cl->buf->last;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
size = cl->buf->last - cl->buf->pos;
|
||||||
|
|
||||||
|
if (send + size > limit) {
|
||||||
|
size = limit - send;
|
||||||
|
}
|
||||||
|
|
||||||
|
len += size;
|
||||||
|
prev = cl->buf->pos + size;
|
||||||
|
send += size;
|
||||||
cl = cl->next;
|
cl = cl->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
n = ngx_aio_write(c, buf, size);
|
n = ngx_aio_write(c, buf, len);
|
||||||
|
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "aio_write: %d", n);
|
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "aio_write: %d", n);
|
||||||
|
|
||||||
|
@ -2,7 +2,8 @@
|
|||||||
#define _NGX_FREEBSD_H_INCLUDED_
|
#define _NGX_FREEBSD_H_INCLUDED_
|
||||||
|
|
||||||
|
|
||||||
ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in);
|
ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in,
|
||||||
|
off_t limit);
|
||||||
|
|
||||||
|
|
||||||
extern int ngx_freebsd_kern_osreldate;
|
extern int ngx_freebsd_kern_osreldate;
|
||||||
|
@ -28,21 +28,22 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
|
ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in,
|
||||||
|
off_t limit)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
u_char *prev;
|
u_char *prev;
|
||||||
off_t sent, fprev, send, limit;
|
off_t fprev, sent, send, sprev, aligned;
|
||||||
size_t hsize, fsize;
|
size_t hsize, fsize;
|
||||||
ssize_t size;
|
ssize_t size;
|
||||||
ngx_uint_t eintr, eagain, ready;
|
ngx_uint_t eintr, eagain, complete;
|
||||||
struct iovec *iov;
|
struct iovec *iov;
|
||||||
struct sf_hdtr hdtr;
|
struct sf_hdtr hdtr;
|
||||||
ngx_err_t err;
|
ngx_err_t err;
|
||||||
ngx_buf_t *file;
|
ngx_buf_t *file;
|
||||||
ngx_array_t header, trailer;
|
ngx_array_t header, trailer;
|
||||||
ngx_event_t *wev;
|
ngx_event_t *wev;
|
||||||
ngx_chain_t *cl, *tail;
|
ngx_chain_t *cl;
|
||||||
|
|
||||||
wev = c->write;
|
wev = c->write;
|
||||||
|
|
||||||
@ -62,20 +63,16 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if 1
|
send = 0;
|
||||||
limit = 4096;
|
eagain = 0;
|
||||||
#else
|
|
||||||
limit = OFF_T_MAX_VALUE;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
do {
|
for ( ;; ) {
|
||||||
file = NULL;
|
file = NULL;
|
||||||
fsize = 0;
|
fsize = 0;
|
||||||
hsize = 0;
|
hsize = 0;
|
||||||
send = 0;
|
|
||||||
eintr = 0;
|
eintr = 0;
|
||||||
eagain = 0;
|
complete = 0;
|
||||||
ready = 0;
|
sprev = send;
|
||||||
|
|
||||||
ngx_init_array(header, c->pool, 10, sizeof(struct iovec),
|
ngx_init_array(header, c->pool, 10, sizeof(struct iovec),
|
||||||
NGX_CHAIN_ERROR);
|
NGX_CHAIN_ERROR);
|
||||||
@ -87,7 +84,10 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
|
|||||||
prev = NULL;
|
prev = NULL;
|
||||||
iov = NULL;
|
iov = NULL;
|
||||||
|
|
||||||
for (cl = in; cl && header.nelts < IOV_MAX; cl = cl->next) {
|
for (cl = in;
|
||||||
|
cl && header.nelts < IOV_MAX && send < limit;
|
||||||
|
cl = cl->next)
|
||||||
|
{
|
||||||
if (ngx_buf_special(cl->buf)) {
|
if (ngx_buf_special(cl->buf)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -118,7 +118,7 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
|
|||||||
|
|
||||||
/* get the file buf */
|
/* get the file buf */
|
||||||
|
|
||||||
if (cl && cl->buf->in_file) {
|
if (cl && cl->buf->in_file && send < limit) {
|
||||||
file = cl->buf;
|
file = cl->buf;
|
||||||
fsize = 0;
|
fsize = 0;
|
||||||
|
|
||||||
@ -129,6 +129,13 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
|
|||||||
|
|
||||||
if (send + size > limit) {
|
if (send + size > limit) {
|
||||||
size = limit - send;
|
size = limit - send;
|
||||||
|
|
||||||
|
aligned = (cl->buf->file_pos + size + ngx_pagesize - 1)
|
||||||
|
& ~(ngx_pagesize - 1);
|
||||||
|
|
||||||
|
if (aligned <= cl->buf->file_last) {
|
||||||
|
size = aligned - cl->buf->file_pos;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fsize += size;
|
fsize += size;
|
||||||
@ -138,6 +145,7 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
|
|||||||
|
|
||||||
} while (cl
|
} while (cl
|
||||||
&& cl->buf->in_file
|
&& cl->buf->in_file
|
||||||
|
&& send < limit
|
||||||
&& file->file->fd == cl->buf->file->fd
|
&& file->file->fd == cl->buf->file->fd
|
||||||
&& fprev == cl->buf->file_pos);
|
&& fprev == cl->buf->file_pos);
|
||||||
}
|
}
|
||||||
@ -148,7 +156,10 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
|
|||||||
prev = NULL;
|
prev = NULL;
|
||||||
iov = NULL;
|
iov = NULL;
|
||||||
|
|
||||||
for ( /* void */; cl && trailer.nelts < IOV_MAX; cl = cl->next) {
|
for (/* void */;
|
||||||
|
cl && header.nelts < IOV_MAX && send < limit;
|
||||||
|
cl = cl->next)
|
||||||
|
{
|
||||||
if (ngx_buf_special(cl->buf)) {
|
if (ngx_buf_special(cl->buf)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -178,13 +189,6 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* the tail is the rest of the chain that exceedes
|
|
||||||
* a single sendfile() capability
|
|
||||||
*/
|
|
||||||
|
|
||||||
tail = cl;
|
|
||||||
|
|
||||||
if (file) {
|
if (file) {
|
||||||
|
|
||||||
if (ngx_freebsd_use_tcp_nopush
|
if (ngx_freebsd_use_tcp_nopush
|
||||||
@ -286,8 +290,8 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
|
|||||||
sent = rc > 0 ? rc : 0;
|
sent = rc > 0 ? rc : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (send == sent) {
|
if (send - sprev == sent) {
|
||||||
ready = 1;
|
complete = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
c->sent += sent;
|
c->sent += sent;
|
||||||
@ -329,12 +333,6 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ready) {
|
|
||||||
return cl;
|
|
||||||
}
|
|
||||||
|
|
||||||
in = cl;
|
|
||||||
|
|
||||||
if (eagain) {
|
if (eagain) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -345,16 +343,22 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
wev->ready = 0;
|
wev->ready = 0;
|
||||||
break;
|
return cl;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* "tail == in" means that a single sendfile() is complete */
|
if (eintr) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
} while ((tail && tail == in) || eintr);
|
if (!complete) {
|
||||||
|
wev->ready = 0;
|
||||||
|
return cl;
|
||||||
|
}
|
||||||
|
|
||||||
if (in) {
|
if (send >= limit || cl == NULL) {
|
||||||
wev->ready = 0;
|
return cl;
|
||||||
|
}
|
||||||
|
|
||||||
|
in = cl;
|
||||||
}
|
}
|
||||||
|
|
||||||
return in;
|
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,8 @@
|
|||||||
#define _NGX_LINUX_H_INCLUDED_
|
#define _NGX_LINUX_H_INCLUDED_
|
||||||
|
|
||||||
|
|
||||||
ngx_chain_t *ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in);
|
ngx_chain_t *ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in,
|
||||||
|
off_t limit);
|
||||||
|
|
||||||
|
|
||||||
#endif /* _NGX_LINUX_H_INCLUDED_ */
|
#endif /* _NGX_LINUX_H_INCLUDED_ */
|
||||||
|
@ -19,19 +19,21 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
ngx_chain_t *ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
|
ngx_chain_t *ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in,
|
||||||
|
off_t limit)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
u_char *prev;
|
u_char *prev;
|
||||||
off_t fprev;
|
off_t fprev, send, sprev, aligned;
|
||||||
size_t size, fsize, sent;
|
size_t fsize;
|
||||||
ngx_int_t eintr;
|
ssize_t size, sent;
|
||||||
|
ngx_uint_t eintr, complete;
|
||||||
struct iovec *iov;
|
struct iovec *iov;
|
||||||
ngx_err_t err;
|
ngx_err_t err;
|
||||||
ngx_buf_t *file;
|
ngx_buf_t *file;
|
||||||
ngx_array_t header;
|
ngx_array_t header;
|
||||||
ngx_event_t *wev;
|
ngx_event_t *wev;
|
||||||
ngx_chain_t *cl, *tail;
|
ngx_chain_t *cl;
|
||||||
#if (HAVE_SENDFILE64)
|
#if (HAVE_SENDFILE64)
|
||||||
off_t offset;
|
off_t offset;
|
||||||
#else
|
#else
|
||||||
@ -44,10 +46,14 @@ ngx_chain_t *ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
|
|||||||
return in;
|
return in;
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
send = 0;
|
||||||
|
|
||||||
|
for ( ;; ) {
|
||||||
file = NULL;
|
file = NULL;
|
||||||
fsize = 0;
|
fsize = 0;
|
||||||
eintr = 0;
|
eintr = 0;
|
||||||
|
complete = 0;
|
||||||
|
sprev = send;
|
||||||
|
|
||||||
ngx_init_array(header, c->pool, 10, sizeof(struct iovec),
|
ngx_init_array(header, c->pool, 10, sizeof(struct iovec),
|
||||||
NGX_CHAIN_ERROR);
|
NGX_CHAIN_ERROR);
|
||||||
@ -57,7 +63,10 @@ ngx_chain_t *ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
|
|||||||
|
|
||||||
/* create the iovec and coalesce the neighbouring bufs */
|
/* create the iovec and coalesce the neighbouring bufs */
|
||||||
|
|
||||||
for (cl = in; cl && header.nelts < IOV_MAX; cl = cl->next) {
|
for (cl = in;
|
||||||
|
cl && header.nelts < IOV_MAX && send < limit;
|
||||||
|
cl = cl->next)
|
||||||
|
{
|
||||||
if (ngx_buf_special(cl->buf)) {
|
if (ngx_buf_special(cl->buf)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -66,16 +75,23 @@ ngx_chain_t *ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size = cl->buf->last - cl->buf->pos;
|
||||||
|
|
||||||
|
if (send + size > limit) {
|
||||||
|
size = limit - send;
|
||||||
|
}
|
||||||
|
|
||||||
if (prev == cl->buf->pos) {
|
if (prev == cl->buf->pos) {
|
||||||
iov->iov_len += cl->buf->last - cl->buf->pos;
|
iov->iov_len += size;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
ngx_test_null(iov, ngx_push_array(&header), NGX_CHAIN_ERROR);
|
ngx_test_null(iov, ngx_push_array(&header), NGX_CHAIN_ERROR);
|
||||||
iov->iov_base = (void *) cl->buf->pos;
|
iov->iov_base = (void *) cl->buf->pos;
|
||||||
iov->iov_len = cl->buf->last - cl->buf->pos;
|
iov->iov_len = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
prev = cl->buf->last;
|
prev = cl->buf->pos + size;
|
||||||
|
send += size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set TCP_CORK if there is a header before a file */
|
/* set TCP_CORK if there is a header before a file */
|
||||||
@ -107,38 +123,41 @@ ngx_chain_t *ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header.nelts == 0 && cl && cl->buf->in_file) {
|
/* get the file buf */
|
||||||
|
|
||||||
/* get the file buf */
|
|
||||||
|
|
||||||
|
if (header.nelts == 0 && cl && cl->buf->in_file && send < limit) {
|
||||||
file = cl->buf;
|
file = cl->buf;
|
||||||
fsize = (size_t) (file->file_last - file->file_pos);
|
fsize = 0;
|
||||||
fprev = file->file_last;
|
|
||||||
cl = cl->next;
|
|
||||||
|
|
||||||
/* coalesce the neighbouring file bufs */
|
/* coalesce the neighbouring file bufs */
|
||||||
|
|
||||||
while (cl && (cl->buf->in_file)) {
|
do {
|
||||||
if (file->file->fd != cl->buf->file->fd
|
size = (size_t) (cl->buf->file_last - cl->buf->file_pos);
|
||||||
|| fprev != cl->buf->file_pos)
|
|
||||||
{
|
if (send + size > limit) {
|
||||||
break;
|
size = limit - send;
|
||||||
|
|
||||||
|
aligned = (cl->buf->file_pos + size + ngx_pagesize - 1)
|
||||||
|
& ~(ngx_pagesize - 1);
|
||||||
|
|
||||||
|
if (aligned <= cl->buf->file_last) {
|
||||||
|
size = aligned - cl->buf->file_pos;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fsize += (size_t) (cl->buf->file_last - cl->buf->file_pos);
|
fsize += size;
|
||||||
fprev = cl->buf->file_last;
|
send += size;
|
||||||
|
fprev = cl->buf->file_pos + size;
|
||||||
cl = cl->next;
|
cl = cl->next;
|
||||||
}
|
|
||||||
|
} while (cl
|
||||||
|
&& cl->buf->in_file
|
||||||
|
&& send < limit
|
||||||
|
&& file->file->fd == cl->buf->file->fd
|
||||||
|
&& fprev == cl->buf->file_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
if (file) {
|
||||||
* the tail is the rest of the chain that exceedes
|
|
||||||
* a single sendfile() capability
|
|
||||||
*/
|
|
||||||
|
|
||||||
tail = cl;
|
|
||||||
|
|
||||||
if (fsize) {
|
|
||||||
#if (HAVE_SENDFILE64)
|
#if (HAVE_SENDFILE64)
|
||||||
offset = file->file_pos;
|
offset = file->file_pos;
|
||||||
#else
|
#else
|
||||||
@ -196,6 +215,10 @@ ngx_chain_t *ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
|
|||||||
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "writev: %d", sent);
|
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "writev: %d", sent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (send - sprev == sent) {
|
||||||
|
complete = 1;
|
||||||
|
}
|
||||||
|
|
||||||
c->sent += sent;
|
c->sent += sent;
|
||||||
|
|
||||||
for (cl = in; cl; cl = cl->next) {
|
for (cl = in; cl; cl = cl->next) {
|
||||||
@ -235,15 +258,19 @@ ngx_chain_t *ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (eintr) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!complete) {
|
||||||
|
wev->ready = 0;
|
||||||
|
return cl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (send >= limit || cl == NULL) {
|
||||||
|
return cl;
|
||||||
|
}
|
||||||
|
|
||||||
in = cl;
|
in = cl;
|
||||||
|
|
||||||
/* "tail == in" means that a single sendfile() is complete */
|
|
||||||
|
|
||||||
} while ((tail && tail == in) || eintr);
|
|
||||||
|
|
||||||
if (in) {
|
|
||||||
wev->ready = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return in;
|
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,8 @@ typedef struct {
|
|||||||
ssize_t (*recv)(ngx_connection_t *c, u_char *buf, size_t size);
|
ssize_t (*recv)(ngx_connection_t *c, u_char *buf, size_t size);
|
||||||
ssize_t (*recv_chain)(ngx_connection_t *c, ngx_chain_t *in);
|
ssize_t (*recv_chain)(ngx_connection_t *c, ngx_chain_t *in);
|
||||||
ssize_t (*send)(ngx_connection_t *c, u_char *buf, size_t size);
|
ssize_t (*send)(ngx_connection_t *c, u_char *buf, size_t size);
|
||||||
ngx_chain_t *(*send_chain)(ngx_connection_t *c, ngx_chain_t *in);
|
ngx_chain_t *(*send_chain)(ngx_connection_t *c, ngx_chain_t *in,
|
||||||
|
off_t limit);
|
||||||
int flags;
|
int flags;
|
||||||
} ngx_os_io_t;
|
} ngx_os_io_t;
|
||||||
|
|
||||||
@ -41,7 +42,8 @@ int ngx_posix_post_conf_init(ngx_log_t *log);
|
|||||||
|
|
||||||
ssize_t ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size);
|
ssize_t ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size);
|
||||||
ssize_t ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *entry);
|
ssize_t ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *entry);
|
||||||
ngx_chain_t *ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in);
|
ngx_chain_t *ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in,
|
||||||
|
off_t limit);
|
||||||
|
|
||||||
|
|
||||||
extern ngx_os_io_t ngx_os_io;
|
extern ngx_os_io_t ngx_os_io;
|
||||||
|
@ -786,7 +786,7 @@ ngx_int_t ngx_write_channel(ngx_socket_t s, ngx_channel_t *ch, size_t size,
|
|||||||
cmsg.cm.cmsg_len = sizeof(cmsg);
|
cmsg.cm.cmsg_len = sizeof(cmsg);
|
||||||
cmsg.cm.cmsg_level = SOL_SOCKET;
|
cmsg.cm.cmsg_level = SOL_SOCKET;
|
||||||
cmsg.cm.cmsg_type = SCM_RIGHTS;
|
cmsg.cm.cmsg_type = SCM_RIGHTS;
|
||||||
*(int *) CMSG_DATA(&cmsg) = ch->fd;
|
*(int *) CMSG_DATA(&cmsg.cm) = ch->fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
@ -896,7 +896,7 @@ ngx_int_t ngx_read_channel(ngx_socket_t s, ngx_channel_t *ch, size_t size,
|
|||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
ch->fd = *(int *) CMSG_DATA(&cmsg);
|
ch->fd = *(int *) CMSG_DATA(&cmsg.cm);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msg.msg_flags & (MSG_TRUNC|MSG_CTRUNC)) {
|
if (msg.msg_flags & (MSG_TRUNC|MSG_CTRUNC)) {
|
||||||
|
@ -2,7 +2,8 @@
|
|||||||
#define _NGX_SOLARIS_H_INCLUDED_
|
#define _NGX_SOLARIS_H_INCLUDED_
|
||||||
|
|
||||||
|
|
||||||
ngx_chain_t *ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in);
|
ngx_chain_t *ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in,
|
||||||
|
off_t limit);
|
||||||
|
|
||||||
|
|
||||||
#endif /* _NGX_SOLARIS_H_INCLUDED_ */
|
#endif /* _NGX_SOLARIS_H_INCLUDED_ */
|
||||||
|
@ -9,14 +9,15 @@
|
|||||||
#include <ngx_event.h>
|
#include <ngx_event.h>
|
||||||
|
|
||||||
|
|
||||||
ngx_chain_t *ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in)
|
ngx_chain_t *ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in,
|
||||||
|
off_t limit)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
u_char *prev;
|
u_char *prev;
|
||||||
off_t fprev;
|
off_t fprev, sprev, send, aligned;
|
||||||
size_t sent, size;
|
size_t size, sent;
|
||||||
ssize_t n;
|
ssize_t n;
|
||||||
ngx_int_t eintr;
|
ngx_int_t eintr, complete;
|
||||||
ngx_err_t err;
|
ngx_err_t err;
|
||||||
sendfilevec_t *sfv;
|
sendfilevec_t *sfv;
|
||||||
ngx_array_t vec;
|
ngx_array_t vec;
|
||||||
@ -29,20 +30,25 @@ ngx_chain_t *ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in)
|
|||||||
return in;
|
return in;
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
send = 0;
|
||||||
|
complete = 0;
|
||||||
|
|
||||||
|
for ( ;; ) {
|
||||||
fd = SFV_FD_SELF;
|
fd = SFV_FD_SELF;
|
||||||
prev = NULL;
|
prev = NULL;
|
||||||
fprev = 0;
|
fprev = 0;
|
||||||
sfv = NULL;
|
sfv = NULL;
|
||||||
eintr = 0;
|
eintr = 0;
|
||||||
sent = 0;
|
sent = 0;
|
||||||
|
sprev = send;
|
||||||
|
|
||||||
ngx_init_array(vec, c->pool, 10, sizeof(sendfilevec_t),
|
ngx_init_array(vec, c->pool, 10, sizeof(sendfilevec_t),
|
||||||
NGX_CHAIN_ERROR);
|
NGX_CHAIN_ERROR);
|
||||||
|
|
||||||
/* create the sendfilevec and coalesce the neighbouring bufs */
|
/* create the sendfilevec and coalesce the neighbouring bufs */
|
||||||
|
|
||||||
for (cl = in; cl && vec.nelts < IOV_MAX; cl = cl->next) {
|
for (cl = in; cl && vec.nelts < IOV_MAX && send < limit; cl = cl->next)
|
||||||
|
{
|
||||||
if (ngx_buf_special(cl->buf)) {
|
if (ngx_buf_special(cl->buf)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -50,24 +56,44 @@ ngx_chain_t *ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in)
|
|||||||
if (ngx_buf_in_memory_only(cl->buf)) {
|
if (ngx_buf_in_memory_only(cl->buf)) {
|
||||||
fd = SFV_FD_SELF;
|
fd = SFV_FD_SELF;
|
||||||
|
|
||||||
|
size = cl->buf->last - cl->buf->pos;
|
||||||
|
|
||||||
|
if (send + size > limit) {
|
||||||
|
size = limit - send;
|
||||||
|
}
|
||||||
|
|
||||||
if (prev == cl->buf->pos) {
|
if (prev == cl->buf->pos) {
|
||||||
sfv->sfv_len += cl->buf->last - cl->buf->pos;
|
sfv->sfv_len += size;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
ngx_test_null(sfv, ngx_push_array(&vec), NGX_CHAIN_ERROR);
|
ngx_test_null(sfv, ngx_push_array(&vec), NGX_CHAIN_ERROR);
|
||||||
sfv->sfv_fd = SFV_FD_SELF;
|
sfv->sfv_fd = SFV_FD_SELF;
|
||||||
sfv->sfv_flag = 0;
|
sfv->sfv_flag = 0;
|
||||||
sfv->sfv_off = (off_t) (uintptr_t) cl->buf->pos;
|
sfv->sfv_off = (off_t) (uintptr_t) cl->buf->pos;
|
||||||
sfv->sfv_len = cl->buf->last - cl->buf->pos;
|
sfv->sfv_len = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
prev = cl->buf->last;
|
prev = cl->buf->pos + size;
|
||||||
|
send += size;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
prev = NULL;
|
prev = NULL;
|
||||||
|
|
||||||
|
size = (size_t) (cl->buf->file_last - cl->buf->file_pos);
|
||||||
|
|
||||||
|
if (send + size > limit) {
|
||||||
|
size = limit - send;
|
||||||
|
|
||||||
|
aligned = (cl->buf->file_pos + size + ngx_pagesize - 1)
|
||||||
|
& ~(ngx_pagesize - 1);
|
||||||
|
|
||||||
|
if (aligned <= cl->buf->file_last) {
|
||||||
|
size = aligned - cl->buf->file_pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (fd == cl->buf->file->fd && fprev == cl->buf->file_pos) {
|
if (fd == cl->buf->file->fd && fprev == cl->buf->file_pos) {
|
||||||
sfv->sfv_len += cl->buf->file_last - cl->buf->file_pos;
|
sfv->sfv_len += size;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
ngx_test_null(sfv, ngx_push_array(&vec), NGX_CHAIN_ERROR);
|
ngx_test_null(sfv, ngx_push_array(&vec), NGX_CHAIN_ERROR);
|
||||||
@ -75,20 +101,14 @@ ngx_chain_t *ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in)
|
|||||||
sfv->sfv_fd = fd;
|
sfv->sfv_fd = fd;
|
||||||
sfv->sfv_flag = 0;
|
sfv->sfv_flag = 0;
|
||||||
sfv->sfv_off = cl->buf->file_pos;
|
sfv->sfv_off = cl->buf->file_pos;
|
||||||
sfv->sfv_len = cl->buf->file_last - cl->buf->file_pos;
|
sfv->sfv_len = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprev = cl->buf->file_last;
|
fprev = cl->buf->file_pos + size;
|
||||||
|
send += size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* the tail is the rest of the chain that exceedes a single
|
|
||||||
* sendfilev() capability, IOV_MAX in Solaris is limited by 16
|
|
||||||
*/
|
|
||||||
|
|
||||||
tail = cl;
|
|
||||||
|
|
||||||
n = sendfilev(c->fd, vec.elts, vec.nelts, &sent);
|
n = sendfilev(c->fd, vec.elts, vec.nelts, &sent);
|
||||||
|
|
||||||
if (n == -1) {
|
if (n == -1) {
|
||||||
@ -113,6 +133,10 @@ ngx_chain_t *ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in)
|
|||||||
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||||
"sendfilev: %d " SIZE_T_FMT, n, sent);
|
"sendfilev: %d " SIZE_T_FMT, n, sent);
|
||||||
|
|
||||||
|
if (send - sprev == sent) {
|
||||||
|
complete = 1;
|
||||||
|
}
|
||||||
|
|
||||||
c->sent += sent;
|
c->sent += sent;
|
||||||
|
|
||||||
for (cl = in; cl; cl = cl->next) {
|
for (cl = in; cl; cl = cl->next) {
|
||||||
@ -152,15 +176,19 @@ ngx_chain_t *ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (eintr) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!complete) {
|
||||||
|
wev->ready = 0;
|
||||||
|
return cl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (send >= limit || cl == NULL) {
|
||||||
|
return cl;
|
||||||
|
}
|
||||||
|
|
||||||
in = cl;
|
in = cl;
|
||||||
|
|
||||||
/* "tail == in" means that a single sendfilev() is complete */
|
|
||||||
|
|
||||||
} while ((tail && tail == in) || eintr);
|
|
||||||
|
|
||||||
if (in) {
|
|
||||||
wev->ready = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return in;
|
|
||||||
}
|
}
|
||||||
|
@ -4,15 +4,15 @@
|
|||||||
#include <ngx_event.h>
|
#include <ngx_event.h>
|
||||||
|
|
||||||
|
|
||||||
ngx_chain_t *ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in)
|
ngx_chain_t *ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
|
||||||
{
|
{
|
||||||
u_char *prev;
|
u_char *prev;
|
||||||
ssize_t n, size;
|
ssize_t n, size;
|
||||||
off_t sent;
|
off_t send, sprev, sent;
|
||||||
struct iovec *iov;
|
struct iovec *iov;
|
||||||
ngx_int_t eintr;
|
ngx_uint_t eintr, complete;
|
||||||
ngx_err_t err;
|
ngx_err_t err;
|
||||||
ngx_array_t io;
|
ngx_array_t vec;
|
||||||
ngx_chain_t *cl;
|
ngx_chain_t *cl;
|
||||||
ngx_event_t *wev;
|
ngx_event_t *wev;
|
||||||
|
|
||||||
@ -34,30 +34,45 @@ ngx_chain_t *ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ngx_init_array(io, c->pool, 10, sizeof(struct iovec), NGX_CHAIN_ERROR);
|
ngx_init_array(vec, c->pool, 10, sizeof(struct iovec), NGX_CHAIN_ERROR);
|
||||||
|
|
||||||
do {
|
send = 0;
|
||||||
|
complete = 0;
|
||||||
|
|
||||||
|
for ( ;; ) {
|
||||||
prev = NULL;
|
prev = NULL;
|
||||||
iov = NULL;
|
iov = NULL;
|
||||||
eintr = 0;
|
eintr = 0;
|
||||||
|
sprev = send;
|
||||||
|
|
||||||
/* create the iovec and coalesce the neighbouring bufs */
|
/* create the iovec and coalesce the neighbouring bufs */
|
||||||
|
|
||||||
for (cl = in; cl; cl = cl->next) {
|
for (cl = in; cl && vec.nelts < IOV_MAX && send < limit; cl = cl->next)
|
||||||
|
{
|
||||||
|
if (ngx_buf_special(cl->buf)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
size = cl->buf->last - cl->buf->pos;
|
||||||
|
|
||||||
|
if (send + size > limit) {
|
||||||
|
size = limit - send;
|
||||||
|
}
|
||||||
|
|
||||||
if (prev == cl->buf->pos) {
|
if (prev == cl->buf->pos) {
|
||||||
iov->iov_len += cl->buf->last - cl->buf->pos;
|
iov->iov_len += size;
|
||||||
prev = cl->buf->last;
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
ngx_test_null(iov, ngx_push_array(&io), NGX_CHAIN_ERROR);
|
ngx_test_null(iov, ngx_push_array(&vec), NGX_CHAIN_ERROR);
|
||||||
iov->iov_base = (void *) cl->buf->pos;
|
iov->iov_base = (void *) cl->buf->pos;
|
||||||
iov->iov_len = cl->buf->last - cl->buf->pos;
|
iov->iov_len = size;
|
||||||
prev = cl->buf->last;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prev = cl->buf->pos + size;
|
||||||
|
send += size;
|
||||||
}
|
}
|
||||||
|
|
||||||
n = writev(c->fd, io.elts, io.nelts);
|
n = writev(c->fd, vec.elts, vec.nelts);
|
||||||
|
|
||||||
if (n == -1) {
|
if (n == -1) {
|
||||||
err = ngx_errno;
|
err = ngx_errno;
|
||||||
@ -82,34 +97,48 @@ ngx_chain_t *ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in)
|
|||||||
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||||
"writev: " OFF_T_FMT, sent);
|
"writev: " OFF_T_FMT, sent);
|
||||||
|
|
||||||
|
if (send - sprev == sent) {
|
||||||
|
complete = 1;
|
||||||
|
}
|
||||||
|
|
||||||
c->sent += sent;
|
c->sent += sent;
|
||||||
|
|
||||||
for (cl = in; cl && sent > 0; cl = cl->next) {
|
for (cl = in; cl && sent > 0; cl = cl->next) {
|
||||||
|
if (ngx_buf_special(cl->buf)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sent == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
size = cl->buf->last - cl->buf->pos;
|
size = cl->buf->last - cl->buf->pos;
|
||||||
|
|
||||||
if (sent >= size) {
|
if (sent >= size) {
|
||||||
sent -= size;
|
sent -= size;
|
||||||
|
cl->buf->pos = cl->buf->last;
|
||||||
if (ngx_buf_in_memory(cl->buf)) {
|
|
||||||
cl->buf->pos = cl->buf->last;
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ngx_buf_in_memory(cl->buf)) {
|
cl->buf->pos += sent;
|
||||||
cl->buf->pos += sent;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
} while (eintr);
|
if (eintr) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (cl) {
|
if (!complete) {
|
||||||
wev->ready = 0;
|
wev->ready = 0;
|
||||||
|
return cl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (send >= limit || cl == NULL) {
|
||||||
|
return cl;
|
||||||
|
}
|
||||||
|
|
||||||
|
in = cl;
|
||||||
}
|
}
|
||||||
|
|
||||||
return cl;
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user