rbb 99/05/18 05:19:36
Modified: apr/test ab_apr.c Log: Reformatted to fit style guide. Revision Changes Path 1.6 +454 -469 apache-apr/apr/test/ab_apr.c Index: ab_apr.c =================================================================== RCS file: /home/cvs/apache-apr/apr/test/ab_apr.c,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- ab_apr.c 1999/05/10 14:36:32 1.5 +++ ab_apr.c 1999/05/18 12:19:36 1.6 @@ -110,7 +110,7 @@ #include <stdlib.h> #include <stdio.h> #include <fcntl.h> -/*#include <netinet/in.h>*/ +/*#include <netinet/in.h> */ #include <netdb.h> #include <errno.h> #include <sys/ioctl.h> @@ -118,11 +118,11 @@ #include "apr_network_io.h" -/*#define ap_select select*/ +/*#define ap_select select */ /*#else (!)NO_APACHE_INCLUDES */ -/*#include "apr_config.h"*/ -/*#include <fcntl.h>*/ -/*#include <sys/time.h>*/ +/*#include "apr_config.h" */ +/*#include <fcntl.h> */ +/*#include <sys/time.h> */ /*#endif NO_APACHE_INCLUDES */ /* ------------------- DEFINITIONS -------------------------- */ @@ -137,7 +137,7 @@ #define CBUFFSIZE 512 struct connection { - ap_socket_t * aprsock; + ap_socket_t *aprsock; int state; int read; /* amount of bytes read */ int bread; /* amount of body read */ @@ -147,6 +147,7 @@ int keepalive; /* non-zero if a keep-alive request */ int gotheader; /* non-zero if we have the entire header in cbuff */ struct timeval start, connect, done; + int socknum; }; struct data { @@ -174,7 +175,7 @@ int postlen = 0; /* length of data to be POSTed */ char content_type[1024]; /* content type to put in POST header */ int port = 80; /* port number */ -time_t aprtimeout = 30000; /* timeout value...*/ +time_t aprtimeout = 30000; /* timeout value... */ int use_html = 0; /* use html in the report */ char *tablestring; @@ -204,8 +205,9 @@ struct connection *con; /* connection array */ struct data *stats; /* date for each request */ +ap_context_t *cntxt; -ap_sd_set_t readbits, writebits; +ap_pollfd_t *readbits; /* --------------------------------------------------------- */ @@ -214,10 +216,10 @@ static void err(char *s) { if (errno) { - perror(s); + perror(s); } else { - printf("%s", s); + printf("%s", s); } exit(errno); } @@ -230,32 +232,31 @@ static void write_request(struct connection *c) { gettimeofday(&c->connect, 0); - if (ap_send(c->aprsock, request, reqlen, 30) != reqlen){ - printf ("Send request failed!\n"); - } + if (ap_send(cntxt, c->aprsock, request, reqlen, 30) != reqlen) { + printf("Send request failed!\n"); + } if (posting) { - ap_send(c->aprsock, postdata, postlen, 30); - totalposted += (reqlen + postlen); + ap_send(cntxt, c->aprsock, postdata, postlen, 30); + totalposted += (reqlen + postlen); } c->state = STATE_READ; - ap_sd_set(c->aprsock, &readbits); - ap_sd_clr(c->aprsock, &writebits); + ap_add_poll_socket(cntxt, readbits, c->aprsock, APR_POLLIN, c->socknum); } -/* --------------------------------------------------------- */ + /* --------------------------------------------------------- */ -/* make an fd non blocking */ + /* make an fd non blocking */ static void nonblock(ap_socket_t * sock) { int i = 1; - /*ap_setsocketopt(sock, APR_SO_NONBLOCK, i);*/ + /*ap_setsocketopt(sock, APR_SO_NONBLOCK, i); */ } -/* --------------------------------------------------------- */ + /* --------------------------------------------------------- */ -/* returns the time in ms between two timevals */ + /* returns the time in ms between two timevals */ static int timedif(struct timeval a, struct timeval b) { @@ -268,9 +269,9 @@ return s + us; } -/* --------------------------------------------------------- */ + /* --------------------------------------------------------- */ -/* calculate and output results */ + /* calculate and output results */ static void output_results(void) { @@ -289,63 +290,63 @@ printf("\n"); printf("Concurrency Level: %d\n", concurrency); printf("Time taken for tests: %d.%03d seconds\n", - timetaken / 1000, timetaken % 1000); + timetaken / 1000, timetaken % 1000); printf("Complete requests: %d\n", done); printf("Failed requests: %d\n", bad); if (bad) - printf(" (Connect: %d, Length: %d, Exceptions: %d)\n", - err_conn, err_length, err_except); + printf(" (Connect: %d, Length: %d, Exceptions: %d)\n", + err_conn, err_length, err_except); if (err_response) - printf("Non-2xx responses: %d\n", err_response); + printf("Non-2xx responses: %d\n", err_response); if (keepalive) - printf("Keep-Alive requests: %d\n", doneka); + printf("Keep-Alive requests: %d\n", doneka); printf("Total transferred: %d bytes\n", totalread); if (posting) - printf("Total POSTed: %d\n", totalposted); + printf("Total POSTed: %d\n", totalposted); printf("HTML transferred: %d bytes\n", totalbread); /* avoid divide by zero */ if (timetaken) { - printf("Requests per second: %.2f\n", 1000 * (float) (done) / timetaken); - printf("Transfer rate: %.2f kb/s received\n", - (float) (totalread) / timetaken); - if (posting) { - printf(" %.2f kb/s sent\n", - (float) (totalposted) / timetaken); - printf(" %.2f kb/s total\n", - (float) (totalread + totalposted) / timetaken); - } + printf("Requests per second: %.2f\n", 1000 * (float) (done) / timetaken); + printf("Transfer rate: %.2f kb/s received\n", + (float) (totalread) / timetaken); + if (posting) { + printf(" %.2f kb/s sent\n", + (float) (totalposted) / timetaken); + printf(" %.2f kb/s total\n", + (float) (totalread + totalposted) / timetaken); + } } { - /* work out connection times */ - int i; - int totalcon = 0, total = 0; - int mincon = 9999999, mintot = 999999; - int maxcon = 0, maxtot = 0; - - for (i = 0; i < requests; i++) { - struct data s = stats[i]; - mincon = ap_min(mincon, s.ctime); - mintot = ap_min(mintot, s.time); - maxcon = ap_max(maxcon, s.ctime); - maxtot = ap_max(maxtot, s.time); - totalcon += s.ctime; - total += s.time; - } - printf("\nConnnection Times (ms)\n"); - printf(" min avg max\n"); - printf("Connect: %5d %5d %5d\n", mincon, totalcon / requests, maxcon); - printf("Processing: %5d %5d %5d\n", - mintot - mincon, (total / requests) - (totalcon / requests), - maxtot - maxcon); - printf("Total: %5d %5d %5d\n", mintot, total / requests, maxtot); + /* work out connection times */ + int i; + int totalcon = 0, total = 0; + int mincon = 9999999, mintot = 999999; + int maxcon = 0, maxtot = 0; + + for (i = 0; i < requests; i++) { + struct data s = stats[i]; + mincon = ap_min(mincon, s.ctime); + mintot = ap_min(mintot, s.time); + maxcon = ap_max(maxcon, s.ctime); + maxtot = ap_max(maxtot, s.time); + totalcon += s.ctime; + total += s.time; + } + printf("\nConnnection Times (ms)\n"); + printf(" min avg max\n"); + printf("Connect: %5d %5d %5d\n", mincon, totalcon / requests, maxcon); + printf("Processing: %5d %5d %5d\n", + mintot - mincon, (total / requests) - (totalcon / requests), + maxtot - maxcon); + printf("Total: %5d %5d %5d\n", mintot, total / requests, maxtot); } } -/* --------------------------------------------------------- */ + /* --------------------------------------------------------- */ -/* calculate and output results in HTML */ + /* calculate and output results in HTML */ static void output_html_results(void) { @@ -356,112 +357,112 @@ printf("\n\n<table %s>\n", tablestring); printf("<tr %s><th colspan=2 %s>Server Software:</th>" - "<td colspan=2 %s>%s</td></tr>\n", - trstring, tdstring, tdstring, servername); + "<td colspan=2 %s>%s</td></tr>\n", + trstring, tdstring, tdstring, servername); printf("<tr %s><th colspan=2 %s>Server Hostname:</th>" - "<td colspan=2 %s>%s</td></tr>\n", - trstring, tdstring, tdstring, hostname); + "<td colspan=2 %s>%s</td></tr>\n", + trstring, tdstring, tdstring, hostname); printf("<tr %s><th colspan=2 %s>Server Port:</th>" - "<td colspan=2 %s>%d</td></tr>\n", - trstring, tdstring, tdstring, port); + "<td colspan=2 %s>%d</td></tr>\n", + trstring, tdstring, tdstring, port); printf("<tr %s><th colspan=2 %s>Document Path:</th>" - "<td colspan=2 %s>%s</td></tr>\n", - trstring, tdstring, tdstring, path); + "<td colspan=2 %s>%s</td></tr>\n", + trstring, tdstring, tdstring, path); printf("<tr %s><th colspan=2 %s>Document Length:</th>" - "<td colspan=2 %s>%d bytes</td></tr>\n", - trstring, tdstring, tdstring, doclen); + "<td colspan=2 %s>%d bytes</td></tr>\n", + trstring, tdstring, tdstring, doclen); printf("<tr %s><th colspan=2 %s>Concurrency Level:</th>" - "<td colspan=2 %s>%d</td></tr>\n", - trstring, tdstring, tdstring, concurrency); + "<td colspan=2 %s>%d</td></tr>\n", + trstring, tdstring, tdstring, concurrency); printf("<tr %s><th colspan=2 %s>Time taken for tests:</th>" - "<td colspan=2 %s>%d.%03d seconds</td></tr>\n", - trstring, tdstring, tdstring, timetaken / 1000, timetaken % 1000); + "<td colspan=2 %s>%d.%03d seconds</td></tr>\n", + trstring, tdstring, tdstring, timetaken / 1000, timetaken % 1000); printf("<tr %s><th colspan=2 %s>Complete requests:</th>" - "<td colspan=2 %s>%d</td></tr>\n", - trstring, tdstring, tdstring, done); + "<td colspan=2 %s>%d</td></tr>\n", + trstring, tdstring, tdstring, done); printf("<tr %s><th colspan=2 %s>Failed requests:</th>" - "<td colspan=2 %s>%d</td></tr>\n", - trstring, tdstring, tdstring, bad); + "<td colspan=2 %s>%d</td></tr>\n", + trstring, tdstring, tdstring, bad); if (bad) - printf("<tr %s><td colspan=4 %s > (Connect: %d, Length: %d, Exceptions: %d)</td></tr>\n", - trstring, tdstring, err_conn, err_length, err_except); + printf("<tr %s><td colspan=4 %s > (Connect: %d, Length: %d, Exceptions: %d)</td></tr>\n", + trstring, tdstring, err_conn, err_length, err_except); if (err_response) - printf("<tr %s><th colspan=2 %s>Non-2xx responses:</th>" - "<td colspan=2 %s>%d</td></tr>\n", - trstring, tdstring, tdstring, err_response); + printf("<tr %s><th colspan=2 %s>Non-2xx responses:</th>" + "<td colspan=2 %s>%d</td></tr>\n", + trstring, tdstring, tdstring, err_response); if (keepalive) - printf("<tr %s><th colspan=2 %s>Keep-Alive requests:</th>" - "<td colspan=2 %s>%d</td></tr>\n", - trstring, tdstring, tdstring, doneka); + printf("<tr %s><th colspan=2 %s>Keep-Alive requests:</th>" + "<td colspan=2 %s>%d</td></tr>\n", + trstring, tdstring, tdstring, doneka); printf("<tr %s><th colspan=2 %s>Total transferred:</th>" - "<td colspan=2 %s>%d bytes</td></tr>\n", - trstring, tdstring, tdstring, totalread); + "<td colspan=2 %s>%d bytes</td></tr>\n", + trstring, tdstring, tdstring, totalread); if (posting) - printf("<tr %s><th colspan=2 %s>Total POSTed:</th>" - "<td colspan=2 %s>%d</td></tr>\n", - trstring, tdstring, tdstring, totalposted); + printf("<tr %s><th colspan=2 %s>Total POSTed:</th>" + "<td colspan=2 %s>%d</td></tr>\n", + trstring, tdstring, tdstring, totalposted); printf("<tr %s><th colspan=2 %s>HTML transferred:</th>" - "<td colspan=2 %s>%d bytes</td></tr>\n", - trstring, tdstring, tdstring, totalbread); + "<td colspan=2 %s>%d bytes</td></tr>\n", + trstring, tdstring, tdstring, totalbread); /* avoid divide by zero */ if (timetaken) { - printf("<tr %s><th colspan=2 %s>Requests per second:</th>" - "<td colspan=2 %s>%.2f</td></tr>\n", - trstring, tdstring, tdstring, 1000 * (float) (done) / timetaken); - printf("<tr %s><th colspan=2 %s>Transfer rate:</th>" - "<td colspan=2 %s>%.2f kb/s received</td></tr>\n", - trstring, tdstring, tdstring, (float) (totalread) / timetaken); - if (posting) { - printf("<tr %s><td colspan=2 %s> </td>" - "<td colspan=2 %s>%.2f kb/s sent</td></tr>\n", - trstring, tdstring, tdstring, - (float) (totalposted) / timetaken); - printf("<tr %s><td colspan=2 %s> </td>" - "<td colspan=2 %s>%.2f kb/s total</td></tr>\n", - trstring, tdstring, tdstring, - (float) (totalread + totalposted) / timetaken); - } + printf("<tr %s><th colspan=2 %s>Requests per second:</th>" + "<td colspan=2 %s>%.2f</td></tr>\n", + trstring, tdstring, tdstring, 1000 * (float) (done) / timetaken); + printf("<tr %s><th colspan=2 %s>Transfer rate:</th>" + "<td colspan=2 %s>%.2f kb/s received</td></tr>\n", + trstring, tdstring, tdstring, (float) (totalread) / timetaken); + if (posting) { + printf("<tr %s><td colspan=2 %s> </td>" + "<td colspan=2 %s>%.2f kb/s sent</td></tr>\n", + trstring, tdstring, tdstring, + (float) (totalposted) / timetaken); + printf("<tr %s><td colspan=2 %s> </td>" + "<td colspan=2 %s>%.2f kb/s total</td></tr>\n", + trstring, tdstring, tdstring, + (float) (totalread + totalposted) / timetaken); + } } { - /* work out connection times */ - int i; - int totalcon = 0, total = 0; - int mincon = 9999999, mintot = 999999; - int maxcon = 0, maxtot = 0; - - for (i = 0; i < requests; i++) { - struct data s = stats[i]; - mincon = ap_min(mincon, s.ctime); - mintot = ap_min(mintot, s.time); - maxcon = ap_max(maxcon, s.ctime); - maxtot = ap_max(maxtot, s.time); - totalcon += s.ctime; - total += s.time; - } - - printf("<tr %s><th %s colspan=4>Connnection Times (ms)</th></tr>\n", - trstring, tdstring); - printf("<tr %s><th %s> </th> <th %s>min</th> <th %s>avg</th> <th %s>max</th></tr>\n", - trstring, tdstring, tdstring, tdstring, tdstring); - printf("<tr %s><th %s>Connect:</th>" - "<td %s>%5d</td>" - "<td %s>%5d</td>" - "<td %s>%5d</td></tr>\n", - trstring, tdstring, tdstring, mincon, tdstring, totalcon / requests, tdstring, maxcon); - printf("<tr %s><th %s>Processing:</th>" - "<td %s>%5d</td>" - "<td %s>%5d</td>" - "<td %s>%5d</td></tr>\n", - trstring, tdstring, tdstring, mintot - mincon, tdstring, - (total / requests) - (totalcon / requests), tdstring, maxtot - maxcon); - printf("<tr %s><th %s>Total:</th>" - "<td %s>%5d</td>" - "<td %s>%5d</td>" - "<td %s>%5d</td></tr>\n", - trstring, tdstring, tdstring, mintot, tdstring, total / requests, tdstring, maxtot); - printf("</table>\n"); + /* work out connection times */ + int i; + int totalcon = 0, total = 0; + int mincon = 9999999, mintot = 999999; + int maxcon = 0, maxtot = 0; + + for (i = 0; i < requests; i++) { + struct data s = stats[i]; + mincon = ap_min(mincon, s.ctime); + mintot = ap_min(mintot, s.time); + maxcon = ap_max(maxcon, s.ctime); + maxtot = ap_max(maxtot, s.time); + totalcon += s.ctime; + total += s.time; + } + + printf("<tr %s><th %s colspan=4>Connnection Times (ms)</th></tr>\n", + trstring, tdstring); + printf("<tr %s><th %s> </th> <th %s>min</th> <th %s>avg</th> <th %s>max</th></tr>\n", + trstring, tdstring, tdstring, tdstring, tdstring); + printf("<tr %s><th %s>Connect:</th>" + "<td %s>%5d</td>" + "<td %s>%5d</td>" + "<td %s>%5d</td></tr>\n", + trstring, tdstring, tdstring, mincon, tdstring, totalcon / requests, tdstring, maxcon); + printf("<tr %s><th %s>Processing:</th>" + "<td %s>%5d</td>" + "<td %s>%5d</td>" + "<td %s>%5d</td></tr>\n", + trstring, tdstring, tdstring, mintot - mincon, tdstring, + (total / requests) - (totalcon / requests), tdstring, maxtot - maxcon); + printf("<tr %s><th %s>Total:</th>" + "<td %s>%5d</td>" + "<td %s>%5d</td>" + "<td %s>%5d</td></tr>\n", + trstring, tdstring, tdstring, mintot, tdstring, total / requests, tdstring, maxtot); + printf("</table>\n"); } } @@ -477,30 +478,23 @@ c->cbx = 0; c->gotheader = 0; - if ((c->aprsock = ap_create_tcp_socket()) ==NULL) + if ((c->aprsock = ap_create_tcp_socket(cntxt)) == NULL) err("Socket:"); nonblock(c->aprsock); gettimeofday(&c->start, 0); - if (ap_connect(c->aprsock, hostname, port) == APR_FAILURE){ - printf ("Connect failed.\n"); - if (errno == EINPROGRESS) { - printf ("Error - EINPROGRESS\n"); - c->state = STATE_CONNECTING; - ap_sd_set(c->aprsock, &writebits); - return; - } - else { - /*we don't have to close the socket. If we have an error this bad, - ap_connect will destroy it for us. */ - err_conn++; - if (bad++ > 10) { - err("\nTest aborted after 10 failures\n\n"); - } - start_connect(c); - } + if (ap_connect(cntxt, c->aprsock, hostname)) { + return; } - - printf ("Writing request...\n"); + else { + /*we don't have to close the socket. If we have an error this bad, + ap_connect will destroy it for us. */ + err_conn++; + if (bad++ > 10) { + err("\nTest aborted after 10 failures\n\n"); + } + start_connect(c); + } + printf("Writing request...\n"); /* connected first time */ write_request(c); } @@ -512,34 +506,31 @@ static void close_connection(struct connection *c) { if (c->read == 0 && c->keepalive) { - /* server has legitimately shut down an idle keep alive request */ - good--; /* connection never happend */ + /* server has legitimately shut down an idle keep alive request */ + good--; /* connection never happend */ } else { - if (good == 1) { - /* first time here */ - doclen = c->bread; - } - else if (c->bread != doclen) { - bad++; - err_length++; - } - - /* save out time */ - if (done < requests) { - struct data s; - gettimeofday(&c->done, 0); - s.read = c->read; - s.ctime = timedif(c->connect, c->start); - s.time = timedif(c->done, c->start); - stats[done++] = s; - } - } - - ap_sd_clr(c->aprsock, &readbits); - ap_sd_clr(c->aprsock, &writebits); - ap_close_socket(c->aprsock); + if (good == 1) { + /* first time here */ + doclen = c->bread; + } + else if (c->bread != doclen) { + bad++; + err_length++; + } + /* save out time */ + if (done < requests) { + struct data s; + gettimeofday(&c->done, 0); + s.read = c->read; + s.ctime = timedif(c->connect, c->start); + s.time = timedif(c->done, c->start); + stats[done++] = s; + } + } + ap_close_socket(cntxt, c->aprsock); + /* connect again */ start_connect(c); return; @@ -555,143 +546,143 @@ char *part; char respcode[4]; /* 3 digits and null */ - r = ap_recv(c->aprsock, buffer, sizeof(buffer),aprtimeout); + r = ap_recv(cntxt, c->aprsock, buffer, sizeof(buffer), aprtimeout); if (r == 0 || (r < 0 && errno != EAGAIN)) { - good++; - close_connection(c); - return; + good++; + close_connection(c); + return; } if (r < 0 && errno == EAGAIN) - return; + return; c->read += r; totalread += r; if (!c->gotheader) { - char *s; - int l = 4; - int space = CBUFFSIZE - c->cbx - 1; /* -1 to allow for 0 terminator */ - int tocopy = (space < r) ? space : r; + char *s; + int l = 4; + int space = CBUFFSIZE - c->cbx - 1; /* -1 to allow for 0 terminator */ + int tocopy = (space < r) ? space : r; #ifndef CHARSET_EBCDIC - memcpy(c->cbuff + c->cbx, buffer, space); + memcpy(c->cbuff + c->cbx, buffer, space); #else /*CHARSET_EBCDIC */ - ascii2ebcdic(c->cbuff + c->cbx, buffer, space); + ascii2ebcdic(c->cbuff + c->cbx, buffer, space); #endif /*CHARSET_EBCDIC */ - c->cbx += tocopy; - space -= tocopy; - c->cbuff[c->cbx] = 0; /* terminate for benefit of strstr */ - if (verbosity >= 4) { - printf("LOG: header received:\n%s\n", c->cbuff); - } - s = strstr(c->cbuff, "\r\n\r\n"); - /* this next line is so that we talk to NCSA 1.5 which blatantly breaks - the http specifaction */ - if (!s) { - s = strstr(c->cbuff, "\n\n"); - l = 2; - } - - if (!s) { - /* read rest next time */ - if (space) - return; - else { - /* header is in invalid or too big - close connection */ - ap_close_socket(c->aprsock); - if (bad++ > 10) { - err("\nTest aborted after 10 failures\n\n"); - } - ap_sd_clr(c->aprsock, &writebits); - start_connect(c); - } - } - else { - /* have full header */ - if (!good) { - /* this is first time, extract some interesting info */ - char *p, *q; - p = strstr(c->cbuff, "Server:"); - q = servername; - if (p) { - p += 8; - while (*p > 32) - *q++ = *p++; - } - *q = 0; - } - - /* XXX: this parsing isn't even remotely HTTP compliant... - * but in the interest of speed it doesn't totally have to be, - * it just needs to be extended to handle whatever servers - * folks want to test against. -djg */ - - /* check response code */ - part = strstr(c->cbuff, "HTTP"); /* really HTTP/1.x_ */ - strncpy(respcode, (part + strlen("HTTP/1.x_")), 3); - respcode[3] = '\0'; - if (respcode[0] != '2') { - err_response++; - if (verbosity >= 2) - printf("WARNING: Response code not 2xx (%s)\n", respcode); - } - else if (verbosity >= 3) { - printf("LOG: Response code = %s\n", respcode); - } - - c->gotheader = 1; - *s = 0; /* terminate at end of header */ - if (keepalive && - (strstr(c->cbuff, "Keep-Alive") - || strstr(c->cbuff, "keep-alive"))) { /* for benefit of MSIIS */ - char *cl; - cl = strstr(c->cbuff, "Content-Length:"); - /* handle NCSA, which sends Content-length: */ - if (!cl) - cl = strstr(c->cbuff, "Content-length:"); - if (cl) { - c->keepalive = 1; - c->length = atoi(cl + 16); - } - } - c->bread += c->cbx - (s + l - c->cbuff) + r - tocopy; - totalbread += c->bread; - } + c->cbx += tocopy; + space -= tocopy; + c->cbuff[c->cbx] = 0; /* terminate for benefit of strstr */ + if (verbosity >= 4) { + printf("LOG: header received:\n%s\n", c->cbuff); + } + s = strstr(c->cbuff, "\r\n\r\n"); + /* this next line is so that we talk to NCSA 1.5 which blatantly breaks + the http specifaction */ + if (!s) { + s = strstr(c->cbuff, "\n\n"); + l = 2; + } + + if (!s) { + /* read rest next time */ + if (space) { + return; + } + else { +/* header is in invalid or too big - close connection */ + ap_close_socket(cntxt, c->aprsock); + if (bad++ > 10) { + err("\nTest aborted after 10 failures\n\n"); + } + start_connect(c); + } + } + else { + /* have full header */ + if (!good) { + /* this is first time, extract some interesting info */ + char *p, *q; + p = strstr(c->cbuff, "Server:"); + q = servername; + if (p) { + p += 8; + while (*p > 32) + *q++ = *p++; + } + *q = 0; + } + + /* XXX: this parsing isn't even remotely HTTP compliant... + * but in the interest of speed it doesn't totally have to be, + * it just needs to be extended to handle whatever servers + * folks want to test against. -djg */ + + /* check response code */ + part = strstr(c->cbuff, "HTTP"); /* really HTTP/1.x_ */ + strncpy(respcode, (part + strlen("HTTP/1.x_")), 3); + respcode[3] = '\0'; + if (respcode[0] != '2') { + err_response++; + if (verbosity >= 2) + printf("WARNING: Response code not 2xx (%s)\n", respcode); + } + else if (verbosity >= 3) { + printf("LOG: Response code = %s\n", respcode); + } + + c->gotheader = 1; + *s = 0; /* terminate at end of header */ + if (keepalive && + (strstr(c->cbuff, "Keep-Alive") + || strstr(c->cbuff, "keep-alive"))) { /* for benefit of MSIIS */ + char *cl; + cl = strstr(c->cbuff, "Content-Length:"); + /* handle NCSA, which sends Content-length: */ + if (!cl) + cl = strstr(c->cbuff, "Content-length:"); + if (cl) { + c->keepalive = 1; + c->length = atoi(cl + 16); + } + } + c->bread += c->cbx - (s + l - c->cbuff) + r - tocopy; + totalbread += c->bread; + } } else { - /* outside header, everything we have read is entity body */ - c->bread += r; - totalbread += r; + /* outside header, everything we have read is entity body */ + c->bread += r; + totalbread += r; } if (c->keepalive && (c->bread >= c->length)) { - /* finished a keep-alive connection */ - good++; - doneka++; - /* save out time */ - if (good == 1) { - /* first time here */ - doclen = c->bread; - } - else if (c->bread != doclen) { - bad++; - err_length++; - } - if (done < requests) { - struct data s; - gettimeofday(&c->done, 0); - s.read = c->read; - s.ctime = timedif(c->connect, c->start); - s.time = timedif(c->done, c->start); - stats[done++] = s; - } - c->keepalive = 0; - c->length = 0; - c->gotheader = 0; - c->cbx = 0; - c->read = c->bread = 0; - write_request(c); - c->start = c->connect; /* zero connect time with keep-alive */ + /* finished a keep-alive connection */ + good++; + doneka++; + /* save out time */ + if (good == 1) { + /* first time here */ + doclen = c->bread; + } + else if (c->bread != doclen) { + bad++; + err_length++; + } + if (done < requests) { + struct data s; + gettimeofday(&c->done, 0); + s.read = c->read; + s.ctime = timedif(c->connect, c->start); + s.time = timedif(c->done, c->start); + stats[done++] = s; + } + c->keepalive = 0; + c->length = 0; + c->gotheader = 0; + c->cbx = 0; + c->read = c->bread = 0; + write_request(c); + c->start = c->connect; /* zero connect time with keep-alive */ } } @@ -702,53 +693,51 @@ static void test(void) { struct timeval timeout, now; - ap_sd_set_t sel_read, sel_except, sel_write; - + int i; if (!use_html) { - printf("Benchmarking %s (be patient)...", hostname); - fflush(stdout); + printf("Benchmarking %s (be patient)...", hostname); + fflush(stdout); } con = malloc(concurrency * sizeof(struct connection)); memset(con, 0, concurrency * sizeof(struct connection)); stats = malloc(requests * sizeof(struct data)); - ap_sd_zero(&readbits); - ap_sd_zero(&writebits); + readbits = ap_setup_poll(cntxt, concurrency); /* setup request */ if (!posting) { - sprintf(request, "GET %s HTTP/1.0\r\n" - "User-Agent: ApacheBench/%s\r\n" - "%s" - "Host: %s\r\n" - "Accept: */*\r\n" - "\r\n", - path, - VERSION, - keepalive ? "Connection: Keep-Alive\r\n" : "", - hostname); + sprintf(request, "GET %s HTTP/1.0\r\n" + "User-Agent: ApacheBench/%s\r\n" + "%s" + "Host: %s\r\n" + "Accept: */*\r\n" + "\r\n", + path, + VERSION, + keepalive ? "Connection: Keep-Alive\r\n" : "", + hostname); } else { - sprintf(request, "POST %s HTTP/1.0\r\n" - "User-Agent: ApacheBench/%s\r\n" - "%s" - "Host: %s\r\n" - "Accept: */*\r\n" - "Content-length: %d\r\n" - "Content-type: %s\r\n" - "\r\n", - path, - VERSION, - keepalive ? "Connection: Keep-Alive\r\n" : "", - hostname, postlen, - (content_type[0]) ? content_type : "text/plain"); + sprintf(request, "POST %s HTTP/1.0\r\n" + "User-Agent: ApacheBench/%s\r\n" + "%s" + "Host: %s\r\n" + "Accept: */*\r\n" + "Content-length: %d\r\n" + "Content-type: %s\r\n" + "\r\n", + path, + VERSION, + keepalive ? "Connection: Keep-Alive\r\n" : "", + hostname, postlen, + (content_type[0]) ? content_type : "text/plain"); } if (verbosity >= 2) - printf("INFO: POST header == \n---\n%s\n---\n", request); + printf("INFO: POST header == \n---\n%s\n---\n", request); reqlen = strlen(request); @@ -761,50 +750,46 @@ /* initialise lots of requests */ for (i = 0; i < concurrency; i++) - start_connect(&con[i]); + start_connect(&con[i]); while (done < requests) { - ap_int32_t n; - /* setup bit arrays */ - memcpy(&sel_except, &readbits, sizeof(readbits)); - memcpy(&sel_read, &readbits, sizeof(readbits)); - memcpy(&sel_write, &writebits, sizeof(readbits)); - - /* check for time limit expiry */ - gettimeofday(&now, 0); - if (tlimit && timedif(now, start) > (tlimit * 1000)) { - requests = done; /* so stats are correct */ - } - /* Timeout of 30 seconds. */ - timeout.tv_sec = 30; - timeout.tv_usec = 0; - - n = ap_select(FD_SETSIZE, &sel_read, &sel_write, &sel_except, &timeout); - - if (!n) { - err("\nServer timed out\n\n"); - } - if (n < 1) - err("select"); - - for (i = 0; i < concurrency; i++) { - ap_socket_t *s = con[i].aprsock; - if (ap_sd_isset(s,&sel_except) == APR_SUCCESS){ - bad++; - err_except++; - start_connect(&con[i]); - continue; - } - if (ap_sd_isset(s,&sel_read) == APR_SUCCESS) - read_connection(&con[i]); - if (ap_sd_isset(s, &sel_write) == APR_SUCCESS) - write_request(&con[i]); - } + ap_int32_t n; + + /* check for time limit expiry */ + gettimeofday(&now, 0); + if (tlimit && timedif(now, start) > (tlimit * 1000)) { + requests = done; /* so stats are correct */ + } + /* Timeout of 30 seconds. */ + timeout.tv_sec = 30; + timeout.tv_usec = 0; + + n = ap_poll(cntxt, readbits, concurrency, &timeout); + + if (!n) { + err("\nServer timed out\n\n"); + } + if (n < 1) + err("select"); + + for (i = 0; i < concurrency; i++) { + ap_pollfd_t *s = readbits[con[i].socknum]; + if ( == APR_SUCCESS) { + bad++; + err_except++; + start_connect(&con[i]); + continue; + } + if (ap_sd_isset(s, &sel_read) == APR_SUCCESS) + read_connection(&con[i]); + if (ap_sd_isset(s, &sel_write) == APR_SUCCESS) + write_request(&con[i]); + } } if (use_html) - output_html_results(); + output_html_results(); else - output_results(); + output_results(); } /* ------------------------------------------------------- */ @@ -813,17 +798,17 @@ static void copyright(void) { if (!use_html) { - printf("This is ApacheBench, Version %s\n", VERSION); - printf("Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/\n"); - printf("Copyright (c) 1998-1999 The Apache Group, http://www.apache.org/\n"); - printf("\n"); + printf("This is ApacheBench, Version %s\n", VERSION); + printf("Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/\n"); + printf("Copyright (c) 1998-1999 The Apache Group, http://www.apache.org/\n"); + printf("\n"); } else { - printf("<p>\n"); - printf(" This is ApacheBench, Version %s<br>\n", VERSION); - printf(" Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/<br>\n"); - printf(" Copyright (c) 1998-1999 The Apache Group, http://www.apache.org/<br>\n"); - printf("</p>\n<p>\n"); + printf("<p>\n"); + printf(" This is ApacheBench, Version %s<br>\n", VERSION); + printf(" Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/<br>\n"); + printf(" Copyright (c) 1998-1999 The Apache Group, http://www.apache.org/<br>\n"); + printf("</p>\n<p>\n"); } } @@ -859,20 +844,20 @@ char *p = NULL; if (strlen(url) > 7 && strncmp(url, "http://", 7) == 0) - url += 7; + url += 7; h = url; if ((cp = strchr(url, ':')) != NULL) { - *cp++ = '\0'; - p = cp; - url = cp; + *cp++ = '\0'; + p = cp; + url = cp; } if ((cp = strchr(url, '/')) == NULL) - return 1; + return 1; strcpy(path, cp); *cp = '\0'; strcpy(hostname, h); if (p != NULL) - port = atoi(p); + port = atoi(p); return 0; } @@ -886,21 +871,21 @@ struct stat postfilestat; if ((postfd = open(pfile, O_RDONLY)) == -1) { - printf("Invalid postfile name (%s)\n", pfile); - return errno; + printf("Invalid postfile name (%s)\n", pfile); + return errno; } if ((status = fstat(postfd, &postfilestat)) == -1) { - perror("Can\'t stat postfile\n"); - return status; + perror("Can\'t stat postfile\n"); + return status; } postdata = malloc(postfilestat.st_size); if (!postdata) { - printf("Can\'t alloc postfile buffer\n"); - return ENOMEM; + printf("Can\'t alloc postfile buffer\n"); + return ENOMEM; } if (read(postfd, postdata, postfilestat.st_size) != postfilestat.st_size) { - printf("error reading postfilen"); - return EIO; + printf("error reading postfilen"); + return EIO; } postlen = postfilestat.st_size; return 0; @@ -923,74 +908,74 @@ optind = 1; while ((c = getopt(argc, argv, "n:c:t:T:p:v:kVhwx:y:z:")) > 0) { - switch (c) { - case 'n': - requests = atoi(optarg); - if (!requests) { - err("Invalid number of requests\n"); - } - break; - case 'k': - keepalive = 1; - break; - case 'c': - concurrency = atoi(optarg); - break; - case 'p': - if (0 == (r = open_postfile(optarg))) { - posting = 1; - } - else if (postdata) { - exit(r); - } - break; - case 'v': - verbosity = atoi(optarg); - break; - case 't': - tlimit = atoi(optarg); - requests = MAX_REQUESTS; /* need to size data array on something */ - break; - case 'T': - strcpy(content_type, optarg); - break; - case 'V': - copyright(); - exit(0); - break; - case 'w': - use_html = 1; - break; - /* if any of the following three are used, turn on html output automatically */ - case 'x': - use_html = 1; - tablestring = optarg; - break; - case 'y': - use_html = 1; - trstring = optarg; - break; - case 'z': - use_html = 1; - tdstring = optarg; - break; - case 'h': - usage(argv[0]); - break; - default: - fprintf(stderr, "%s: invalid option `%c'\n", argv[0], c); - usage(argv[0]); - break; - } + switch (c) { + case 'n': + requests = atoi(optarg); + if (!requests) { + err("Invalid number of requests\n"); + } + break; + case 'k': + keepalive = 1; + break; + case 'c': + concurrency = atoi(optarg); + break; + case 'p': + if (0 == (r = open_postfile(optarg))) { + posting = 1; + } + else if (postdata) { + exit(r); + } + break; + case 'v': + verbosity = atoi(optarg); + break; + case 't': + tlimit = atoi(optarg); + requests = MAX_REQUESTS; /* need to size data array on something */ + break; + case 'T': + strcpy(content_type, optarg); + break; + case 'V': + copyright(); + exit(0); + break; + case 'w': + use_html = 1; + break; + /* if any of the following three are used, turn on html output automatically */ + case 'x': + use_html = 1; + tablestring = optarg; + break; + case 'y': + use_html = 1; + trstring = optarg; + break; + case 'z': + use_html = 1; + tdstring = optarg; + break; + case 'h': + usage(argv[0]); + break; + default: + fprintf(stderr, "%s: invalid option `%c'\n", argv[0], c); + usage(argv[0]); + break; + } } if (optind != argc - 1) { - fprintf(stderr, "%s: wrong number of arguments\n", argv[0]); - usage(argv[0]); + fprintf(stderr, "%s: wrong number of arguments\n", argv[0]); + usage(argv[0]); } if (parse_url(argv[optind++])) { - fprintf(stderr, "%s: invalid URL\n", argv[0]); - usage(argv[0]); + fprintf(stderr, "%s: invalid URL\n", argv[0]); + usage(argv[0]); } copyright();