diff options
author | Max Romanov <max.romanov@nginx.com> | 2020-03-12 17:54:29 +0300 |
---|---|---|
committer | Max Romanov <max.romanov@nginx.com> | 2020-03-12 17:54:29 +0300 |
commit | 5296be0b82784eb90abc86339e6c16841e9a9727 (patch) | |
tree | 442b315416f9c7ce00b9583ecf6daca07ae68290 /src/nxt_conn_write.c | |
parent | 08b65721e25b1b94affc12078a623a11341525d1 (diff) | |
download | unit-5296be0b82784eb90abc86339e6c16841e9a9727.tar.gz unit-5296be0b82784eb90abc86339e6c16841e9a9727.tar.bz2 |
Using disk file to store large request body.
This closes #386 on GitHub.
Diffstat (limited to 'src/nxt_conn_write.c')
-rw-r--r-- | src/nxt_conn_write.c | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/src/nxt_conn_write.c b/src/nxt_conn_write.c index 298d8f75..d7a6a8da 100644 --- a/src/nxt_conn_write.c +++ b/src/nxt_conn_write.c @@ -9,6 +9,8 @@ static void nxt_conn_write_timer_handler(nxt_task_t *task, void *obj, void *data); +static ssize_t nxt_conn_io_sendfile(nxt_task_t *task, nxt_sendbuf_t *sb); +static ssize_t nxt_sendfile(int fd, int s, off_t pos, size_t size); void @@ -170,10 +172,104 @@ nxt_conn_io_sendbuf(nxt_task_t *task, nxt_sendbuf_t *sb) return 0; } + if (niov == 0 && nxt_buf_is_file(sb->buf)) { + return nxt_conn_io_sendfile(task, sb); + } + return nxt_conn_io_writev(task, sb, iov, niov); } +static ssize_t +nxt_conn_io_sendfile(nxt_task_t *task, nxt_sendbuf_t *sb) +{ + size_t size; + ssize_t n; + nxt_buf_t *b; + nxt_err_t err; + + b = sb->buf; + + for ( ;; ) { + size = b->file_end - b->file_pos; + + n = nxt_sendfile(b->file->fd, sb->socket, b->file_pos, size); + + err = (n == -1) ? nxt_errno : 0; + + nxt_debug(task, "sendfile(%FD, %d, @%O, %uz): %z", + b->file->fd, sb->socket, b->file_pos, size, n); + + if (n > 0) { + if (n < (ssize_t) size) { + sb->ready = 0; + } + + return n; + } + + if (nxt_slow_path(n == 0)) { + nxt_alert(task, "sendfile() reported that file was truncated at %O", + b->file_pos); + + return NXT_ERROR; + } + + /* n == -1 */ + + switch (err) { + + case NXT_EAGAIN: + sb->ready = 0; + nxt_debug(task, "sendfile() %E", err); + + return NXT_AGAIN; + + case NXT_EINTR: + nxt_debug(task, "sendfile() %E", err); + continue; + + default: + sb->error = err; + nxt_log(task, nxt_socket_error_level(err), + "sendfile(%FD, %d, @%O, %uz) failed %E", + b->file->fd, sb->socket, b->file_pos, size, err); + + return NXT_ERROR; + } + } +} + + +static ssize_t +nxt_sendfile(int fd, int s, off_t pos, size_t size) +{ + ssize_t res; + +#ifdef NXT_HAVE_MACOSX_SENDFILE + off_t sent = size; + + int rc = sendfile(fd, s, pos, &sent, NULL, 0); + + res = (rc == 0 || sent > 0) ? sent : -1; +#endif + +#ifdef NXT_HAVE_FREEBSD_SENDFILE + off_t sent = 0; + + int rc = sendfile(fd, s, pos, size, NULL, &sent, 0); + + res = (rc == 0 || sent > 0) ? sent : -1; +#endif + +#ifdef NXT_HAVE_LINUX_SENDFILE + res = sendfile(s, fd, &pos, size); +#endif + + return res; +} + + ssize_t nxt_conn_io_writev(nxt_task_t *task, nxt_sendbuf_t *sb, struct iovec *iov, nxt_uint_t niov) |