aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWilmer van der Gaast <wilmer@gaast.net>2006-05-13 21:01:14 +0200
committerWilmer van der Gaast <wilmer@gaast.net>2006-05-13 21:01:14 +0200
commit782d988a88582a0f3dd6539664d535fb790df024 (patch)
treefa8d1bc22b6f96611111794bb2a9caf016a5e728
parent309cb9e19395261d020f7ea649807ff1adbe76de (diff)
libevent code works better with epoll() now in some (pretty common) situations.
-rw-r--r--protocols/events.h8
-rw-r--r--protocols/events_glib.c2
-rw-r--r--protocols/events_libevent.c78
-rw-r--r--protocols/ssl_openssl.c2
4 files changed, 65 insertions, 25 deletions
diff --git a/protocols/events.h b/protocols/events.h
index 5b684f8c..a61dc98c 100644
--- a/protocols/events.h
+++ b/protocols/events.h
@@ -39,8 +39,8 @@
#include <gmodule.h>
typedef enum {
- GAIM_INPUT_READ = 1 << 0,
- GAIM_INPUT_WRITE = 1 << 1
+ GAIM_INPUT_READ = 1 << 1,
+ GAIM_INPUT_WRITE = 1 << 2
} b_input_condition;
typedef gboolean (*b_event_handler)(gpointer data, gint fd, b_input_condition cond);
@@ -48,8 +48,8 @@ typedef gboolean (*b_event_handler)(gpointer data, gint fd, b_input_condition co
#define GAIM_WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL)
#define GAIM_ERR_COND (G_IO_HUP | G_IO_ERR | G_IO_NVAL)
-// #define event_debug( x... ) printf( x )
-#define event_debug( x... )
+#define event_debug( x... ) printf( x )
+// #define event_debug( x... )
G_MODULE_EXPORT void b_main_init();
G_MODULE_EXPORT void b_main_run();
diff --git a/protocols/events_glib.c b/protocols/events_glib.c
index 01265fd8..ff6e5a74 100644
--- a/protocols/events_glib.c
+++ b/protocols/events_glib.c
@@ -130,7 +130,7 @@ gint b_timeout_add(gint timeout, b_event_handler func, gpointer data)
void b_event_remove(gint tag)
{
- event_debug( "g_source_remove( %d )\n", tag );
+ event_debug( "b_event_remove( %d )\n", tag );
if (tag > 0)
g_source_remove(tag);
diff --git a/protocols/events_libevent.c b/protocols/events_libevent.c
index bcfb3b45..d4767348 100644
--- a/protocols/events_libevent.c
+++ b/protocols/events_libevent.c
@@ -38,6 +38,13 @@
static guint id_next;
static GHashTable *id_hash;
+/* Since libevent doesn't handle two event handlers for one fd-condition
+ very well (which happens sometimes when BitlBee changes event handlers
+ for a combination), let's buid some indexes so we can delete them here
+ already, just in time. */
+static GHashTable *read_hash;
+static GHashTable *write_hash;
+
struct b_event_data
{
guint id;
@@ -52,6 +59,8 @@ void b_main_init()
id_next = 1;
id_hash = g_hash_table_new( g_int_hash, g_int_equal );
+ read_hash = g_hash_table_new( g_int_hash, g_int_equal );
+ write_hash = g_hash_table_new( g_int_hash, g_int_equal );
}
void b_main_run()
@@ -96,26 +105,49 @@ static void b_event_passthrough( int fd, short event, void *data )
gint b_input_add( gint fd, b_input_condition condition, b_event_handler function, gpointer data )
{
- struct b_event_data *b_ev = g_new0( struct b_event_data, 1 );
- GIOCondition out_cond;
-
- b_ev->id = id_next++;
- b_ev->function = function;
- b_ev->data = data;
+ struct b_event_data *b_ev;
- out_cond = EV_PERSIST;
- if( condition & GAIM_INPUT_READ )
- out_cond |= EV_READ;
- if( condition & GAIM_INPUT_WRITE )
- out_cond |= EV_WRITE;
+ event_debug( "b_input_add( %d, %d, 0x%x, 0x%x ) ", fd, condition, function, data );
- event_set( &b_ev->evinfo, fd, out_cond, b_event_passthrough, b_ev );
- event_add( &b_ev->evinfo, NULL );
-
- event_debug( "b_input_add( %d, %d, 0x%x, 0x%x ) = %d\n", fd, condition, function, data, b_ev->id );
+ if( ( condition & GAIM_INPUT_READ && ( b_ev = g_hash_table_lookup( read_hash, &fd ) ) ) ||
+ ( condition & GAIM_INPUT_WRITE && ( b_ev = g_hash_table_lookup( write_hash, &fd ) ) ) )
+ {
+ /* We'll stick with this libevent entry, but give it a new BitlBee id. */
+ g_hash_table_remove( id_hash, &b_ev->id );
+
+ event_debug( "(replacing old handler (id = %d)) = %d\n", b_ev->id, id_next );
+
+ b_ev->id = id_next++;
+ b_ev->function = function;
+ b_ev->data = data;
+ }
+ else
+ {
+ GIOCondition out_cond;
+
+ event_debug( "(new) = %d\n", id_next );
+
+ b_ev = g_new0( struct b_event_data, 1 );
+ b_ev->id = id_next++;
+ b_ev->function = function;
+ b_ev->data = data;
+
+ out_cond = EV_PERSIST;
+ if( condition & GAIM_INPUT_READ )
+ out_cond |= EV_READ;
+ if( condition & GAIM_INPUT_WRITE )
+ out_cond |= EV_WRITE;
+
+ event_set( &b_ev->evinfo, fd, out_cond, b_event_passthrough, b_ev );
+ event_add( &b_ev->evinfo, NULL );
+
+ if( out_cond & EV_READ )
+ g_hash_table_insert( read_hash, &b_ev->evinfo.ev_fd, b_ev );
+ if( out_cond & EV_WRITE )
+ g_hash_table_insert( write_hash, &b_ev->evinfo.ev_fd, b_ev );
+ }
g_hash_table_insert( id_hash, &b_ev->id, b_ev );
-
return b_ev->id;
}
@@ -135,7 +167,7 @@ gint b_timeout_add( gint timeout, b_event_handler function, gpointer data )
evtimer_set( &b_ev->evinfo, b_event_passthrough, b_ev );
evtimer_add( &b_ev->evinfo, &tv );
- event_debug( "b_timeout_add( %d, %d, 0x%x ) = %d\n", timeout, function, data, b_ev->id );
+ event_debug( "b_timeout_add( %d, 0x%x, 0x%x ) = %d\n", timeout, function, data, b_ev->id );
g_hash_table_insert( id_hash, &b_ev->id, b_ev );
@@ -149,13 +181,21 @@ void b_event_remove( gint id )
event_debug( "b_event_remove( %d )\n", id );
if( b_ev )
{
- event_del( &b_ev->evinfo );
g_hash_table_remove( id_hash, &b_ev->id );
+ if( b_ev->evinfo.ev_fd >= 0 )
+ {
+ if( b_ev->evinfo.ev_events & EV_READ )
+ g_hash_table_remove( read_hash, &b_ev->evinfo.ev_fd );
+ if( b_ev->evinfo.ev_events & EV_WRITE )
+ g_hash_table_remove( write_hash, &b_ev->evinfo.ev_fd );
+ }
+
+ event_del( &b_ev->evinfo );
g_free( b_ev );
}
else
{
- event_debug( "Double remove?\n" );
+ event_debug( "Already removed?\n" );
}
}
diff --git a/protocols/ssl_openssl.c b/protocols/ssl_openssl.c
index 54788ec3..5aa0263e 100644
--- a/protocols/ssl_openssl.c
+++ b/protocols/ssl_openssl.c
@@ -114,7 +114,7 @@ static gboolean ssl_handshake( gpointer data, gint source, b_input_condition con
struct scd *conn = data;
int st;
- if( conn->inpa != -1 )
+ if( 0 && conn->inpa != -1 )
{
b_event_remove( conn->inpa );
conn->inpa = -1;