]> granicus.if.org Git - libevent/commitdiff
change evbuffer_read so that it reads directly into the memory allocated to
authorNiels Provos <provos@gmail.com>
Tue, 13 Jul 2004 08:02:45 +0000 (08:02 +0000)
committerNiels Provos <provos@gmail.com>
Tue, 13 Jul 2004 08:02:45 +0000 (08:02 +0000)
the evbuffer; this avoids one unnecessary data copy.

svn:r110

buffer.c
configure.in
event.h

index afdcb1d27bfe2d172273cfd23b004ec8022c3496..b8a9dc8561522fb8774b50dde0f891061b96ffdd 100644 (file)
--- a/buffer.c
+++ b/buffer.c
 #include <sys/time.h>
 #endif
 
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+
 #include <err.h>
 #include <errno.h>
 #include <stdio.h>
@@ -178,6 +182,44 @@ evbuffer_align(struct evbuffer *buf)
        buf->misalign = 0;
 }
 
+/* Expands the available space in the event buffer to at least datlen */
+
+int
+evbuffer_expand(struct evbuffer *buf, size_t datlen)
+{
+       size_t need = buf->misalign + buf->off + datlen;
+
+       /* If we can fit all the data, then we don't have to do anything */
+       if (buf->totallen >= need)
+               return (0);
+
+       /*
+        * If the misalignment fulfills our data needs, we just force an
+        * alignment to happen.  Afterwards, we have enough space.
+        */
+       if (buf->misalign >= datlen) {
+               evbuffer_align(buf);
+       } else {
+               void *newbuf;
+               size_t length = buf->totallen;
+
+               if (length < 256)
+                       length = 256;
+               while (length < need)
+                       length <<= 1;
+
+               if (buf->orig_buffer != buf->buffer)
+                       evbuffer_align(buf);
+               if ((newbuf = realloc(buf->buffer, length)) == NULL)
+                       return (-1);
+
+               buf->orig_buffer = buf->buffer = newbuf;
+               buf->totallen = length;
+       }
+
+       return (0);
+}
+
 int
 evbuffer_add(struct evbuffer *buf, void *data, size_t datlen)
 {
@@ -185,25 +227,8 @@ evbuffer_add(struct evbuffer *buf, void *data, size_t datlen)
        size_t oldoff = buf->off;
 
        if (buf->totallen < need) {
-               if (buf->misalign >= datlen) {
-                       evbuffer_align(buf);
-               } else {
-                       void *newbuf;
-                       size_t length = buf->totallen;
-
-                       if (length < 256)
-                               length = 256;
-                       while (length < need)
-                               length <<= 1;
-
-                       if (buf->orig_buffer != buf->buffer)
-                               evbuffer_align(buf);
-                       if ((newbuf = realloc(buf->buffer, length)) == NULL)
-                               return (-1);
-
-                       buf->orig_buffer = buf->buffer = newbuf;
-                       buf->totallen = length;
-               }
+               if (evbuffer_expand(buf, datlen) == -1)
+                       return (-1);
        }
 
        memcpy(buf->buffer + buf->off, data, datlen);
@@ -239,26 +264,44 @@ evbuffer_drain(struct evbuffer *buf, size_t len)
 
 }
 
+/*
+ * Reads data from a file descriptor into a buffer.
+ */
+
+#define EVBUFFER_MAX_READ      4096
+
 int
-evbuffer_read(struct evbuffer *buffer, int fd, int howmuch)
+evbuffer_read(struct evbuffer *buf, int fd, int howmuch)
 {
-       u_char inbuf[4096];
-       int n;
+       u_char *p;
+       size_t oldoff = buf->off;
+       int n = EVBUFFER_MAX_READ;
 #ifdef WIN32
        DWORD dwBytesRead;
 #endif
-       
-       if (howmuch < 0 || howmuch > sizeof(inbuf))
-               howmuch = sizeof(inbuf);
+
+#ifdef FIONREAD
+       if (ioctl(fd, FIONREAD, &n) == -1)
+               n = EVBUFFER_MAX_READ;
+#endif 
+       if (howmuch < 0 || howmuch > n)
+               howmuch = n;
+
+       /* If we don't have FIONREAD, we might waste some space here */
+       if (evbuffer_expand(buf, howmuch) == -1)
+               return (-1);
+
+       /* We can append new data at this point */
+       p = buf->buffer + buf->off;
 
 #ifndef WIN32
-       n = read(fd, inbuf, howmuch);
+       n = read(fd, p, howmuch);
        if (n == -1)
                return (-1);
        if (n == 0)
                return (0);
 #else
-       n = ReadFile((HANDLE)fd, inbuf, howmuch, &dwBytesRead, NULL);
+       n = ReadFile((HANDLE)fd, p, howmuch, &dwBytesRead, NULL);
        if (n == 0)
                return (-1);
        if (dwBytesRead == 0)
@@ -266,7 +309,11 @@ evbuffer_read(struct evbuffer *buffer, int fd, int howmuch)
        n = dwBytesRead;
 #endif
 
-       evbuffer_add(buffer, inbuf, n);
+       buf->off += n;
+
+       /* Tell someone about changes in this buffer */
+       if (buf->off != oldoff && buf->cb != NULL)
+               (*buf->cb)(buf, oldoff, buf->off, buf->cbarg);
 
        return (n);
 }
index 7a10f589594d24a8f1ed1b23b88e5e152bb3653a..358884f15e0e5c67c7cfb5a5331d374d4ee89432 100644 (file)
@@ -27,7 +27,7 @@ AC_CHECK_LIB(socket, socket)
 
 dnl Checks for header files.
 AC_HEADER_STDC
-AC_CHECK_HEADERS(stdarg.h inttypes.h stdint.h poll.h signal.h unistd.h sys/epoll.h sys/time.h sys/queue.h sys/event.h)
+AC_CHECK_HEADERS(stdarg.h inttypes.h stdint.h poll.h signal.h unistd.h sys/epoll.h sys/time.h sys/queue.h sys/event.h sys/ioctl.h)
 if test "x$ac_cv_header_sys_queue_h" = "xyes"; then
        AC_MSG_CHECKING(for TAILQ_FOREACH in sys/queue.h)
        AC_EGREP_CPP(yes,
@@ -61,7 +61,7 @@ dnl Checks for typedefs, structures, and compiler characteristics.
 AC_HEADER_TIME
 
 dnl Checks for library functions.
-AC_CHECK_FUNCS(gettimeofday vasprintf)
+AC_CHECK_FUNCS(gettimeofday vasprintf fcntl)
 
 needsignal=no
 haveselect=no
diff --git a/event.h b/event.h
index 96a725c5747c4b878a469a3f4b70e2c9e1b8701d..875560c6f56f1a3731a94dd21aedda0021f62675 100644 (file)
--- a/event.h
+++ b/event.h
@@ -236,6 +236,7 @@ void bufferevent_settimeout(struct bufferevent *bufev,
 
 struct evbuffer *evbuffer_new(void);
 void evbuffer_free(struct evbuffer *);
+int evbuffer_expand(struct evbuffer *, size_t);
 int evbuffer_add(struct evbuffer *, void *, size_t);
 int evbuffer_remove(struct evbuffer *, void *, size_t);
 int evbuffer_add_buffer(struct evbuffer *, struct evbuffer *);