diff --git a/httperf/configure.ac b/httperf/configure.ac index 0a1e5c4..eaf7700 100755 --- a/httperf/configure.ac +++ b/httperf/configure.ac @@ -25,6 +25,14 @@ AC_ARG_ENABLE([idleconn], [enable_idleconn=$enableval], [enable_idleconn=no]) +if test "$enable_idleconn" = "yes"; then +AC_CHECK_LIB([event], + [event_init], + , + [AC_MSG_ERROR([libevent is required to build idleconn])]) +fi + + AM_CONDITIONAL(IDLECONN, [test "x$enable_idleconn" = xyes]) @@ -32,10 +40,6 @@ AM_CONDITIONAL(IDLECONN, AC_CHECK_LIB(m, sqrt) AC_CHECK_LIB(crypto, main) AC_CHECK_LIB(ssl, SSL_version, , AC_MSG_WARN([SSL Disabled]) ) -AC_CHECK_LIB([event], - [event_init], - , - [AC_MSG_ERROR([libevent is required to build idleconn])]) # The following checks are for solaris and its ilk AC_SEARCH_LIBS([getsockopt], [socket]) AC_SEARCH_LIBS([socket], [socket nsl]) diff --git a/httperf/src/conn.c b/httperf/src/conn.c index d42ea0e..8013129 100755 --- a/httperf/src/conn.c +++ b/httperf/src/conn.c @@ -40,7 +40,6 @@ #include #include -#include #include #include diff --git a/httperf/src/conn.h b/httperf/src/conn.h index c66a0d3..656d8e8 100755 --- a/httperf/src/conn.h +++ b/httperf/src/conn.h @@ -105,7 +105,6 @@ typedef struct Conn #ifdef HAVE_SSL SSL *ssl; /* SSL connection info */ #endif - struct event ev_read, ev_write; } Conn; diff --git a/httperf/src/core.c b/httperf/src/core.c index c14469b..53fa4b5 100755 --- a/httperf/src/core.c +++ b/httperf/src/core.c @@ -54,7 +54,6 @@ #include #include /* after sys/types.h for BSD (in generic_types.h) */ -#include #include #include @@ -73,6 +72,7 @@ static int running = 1; static int iteration; static u_long max_burst_len; +static fd_set rdfds, wrfds; static int min_sd = 0x7fffffff, max_sd = 0, alloced_sd_to_conn = 0; static struct timeval select_timeout; static struct sockaddr_in myaddr; @@ -134,8 +134,6 @@ static u_int syscall_count[SC_NUM_SYSCALLS]; while (errno == EINTR); \ } #endif -static void conn_handle_read_event(int sd, short ev, void *a); -static void conn_handle_write_event(int sd, short ev, void *a); struct hash_entry { const char *hostname; @@ -274,34 +272,6 @@ port_get(void) return port; } -static void -conn_read_set(Conn *s) -{ - if (s->sd > -1) - event_add(&s->ev_read, NULL); -} - -static void -conn_read_clear(Conn *s) -{ - if (s->sd > -1) - event_del(&s->ev_read); -} - -static void -conn_write_set(Conn *s) -{ - if (s->sd > -1) - event_add(&s->ev_write, NULL); -} - -static void -conn_write_clear(Conn *s) -{ - if (s->sd > -1) - event_del(&s->ev_write); -} - static void conn_failure(Conn * s, int err) { @@ -327,9 +297,11 @@ conn_timeout(struct Timer *t, Any_Type arg) c = 0; if (s->sd >= 0) { now = timer_now(); - if (s->recvq && now >= s->recvq->timeout) + if (FD_ISSET(s->sd, &rdfds) + && s->recvq && now >= s->recvq->timeout) c = s->recvq; - else if (s->sendq && now >= s->sendq->timeout) + else if (FD_ISSET(s->sd, &wrfds) + && s->sendq && now >= s->sendq->timeout) c = s->sendq; } if (DBG > 0) { @@ -347,11 +319,18 @@ conn_timeout(struct Timer *t, Any_Type arg) } static void -set_active_shared(Conn * s) +set_active(Conn * s, fd_set * fdset) { + int sd = s->sd; Any_Type arg; Time timeout; + FD_SET(sd, fdset); + if (sd < min_sd) + min_sd = sd; + if (sd >= max_sd) + max_sd = sd; + if (s->watchdog) return; @@ -368,32 +347,6 @@ set_active_shared(Conn * s) } } -static void -set_active_read(Conn *s) -{ - int sd = s->sd; - - conn_read_set(s); - if (sd < min_sd) - min_sd = sd; - if (sd >= max_sd) - max_sd = sd; - set_active_shared(s); -} - -static void -set_active_write(Conn *s) -{ - int sd = s->sd; - - conn_write_set(s); - if (sd < min_sd) - min_sd = sd; - if (sd >= max_sd) - max_sd = sd; - set_active_shared(s); -} - static void do_send(Conn * conn) { @@ -481,7 +434,7 @@ do_send(Conn * conn) */ call->timeout = param.timeout ? timer_now() + param.timeout : 0.0; - set_active_write(conn); + set_active(conn, &wrfds); return; } @@ -491,7 +444,7 @@ do_send(Conn * conn) conn->sendq = call->sendq_next; if (!conn->sendq) { conn->sendq_tail = 0; - conn_write_clear(conn); + FD_CLR(sd, &wrfds); } arg.l = 0; event_signal(EV_CALL_SEND_STOP, (Object *) call, arg); @@ -515,7 +468,7 @@ do_send(Conn * conn) call->timeout = param.timeout + param.think_timeout; if (call->timeout > 0.0) call->timeout += timer_now(); - set_active_read(conn); + set_active(conn, &rdfds); if (conn->state < S_REPLY_STATUS) conn->state = S_REPLY_STATUS; /* expecting reply * status */ @@ -538,7 +491,7 @@ recv_done(Call * call) conn->recvq = call->recvq_next; if (!conn->recvq) { - conn_read_clear(conn); + FD_CLR(conn->sd, &rdfds); conn->recvq_tail = 0; } /* @@ -649,7 +602,7 @@ do_recv(Conn * s) while (buf_len > 0); if (s->recvq) - set_active_read(c->conn); + set_active(c->conn, &rdfds); } struct sockaddr_in * @@ -698,6 +651,8 @@ core_init(void) struct rlimit rlimit; memset(&hash_table, 0, sizeof(hash_table)); + memset(&rdfds, 0, sizeof(rdfds)); + memset(&wrfds, 0, sizeof(wrfds)); memset(&myaddr, 0, sizeof(myaddr)); memset(&port_free_map, 0xff, sizeof(port_free_map)); @@ -734,15 +689,12 @@ core_init(void) exit(1); } - /* Disable the FD_SETSIZE check for now - perhaps only enforce on libevent select()? */ -#if 0 if (rlimit.rlim_max > FD_SETSIZE) { fprintf(stderr, "%s: warning: open file limit > FD_SETSIZE; " "limiting max. # of open files to FD_SETSIZE\n", prog_name); rlimit.rlim_max = FD_SETSIZE; } -#endif rlimit.rlim_cur = rlimit.rlim_max; if (setrlimit(RLIMIT_NOFILE, &rlimit) < 0) { @@ -789,12 +741,14 @@ core_ssl_connect(Conn * s) (reason == SSL_ERROR_WANT_READ) ? "read" : "write"); - if (reason == SSL_ERROR_WANT_READ) { - conn_write_clear(s); - set_active_read(s); - } else if (reason == SSL_ERROR_WANT_WRITE) { - conn_read_clear(s); - set_active_write(s); + if (reason == SSL_ERROR_WANT_READ + && !FD_ISSET(s->sd, &rdfds)) { + FD_CLR(s->sd, &wrfds); + set_active(s, &rdfds); + } else if (reason == SSL_ERROR_WANT_WRITE + && !FD_ISSET(s->sd, &wrfds)) { + FD_CLR(s->sd, &rdfds); + set_active(s, &wrfds); } return; } @@ -905,8 +859,6 @@ core_connect(Conn * s) } s->sd = sd; - event_set(&s->ev_read, sd, EV_READ | EV_PERSIST, conn_handle_read_event, s); - event_set(&s->ev_write, sd, EV_WRITE | EV_PERSIST, conn_handle_write_event, s); if (sd >= alloced_sd_to_conn) { size_t size, old_size; @@ -987,7 +939,7 @@ core_connect(Conn * s) * connection establishment. */ s->state = S_CONNECTING; - set_active_write(s); + set_active(s, &wrfds); if (param.timeout > 0.0) { arg.vp = s; assert(!s->watchdog); @@ -1088,7 +1040,7 @@ core_send(Conn * conn, Call * call) return -1; call->timeout = param.timeout ? timer_now() + param.timeout : 0.0; - set_active_write(conn); + set_active(conn, &wrfds); } else { conn->sendq_tail->sendq_next = call; conn->sendq_tail = call; @@ -1145,8 +1097,8 @@ core_close(Conn * conn) if (sd >= 0) { close(sd); sd_to_conn[sd] = 0; - conn_read_clear(conn); - conn_write_clear(conn); + FD_CLR(sd, &wrfds); + FD_CLR(sd, &rdfds); } if (conn->myport > 0) port_put(conn->myport); @@ -1159,60 +1111,99 @@ core_close(Conn * conn) conn_dec_ref(conn); } -static void -conn_handle_read_event(int sd, short ev, void *a) -{ - Conn *conn = sd_to_conn[sd]; - - conn_inc_ref(conn); - - if (conn->watchdog) { - timer_cancel(conn->watchdog); - conn->watchdog = 0; - } - - if (conn->recvq) - do_recv(conn); - - conn_dec_ref(conn); -} - -static void -conn_handle_write_event(int sd, short ev, void *a) -{ - Conn *conn = sd_to_conn[sd]; - Any_Type arg; - - conn_inc_ref(conn); - - if (conn->watchdog) { - timer_cancel(conn->watchdog); - conn->watchdog = 0; - } - - if (conn->state == S_CONNECTING) { -#ifdef HAVE_SSL - if (param.use_ssl) - core_ssl_connect (conn); - else { -#endif - conn_write_clear(conn); - conn->state = S_CONNECTED; - arg.l = 0; - event_signal(EV_CONN_CONNECTED, (Object *) conn, arg); - } - } else if (conn->sendq) - do_send(conn); - - conn_dec_ref(conn); -} - void core_loop(void) { + int is_readable, is_writable, n, sd, bit, min_i, max_i, i = 0; + fd_set readable, writable; + fd_mask mask; + Any_Type arg; + Conn *conn; + while (running) { - timer_tick(); - (void) event_loop(EVLOOP_ONCE); + struct timeval tv = select_timeout; + + timer_tick(); + + readable = rdfds; + writable = wrfds; + min_i = min_sd / NFDBITS; + max_i = max_sd / NFDBITS; + + SYSCALL(SELECT, n = select(max_sd + 1, &readable, &writable, 0, &tv)); + + ++iteration; + + if (n <= 0) { + if (n < 0) { + fprintf(stderr, "%s.core_loop: select failed: %s\n", prog_name, strerror(errno)); + exit(1); + } + continue; + } + + while (n > 0) { + /* + * find the index of the fdmask that has something + * going on: + */ + do { + ++i; + if (i > max_i) + i = min_i; + + assert(i <= max_i); + mask = readable.fds_bits[i] | writable.fds_bits[i]; + } while (!mask); + bit = 0; + sd = i * NFDBITS + bit; + do { + if (mask & 1) { + --n; + is_readable = (FD_ISSET(sd, &readable) && FD_ISSET(sd, &rdfds)); + is_writable = (FD_ISSET(sd, &writable) && FD_ISSET(sd, &wrfds)); + + if (is_readable || is_writable) { + /* + * only handle sockets that + * haven't timed out yet + */ + conn = sd_to_conn[sd]; + conn_inc_ref(conn); + + if (conn->watchdog) { + timer_cancel(conn->watchdog); + conn->watchdog = 0; + } + if (conn->state == S_CONNECTING) { +#ifdef HAVE_SSL + if (param.use_ssl) + core_ssl_connect(conn); + else +#endif + if (is_writable) { + FD_CLR(sd, &wrfds); + conn->state = S_CONNECTED; + arg.l = 0; + event_signal(EV_CONN_CONNECTED, (Object*)conn, arg); + } + } else { + if (is_writable && conn->sendq) + do_send(conn); + if (is_readable && conn->recvq) + do_recv(conn); + } + + conn_dec_ref(conn); + + if (n > 0) + timer_tick(); + } + } + mask = ((u_long) mask) >> 1; + ++sd; + } while (mask); + } } } diff --git a/httperf/src/gen/call_seq.c b/httperf/src/gen/call_seq.c index d134fbc..fc0474b 100755 --- a/httperf/src/gen/call_seq.c +++ b/httperf/src/gen/call_seq.c @@ -40,7 +40,6 @@ #include #include -#include #include #include diff --git a/httperf/src/gen/conn_rate.c b/httperf/src/gen/conn_rate.c index 9d828d0..ccba89a 100755 --- a/httperf/src/gen/conn_rate.c +++ b/httperf/src/gen/conn_rate.c @@ -41,7 +41,6 @@ #include #include -#include #include #include diff --git a/httperf/src/gen/sess_cookie.c b/httperf/src/gen/sess_cookie.c index c6db263..89db2b5 100755 --- a/httperf/src/gen/sess_cookie.c +++ b/httperf/src/gen/sess_cookie.c @@ -50,7 +50,6 @@ #include #include -#include #include #include diff --git a/httperf/src/gen/session.c b/httperf/src/gen/session.c index c2d9af3..e89df42 100755 --- a/httperf/src/gen/session.c +++ b/httperf/src/gen/session.c @@ -66,7 +66,6 @@ #include #include #include -#include #include #include diff --git a/httperf/src/gen/uri_wlog.c b/httperf/src/gen/uri_wlog.c index 19b5d34..0a639eb 100755 --- a/httperf/src/gen/uri_wlog.c +++ b/httperf/src/gen/uri_wlog.c @@ -78,7 +78,6 @@ #include #include -#include #include #include diff --git a/httperf/src/gen/wsess.c b/httperf/src/gen/wsess.c index 70d9f26..015f8ab 100755 --- a/httperf/src/gen/wsess.c +++ b/httperf/src/gen/wsess.c @@ -44,7 +44,6 @@ #include #include -#include #include #include diff --git a/httperf/src/gen/wsesslog.c b/httperf/src/gen/wsesslog.c index 9819d90..6296ca6 100755 --- a/httperf/src/gen/wsesslog.c +++ b/httperf/src/gen/wsesslog.c @@ -83,7 +83,6 @@ #include #include -#include #include #include diff --git a/httperf/src/gen/wsesspage.c b/httperf/src/gen/wsesspage.c index 65c543b..ea1a1a6 100755 --- a/httperf/src/gen/wsesspage.c +++ b/httperf/src/gen/wsesspage.c @@ -49,7 +49,6 @@ #include #include -#include #include #include diff --git a/httperf/src/http.c b/httperf/src/http.c index 03778fa..9d3bf45 100755 --- a/httperf/src/http.c +++ b/httperf/src/http.c @@ -42,8 +42,6 @@ #include #include -#include - #include #include diff --git a/httperf/src/httperf.c b/httperf/src/httperf.c index 1bc792c..0a70b24 100755 --- a/httperf/src/httperf.c +++ b/httperf/src/httperf.c @@ -73,7 +73,6 @@ #include #include /* after sys/types.h for BSD (in generic_types.h) */ -#include #include #include @@ -274,9 +273,6 @@ main(int argc, char **argv) param.ssl_reuse = 1; #endif - /* setup event stuff early */ - event_init(); - /* * get program name: */ diff --git a/httperf/src/object.c b/httperf/src/object.c index 3cbf0b7..c458c37 100755 --- a/httperf/src/object.c +++ b/httperf/src/object.c @@ -41,7 +41,6 @@ #include #include -#include #include #include diff --git a/httperf/src/stat/basic.c b/httperf/src/stat/basic.c index 1fe20fe..f076ce6 100755 --- a/httperf/src/stat/basic.c +++ b/httperf/src/stat/basic.c @@ -43,7 +43,6 @@ #include #include -#include #include #include diff --git a/httperf/src/stat/print_reply.c b/httperf/src/stat/print_reply.c index e07e828..ee28bcb 100755 --- a/httperf/src/stat/print_reply.c +++ b/httperf/src/stat/print_reply.c @@ -43,7 +43,6 @@ #include #include -#include #include #include diff --git a/httperf/src/stat/sess_stat.c b/httperf/src/stat/sess_stat.c index cfcc110..dee2957 100755 --- a/httperf/src/stat/sess_stat.c +++ b/httperf/src/stat/sess_stat.c @@ -43,7 +43,6 @@ #include #include -#include #include #include