[core] read up-to fixed size chunk before fionread
parent
f24e6d696a
commit
de73b190a4
30
src/chunk.c
30
src/chunk.c
|
@ -421,21 +421,25 @@ char * chunkqueue_get_memory(chunkqueue *cq, size_t *len) {
|
|||
return b->ptr;
|
||||
}
|
||||
|
||||
void chunkqueue_use_memory(chunkqueue *cq, size_t len) {
|
||||
buffer *b;
|
||||
void chunkqueue_use_memory(chunkqueue *cq, chunk *ckpt, size_t len) {
|
||||
buffer *b = cq->last->mem;
|
||||
|
||||
force_assert(NULL != cq);
|
||||
force_assert(NULL != cq->last && MEM_CHUNK == cq->last->type);
|
||||
b = cq->last->mem;
|
||||
if (len > 0) {
|
||||
buffer_commit(b, len);
|
||||
cq->bytes_in += len;
|
||||
if (cq->last == ckpt || NULL == ckpt || MEM_CHUNK != ckpt->type
|
||||
|| len > chunk_buffer_string_space(ckpt->mem)) return;
|
||||
|
||||
if (len > 0) {
|
||||
buffer_commit(b, len);
|
||||
cq->bytes_in += len;
|
||||
} else if (chunk_buffer_string_is_empty(b)) {
|
||||
/* scan chunkqueue to remove empty last chunk
|
||||
* (generally not expecting a deep queue) */
|
||||
chunkqueue_remove_empty_chunks(cq);
|
||||
}
|
||||
buffer_append_string_buffer(ckpt->mem, b);
|
||||
}
|
||||
else if (!chunk_buffer_string_is_empty(b)) { /*(cq->last == ckpt)*/
|
||||
return; /* last chunk is not empty */
|
||||
}
|
||||
|
||||
/* remove empty last chunk */
|
||||
chunk_release(cq->last);
|
||||
cq->last = ckpt;
|
||||
*(ckpt ? &ckpt->next : &cq->first) = NULL;
|
||||
}
|
||||
|
||||
void chunkqueue_set_tempdirs_default (const array *tempdirs, off_t upload_temp_file_size) {
|
||||
|
|
|
@ -100,7 +100,7 @@ int chunkqueue_append_mem_to_tempfile(chunkqueue *cq, const char *mem, size_t le
|
|||
__attribute_returns_nonnull__
|
||||
char * chunkqueue_get_memory(chunkqueue *cq, size_t *len);
|
||||
/* commit len bytes of mem obtained from chunkqueue_get_memory() */
|
||||
void chunkqueue_use_memory(chunkqueue *cq, size_t len);
|
||||
void chunkqueue_use_memory(chunkqueue *cq, chunk *ckpt, size_t len);
|
||||
|
||||
/* mark first "len" bytes as written (incrementing chunk offsets)
|
||||
* and remove finished chunks
|
||||
|
|
|
@ -1001,90 +1001,95 @@ connection *connection_accept(server *srv, server_socket *srv_socket) {
|
|||
}
|
||||
|
||||
|
||||
__attribute_cold__
|
||||
static int connection_read_cq_err(connection *con) {
|
||||
#if defined(__WIN32)
|
||||
int lastError = WSAGetLastError();
|
||||
switch (lastError) {
|
||||
case EAGAIN:
|
||||
return 0;
|
||||
case EINTR:
|
||||
/* we have been interrupted before we could read */
|
||||
con->is_readable = 1;
|
||||
return 0;
|
||||
case ECONNRESET:
|
||||
/* suppress logging for this error, expected for keep-alive */
|
||||
break;
|
||||
default:
|
||||
log_error(con->conf.errh, __FILE__, __LINE__,
|
||||
"connection closed - recv failed: %d", lastError);
|
||||
break;
|
||||
}
|
||||
#else /* __WIN32 */
|
||||
switch (errno) {
|
||||
case EAGAIN:
|
||||
return 0;
|
||||
case EINTR:
|
||||
/* we have been interrupted before we could read */
|
||||
con->is_readable = 1;
|
||||
return 0;
|
||||
case ECONNRESET:
|
||||
/* suppress logging for this error, expected for keep-alive */
|
||||
break;
|
||||
default:
|
||||
log_perror(con->conf.errh, __FILE__, __LINE__,
|
||||
"connection closed - read failed");
|
||||
break;
|
||||
}
|
||||
#endif /* __WIN32 */
|
||||
|
||||
connection_set_state(con, CON_STATE_ERROR);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* 0: everything ok, -1: error, -2: con closed */
|
||||
static int connection_read_cq(connection *con, chunkqueue *cq, off_t max_bytes) {
|
||||
ssize_t len;
|
||||
char *mem = NULL;
|
||||
size_t mem_len = 0;
|
||||
force_assert(cq == con->read_queue); /*(code transform assumption; minimize diff)*/
|
||||
force_assert(max_bytes == MAX_READ_LIMIT); /*(code transform assumption; minimize diff)*/
|
||||
ssize_t len;
|
||||
size_t mem_len = 0;
|
||||
force_assert(cq == con->read_queue); /*(code transform assumption; minimize diff)*/
|
||||
/*force_assert(max_bytes == MAX_READ_LIMIT);*//*(code transform assumption; minimize diff)*/
|
||||
|
||||
/* check avail data to read and obtain memory into which to read
|
||||
* fill previous chunk if it has sufficient space
|
||||
* (use mem_len=0 to obtain large buffer at least half of chunk_buf_sz)
|
||||
*/
|
||||
{
|
||||
int frd;
|
||||
if (0 == fdevent_ioctl_fionread(con->fd, S_IFSOCK, &frd)) {
|
||||
mem_len = (frd < MAX_READ_LIMIT) ? (size_t)frd : MAX_READ_LIMIT;
|
||||
}
|
||||
}
|
||||
mem = chunkqueue_get_memory(con->read_queue, &mem_len);
|
||||
do {
|
||||
/* obtain chunk memory into which to read
|
||||
* fill previous chunk if it has a reasonable amount of space available
|
||||
* (use mem_len=0 to obtain large buffer at least half of chunk_buf_sz)
|
||||
*/
|
||||
chunk *ckpt = con->read_queue->last;
|
||||
char * const mem = chunkqueue_get_memory(con->read_queue, &mem_len);
|
||||
if (mem_len > (size_t)max_bytes) mem_len = (size_t)max_bytes;
|
||||
|
||||
#if defined(__WIN32)
|
||||
len = recv(con->fd, mem, mem_len, 0);
|
||||
#else
|
||||
len = read(con->fd, mem, mem_len);
|
||||
#endif /* __WIN32 */
|
||||
#if defined(__WIN32)
|
||||
len = recv(con->fd, mem, mem_len, 0);
|
||||
#else
|
||||
len = read(con->fd, mem, mem_len);
|
||||
#endif /* __WIN32 */
|
||||
|
||||
chunkqueue_use_memory(con->read_queue, len > 0 ? len : 0);
|
||||
chunkqueue_use_memory(con->read_queue, ckpt, len > 0 ? len : 0);
|
||||
|
||||
if (len < 0) {
|
||||
con->is_readable = 0;
|
||||
if (len != (ssize_t)mem_len) {
|
||||
/* we got less then expected, wait for the next fd-event */
|
||||
con->is_readable = 0;
|
||||
|
||||
#if defined(__WIN32)
|
||||
{
|
||||
int lastError = WSAGetLastError();
|
||||
switch (lastError) {
|
||||
case EAGAIN:
|
||||
return 0;
|
||||
case EINTR:
|
||||
/* we have been interrupted before we could read */
|
||||
con->is_readable = 1;
|
||||
return 0;
|
||||
case ECONNRESET:
|
||||
/* suppress logging for this error, expected for keep-alive */
|
||||
break;
|
||||
default:
|
||||
log_error(con->conf.errh, __FILE__, __LINE__, "connection closed - recv failed: %d", lastError);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else /* __WIN32 */
|
||||
switch (errno) {
|
||||
case EAGAIN:
|
||||
return 0;
|
||||
case EINTR:
|
||||
/* we have been interrupted before we could read */
|
||||
con->is_readable = 1;
|
||||
return 0;
|
||||
case ECONNRESET:
|
||||
/* suppress logging for this error, expected for keep-alive */
|
||||
break;
|
||||
default:
|
||||
log_perror(con->conf.errh, __FILE__, __LINE__, "connection closed - read failed");
|
||||
break;
|
||||
}
|
||||
#endif /* __WIN32 */
|
||||
if (len > 0) {
|
||||
con->bytes_read += len;
|
||||
return 0;
|
||||
}
|
||||
else if (0 == len) /* other end close connection -> KEEP-ALIVE */
|
||||
return -2; /* (pipelining) */
|
||||
else
|
||||
return connection_read_cq_err(con);
|
||||
}
|
||||
|
||||
connection_set_state(con, CON_STATE_ERROR);
|
||||
con->bytes_read += len;
|
||||
max_bytes -= len;
|
||||
|
||||
return -1;
|
||||
} else if (len == 0) {
|
||||
con->is_readable = 0;
|
||||
/* the other end close the connection -> KEEP-ALIVE */
|
||||
|
||||
/* pipelining */
|
||||
|
||||
return -2;
|
||||
} else if (len != (ssize_t) mem_len) {
|
||||
/* we got less then expected, wait for the next fd-event */
|
||||
|
||||
con->is_readable = 0;
|
||||
}
|
||||
|
||||
con->bytes_read += len;
|
||||
return 0;
|
||||
int frd;
|
||||
mem_len = (0 == fdevent_ioctl_fionread(con->fd, S_IFSOCK, &frd))
|
||||
? (frd < max_bytes) ? (size_t)frd : (size_t)max_bytes
|
||||
: 0;
|
||||
} while (max_bytes);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1898,14 +1898,15 @@ connection_read_cq_ssl (connection *con, chunkqueue *cq, off_t max_bytes)
|
|||
do {
|
||||
len = SSL_pending(hctx->ssl);
|
||||
mem_len = len < 2048 ? 2048 : (size_t)len;
|
||||
chunk * const ckpt = con->read_queue->last;
|
||||
mem = chunkqueue_get_memory(con->read_queue, &mem_len);
|
||||
|
||||
len = SSL_read(hctx->ssl, mem, mem_len);
|
||||
if (len > 0) {
|
||||
chunkqueue_use_memory(con->read_queue, len);
|
||||
chunkqueue_use_memory(con->read_queue, ckpt, len);
|
||||
con->bytes_read += len;
|
||||
} else {
|
||||
chunkqueue_use_memory(con->read_queue, 0);
|
||||
chunkqueue_use_memory(con->read_queue, ckpt, 0);
|
||||
}
|
||||
|
||||
if (hctx->renegotiations > 1
|
||||
|
|
Loading…
Reference in New Issue