summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGlenn Strauss <gstrauss@gluelogic.com>2019-05-12 00:18:03 -0400
committerGlenn Strauss <gstrauss@gluelogic.com>2019-05-13 20:27:49 -0400
commit6572976e06758d6faf5d2eebaf88fe0b92487f14 (patch)
tree6e82ab350df2ef8940cad6b459264a85a911ed16
parent4f0261e5e1283984b0ab3708b25fe84b564924a7 (diff)
downloadlighttpd1.4-6572976e06758d6faf5d2eebaf88fe0b92487f14.tar.gz
lighttpd1.4-6572976e06758d6faf5d2eebaf88fe0b92487f14.zip
[core] chunkqueue perf: code reuse
code reuse, simplification, and inlining remove excess calls to chunkqueue_remove_finished_chunks() (it may still be possible for there to be an empty chunk in chunkqueue if nothing were written to a temporary file (need to verify this), so preserve some calls to chunkqueue_remove_finished_chunks() for now)
-rw-r--r--src/chunk.c135
-rw-r--r--src/connections-glue.c5
-rw-r--r--src/connections.c4
-rw-r--r--src/gw_backend.c2
-rw-r--r--src/mod_webdav.c3
5 files changed, 50 insertions, 99 deletions
diff --git a/src/chunk.c b/src/chunk.c
index 73c9fd68..d2419990 100644
--- a/src/chunk.c
+++ b/src/chunk.c
@@ -208,55 +208,36 @@ void chunkqueue_chunk_pool_free(void)
}
static off_t chunk_remaining_length(const chunk *c) {
- off_t len = 0;
- switch (c->type) {
- case MEM_CHUNK:
- len = buffer_string_length(c->mem);
- break;
- case FILE_CHUNK:
- len = c->file.length;
- break;
- default:
- force_assert(c->type == MEM_CHUNK || c->type == FILE_CHUNK);
- break;
- }
- force_assert(c->offset <= len);
- return len - c->offset;
+ /* MEM_CHUNK or FILE_CHUNK */
+ return (c->type == MEM_CHUNK
+ ? (off_t)buffer_string_length(c->mem)
+ : c->file.length)
+ - c->offset;
+}
+
+static void chunkqueue_release_chunks(chunkqueue *cq) {
+ cq->last = NULL;
+ for (chunk *c; (c = cq->first); ) {
+ cq->first = c->next;
+ chunk_release(c);
+ }
}
void chunkqueue_free(chunkqueue *cq) {
- chunk *c, *pc;
-
- if (NULL == cq) return;
-
- for (c = cq->first; c; ) {
- pc = c;
- c = c->next;
- chunk_release(pc);
- }
-
- free(cq);
+ if (NULL == cq) return;
+ chunkqueue_release_chunks(cq);
+ free(cq);
}
static void chunkqueue_prepend_chunk(chunkqueue *cq, chunk *c) {
- c->next = cq->first;
- cq->first = c;
-
- if (NULL == cq->last) {
- cq->last = c;
- }
+ if (NULL == (c->next = cq->first)) cq->last = c;
+ cq->first = c;
}
static void chunkqueue_append_chunk(chunkqueue *cq, chunk *c) {
- c->next = NULL;
- if (cq->last) {
- cq->last->next = c;
- }
- cq->last = c;
-
- if (NULL == cq->first) {
- cq->first = c;
- }
+ c->next = NULL;
+ *(cq->last ? &cq->last->next : &cq->first) = c;
+ cq->last = c;
}
static chunk * chunkqueue_prepend_mem_chunk(chunkqueue *cq, size_t sz) {
@@ -283,19 +264,10 @@ static chunk * chunkqueue_append_file_chunk(chunkqueue *cq, buffer *fn, off_t of
}
void chunkqueue_reset(chunkqueue *cq) {
- chunk *cur = cq->first;
-
- cq->first = cq->last = NULL;
-
- while (NULL != cur) {
- chunk *next = cur->next;
- chunk_release(cur);
- cur = next;
- }
-
- cq->bytes_in = 0;
- cq->bytes_out = 0;
- cq->tempdir_idx = 0;
+ chunkqueue_release_chunks(cq);
+ cq->bytes_in = 0;
+ cq->bytes_out = 0;
+ cq->tempdir_idx = 0;
}
void chunkqueue_append_file_fd(chunkqueue *cq, buffer *fn, int fd, off_t offset, off_t len) {
@@ -723,49 +695,38 @@ off_t chunkqueue_length(chunkqueue *cq) {
}
void chunkqueue_mark_written(chunkqueue *cq, off_t len) {
- off_t written = len;
- chunk *c;
- force_assert(len >= 0);
-
- for (c = cq->first; NULL != c; c = cq->first) {
- off_t c_len = chunk_remaining_length(c);
-
- if (0 == written && 0 != c_len) break; /* no more finished chunks */
-
- if (written >= c_len) { /* chunk got finished */
- c->offset += c_len;
- written -= c_len;
-
- cq->first = c->next;
- if (c == cq->last) cq->last = NULL;
- chunk_release(c);
- } else { /* partial chunk */
- c->offset += written;
- written = 0;
- break; /* chunk not finished */
- }
- }
+ cq->bytes_out += len;
+
+ for (chunk *c; (c = cq->first); ) {
+ off_t c_len = chunk_remaining_length(c);
+ if (len >= c_len) { /* chunk got finished */
+ len -= c_len;
+ cq->first = c->next;
+ chunk_release(c);
+ if (0 == len) break;
+ }
+ else { /* partial chunk */
+ c->offset += len;
+ return; /* chunk not finished */
+ }
+ }
- force_assert(0 == written);
- cq->bytes_out += len;
+ if (NULL == cq->first)
+ cq->last = NULL;
+ else
+ chunkqueue_remove_finished_chunks(cq);
}
void chunkqueue_remove_finished_chunks(chunkqueue *cq) {
- chunk *c;
-
- for (c = cq->first; c; c = cq->first) {
- if (0 != chunk_remaining_length(c)) break; /* not finished yet */
-
- cq->first = c->next;
- if (c == cq->last) cq->last = NULL;
- chunk_release(c);
- }
+ for (chunk *c; (c = cq->first) && 0 == chunk_remaining_length(c); ){
+ if (NULL == (cq->first = c->next)) cq->last = NULL;
+ chunk_release(c);
+ }
}
static void chunkqueue_remove_empty_chunks(chunkqueue *cq) {
chunk *c;
chunkqueue_remove_finished_chunks(cq);
- if (chunkqueue_is_empty(cq)) return;
for (c = cq->first; c && c->next; c = c->next) {
if (0 == chunk_remaining_length(c->next)) {
diff --git a/src/connections-glue.c b/src/connections-glue.c
index e1657966..d8c4a536 100644
--- a/src/connections-glue.c
+++ b/src/connections-glue.c
@@ -344,7 +344,6 @@ int connection_write_chunkqueue(server *srv, connection *con, chunkqueue *cq, of
ret = con->network_write(srv, con, cq, max_bytes);
if (ret >= 0) {
- chunkqueue_remove_finished_chunks(cq);
ret = chunkqueue_is_empty(cq) ? 0 : 1;
}
@@ -394,9 +393,7 @@ static int connection_write_100_continue(server *srv, connection *con) {
return 0; /* error */
}
- if (written == sizeof(http_100_continue)-1) {
- chunkqueue_remove_finished_chunks(cq);
- } else if (0 == written) {
+ if (0 == written) {
/* skip sending 100 Continue if send would block */
chunkqueue_mark_written(cq, sizeof(http_100_continue)-1);
con->is_writable = 0;
diff --git a/src/connections.c b/src/connections.c
index 7cc73007..6375e1fa 100644
--- a/src/connections.c
+++ b/src/connections.c
@@ -741,12 +741,10 @@ static void connection_read_header(server *srv, connection *con) {
if (len > hlen) len = hlen;
buffer_append_string_len(con->request.request,
c->mem->ptr + c->offset, len);
- c->offset += len;
- cq->bytes_out += len;
if (0 == (hlen -= len)) break;
}
- chunkqueue_remove_finished_chunks(cq);
+ chunkqueue_mark_written(cq, con->header_len);
/* skip past \r\n or \n after previous POST request when keep-alive */
if (con->request_count > 1) {
diff --git a/src/gw_backend.c b/src/gw_backend.c
index b7976ec5..2020111d 100644
--- a/src/gw_backend.c
+++ b/src/gw_backend.c
@@ -1831,8 +1831,6 @@ static handler_t gw_write_request(server *srv, gw_handler_ctx *hctx) {
ret = srv->network_backend_write(srv, hctx->fd, hctx->wb,
MAX_WRITE_LIMIT);
- chunkqueue_remove_finished_chunks(hctx->wb);
-
if (ret < 0) {
switch(errno) {
case EPIPE:
diff --git a/src/mod_webdav.c b/src/mod_webdav.c
index 5ac16ca0..121e4033 100644
--- a/src/mod_webdav.c
+++ b/src/mod_webdav.c
@@ -3440,7 +3440,6 @@ webdav_parse_chunkqueue (connection * const con,
weWant -= weHave;
chunkqueue_mark_written(cq, weHave);
- chunkqueue_remove_finished_chunks(cq);
}
if (XML_ERR_OK == err) {
@@ -4105,7 +4104,6 @@ mod_webdav_write_cq_first_chunk (connection * const con, chunkqueue * const cq,
if (wr > 0) {
chunkqueue_mark_written(cq, wr);
- chunkqueue_remove_finished_chunks(cq);
}
else if (wr < 0)
http_status_set_error(con, (errno == ENOSPC) ? 507 : 403);
@@ -4327,7 +4325,6 @@ mod_webdav_put_linkat_rename (connection * const con,
}
chunkqueue_mark_written(cq, c->file.length);
- chunkqueue_remove_finished_chunks(cq);
return 1;
}