|
|
|
@ -784,8 +784,7 @@ void chunkqueue_compact_mem(chunkqueue *cq, size_t clen) {
|
|
|
|
|
* no data added/removed from chunkqueue; consolidated only */ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int chunkqueue_open_file_chunk(chunkqueue * const restrict cq, log_error_st * const restrict errh) { |
|
|
|
|
chunk* const c = cq->first; |
|
|
|
|
static int chunk_open_file_chunk(chunk * const restrict c, log_error_st * const restrict errh) { |
|
|
|
|
off_t offset, toSend; |
|
|
|
|
struct stat st; |
|
|
|
|
|
|
|
|
@ -820,6 +819,10 @@ int chunkqueue_open_file_chunk(chunkqueue * const restrict cq, log_error_st * co
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int chunkqueue_open_file_chunk(chunkqueue * const restrict cq, log_error_st * const restrict errh) { |
|
|
|
|
return chunk_open_file_chunk(cq->first, errh); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
chunkqueue_small_resp_optim (chunkqueue * const restrict cq) |
|
|
|
@ -865,3 +868,114 @@ chunkqueue_small_resp_optim (chunkqueue * const restrict cq)
|
|
|
|
|
filec->offset += offset; |
|
|
|
|
chunkqueue_remove_empty_chunks(cq); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int |
|
|
|
|
chunkqueue_peek_data (chunkqueue * const cq, |
|
|
|
|
char ** const data, uint32_t * const dlen, |
|
|
|
|
log_error_st * const errh) |
|
|
|
|
{ |
|
|
|
|
char * const data_in = *data; |
|
|
|
|
const uint32_t data_insz = *dlen; |
|
|
|
|
*dlen = 0; |
|
|
|
|
|
|
|
|
|
for (chunk *c = cq->first; c; ) { |
|
|
|
|
uint32_t space = data_insz - *dlen; |
|
|
|
|
switch (c->type) { |
|
|
|
|
case MEM_CHUNK: |
|
|
|
|
{ |
|
|
|
|
uint32_t have = buffer_string_length(c->mem) - (uint32_t)c->offset; |
|
|
|
|
if (have > space) |
|
|
|
|
have = space; |
|
|
|
|
if (*dlen) |
|
|
|
|
memcpy(data_in + *dlen, c->mem->ptr + c->offset, have); |
|
|
|
|
else |
|
|
|
|
*data = c->mem->ptr + c->offset; /*(reference; defer copy)*/ |
|
|
|
|
*dlen += have; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
case FILE_CHUNK: |
|
|
|
|
if (0 == chunk_open_file_chunk(c, errh)) { |
|
|
|
|
off_t offset = c->file.start + c->offset; |
|
|
|
|
off_t toSend = c->file.length - c->offset; |
|
|
|
|
if (toSend > (off_t)space) |
|
|
|
|
toSend = (off_t)space; |
|
|
|
|
|
|
|
|
|
if (-1 == lseek(c->file.fd, offset, SEEK_SET)) { |
|
|
|
|
log_perror(errh, __FILE__, __LINE__, "lseek"); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
toSend = read(c->file.fd, data_in + *dlen, (size_t)toSend); |
|
|
|
|
if (-1 == toSend) { |
|
|
|
|
log_perror(errh, __FILE__, __LINE__, "read"); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
*dlen += (uint32_t)toSend; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
default: |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (*dlen == data_insz) |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
c = c->next; |
|
|
|
|
if (NULL == c) |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
if (*dlen && *data != data_in) { |
|
|
|
|
memcpy(data_in, *data, *dlen); |
|
|
|
|
*data = data_in; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int |
|
|
|
|
chunkqueue_read_data (chunkqueue * const cq, |
|
|
|
|
char * const data, const uint32_t dlen, |
|
|
|
|
log_error_st * const errh) |
|
|
|
|
{ |
|
|
|
|
char *ptr = data; |
|
|
|
|
uint32_t len = dlen; |
|
|
|
|
if (chunkqueue_peek_data(cq, &ptr, &len, errh) < 0 || len != dlen) |
|
|
|
|
return -1; |
|
|
|
|
if (data != ptr) memcpy(data, ptr, len); |
|
|
|
|
chunkqueue_mark_written(cq, len); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
buffer * |
|
|
|
|
chunkqueue_read_squash (chunkqueue * const restrict cq, log_error_st * const restrict errh) |
|
|
|
|
{ |
|
|
|
|
/* read and replace chunkqueue contents with single MEM_CHUNK.
|
|
|
|
|
* cq->bytes_out is not modified */ |
|
|
|
|
|
|
|
|
|
off_t cqlen = chunkqueue_length(cq); |
|
|
|
|
if (cqlen >= UINT32_MAX) return NULL; |
|
|
|
|
|
|
|
|
|
if (cq->first && NULL == cq->first->next && cq->first->type == MEM_CHUNK) |
|
|
|
|
return cq->first->mem; |
|
|
|
|
|
|
|
|
|
chunk * const c = chunk_acquire((uint32_t)cqlen+1); |
|
|
|
|
char *data = c->mem->ptr; |
|
|
|
|
uint32_t dlen = (uint32_t)cqlen; |
|
|
|
|
int rc = chunkqueue_peek_data(cq, &data, &dlen, errh); |
|
|
|
|
if (rc < 0) { |
|
|
|
|
chunk_release(c); |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
buffer_string_set_length(c->mem, dlen); |
|
|
|
|
|
|
|
|
|
chunkqueue_release_chunks(cq); |
|
|
|
|
chunkqueue_append_chunk(cq, c); |
|
|
|
|
return c->mem; |
|
|
|
|
} |
|
|
|
|