[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[or-cvs] r10677: Worked on sa_bufferevent timeouts. Code is written and being (in libevent-urz/trunk: . doc test)
Author: Urz
Date: 2007-06-25 08:10:45 -0400 (Mon, 25 Jun 2007)
New Revision: 10677
Added:
libevent-urz/trunk/test/test-sa_bufferevents.c
Modified:
libevent-urz/trunk/buffer.c
libevent-urz/trunk/doc/plan.txt
libevent-urz/trunk/sa_evbuffer.c
libevent-urz/trunk/test/Makefile.am
libevent-urz/trunk/test/regress.c
Log:
Worked on sa_bufferevent timeouts. Code is written and being debugged. Current problem appears to be a stack corruption issue. Minor timeline shifts to the plan. Fixed bug in evbuffer_add_vsnprintf on windows. Tried to make regression testing build, but it's horribly broken on windows. Rolled my own, and is working, besides timeouts as mentioned above.
Modified: libevent-urz/trunk/buffer.c
===================================================================
--- libevent-urz/trunk/buffer.c 2007-06-25 07:44:58 UTC (rev 10676)
+++ libevent-urz/trunk/buffer.c 2007-06-25 12:10:45 UTC (rev 10677)
@@ -216,6 +216,21 @@
evbuffer_lock(buf, __func__);
+ /* on Windows, the buffer[space - 1] = '\0'; will segfault if
+ the buffer has not had expand called on it ever before (because
+ the buffer is null). Note also :
+ "If buffer or format is NULL, ...
+ these functions return -1 and set errno to EINVAL."
+ http://msdn2.microsoft.com/en-us/library/1kt27hek(VS.80).aspx
+ */
+ space = buf->totallen - buf->misalign - buf->off;
+ if(space == 0) {
+ if (evbuffer_expand(buf, 100) == -1) {
+ evbuffer_unlock(buf, __func__);
+ return (-1);
+ }
+ }
+
for (;;) {
buffer = (char *)buf->buffer + buf->off;
space = buf->totallen - buf->misalign - buf->off;
@@ -234,9 +249,10 @@
va_end(aq);
- if (sz == -1)
+ if (sz == -1) {
evbuffer_unlock(buf, __func__);
return (-1);
+ }
if (sz < space) {
buf->off += sz;
if (buf->cb != NULL)
@@ -244,9 +260,10 @@
evbuffer_unlock(buf, __func__);
return (sz);
}
- if (evbuffer_expand(buf, sz + 1) == -1)
+ if (evbuffer_expand(buf, sz + 1) == -1) {
evbuffer_unlock(buf, __func__);
return (-1);
+ }
}
/* NOTREACHED */
Modified: libevent-urz/trunk/doc/plan.txt
===================================================================
--- libevent-urz/trunk/doc/plan.txt 2007-06-25 07:44:58 UTC (rev 10676)
+++ libevent-urz/trunk/doc/plan.txt 2007-06-25 12:10:45 UTC (rev 10677)
@@ -21,35 +21,11 @@
It it more generally useful than 1) or 3), and can stand alone better.
Coding:
-Alter evbuffer (event.h:212) struct.
- - Mutex added. Most of the data is stored in the bufferevent struct now, as per
- IRC conversation with nickm.
-
-Add a new event_add / event_del for delayed evbuffer events
-(so the user doesn't have to know about the socketpair trick).
- - Done by sa_bufferevent_new, at sa_evbuffer.c:270
+Everything is done, except:
+Regression Tests
+Timeout
+Man pages
-Alter the evbuffer functions (add, drain, etc) to use the mutex on the evbuffer struct,
-to set the bufferevent flags to let the main thread know callbacks are ready, and to call
-a function to ensure the main event-loop is notified of events.
- - Mutex work is done.
- - Notification function written, used as needed.
- - bufferevent pending callback flags set as needed.
-
-Write a short read event handler for the event_loop half of the socketpair which
-simply reads all there is to be read (no blocking!) and calls the real read/write callbacks
-depending on what it reads.
- - Done
-
-
-TODOs for tomorrow:
-Write regression tests.
-Compile and Test.
-Write sample code
-Talk to nickm, re:
- - Timeouts
- - Automake
-
Testing:
Add test cases to libevent testing code... test/regress.c I believe
@@ -65,6 +41,9 @@
Should be done by 10th June.
I have 3 big assignments due 30th May, 31st May, and 1st June, but I would still like to
have most of it done by the 3rd of June.
+Well that didn't quite happen. Re-baselined: 26th June.
+This probably seems like a huge slip, but considering the exam placement (No Tor work
+done at all between 9th and 20th of June) it's not that big a slip.
/////////////// Item 2: ///////////////////////////
Do 1) Second
@@ -94,7 +73,7 @@
Schedule:
This is not a big section, but I have 4 exams shortly after the 10th, (12th, 18th, 18th, 20th)
-so I will say the 1st July.
+so I will say the 9th July.
(Note: First evaluation begins 9th July)
//////////////////////// Item 3: //////////////////////
@@ -136,8 +115,5 @@
//////////////////////////////////////////////////////////////
Random notes:
-event.h has a whole lot of bufferevent stuff, but I can't find the functions themselves.
-Where are they? do they even exist? are they related to this?
-
What about closing the connection? How will this be done in a connection independent way?
-When the buffer is freed?
\ No newline at end of file
+When the buffer is freed?
Modified: libevent-urz/trunk/sa_evbuffer.c
===================================================================
--- libevent-urz/trunk/sa_evbuffer.c 2007-06-25 07:44:58 UTC (rev 10676)
+++ libevent-urz/trunk/sa_evbuffer.c 2007-06-25 12:10:45 UTC (rev 10677)
@@ -123,6 +123,28 @@
}
}
+static int
+timeout_reset(struct event *ev, int timeout)
+{
+ struct timeval tv, *ptv = NULL;
+
+ event_del(ev);
+
+ if (timeout) {
+ timerclear(&tv);
+ tv.tv_sec = timeout;
+ ptv = &tv;
+ } else {
+ /*
+ For sa_bufferevents it does not make any sense to
+ set events without timeouts
+ */
+ return -1;
+ }
+
+ return (event_add(ev, ptv));
+}
+
/* Code to do setup / initialization of the evbuffer delayed callbacks
* Initially copied from ev_signal_init, then modified.
*/
@@ -135,7 +157,7 @@
/* printf("sa_evbuffer initializing\n"); */
if(del_notifier_status != NOTIFIER_UNINIT) {
- printf("Initialized already, returning\n");
+ /* printf("Initialized already, returning\n"); */
return;
} else {
status_mutex = CreateMutex(NULL, FALSE, NULL);
@@ -193,7 +215,12 @@
{
int res = 0;
size_t toload;
-
+
+ evbuffer_lock(bufev->input, __func__);
+
+ if(size)
+ timeout_reset(&(bufev->ev_read), bufev->timeout_read);
+
/*
* If we have a high watermark configured then we don't want to
* read more data than would make us reach the watermark.
@@ -206,6 +233,7 @@
res = evbuffer_add(bufev->input, data, toload);
if (res == -1) {
+ evbuffer_unlock(bufev->input, __func__);
return 0;
}
@@ -222,6 +250,9 @@
bufev->del_read_event_set = 1;
notify();
}
+
+ evbuffer_unlock(bufev->input, __func__);
+
return toload;
}
@@ -243,6 +274,9 @@
evbuffer_lock(bufev->output, __func__);
+ if(size)
+ timeout_reset(&(bufev->ev_read), bufev->timeout_read);
+
if(EVBUFFER_LENGTH(bufev->output) < size) {
copysize = EVBUFFER_LENGTH(bufev->output);
} else {
Modified: libevent-urz/trunk/test/Makefile.am
===================================================================
--- libevent-urz/trunk/test/Makefile.am 2007-06-25 07:44:58 UTC (rev 10676)
+++ libevent-urz/trunk/test/Makefile.am 2007-06-25 12:10:45 UTC (rev 10677)
@@ -6,7 +6,8 @@
EXTRA_DIST = regress.rpc
-noinst_PROGRAMS = test-init test-eof test-weof test-time regress bench
+#noinst_PROGRAMS = test-init test-eof test-weof test-time regress bench
+noinst_PROGRAMS = regress
BUILT_SOURCES = regress.gen.c regress.gen.h
test_init_SOURCES = test-init.c
@@ -23,7 +24,8 @@
DISTCLEANFILES = *~
CLEANFILES = regress.gen.h regress.gen.c
-test: test-init test-eof test-weof test-time regress
+#test: test-init test-eof test-weof test-time regress
+test: regress
verify: test
@./test.sh
Modified: libevent-urz/trunk/test/regress.c
===================================================================
--- libevent-urz/trunk/test/regress.c 2007-06-25 07:44:58 UTC (rev 10676)
+++ libevent-urz/trunk/test/regress.c 2007-06-25 12:10:45 UTC (rev 10677)
@@ -535,6 +535,36 @@
}
void
+sa_readcb(struct sa_bufferevent *bev, void *arg)
+{
+ char buffer[8333];
+ size_t bufsize;
+ bufsize sa_bufferevent_read(bev, buffer, 8333);
+
+ if (bufsize == 8333) {
+ sa_bufferevent_disable(bev, EV_READ);
+ test_ok++;
+ }
+
+ sa_bufferevent_write(bev, buffer, bufsize);
+}
+
+void
+sa_writecb(struct sa_bufferevent *bev, void *arg)
+{
+ if (EVBUFFER_LENGTH(bev->output) == 0) {
+ test_ok++;
+ sa_bufferevent_disable(bev, EV_WRITE);
+ }
+}
+
+void
+sa_errorcb(struct sa_bufferevent *bev, short what, void *arg)
+{
+ test_ok = -2;
+}
+
+void
test_bufferevent(void)
{
struct bufferevent *bev1, *bev2;
@@ -552,8 +582,8 @@
for (i = 0; i < sizeof(buffer); i++)
buffer[0] = i;
- bufferevent_write(bev1, buffer, sizeof(buffer));
-
+ sa_bufferevent_write(bev1, buffer, sizeof(buffer));
+
event_dispatch();
bufferevent_free(bev1);
@@ -565,6 +595,39 @@
cleanup_test();
}
+void
+test_sa_bufferevent(void)
+{
+ struct sa_bufferevent *bev1;
+ char buffer[8333];
+ int i;
+
+ setup_test("SemiAutomatic Bufferevent: ");
+
+ bev1 = sa_bufferevent_new(sa_readcb, writecb, errorcb, NULL);
+
+ sa_bufferevent_enable(bev1, EV_READ);
+ sa_bufferevent_enable(bev1, EV_WRITE);
+
+ for (i = 0; i < sizeof(buffer); i++)
+ buffer[0] = i;
+
+ sa_bufferevent_load(bev1, buffer, sizeof(buffer));
+
+ event_loop(EVLOOP_ONCE);
+
+ sa_bufferevent_unload(bev1, buffer, sizeof(buffer));
+
+ event_loop(EVLOOP_ONCE);
+
+ bufferevent_free(bev1);
+
+ if (test_ok != 2)
+ test_ok = 0;
+
+ cleanup_test();
+}
+
struct test_pri_event {
struct event ev;
int count;
@@ -920,6 +983,8 @@
test_evbuffer();
test_bufferevent();
+
+ test_sa_bufferevent();
test_priorities(1);
test_priorities(2);
Added: libevent-urz/trunk/test/test-sa_bufferevents.c
===================================================================
--- libevent-urz/trunk/test/test-sa_bufferevents.c (rev 0)
+++ libevent-urz/trunk/test/test-sa_bufferevents.c 2007-06-25 12:10:45 UTC (rev 10677)
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2003, 2004 Niels Provos <provos@xxxxxxxxxxxxxx>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef WIN32
+#include <winsock2.h>
+#include <windows.h>
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#include <sys/queue.h>
+#ifndef WIN32
+#include <sys/socket.h>
+#include <sys/signal.h>
+#include <unistd.h>
+#else
+#include "../WIN32-Code/misc.h"
+#include <Windows.h>
+#endif
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include "event.h"
+#include "log.h"
+
+#include "regress.h"
+
+int pair[2];
+int test_ok;
+static int called;
+static struct event_base *event_base;
+
+int
+setup_test(char *name)
+{
+
+ fprintf(stdout, "%s", name);
+
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) {
+ fprintf(stderr, "%s: socketpair\n", __func__);
+ exit(1);
+ }
+
+#ifdef HAVE_FCNTL
+ if (fcntl(pair[0], F_SETFL, O_NONBLOCK) == -1)
+ fprintf(stderr, "fcntl(O_NONBLOCK)");
+
+ if (fcntl(pair[1], F_SETFL, O_NONBLOCK) == -1)
+ fprintf(stderr, "fcntl(O_NONBLOCK)");
+#endif
+
+ test_ok = 0;
+ called = 0;
+ return (0);
+}
+
+int
+cleanup_test(void)
+{
+#ifndef WIN32
+ close(pair[0]);
+ close(pair[1]);
+#else
+ CloseHandle((HANDLE)pair[0]);
+ CloseHandle((HANDLE)pair[1]);
+#endif
+ if (test_ok)
+ fprintf(stdout, "OK\n");
+ else {
+ fprintf(stdout, "FAILED\n");
+ exit(1);
+ }
+
+ return (0);
+}
+
+void
+test_evbuffer(void) {
+ setup_test("Evbuffer: ");
+
+ struct evbuffer *evb = evbuffer_new();
+
+ evbuffer_add_printf(evb, "%s/%d", "hello", 1);
+
+ if (EVBUFFER_LENGTH(evb) == 7 &&
+ strcmp(EVBUFFER_DATA(evb), "hello/1") == 0)
+ test_ok = 1;
+
+ cleanup_test();
+}
+
+void
+sa_readcb(struct sa_bufferevent *bev, void *arg)
+{
+ char buffer[8333];
+ size_t bufsize;
+ bufsize = sa_bufferevent_read(bev, buffer, 8333);
+
+ if (bufsize == 8333) {
+ sa_bufferevent_disable(bev, EV_READ);
+ test_ok++;
+ }
+
+ sa_bufferevent_write(bev, buffer, bufsize);
+}
+
+void
+sa_writecb(struct sa_bufferevent *bev, void *arg)
+{
+ if (EVBUFFER_LENGTH(bev->output) == 0) {
+ test_ok++;
+ sa_bufferevent_disable(bev, EV_WRITE);
+ }
+}
+
+void
+sa_errorcb(struct sa_bufferevent *bev, short what, void *arg)
+{
+ test_ok = -2;
+}
+
+void
+sa_timecb(int fd, short what, void *arg)
+{
+ test_ok++;
+}
+
+void
+test_sa_bufferevent(void)
+{
+ struct sa_bufferevent *bev1;
+ char buffer[8333];
+ int i;
+
+ setup_test("SemiAutomatic Bufferevents: ");
+
+ bev1 = sa_bufferevent_new(sa_readcb, sa_writecb, sa_errorcb, NULL);
+
+ sa_bufferevent_enable(bev1, EV_READ);
+ sa_bufferevent_enable(bev1, EV_WRITE);
+
+ for (i = 0; i < sizeof(buffer); i++)
+ buffer[0] = i;
+
+ sa_bufferevent_load(bev1, buffer, sizeof(buffer));
+
+ event_loop(EVLOOP_ONCE);
+
+ sa_bufferevent_unload(bev1, buffer, sizeof(buffer));
+
+ event_loop(EVLOOP_ONCE);
+
+ sa_bufferevent_free(bev1);
+
+ if (test_ok != 2)
+ test_ok = 0;
+
+ cleanup_test();
+}
+
+void
+test_sa_bufferevent_timeouts(void)
+{
+ struct sa_bufferevent *bev1;
+ char buffer[8333];
+ int i;
+
+ setup_test("SemiAutomatic Bufferevent Timeouts: ");
+
+ bev1 = sa_bufferevent_new(sa_readcb, sa_writecb, sa_errorcb, NULL);
+
+ sa_bufferevent_enable(bev1, EV_READ);
+ sa_bufferevent_enable(bev1, EV_WRITE);
+
+ sa_bufferevent_settimeout(bev1, 1, 1);
+ event_set(&bev1->ev_write, -1, EV_TIMEOUT, sa_timecb, NULL);
+
+ for (i = 0; i < sizeof(buffer); i++)
+ buffer[0] = i;
+
+ sa_bufferevent_load(bev1, buffer, sizeof(buffer));
+
+ event_loop(EVLOOP_ONCE);
+
+ event_loop(EVLOOP_ONCE);
+
+ sa_bufferevent_free(bev1);
+
+ if (test_ok != 2)
+ test_ok = 0;
+
+ cleanup_test();
+}
+
+int
+main (int argc, char **argv)
+{
+#ifdef WIN32
+ WORD wVersionRequested;
+ WSADATA wsaData;
+ int err;
+
+ wVersionRequested = MAKEWORD( 2, 2 );
+
+ err = WSAStartup( wVersionRequested, &wsaData );
+#endif
+
+ setvbuf(stdout, NULL, _IONBF, 0);
+
+ /* Initalize the event library */
+ event_base = event_init();
+
+ test_evbuffer();
+
+ test_sa_bufferevent();
+
+ test_sa_bufferevent_timeouts();
+
+ return (0);
+}
+