From: Niels Provos Date: Sat, 3 May 2008 03:05:28 +0000 (+0000) Subject: introduce evbuffer_reserve_space() and evbuffer_commit_space() to make processing... X-Git-Tag: release-2.0.1-alpha~340 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f04497e493c6b665d6cc889a57f2441d71d176d1;p=libevent introduce evbuffer_reserve_space() and evbuffer_commit_space() to make processing in filters more efficient svn:r757 --- diff --git a/ChangeLog b/ChangeLog index c31573ed..d6cb1f12 100644 --- a/ChangeLog +++ b/ChangeLog @@ -84,6 +84,7 @@ Changes in current version: o add new evtimer_assign, signal_assign, evtimer_new, and signal_new functions to manipulate timer and signal events, analagous to the now-recommended event_assign and event_new o switch internal uses of event_set over to use event_assign. o introduce evbuffer_contiguous_space() api that tells a user how much data is available in the first buffer chain + o introduce evbuffer_reserve_space() and evbuffer_commit_space() to make processing in filters more efficient. Changes in 1.4.0: o allow \r or \n individually to separate HTTP headers instead of the standard "\r\n"; from Charles Kerr. diff --git a/buffer.c b/buffer.c index 20dfb160..eec9b783 100644 --- a/buffer.c +++ b/buffer.c @@ -131,6 +131,34 @@ evbuffer_contiguous_space(struct evbuffer *buf) return (chain != NULL ? chain->off : 0); } +u_char * +evbuffer_reserve_space(struct evbuffer *buf, size_t size) +{ + struct evbuffer_chain *chain; + + if (evbuffer_expand(buf, size) == -1) + return (NULL); + + chain = buf->last; + + return (chain->buffer + chain->misalign + chain->off); +} + +int +evbuffer_commit_space(struct evbuffer *buf, size_t size) +{ + struct evbuffer_chain *chain = buf->last; + + if (chain == NULL || + chain->buffer_len - chain->off - chain->misalign < size) + return (-1); + + chain->off += size; + buf->total_len += size; + + return (0); +} + #define ZERO_CHAIN(dst) do { \ (dst)->first = NULL; \ (dst)->last = NULL; \ diff --git a/include/event2/buffer.h b/include/event2/buffer.h index 637cc2e0..9d70555b 100644 --- a/include/event2/buffer.h +++ b/include/event2/buffer.h @@ -118,6 +118,38 @@ size_t evbuffer_contiguous_space(struct evbuffer *buf); */ int evbuffer_expand(struct evbuffer *buf, size_t datlen); +/** + Reserves space in the last chain of an event buffer. + + Makes space available in the last chain of an event buffer that can + be arbitrarily written to by a user. The space does not become + available for reading until it has been committed. + + Multiple subsequent calls to this function will make the same space + available until evbuffer_commit_space() has been called. + + @param buf the event buffer in which to reserve space. + @param size how much space to make available. + @return the pointer to the available space or NULL on error. + @see evbuffer_commit_space +*/ + +u_char *evbuffer_reserve_space(struct evbuffer *buf, size_t size); + +/** + Commits previously reserved space. + + Commits some of the space previously reserved. It then becomes + available for reading. + + @param buf the event buffer in which to reserve space. + @param size how much space to commit. + @return 0 on success, -1 on error + @see evbuffer_reserve_space +*/ + +int evbuffer_commit_space(struct evbuffer *buf, size_t size); + /** Append data to the end of an evbuffer. diff --git a/test/regress.c b/test/regress.c index 00dbffe9..993fba54 100644 --- a/test/regress.c +++ b/test/regress.c @@ -1013,6 +1013,31 @@ test_evbuffer(void) goto out; evbuffer_validate(evb); + + /* testing reserve and commit */ + { + u_char *buf; + int i, j; + + for (i = 0; i < 3; ++i) { + buf = evbuffer_reserve_space(evb, 10000); + assert(buf != NULL); + evbuffer_validate(evb); + for (j = 0; j < 10000; ++j) { + buf[j] = j; + } + evbuffer_validate(evb); + + assert(evbuffer_commit_space(evb, 10000) == 0); + evbuffer_validate(evb); + + assert(evbuffer_length(evb) >= 10000); + + evbuffer_drain(evb, j * 5000); + evbuffer_validate(evb); + } + } + test_ok = 1; out: diff --git a/test/regress_zlib.c b/test/regress_zlib.c index 434054c4..48bea35d 100644 --- a/test/regress_zlib.c +++ b/test/regress_zlib.c @@ -103,7 +103,6 @@ static enum bufferevent_filter_result zlib_input_filter(struct evbuffer *src, struct evbuffer *dst, enum bufferevent_filter_state state, void *ctx) { - char tmp[4096]; int nread, nwrite; int res; @@ -114,8 +113,8 @@ zlib_input_filter(struct evbuffer *src, struct evbuffer *dst, p->avail_in = evbuffer_contiguous_space(src); p->next_in = evbuffer_pullup(src, p->avail_in); - p->next_out = (unsigned char *)tmp; - p->avail_out = sizeof(tmp); + p->next_out = evbuffer_reserve_space(dst, 4096); + p->avail_out = 4096; /* we need to flush zlib if we got a flush */ res = inflate(p, state == BEV_FLUSH ? @@ -124,10 +123,10 @@ zlib_input_filter(struct evbuffer *src, struct evbuffer *dst, /* let's figure out how much was compressed */ nread = evbuffer_contiguous_space(src) - p->avail_in; - nwrite = sizeof(tmp) - p->avail_out; + nwrite = 4096 - p->avail_out; evbuffer_drain(src, nread); - evbuffer_add(dst, tmp, nwrite); + evbuffer_commit_space(dst, nwrite); } while (EVBUFFER_LENGTH(src) > 0); test_ok++; @@ -139,7 +138,6 @@ static enum bufferevent_filter_result zlib_output_filter(struct evbuffer *src, struct evbuffer *dst, enum bufferevent_filter_state state, void *ctx) { - char tmp[4096]; int nread, nwrite; int res; @@ -150,8 +148,8 @@ zlib_output_filter(struct evbuffer *src, struct evbuffer *dst, p->avail_in = evbuffer_contiguous_space(src); p->next_in = evbuffer_pullup(src, p->avail_in); - p->next_out = (unsigned char *)tmp; - p->avail_out = sizeof(tmp); + p->next_out = evbuffer_reserve_space(dst, 4096); + p->avail_out = 4096; /* we need to flush zlib if we got a flush */ res = deflate(p, state == BEV_FLUSH ? Z_FINISH : Z_NO_FLUSH); @@ -159,10 +157,10 @@ zlib_output_filter(struct evbuffer *src, struct evbuffer *dst, /* let's figure out how much was compressed */ nread = evbuffer_contiguous_space(src) - p->avail_in; - nwrite = sizeof(tmp) - p->avail_out; + nwrite = 4096 - p->avail_out; evbuffer_drain(src, nread); - evbuffer_add(dst, tmp, nwrite); + evbuffer_commit_space(dst, nwrite); } while (EVBUFFER_LENGTH(src) > 0); test_ok++;