summaryrefslogtreecommitdiffhomepage
path: root/src/nxt_conn_write.c
diff options
context:
space:
mode:
authorMax Romanov <max.romanov@nginx.com>2020-03-12 17:54:29 +0300
committerMax Romanov <max.romanov@nginx.com>2020-03-12 17:54:29 +0300
commit5296be0b82784eb90abc86339e6c16841e9a9727 (patch)
tree442b315416f9c7ce00b9583ecf6daca07ae68290 /src/nxt_conn_write.c
parent08b65721e25b1b94affc12078a623a11341525d1 (diff)
downloadunit-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.c96
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)