diff options
author | Igor Sysoev <igor@sysoev.ru> | 2003-10-21 07:47:21 +0000 |
---|---|---|
committer | Igor Sysoev <igor@sysoev.ru> | 2003-10-21 07:47:21 +0000 |
commit | 9760a1336f0eb4057b6e2ccdd4b0145087102b17 (patch) | |
tree | dcaf614b7b3181c53eca9cbe7ff3c37f850c2804 /src/os/unix/ngx_freebsd_sendfile_chain.c | |
parent | 54276be80c35fcff04da8cd129452995e9ba8ba5 (diff) | |
download | nginx-9760a1336f0eb4057b6e2ccdd4b0145087102b17.tar.gz nginx-9760a1336f0eb4057b6e2ccdd4b0145087102b17.zip |
nginx-0.0.1-2003-10-21-11:47:21 import
Diffstat (limited to 'src/os/unix/ngx_freebsd_sendfile_chain.c')
-rw-r--r-- | src/os/unix/ngx_freebsd_sendfile_chain.c | 76 |
1 files changed, 55 insertions, 21 deletions
diff --git a/src/os/unix/ngx_freebsd_sendfile_chain.c b/src/os/unix/ngx_freebsd_sendfile_chain.c index f7751a772..1633b2fb8 100644 --- a/src/os/unix/ngx_freebsd_sendfile_chain.c +++ b/src/os/unix/ngx_freebsd_sendfile_chain.c @@ -14,8 +14,8 @@ * and the first part of the file in one packet but also sends 4K pages * in the full packets. * - * Until FreeBSD 4.5 the turning TCP_NOPUSH off does not flush - * the pending data that less than MSS so the data is sent with 5 second delay. + * Until FreeBSD 4.5 the turning TCP_NOPUSH off does not flush the pending + * data that less than MSS so the data can be sent with 5 second delay. * We do not use TCP_NOPUSH on FreeBSD prior to 4.5 although it can be used * for non-keepalive HTTP connections. */ @@ -23,10 +23,10 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in) { - int rc, eintr; + int rc, eintr, eagain; char *prev; - ssize_t hsize, size; - off_t sent; + ssize_t hsize, fsize, size; + off_t sent, fprev; struct iovec *iov; struct sf_hdtr hdtr; ngx_err_t err; @@ -41,8 +41,10 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in) do { ce = in; file = NULL; + fsize = 0; hsize = 0; eintr = 0; + eagain = 0; ngx_init_array(header, c->pool, 10, sizeof(struct iovec), NGX_CHAIN_ERROR); @@ -77,11 +79,27 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in) hsize += ce->hunk->last - ce->hunk->pos; } - /* TODO: coalesce the neighbouring file hunks */ + /* get the file hunk */ if (ce && (ce->hunk->type & NGX_HUNK_FILE)) { file = ce->hunk; ce = ce->next; + fsize = (size_t) (file->file_last - file->file_pos); + fprev = file->file_last; + + /* coalesce the neighbouring file hunks */ + + while (ce && (ce->hunk->type & NGX_HUNK_FILE)) { + if (file->file->fd != ce->hunk->file->fd + || fprev != ce->hunk->file_pos) + { + break; + } + + fsize += (size_t) (ce->hunk->file_last - ce->hunk->file_pos); + fprev = ce->hunk->file_last; + ce = ce->next; + } } /* create the iovec and coalesce the neighbouring chain entries */ @@ -110,6 +128,11 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in) } } + /* + * the tail is the rest of the chain that exceeded + * a single sendfile() capability + */ + tail = ce; if (file) { @@ -136,8 +159,7 @@ ngx_log_debug(c->log, "NOPUSH"); } rc = sendfile(file->file->fd, c->fd, file->file_pos, - (size_t) (file->file_last - file->file_pos) + hsize, - &hdtr, &sent, 0); + fsize + hsize, &hdtr, &sent, 0); if (rc == -1) { err = ngx_errno; @@ -146,6 +168,10 @@ ngx_log_debug(c->log, "NOPUSH"); eintr = 1; } + if (err == NGX_EAGAIN) { + eagain = 1; + } + if (err == NGX_EAGAIN || err == NGX_EINTR) { ngx_log_error(NGX_LOG_INFO, c->log, err, "sendfile() sent only %qd bytes", sent); @@ -159,8 +185,7 @@ ngx_log_debug(c->log, "NOPUSH"); #if (NGX_DEBUG_WRITE_CHAIN) ngx_log_debug(c->log, "sendfile: %d, @%qd %qd:%d" _ - rc _ file->file_pos _ sent _ - (size_t) (file->file_last - file->file_pos) + hsize); + rc _ file->file_pos _ sent _ fsize + hsize); #endif } else { @@ -169,6 +194,7 @@ ngx_log_debug(c->log, "NOPUSH"); if (rc == -1) { err = ngx_errno; if (err == NGX_EAGAIN) { + eagain = 1; ngx_log_error(NGX_LOG_INFO, c->log, err, "writev() EAGAIN"); } else if (err == NGX_EINTR) { @@ -190,14 +216,18 @@ ngx_log_debug(c->log, "NOPUSH"); c->sent += sent; - for (ce = in; ce && sent > 0; ce = ce->next) { + for (ce = in; ce; ce = ce->next) { - if (ce->hunk->type & NGX_HUNK_IN_MEMORY) { - size = ce->hunk->last - ce->hunk->pos; - } else { - size = ce->hunk->file_last - ce->hunk->file_pos; + if (ngx_hunk_special(ce->hunk)) { + continue; + } + + if (sent == 0) { + break; } + size = ngx_hunk_size(ce->hunk); + if (sent >= size) { sent -= size; @@ -223,16 +253,20 @@ ngx_log_debug(c->log, "NOPUSH"); break; } - ngx_destroy_array(&trailer); - ngx_destroy_array(&header); - in = ce; - } while ((tail && tail == ce) || eintr); + if (eagain) { + c->write->ready = 0; + break; + } + + /* "tail == in" means that a single sendfile() is complete */ + + } while ((tail && tail == in) || eintr); - if (ce) { + if (in) { c->write->ready = 0; } - return ce; + return in; } |