Browse Source

[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)
personal/stbuehler/ci-build
Glenn Strauss 2 years ago
parent
commit
6572976e06
  1. 135
      src/chunk.c
  2. 5
      src/connections-glue.c
  3. 4
      src/connections.c
  4. 2
      src/gw_backend.c
  5. 3
      src/mod_webdav.c

135
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)) {

5
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;

4
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) {

2
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:

3
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;
}

Loading…
Cancel
Save