From e470ad3c354c586a3a995ce3a1fe7d093ebf999c Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 10 Mar 2010 23:39:30 -0500 Subject: [PATCH] Allow evbuffer_read() to split across more than 2 iovecs Previously it would only accept 2 iovecs at most, because our previous_to_last nonsense didn't let it take any more. This forced us to do more reallocations in some cases when an extra small malloc would have sufficed. --- buffer.c | 46 +++++++++++++++++++++------------------------- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/buffer.c b/buffer.c index 700a1945..6f56dcb8 100644 --- a/buffer.c +++ b/buffer.c @@ -1639,17 +1639,18 @@ _evbuffer_expand_fast(struct evbuffer *buf, size_t datlen, int n) #ifdef _EVENT_HAVE_SYS_UIO_H /* number of iovec we use for writev, fragmentation is going to determine * how much we end up writing */ -#define NUM_IOVEC 128 +#define NUM_WRITE_IOVEC 128 #define IOV_TYPE struct iovec #define IOV_PTR_FIELD iov_base #define IOV_LEN_FIELD iov_len #else -#define NUM_IOVEC 16 +#define NUM_WRITE_IOVEC 16 #define IOV_TYPE WSABUF #define IOV_PTR_FIELD buf #define IOV_LEN_FIELD len #endif #endif +#define NUM_READ_IOVEC 4 #define EVBUFFER_MAX_READ 4096 @@ -1710,7 +1711,7 @@ evbuffer_read(struct evbuffer *buf, evutil_socket_t fd, int howmuch) int result; #ifdef USE_IOVEC_IMPL - int nvecs; + int nvecs, i, remaining; #else unsigned char *p; #endif @@ -1753,28 +1754,24 @@ evbuffer_read(struct evbuffer *buf, evutil_socket_t fd, int howmuch) #ifdef USE_IOVEC_IMPL /* Since we can use iovecs, we're willing to use the last - * _two_ chains. */ - if (_evbuffer_expand_fast(buf, howmuch, 2) == -1) { + * NUM_READ_IOVEC chains. */ + if (_evbuffer_expand_fast(buf, howmuch, NUM_READ_IOVEC) == -1) { result = -1; goto done; } else { - IOV_TYPE vecs[2]; + IOV_TYPE vecs[NUM_READ_IOVEC]; #ifdef _EVBUFFER_IOVEC_IS_NATIVE - nvecs = _evbuffer_read_setup_vecs(buf, howmuch, vecs, 2, - &chain, 1); + nvecs = _evbuffer_read_setup_vecs(buf, howmuch, vecs, + NUM_READ_IOVEC, &chain, 1); #else /* We aren't using the native struct iovec. Therefore, we are on win32. */ - struct evbuffer_iovec ev_vecs[2]; + struct evbuffer_iovec ev_vecs[NUM_READ_IOVEC]; nvecs = _evbuffer_read_setup_vecs(buf, howmuch, ev_vecs, 2, &chain, 1); - if (nvecs == 2) { - WSABUF_FROM_EVBUFFER_IOV(&vecs[1], &ev_vecs[1]); - WSABUF_FROM_EVBUFFER_IOV(&vecs[0], &ev_vecs[0]); - } else if (nvecs == 1) { - WSABUF_FROM_EVBUFFER_IOV(&vecs[0], &ev_vecs[0]); - } + for (i=0; i < n_vecs; ++i) + WSABUF_FROM_EVBUFFER_IOV(&vecs[i], &ev_vecs[i]); #endif #ifdef WIN32 @@ -1827,19 +1824,18 @@ evbuffer_read(struct evbuffer *buf, evutil_socket_t fd, int howmuch) } #ifdef USE_IOVEC_IMPL - if (nvecs == 2) { + remaining = n; + for (i=0; i < nvecs; ++i) { ev_ssize_t space = CHAIN_SPACE_LEN(chain); - if (space < n) { + if (space < remaining) { chain->off += space; - chain->next->off += n-space; - buf->last_with_data = chain->next; + remaining -= space; } else { - chain->off += n; + chain->off += remaining; buf->last_with_data = chain; + break; } - } else { - chain->off += n; - buf->last_with_data = chain; + chain = chain->next; } #else chain->off += n; @@ -1861,7 +1857,7 @@ static inline int evbuffer_write_iovec(struct evbuffer *buffer, evutil_socket_t fd, ev_ssize_t howmuch) { - IOV_TYPE iov[NUM_IOVEC]; + IOV_TYPE iov[NUM_WRITE_IOVEC]; struct evbuffer_chain *chain = buffer->first; int n, i = 0; @@ -1872,7 +1868,7 @@ evbuffer_write_iovec(struct evbuffer *buffer, evutil_socket_t fd, /* XXX make this top out at some maximal data length? if the * buffer has (say) 1MB in it, split over 128 chains, there's * no way it all gets written in one go. */ - while (chain != NULL && i < NUM_IOVEC && howmuch) { + while (chain != NULL && i < NUM_WRITE_IOVEC && howmuch) { #ifdef USE_SENDFILE /* we cannot write the file info via writev */ if (chain->flags & EVBUFFER_SENDFILE) -- 2.40.0