diff --git a/httperf/ChangeLog b/httperf/ChangeLog index 9242f17..c1b4b58 100755 --- a/httperf/ChangeLog +++ b/httperf/ChangeLog @@ -1,3 +1,8 @@ +2008-01-31 Ted Bullock + + * src/idleconn.c: Complete rewrite to use libevent backend; slight + performance improvement thanks to use of libevent notification system + 2007-11-16 Ted Bullock * configure.ac: Enable libevent dependancy diff --git a/httperf/NEWS b/httperf/NEWS index a8bfc52..373d196 100755 --- a/httperf/NEWS +++ b/httperf/NEWS @@ -1,4 +1,5 @@ * New in version 1.0.0 +** Complete re-write of idleconn.c to use libevent notification system * New in version 0.9.1: ** timer re-write to reduce memory and fix memory leaks diff --git a/httperf/src/idleconn.c b/httperf/src/idleconn.c index 0c2771e..d20ba82 100755 --- a/httperf/src/idleconn.c +++ b/httperf/src/idleconn.c @@ -35,7 +35,11 @@ #include /* For strrchr() */ #include #include +#include +#include +#include #include +#include #include #include @@ -48,14 +52,14 @@ * Events allocated onto the heap */ static struct List *active_events = NULL; -static struct List *inactive_events = NULL; static const char *prog_name = NULL; static unsigned long num_conn = 0, num_closed = 0; static struct timeval start_time; +static struct sockaddr_in server_addr; static char *server = NULL; -static int desired = 0; +static int desired = 0; /* Number of desired connections */ static int port = 0; static void @@ -64,6 +68,8 @@ cleanup() if (active_events != NULL) { while (!is_list_empty(active_events)) { Any_Type a = list_pop(active_events); + struct event *evsock = (struct event *) a.vp; + event_del(evsock); free(a.vp); } list_free(active_events); @@ -85,7 +91,9 @@ sigint_exit(int fd, short event, void *arg) printf("%s: total # conn. created = %lu, close() rate = %g conn/sec\n", prog_name, num_conn, num_closed / delta_t); +#ifdef DEBUG printf("%s: caught SIGINT... Exiting.\n", __func__); +#endif /* DEBUG */ evdns_shutdown(0); event_del(signal_int); @@ -93,11 +101,45 @@ sigint_exit(int fd, short event, void *arg) cleanup(); } +void +reconnect(int sd, short event, void *arg) +{ + struct sockaddr_in sin = server_addr; + struct event *evsock = (struct event *) arg; + + close(sd); + num_closed++; + + sd = socket(AF_INET, SOCK_STREAM, 0); + + if (sd == -1) { + perror("socket"); + exit(EXIT_FAILURE); + } + + if (connect(sd, (struct sockaddr *) &sin, sizeof(sin)) < 0) { + perror("connect"); + cleanup(); + exit(EXIT_FAILURE); + } + + event_set(evsock, sd, EV_READ, reconnect, evsock); + event_add(evsock, NULL); + num_conn++; + +} + +/* + * For the explanation of these parameters, please refer to the libevent evdns + * callback API + */ void dns_lookup_callback(int result, char type, int count, int ttl, void *addresses, void *arg) { - uint8_t i; + uint32_t i; + uint8_t oct[4]; + struct in_addr *address_list = (struct in_addr *) addresses; if (result != DNS_ERR_NONE) { printf("DNS Lookup: result(%d)\n", @@ -105,22 +147,55 @@ dns_lookup_callback(int result, char type, int count, int ttl, void *addresses, exit(EXIT_FAILURE); } - printf("Resolved %s\n", server); + memset(&server_addr, 0, sizeof(server_addr)); + server_addr.sin_family = AF_INET; + server_addr.sin_port = htons(port); + server_addr.sin_addr = address_list[0]; + + /* + * Echo the resolved address + */ + printf("Resolved %s\n\t(%s)\n", server, inet_ntoa(address_list[0])); + + /* + * Open the number of `desired` connections + */ + for (i = 0; i < desired; i++) { + struct sockaddr_in sin; + int sd = socket(AF_INET, SOCK_STREAM, 0); + + struct event *evsock = NULL; + + if (sd == -1) { + perror("socket"); + continue; + } + + sin = server_addr; + + if (connect(sd, (struct sockaddr *) &sin, sizeof(sin)) < 0) { + perror("connect"); + cleanup(); + exit(EXIT_FAILURE); + } + + evsock = (struct event *) malloc(sizeof(struct event)); + + if (evsock == NULL) { + cleanup(); + exit(EXIT_FAILURE); + } + + event_set(evsock, sd, EV_READ, reconnect, evsock); + list_push(active_events, (Any_Type) (void *) evsock); + num_conn++; + + event_add(evsock, NULL); - for (i = 0; i < count; ++i) { - uint32_t *address_list = (uint32_t *) addresses; - uint8_t oct[4]; - oct[0] = (uint8_t) (address_list[i] & 0x000000ff); - oct[1] = (uint8_t) ((address_list[i] & 0x0000ff00) >> 8); - oct[2] = (uint8_t) ((address_list[i] & 0x00ff0000) >> 16); - oct[3] = (uint8_t) ((address_list[i] & 0xff000000) >> 24); - printf("\t(%u.%u.%u.%u)\n", oct[0], oct[1], oct[2], oct[3]); } - - } -void +int main(int argc, char *argv[]) { struct event signal_int; @@ -129,10 +204,6 @@ main(int argc, char *argv[]) if (active_events == NULL) goto init_failure; - inactive_events = list_create(); - if (inactive_events == NULL) - goto init_failure; - event_init(); evdns_init(); @@ -181,4 +252,9 @@ main(int argc, char *argv[]) init_failure: cleanup(); exit(EXIT_FAILURE); + + /* + * Should never reach here + */ + return 0; }