From a86ea83b5a20eb75bc86a66f6feeb7f3c1520719 Mon Sep 17 00:00:00 2001 From: Glenn Strauss Date: Sun, 12 May 2019 18:31:43 -0400 Subject: [PATCH] [core] chunkqueue perf: read small files into mem --- src/http-header-glue.c | 10 +++++++--- src/http_chunk.c | 39 +++++++++++++++++++++++++++++++++++++-- src/http_chunk.h | 2 +- 3 files changed, 45 insertions(+), 6 deletions(-) diff --git a/src/http-header-glue.c b/src/http-header-glue.c index 08cc03cb..b7f03309 100644 --- a/src/http-header-glue.c +++ b/src/http-header-glue.c @@ -591,9 +591,13 @@ void http_response_send_file (server *srv, connection *con, buffer *path) { * the HEAD request will drop it afterwards again */ - http_chunk_append_file_fd(srv, con, path, fd, sce->st.st_size); - con->http_status = 200; - con->file_finished = 1; + if (0 == http_chunk_append_file_fd(srv, con, path, fd, sce->st.st_size)) { + con->http_status = 200; + con->file_finished = 1; + } + else { + con->http_status = 500; + } } diff --git a/src/http_chunk.c b/src/http_chunk.c index 302e94b3..e973d6e0 100644 --- a/src/http_chunk.c +++ b/src/http_chunk.c @@ -43,6 +43,36 @@ static int http_chunk_append_file_open_fstat(server *srv, connection *con, buffe return stat_cache_open_rdonly_fstat(fn, st, con->conf.follow_symlink); } +static int http_chunk_append_read_fd_range(server *srv, connection *con, buffer *fn, int fd, off_t offset, off_t len) { + /* note: this routine should not be used for range requests + * unless the total size of ranges requested is small */ + /* note: future: could read into existing MEM_CHUNK in cq->last if + * there is sufficient space, but would need to adjust for existing + * offset in for cq->bytes_in in chunkqueue_append_buffer_commit() */ + UNUSED(fn); + + if (con->response.send_chunked) { + http_chunk_append_len(srv, con, (uintmax_t)len); + } + + if (0 != offset && -1 == lseek(fd, offset, SEEK_SET)) return -1; + chunkqueue * const cq = con->write_queue; + buffer * const b = chunkqueue_append_buffer_open_sz(cq, len+2); + ssize_t rd; + offset = 0; + do { + rd = read(fd, b->ptr+offset, len-offset); + } while ((rd > 0 && (offset += rd, len -= rd)) || errno == EINTR); + buffer_commit(b, offset); + + if (con->response.send_chunked) { + buffer_append_string_len(b, CONST_STR_LEN("\r\n")); + } + + chunkqueue_append_buffer_commit(cq); + return (rd >= 0) ? 0 : -1; +} + static void http_chunk_append_file_fd_range(server *srv, connection *con, buffer *fn, int fd, off_t offset, off_t len) { chunkqueue *cq = con->write_queue; @@ -85,11 +115,16 @@ int http_chunk_append_file(server *srv, connection *con, buffer *fn) { return 0; } -void http_chunk_append_file_fd(server *srv, connection *con, buffer *fn, int fd, off_t sz) { - if (0 != sz) { +int http_chunk_append_file_fd(server *srv, connection *con, buffer *fn, int fd, off_t sz) { + if (sz > 32768) { http_chunk_append_file_fd_range(srv, con, fn, fd, 0, sz); + return 0; } else { + int rc = (0 != sz) /*(read small files into memory)*/ + ? http_chunk_append_read_fd_range(srv, con, fn, fd, 0, sz) + : 0; close(fd); + return rc; } } diff --git a/src/http_chunk.h b/src/http_chunk.h index 404c3a10..d426a997 100644 --- a/src/http_chunk.h +++ b/src/http_chunk.h @@ -8,7 +8,7 @@ int http_chunk_append_mem(server *srv, connection *con, const char * mem, size_t int http_chunk_append_buffer(server *srv, connection *con, buffer *mem); /* may reset "mem" */ int http_chunk_transfer_cqlen(server *srv, connection *con, chunkqueue *src, size_t len); int http_chunk_append_file(server *srv, connection *con, buffer *fn); /* copies "fn" */ -void http_chunk_append_file_fd(server *srv, connection *con, buffer *fn, int fd, off_t sz); +int http_chunk_append_file_fd(server *srv, connection *con, buffer *fn, int fd, off_t sz); int http_chunk_append_file_range(server *srv, connection *con, buffer *fn, off_t offset, off_t len); /* copies "fn" */ void http_chunk_close(server *srv, connection *con); -- 2.11.4.GIT