ngx_chain_t **last;
ngx_connection_t *connection;
ngx_pool_t *pool;
+ off_t limit;
} ngx_chain_writer_ctx_t;
ngx_log_debug1(NGX_LOG_DEBUG_CORE, ctx->connection->log, 0,
"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,
"WRITER1: %X", ctx->out);
unsigned short timedout:1;
unsigned short timer_set:1;
+ unsigned short delayed:1;
+
unsigned short read_discarded:1;
unsigned short unexpected_eof:1;
writer->out = NULL;
writer->last = &writer->out;
writer->connection = c;
+ writer->limit = OFF_T_MAX_VALUE;
if (p->upstream->peer.tries > 1 && p->request_sent) {
ngx_http_proxy_reinit_upstream(p);
ngx_str_t default_type;
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 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 send_timeout; /* send_timeout */
wev = r->connection->write;
wev->event_handler = ngx_http_writer;
- if (wev->ready && r->delayed) {
+ if (wev->ready && wev->delayed) {
return;
}
clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
ngx_http_core_module);
- if (!r->delayed) {
+ if (!wev->delayed) {
ngx_add_timer(wev, clcf->send_timeout);
}
r = c->data;
if (wev->timedout) {
- if (!r->delayed) {
+ if (!wev->delayed) {
ngx_http_client_error(r, 0, NGX_HTTP_REQUEST_TIME_OUT);
return;
}
wev->timedout = 0;
- r->delayed = 0;
+ wev->delayed = 0;
if (!wev->ready) {
clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
}
} else {
- if (r->delayed) {
+ if (wev->delayed) {
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0,
"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;
}
}
if (rc == NGX_AGAIN) {
clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
ngx_http_core_module);
- if (!wev->ready && !r->delayed) {
+ if (!wev->ready && !wev->delayed) {
ngx_add_timer(wev, clcf->send_timeout);
}
/* can we use sendfile ? */
unsigned sendfile:1;
- unsigned delayed:1;
unsigned chunked:1;
unsigned header_only:1;
unsigned keepalive:1;
typedef struct {
- size_t postpone_output;
+ size_t postpone_output; /* postpone_output */
+ size_t limit_rate; /* limit_rate */
} ngx_http_write_filter_conf_t;
static ngx_command_t ngx_http_write_filter_commands[] = {
- /* STUB */
- { ngx_string("buffer_output"),
+ { ngx_string("postpone_output"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_size_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_write_filter_conf_t, postpone_output),
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_conf_set_size_slot,
NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_write_filter_conf_t, postpone_output),
+ offsetof(ngx_http_write_filter_conf_t, limit_rate),
NULL },
ngx_null_command
return NGX_OK;
}
- if (r->delayed) {
+ if (r->connection->write->delayed) {
return NGX_AGAIN;
}
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,
"http write filter %X", chain);
-#if 1
- sent = r->connection->sent - sent;
- r->delayed = 1;
- ngx_add_timer(r->connection->write, sent * 1000 / (4 * 1024));
-#endif
+ if (conf->limit_rate) {
+ sent = r->connection->sent - sent;
+ r->connection->write->delayed = 1;
+ ngx_add_timer(r->connection->write, sent * 1000 / conf->limit_rate);
+ }
if (chain == NGX_CHAIN_ERROR) {
return NGX_ERROR;
NULL);
conf->postpone_output = NGX_CONF_UNSET_SIZE;
+ conf->limit_rate = NGX_CONF_UNSET_SIZE;
return conf;
}
ngx_conf_merge_size_value(conf->postpone_output, prev->postpone_output,
1460);
+ ngx_conf_merge_size_value(conf->limit_rate, prev->limit_rate, 0);
+
return NULL;
}
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_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_ */
#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;
u_char *buf, *prev;
- off_t sent;
- size_t size;
+ off_t send, sent;
+ size_t len;
+ ssize_t size;
ngx_err_t err;
ngx_chain_t *cl;
+ send = 0;
sent = 0;
cl = in;
while (cl) {
- if (cl->buf->last - cl->buf->pos == 0) {
+ if (cl->buf->pos == cl->buf->last) {
cl = cl->next;
continue;
}
buf = cl->buf->pos;
prev = buf;
- size = 0;
+ len = 0;
/* coalesce the neighbouring bufs */
- while (cl && prev == cl->buf->pos) {
- size += cl->buf->last - cl->buf->pos;
- prev = cl->buf->last;
+ while (cl && prev == cl->buf->pos && send < limit) {
+ if (ngx_buf_special(cl->buf)) {
+ 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;
}
- 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);
#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;
*/
-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;
u_char *prev;
- off_t sent, fprev, send, limit;
+ off_t fprev, sent, send, sprev, aligned;
size_t hsize, fsize;
ssize_t size;
- ngx_uint_t eintr, eagain, ready;
+ ngx_uint_t eintr, eagain, complete;
struct iovec *iov;
struct sf_hdtr hdtr;
ngx_err_t err;
ngx_buf_t *file;
ngx_array_t header, trailer;
ngx_event_t *wev;
- ngx_chain_t *cl, *tail;
+ ngx_chain_t *cl;
wev = c->write;
#endif
-#if 1
- limit = 4096;
-#else
- limit = OFF_T_MAX_VALUE;
-#endif
+ send = 0;
+ eagain = 0;
- do {
+ for ( ;; ) {
file = NULL;
fsize = 0;
hsize = 0;
- send = 0;
eintr = 0;
- eagain = 0;
- ready = 0;
+ complete = 0;
+ sprev = send;
ngx_init_array(header, c->pool, 10, sizeof(struct iovec),
NGX_CHAIN_ERROR);
prev = 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)) {
continue;
}
/* get the file buf */
- if (cl && cl->buf->in_file) {
+ if (cl && cl->buf->in_file && send < limit) {
file = cl->buf;
fsize = 0;
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;
+ }
}
fsize += size;
} while (cl
&& cl->buf->in_file
+ && send < limit
&& file->file->fd == cl->buf->file->fd
&& fprev == cl->buf->file_pos);
}
prev = 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)) {
continue;
}
}
}
- /*
- * the tail is the rest of the chain that exceedes
- * a single sendfile() capability
- */
-
- tail = cl;
-
if (file) {
if (ngx_freebsd_use_tcp_nopush
sent = rc > 0 ? rc : 0;
}
- if (send == sent) {
- ready = 1;
+ if (send - sprev == sent) {
+ complete = 1;
}
c->sent += sent;
break;
}
- if (ready) {
- return cl;
- }
-
- in = cl;
-
if (eagain) {
/*
*/
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) {
- wev->ready = 0;
- }
+ if (send >= limit || cl == NULL) {
+ return cl;
+ }
- return in;
+ in = cl;
+ }
}
#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_ */
*/
-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;
u_char *prev;
- off_t fprev;
- size_t size, fsize, sent;
- ngx_int_t eintr;
+ off_t fprev, send, sprev, aligned;
+ size_t fsize;
+ ssize_t size, sent;
+ ngx_uint_t eintr, complete;
struct iovec *iov;
ngx_err_t err;
ngx_buf_t *file;
ngx_array_t header;
ngx_event_t *wev;
- ngx_chain_t *cl, *tail;
+ ngx_chain_t *cl;
#if (HAVE_SENDFILE64)
off_t offset;
#else
return in;
}
- do {
+ send = 0;
+
+ for ( ;; ) {
file = NULL;
fsize = 0;
eintr = 0;
+ complete = 0;
+ sprev = send;
ngx_init_array(header, c->pool, 10, sizeof(struct iovec),
NGX_CHAIN_ERROR);
/* 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)) {
continue;
}
break;
}
+ size = cl->buf->last - cl->buf->pos;
+
+ if (send + size > limit) {
+ size = limit - send;
+ }
+
if (prev == cl->buf->pos) {
- iov->iov_len += cl->buf->last - cl->buf->pos;
+ iov->iov_len += size;
} else {
ngx_test_null(iov, ngx_push_array(&header), NGX_CHAIN_ERROR);
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 */
}
}
- 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;
- fsize = (size_t) (file->file_last - file->file_pos);
- fprev = file->file_last;
- cl = cl->next;
+ fsize = 0;
/* coalesce the neighbouring file bufs */
- while (cl && (cl->buf->in_file)) {
- if (file->file->fd != cl->buf->file->fd
- || fprev != cl->buf->file_pos)
- {
- break;
+ do {
+ 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;
+ }
}
- fsize += (size_t) (cl->buf->file_last - cl->buf->file_pos);
- fprev = cl->buf->file_last;
+ fsize += size;
+ send += size;
+ fprev = cl->buf->file_pos + size;
cl = cl->next;
- }
- }
-
- /*
- * the tail is the rest of the chain that exceedes
- * a single sendfile() capability
- */
- tail = cl;
+ } while (cl
+ && cl->buf->in_file
+ && send < limit
+ && file->file->fd == cl->buf->file->fd
+ && fprev == cl->buf->file_pos);
+ }
- if (fsize) {
+ if (file) {
#if (HAVE_SENDFILE64)
offset = file->file_pos;
#else
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "writev: %d", sent);
}
+ if (send - sprev == sent) {
+ complete = 1;
+ }
+
c->sent += sent;
for (cl = in; cl; cl = cl->next) {
break;
}
- in = cl;
+ if (eintr) {
+ continue;
+ }
- /* "tail == in" means that a single sendfile() is complete */
+ if (!complete) {
+ wev->ready = 0;
+ return cl;
+ }
- } while ((tail && tail == in) || eintr);
+ if (send >= limit || cl == NULL) {
+ return cl;
+ }
- if (in) {
- wev->ready = 0;
+ in = cl;
}
-
- return in;
}
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 (*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;
} ngx_os_io_t;
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);
-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;
cmsg.cm.cmsg_len = sizeof(cmsg);
cmsg.cm.cmsg_level = SOL_SOCKET;
cmsg.cm.cmsg_type = SCM_RIGHTS;
- *(int *) CMSG_DATA(&cmsg) = ch->fd;
+ *(int *) CMSG_DATA(&cmsg.cm) = ch->fd;
}
#else
return NGX_ERROR;
}
- ch->fd = *(int *) CMSG_DATA(&cmsg);
+ ch->fd = *(int *) CMSG_DATA(&cmsg.cm);
}
if (msg.msg_flags & (MSG_TRUNC|MSG_CTRUNC)) {
#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_ */
#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;
u_char *prev;
- off_t fprev;
- size_t sent, size;
+ off_t fprev, sprev, send, aligned;
+ size_t size, sent;
ssize_t n;
- ngx_int_t eintr;
+ ngx_int_t eintr, complete;
ngx_err_t err;
sendfilevec_t *sfv;
ngx_array_t vec;
return in;
}
- do {
+ send = 0;
+ complete = 0;
+
+ for ( ;; ) {
fd = SFV_FD_SELF;
prev = NULL;
fprev = 0;
sfv = NULL;
eintr = 0;
sent = 0;
+ sprev = send;
ngx_init_array(vec, c->pool, 10, sizeof(sendfilevec_t),
NGX_CHAIN_ERROR);
/* 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)) {
continue;
}
if (ngx_buf_in_memory_only(cl->buf)) {
fd = SFV_FD_SELF;
+ size = cl->buf->last - cl->buf->pos;
+
+ if (send + size > limit) {
+ size = limit - send;
+ }
+
if (prev == cl->buf->pos) {
- sfv->sfv_len += cl->buf->last - cl->buf->pos;
+ sfv->sfv_len += size;
} else {
ngx_test_null(sfv, ngx_push_array(&vec), NGX_CHAIN_ERROR);
sfv->sfv_fd = SFV_FD_SELF;
sfv->sfv_flag = 0;
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 {
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) {
- sfv->sfv_len += cl->buf->file_last - cl->buf->file_pos;
+ sfv->sfv_len += size;
} else {
ngx_test_null(sfv, ngx_push_array(&vec), NGX_CHAIN_ERROR);
sfv->sfv_fd = fd;
sfv->sfv_flag = 0;
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);
if (n == -1) {
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
"sendfilev: %d " SIZE_T_FMT, n, sent);
+ if (send - sprev == sent) {
+ complete = 1;
+ }
+
c->sent += sent;
for (cl = in; cl; cl = cl->next) {
break;
}
- in = cl;
+ if (eintr) {
+ continue;
+ }
- /* "tail == in" means that a single sendfilev() is complete */
+ if (!complete) {
+ wev->ready = 0;
+ return cl;
+ }
- } while ((tail && tail == in) || eintr);
+ if (send >= limit || cl == NULL) {
+ return cl;
+ }
- if (in) {
- wev->ready = 0;
+ in = cl;
}
-
- return in;
}
#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;
ssize_t n, size;
- off_t sent;
+ off_t send, sprev, sent;
struct iovec *iov;
- ngx_int_t eintr;
+ ngx_uint_t eintr, complete;
ngx_err_t err;
- ngx_array_t io;
+ ngx_array_t vec;
ngx_chain_t *cl;
ngx_event_t *wev;
#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;
iov = NULL;
eintr = 0;
+ sprev = send;
/* 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) {
- iov->iov_len += cl->buf->last - cl->buf->pos;
- prev = cl->buf->last;
+ iov->iov_len += size;
} 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_len = cl->buf->last - cl->buf->pos;
- prev = cl->buf->last;
+ iov->iov_len = size;
}
+
+ 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) {
err = ngx_errno;
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
"writev: " OFF_T_FMT, sent);
+ if (send - sprev == sent) {
+ complete = 1;
+ }
+
c->sent += sent;
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;
if (sent >= size) {
sent -= size;
-
- if (ngx_buf_in_memory(cl->buf)) {
- cl->buf->pos = cl->buf->last;
- }
+ cl->buf->pos = cl->buf->last;
continue;
}
- if (ngx_buf_in_memory(cl->buf)) {
- cl->buf->pos += sent;
- }
+ cl->buf->pos += sent;
break;
}
- } while (eintr);
+ if (eintr) {
+ continue;
+ }
- if (cl) {
- wev->ready = 0;
- }
+ if (!complete) {
+ wev->ready = 0;
+ return cl;
+ }
- return cl;
+ if (send >= limit || cl == NULL) {
+ return cl;
+ }
+
+ in = cl;
+ }
}