diff options
Diffstat (limited to 'apps/JAWS/clients/WebSTONE/src/webmaster.c')
-rw-r--r-- | apps/JAWS/clients/WebSTONE/src/webmaster.c | 1417 |
1 files changed, 0 insertions, 1417 deletions
diff --git a/apps/JAWS/clients/WebSTONE/src/webmaster.c b/apps/JAWS/clients/WebSTONE/src/webmaster.c deleted file mode 100644 index f98e073a10a..00000000000 --- a/apps/JAWS/clients/WebSTONE/src/webmaster.c +++ /dev/null @@ -1,1417 +0,0 @@ -/************************************************************************** -$Header$ - * * - * Copyright (C) 1995 Silicon Graphics, Inc. * - * * - * These coded instructions, statements, and computer programs were * - * developed by SGI for public use. If any changes are made to this code* - * please try to get the changes back to the author. Feel free to make * - * modifications and changes to the code and release it. * - * * - **************************************************************************/ - -#include <stdio.h> -#include <errno.h> -#include <signal.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> - -#ifndef WIN32 -#include <unistd.h> -#endif /* WIN32 */ - -#include <math.h> - -#ifndef WIN32 -#include <sys/param.h> -#include <sys/types.h> -#include <sys/errno.h> -#include <sys/socket.h> -#include <sys/time.h> -#include <netinet/in.h> -#include <netdb.h> -#else -#define FD_SETSIZE 1024 /* max size for select() - keep before <winsock.h> - * and same size as MAXCLIENTS */ -#include <windows.h> -#include <winsock.h> -#include <io.h> -#include <process.h> -#endif /* WIN32 */ - -#include "sysdep.h" -#include "bench.h" - -/* command line options/data */ -int savefile = 0; -int debug = 0; -int norexec = 0; -int haveproxyserver = 0; -char proxyserver[MAXHOSTNAMELEN]; -char network_mask_str[30] = "255.255.255.0"; -unsigned network_mask = 0; -int servaddrin_config = 0; -int dumpall = 0; -int testtime = 0; -int havewebserver = 0; -int numloops = 0; -NETPORT portnum = 0; -int redirect = 0; -int record_all_transactions = 0; -int uil_filelist_f = 0; -int verbose = 0; -char webserver[MAXHOSTNAMELEN]; -char configfile[MAXPATHLEN]; -char uil_filelist[NCCARGS]; - -char filelist[256][MAXPATHLEN]; -fd_set zerofdset; - -/* other key data */ -long int number_of_pages = 0; -int totalnumclients = 0; -int num_rexecs = 0; -SOCKET socknum[MAXCLIENTS]; -SOCKET sockIO[MAXTOTALPROCS]; -SOCKET sockErr[MAXTOTALPROCS]; -THREAD FILE *debugfile = stderr; -struct hostent *master_phe; /* IP addresses for webmaster */ -struct timeval sumedh_start, sumedh_end; - -void HostEntCpy(struct hostent *dest, struct hostent *src); - -static void -usage(const char *progname) -{ - - fprintf(stderr, "Usage: %s [-a] [-d] -f config_file [-l numloops]\n", - progname); - fprintf(stderr, " [-p port_num] [-r] [-s] [-t run_time] \n"); - fprintf(stderr, "\n"); - fprintf(stderr, "-w webserver URL [URL ...]\n\n"); - fprintf(stderr, "-a print timing information for all clients\n"); - fprintf(stderr, "-d turn on debug statements\n"); - fprintf(stderr, "-f config_file\tfile specifying clients\n"); - fprintf(stderr, "-l number of iterations to retrieve uils\n"); - fprintf(stderr, "-p port number of web server if not 80\n"); - fprintf(stderr, "-r redirect stdout of clients to /tmp/webstone.xxx\n"); - fprintf(stderr, "-s save client gets to /tmp/webstone.data.*\n"); - fprintf(stderr, "-t run_time\tduration of test in minutes\n"); - fprintf(stderr, "-w webserver\tname of webserver host to contact\n"); - fprintf(stderr, "-u URL file\tfilelist of URLs\n"); - fprintf(stderr, "-v verbose mode\n"); - fprintf(stderr, "-P servername\tuse proxy server for transactions\n"); - fprintf(stderr, "-W webserver addresses are in the config file\n"); - fprintf(stderr, "-R record all transactions\n"); - errexit("\n"); -} - -static SOCKET -passivesock(const NETPORT portnum, const char *protocol, const int qlen) -{ - struct protoent *ppe; /* pointer to protocol info entry */ - struct sockaddr_in sin; /* Internet endpoint address */ - SOCKET s; /* socket descriptor */ - int type; /* socket type */ - - D_PRINTF( "Beginning passivesock with errno %d\n",errno ); - - D_PRINTF( "Zeroing address structure\n" ); - memset((char *)&sin, 0, sizeof(sin)); - - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = INADDR_ANY; - - /* NOT USED: Map service name to portnumber */ - D_PRINTF( "Mapping portnum errno %d\n",errno ); - sin.sin_port = htons(portnum); - - /* Map protocol name to number */ - D_PRINTF( "Mapping protocol name errno %d\n",errno ); - if ((ppe = getprotobyname(protocol)) == 0) - { - errexit("Can't get \"%s\" protocol entry\n", protocol); - } - errno = 0; - - /* use protocol to choose socket type */ - D_PRINTF( "Changing socket type, errno %d\n",errno ); - if (strcmp(protocol, "udp") == 0) - { - type = SOCK_DGRAM; - D_PRINTF( "Choosing SOCK_DGRAM\n" ); - } - else - { - type = SOCK_STREAM; - D_PRINTF( "Choosing SOCK_STREAM, errno %d\n",errno ); - } - - /* allocate a socket */ - s = socket(PF_INET, type, ppe->p_proto); - if (BADSOCKET(s)) - { - D_PRINTF( "Socket PF_INET %d %d returned %d with %s\n", - type, ppe->p_proto, s, neterrstr() ); - errexit("Can't create socket: %s\n", neterrstr()); - } - D_PRINTF( "Socket %d created with errno %d\n",s,errno ); - - /* Bind the socket */ - if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) - { - errexit("Can't bind to port %d: %s\n", portnum, neterrstr()); - } - D_PRINTF( "Bind succeeded\n" ); - - /* If it's a stream, listen for connections */ - /* NOTE: ON NT, the listen() backlog parm is silently limited to 5 conns */ - if ((type == SOCK_STREAM) && BADSOCKET(listen(s, qlen))) - { - errexit("Can't listen on port %s: %s\n", portnum, neterrstr()); - } - D_PRINTF( "Listen succeeded\n" ); - - /* all done, return socket descriptor */ - return(s); -} - - -/* abort clients -- called by SIGINT handler */ -static void abort_clients(void) -{ - /* Not supposed to have fprintf in a signal handler, but... */ - fprintf(stdout, "Webmaster received SIGINT. Terminating.\n"); - /* exit will close all open connections */ - exit(2); -} - -/* signal handler for SIGINT */ -static void sig_int(int sig) { - - abort_clients(); -} - -#ifdef WIN32 - -/* echo stdout/stderr from clients */ -void echo_client(void *stream) -{ - SOCKET *sockarr; - FILE *outfile; - int which_stream = (int) stream; - char buf[BUFSIZ]; - int i, len, rv; - fd_set readfds; - - /* This code which handles the timeout may need - to be ifdef'ed for WIN32 */ - struct timeval timeout; - - timeout.tv_sec = (long)5; - timeout.tv_usec = (long)0; - - if (which_stream) { - sockarr = sockIO; - outfile = stdout; - } else { - sockarr = sockErr; - outfile = stderr; - } - - D_PRINTF( "echo_client running\n" ); - signal( SIGINT, SIG_DFL); /* restore default behavior - for SIGINT */ - - while (1) { - FD_ZERO(&readfds); - for (i = 0; i < num_rexecs; i++) - if (sockarr[i] != BADSOCKET_VALUE) - FD_SET(sockarr[i], &readfds); - rv = select(num_rexecs, &readfds, NULL, NULL, &timeout); - if ( rv == 0) - continue; - if (rv < 0 && WSAGetLastError() == WSANOTINITIALISED) - return; - if (rv < 0) - errexit("Error in echo_client(): select() returns %d: %s\n", rv, neterrstr()); - - /* loop over the sockets that are ready with data */ - for (i = 0; i < num_rexecs; i++) { - if (sockarr[i] != BADSOCKET_VALUE && FD_ISSET(sockarr[i], &readfds)) { - len = NETREAD(sockarr[i], buf, sizeof(buf)); - if (len <= 0) { - /* mark connection closed */ - sockarr[i] = BADSOCKET_VALUE; - if (len < 0 && WSAGetLastError() == WSANOTINITIALISED) - return; - if (len < 0) - fprintf(stderr, "Error in echo_client() after NETREAD(): %s\n", neterrstr()); - continue; - } - - /* copy to stdout or stderr */ - fwrite(buf, sizeof(char), len, outfile); - } - } - } - D_PRINTF( "Exiting echo_client\n" ); -} - -#else -static int -echo_client(char *hostname, const int fd) -{ - /* - * WRITE TEXT FROM FILE DESCRIPTOR INTO STDOUT - */ - char buf[BUFSIZ]; - int cc; - D_PRINTF( "echo_client running\n" ); - - while (getppid() != 1) - { - cc = NETREAD(fd, buf, sizeof(buf)); - if (cc > 0) - { - write(STDOUT_FILENO, buf, cc); - } - } - D_PRINTF( "Exiting echo_client\n" ); - NETCLOSE(fd); -} -#endif /* WIN32 */ - -/* Picks the appropriate webmaster IP address based on the address of the client. - * This is significant only for hosts with multiple interfaces - * - * return value is a string with the IP address or hostname (or NULL) - */ -char *pick_webmaster_IP_address(char *client_hostname, struct hostent *master_phe, - unsigned netmask) { -static char buf[20]; -unsigned char addr[4]; -int client_addr; -int i; - - if (client_hostname[0] >= '0' && client_hostname[0] <= '9') { - /* we have an IP address */ - client_addr = inet_addr(client_hostname); - if (client_addr == INADDR_NONE) - return NULL; - } else { - /* we have a hostname, use the webserver hostname */ - return master_phe->h_name; - } - - for (i = 0; master_phe->h_addr_list[i] != NULL; i++) { - if ((*(int *)(master_phe->h_addr_list[i]) & netmask) == - (client_addr & netmask)) - goto gotit; - } - i = 0; /* give up */ - -gotit: - memcpy((char *)addr, master_phe->h_addr_list[i], sizeof(addr)); /* Internet specific */ - sprintf(buf, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]); - return buf; -} - -/* - Command line parsing -*/ - -void ParseCmdLine(int argc, char **argv ) -{ -char getoptch; -int currarg; -extern char *optarg; -extern int optind; - - /* - * PARSE THE COMMAND LINE OPTIONS - */ - while((getoptch = getopt(argc,argv,"P:f:t:l:p:u:R:w:n:M:adrsvWX")) != (const char)EOF) - { - switch(getoptch) - { - case 'M': - strcpy(network_mask_str, optarg); - break; - case 'P': - haveproxyserver = 1; - strcpy(proxyserver, optarg); - break; - case 'R': - record_all_transactions = 1; - break; - case 'X': - norexec = 1; - break; - case 'W': - servaddrin_config = 1; - break; - case 'a': - dumpall = 1; - break; - case 'd': - debug = 1; - break; - case 'f': - strcpy(configfile, optarg); - break; - case 'l': - numloops = atoi(optarg); - break; - case 'p': - portnum = atoi(optarg); - break; - case 'r': - redirect = 1; - break; - case 's': - savefile = 1; - break; - case 't': - testtime = atoi(optarg); - break; - case 'u': - uil_filelist_f = 1; - strcpy(uil_filelist, optarg); - break; - case 'v': - verbose = 1; - break; - case 'w': - havewebserver = 1; - strcpy(webserver, optarg); - break; - default: - usage(argv[0]); - } /* end switch */ - } /* end while */ - - if (numloops && testtime) - errexit("Can't have both -l and -t\n"); - - if(!havewebserver && !servaddrin_config) - { - /* - * THE SERVERS NAME MUST BE SPECIFIED - */ - - fprintf(stderr,"No WWW Server specified\n"); - usage(argv[0]); - } - - if (havewebserver && servaddrin_config) - { - /* - * CAN'T HAVE BOTH -w and -W - */ - fprintf(stderr, "Can't have both -w and -W options\n"); - usage(argv[0]); - } - - network_mask = inet_addr(network_mask_str); - if (network_mask == INADDR_NONE) { - fprintf(stderr, "Invalid network mask (-M %s)\n", network_mask_str); - usage(argv[0]); - } - - if(strlen(configfile) == 0) - { - /* - * THE MASTER MUST HAVE A CONFIGURATION FILE TO READ. - */ - fprintf(stderr,"No Configuration file specified\n"); - usage(argv[0]); - } - /* IF WE DO NOT HAVE A FILE LIST THEN THERE ARE UIL'S AT THE END OF THE - * COMMAND LINE SO GRAB THEM. - */ - if (uil_filelist_f == 0) - { - currarg = optind; - number_of_pages = 0; - while(currarg != argc) - { - /* - * GET THE UILS TO RETRIEVE. - */ - - sscanf(argv[currarg],"%s",filelist[number_of_pages]); - number_of_pages++; - currarg++; - } - } - else - { - /* have filelist; take a stab at the number of valid URLs */ - D_PRINTF( "About to parse filelist %s\n", uil_filelist ); - number_of_pages = count_file_list(uil_filelist); - } - if (number_of_pages == 0) - { - /* - * AT LEAST ONE FILE MUST BE SPECIFIED - */ - fprintf(stderr,"No URL resources specified\n"); - usage(argv[0]); - } -} - -/* - This function sets up the socket we will use to synchronize with the - clients. - Returns the socket number if successful, doesn't return if it fails -*/ - -SOCKET SetupSyncSocket( serveraddr ) -struct sockaddr_in *serveraddr; -{ - int sock,len; - - /* - * SET UP THE SOCKET WE ARE GOING TO USE TO SYNCHRONIZE WITH THE CLIENTS. - */ - D_PRINTF( "About to call sock %d %d\n", portnum, MAXCLIENTS ); - - sock = passivesock(0, "tcp", MAXCLIENTS); - - if (BADSOCKET(sock)) - { - errexit("Couldn't open socket %d: %s\n", sock, neterrstr()); - } - D_PRINTF( "The passivesock call succeeded\n" ); - - D_PRINTF( "calling getsockname\n" ); - - len = sizeof(struct sockaddr); - if(getsockname(sock, (struct sockaddr *)serveraddr, &len) < 0) - { - errexit("Could not get socket informaton\n"); - } - - return( sock ); -} - -/* - Function which generates a commandline for the webclients -*/ -void MakeCmdLine( commandline) -char *commandline; -{ - char tmpcommandline[NCCARGS]; - char hostname[MAXHOSTNAMELEN]; - char *webclient_path, *temp; - int cnt; - struct hostent *master_phe_tmp; /* temp. variable added by - Rajesh Shah*/ - - /* - * BUILD THE PORTIONS OF THE cmdline FOR EACH CLIENT THAT WE CAN BUILD NOW. - * WE WILL FILL IN THE NUMBER OF CLIENTS LATER WITH AN sprintf. - */ - D_PRINTF( "Calling gethostname\n" ); - - if(gethostname(hostname,MAXHOSTNAMELEN) != 0) - { - errexit("Could not retrieve local host name"); - } else { - /* convert hostname to address (to avoid DNS problems for webclients) */ - /* The following lines are add to copy the system - buffer (output of gethostbyname()) into user area. - This is because, there are very good chances that later - on system buffer might be overwritten by some calls and - still if your pointer is pointing to same addr. nothing - but only trouble and trouble! Infact this is what - happening when I tried to run webstone benchmark for more - then one clients. It used to over write the webmaster name - with the first client name and so remaining on client(s) - the webclient process(es) were invoked with wrong webmaster - name! This behaviour is observed Solaris 2.4 this bug - can be hit in any OS. - Rajesh Shah 5/18/96 */ - - /* master_phe = gethostbyname(hostname); */ - master_phe_tmp = gethostbyname(hostname); - master_phe = (struct hostent *)malloc(sizeof(struct hostent)); - HostEntCpy(master_phe, master_phe_tmp); - } - - /* set up executable pathname */ -#ifndef WIN32 - temp = getenv("TMPDIR"); - - if ( temp && *temp ) { - webclient_path = (char *)mymalloc( strlen(temp) + strlen("/webclient") - + 1); - strcpy(webclient_path, temp); - strcat(webclient_path, "/webclient"); - - } else -#else - temp = temp; -#endif /* WIN32 */ - webclient_path = PROGPATH; - - - D_PRINTF( "Path to webclient is: %s\n", webclient_path ); - - sprintf(commandline,"%s", webclient_path); - - if(haveproxyserver) - { - sprintf(tmpcommandline, " -P %s", proxyserver); - strcat(commandline, tmpcommandline); - } - if (debug) - { - strcat(commandline," -d"); - } - if (numloops != 0) - { - sprintf(tmpcommandline," -l %d", numloops); - strcat(commandline,tmpcommandline); - } - if (portnum) - { - sprintf(tmpcommandline," -p %d", portnum); - strcat(commandline,tmpcommandline); - } - if (redirect) - { - strcat(commandline," -r"); - } - if (savefile) - { - strcat(commandline," -s"); - } - if (uil_filelist_f) - { - strcat(commandline," -u "); - strcat(commandline,uil_filelist); - } - if (record_all_transactions) - { - strcat(commandline," -R"); - } - if (testtime != 0) - { - sprintf(tmpcommandline," -t %d", testtime); - strcat(commandline,tmpcommandline); - } - - /* - * SET UP A SPACE FOR THE NUMBER OF CLIENTS ON THE commandline. - */ - sprintf(tmpcommandline,"%s -n %%d -w %%s -c %%s:%%d", commandline); - strcpy(commandline,tmpcommandline); - - if (uil_filelist_f == 0) - { - cnt = 0; - while(cnt < number_of_pages) - { - /* - * PUT THE FILES AT THE END OF THE LIST. - */ - strcat(commandline," "); - strcat(commandline,filelist[cnt]); - cnt++; - } - } - puts(commandline); -} - -/* - rexec to the client hosts and start the webclients -*/ -int RexecClients( commandline, clienthostname, serveraddr) -char *commandline; -char clienthostname[MAXCLIENTS][MAXHOSTNAMELEN]; -struct sockaddr_in *serveraddr; - -{ - int tmpfd; - int numclients = 0; - char tmpcommandline[NCCARGS]; - struct servent *inetport; - int cnt; - char buffer[NCCARGS]; - char login[MAXUSERNAME]; - char password[MAXPASSWD]; - FILE *fp; - int returnval; - char *tmphostname; - - memset(buffer, 0, sizeof(buffer)); - - /* - * OPEN UP THE CONFIG FILE. FOR EACH LINE IN THE CONFIG FILE, CHECK - * ITS VALIDITY AND THEN rexec A COMMAND ON THE CLIENT. - */ - - if ((fp = fopen(configfile,"r")) == NULL) - { - errexit("Could not open config file %s\n", configfile); - } - - if ((inetport = getservbyname("exec","tcp")) == NULL) - { - errexit("Could not get service name for exec/tcp\n"); - } - D_PRINTF( "getservbyname returned %d\n", ntohs(inetport->s_port) ); - - cnt = 0; - - D_PRINTF( "rexec loop\n" ); - while(1) - { - char webserver2[MAXHOSTNAMELEN]; - char linebuf[150]; - int num; - char *primename; - - if (NULL == fgets(linebuf, sizeof(linebuf), fp)) - break; - num = sscanf(linebuf,"%s %s %s %d %s",clienthostname[cnt],login,password, - &numclients, webserver2); - if (num < 4) - break; - if (servaddrin_config) { - if (num == 4) { - errexit("No webserver specified in config file for %s\n", clienthostname[cnt]); - } - strcpy(webserver, webserver2); - } - - if (numclients <= 0) - errexit("Number of clients must be >= 0\n"); - if (numclients > MAXPROCSPERNODE) - { - errexit("Number of clients per node can't exceed %d\n", MAXPROCSPERNODE); - } - totalnumclients += numclients; - - primename = pick_webmaster_IP_address(clienthostname[cnt], master_phe, network_mask); - if (primename == NULL) { - errexit("Bad client address %s for Client %d\n", clienthostname[cnt], cnt); - } - - fprintf(stdout,"Client %d: %s \t# Processes: %d\n Webserver: %s\tWebmaster: %s:%d\n", - cnt, clienthostname[cnt], numclients, webserver, primename, - ntohs(serveraddr->sin_port)); - fflush(stdout); - sprintf(tmpcommandline, commandline, numclients, webserver, primename, - ntohs(serveraddr->sin_port)); - - fprintf(stderr, "tmpcommandline: %s\n", tmpcommandline); - - D_PRINTF( "%s rexec %s\n",&clienthostname[cnt],tmpcommandline ); - if (norexec) { - sleep(30); /* gives some time to start clients for debugging */ - } else { - - tmphostname = &(clienthostname[cnt][0]); - tmpfd = rexec(&tmphostname, inetport->s_port, login, password, - tmpcommandline, &sockErr[cnt]); - if((sockIO[cnt] = tmpfd) < 0) - { - errexit("Could not rexec: rexec to client %s, cmdline %s failed\n", - clienthostname[cnt],tmpcommandline); - } - } - - - returnval = NETREAD(tmpfd, buffer, OKSTRLEN); - D_PRINTF( "read returns %d, %s\n", returnval, buffer ); - - if (returnval <= 0 || memcmp(buffer, OKSTR, OKSTRLEN) != 0) - { - errexit("rexec to client %s, cmdline %s received error %s\n", - clienthostname[cnt],tmpcommandline, buffer); - } - - - cnt++; - if (cnt > MAXCLIENTS || cnt > FD_SETSIZE) - { - errexit("Number of Clients can't exceed %d\n", MAXCLIENTS); - } - } - - num_rexecs = cnt; - if (totalnumclients > MAXTOTALPROCS) - { - errexit("Total number of processes can't exceed %d\n", - MAXTOTALPROCS); - } - -#ifndef WIN32 - /* NOW WE NEED TO HANDLE THE OUTPUT FROM THE REXEC. - * TO DO THIS, WE FORK, THEN HAVE ONE PROCESS READ FROM TMPFD. - * THE OTHER PROCESS CONTINUES WITH THE PROGRAM - */ - D_PRINTF( "Forking webclient stderr/stdout processes\n" ); - switch (fork()) - { - case -1: /* ERROR */ - errexit("fork: %s\n", strerror(errno)); - case 0: /* CHILD */ - exit(echo_client(clienthostname[cnt], tmpfd)); - default: /* PARENT */ - break; - } -#else - /* start threads to echo stdout/stderr from clients */ - _beginthread(echo_client, 0, (void *)0); - _beginthread(echo_client, 0, (void *)1); -#endif /* WIN32 */ - - fprintf(stdout,"\n"); - fprintf(stdout,"\n"); - fclose(fp); - - return totalnumclients; -} - -void GetReady( fdset, totalnumclients, sock ) -fd_set *fdset; -int totalnumclients; -int sock; -{ - int cnt,len; - fd_set tmpfdset, leftfdset; - char buffer[NCCARGS]; - - /* - * NOW WE NEED TO ACCEPT ALL THE CONNECTIONS FROM THE CLIENTS, - * ACCEPT ALL THE READY MESSAGES - */ - - D_PRINTF( "Beginning accept loop\n" ); - for (cnt = 0; cnt < totalnumclients; cnt++) - { - D_PRINTF( "Client %d:\t", cnt ); - - { - fd_set readfds; - struct timeval timeout; - int rv; - - timeout.tv_sec = MAX_ACCEPT_SECS; - timeout.tv_usec = 0; - FD_ZERO(&readfds); - FD_SET(sock, &readfds); - - /* if we're hung, quit */ - D_PRINTF("Before select() on listen() socket\n"); - if (!(rv = select(FD_SETSIZE, &readfds, NULL, NULL, &timeout))) { - fprintf(stdout, - "Listen timeout after %d seconds (%d clients so far)\n", - MAX_ACCEPT_SECS, cnt); - D_PRINTF("select() timed out after %d seconds\n", MAX_ACCEPT_SECS); - errexit("Webmaster terminating\n"); - } - } - - if(BADSOCKET(socknum[cnt] = accept(sock, NULL, 0))) - { - /* - * ERROR accepting FROM THE CLIENTS. WE NEED TO ISSUE AN - * ABORT TO ALL. - */ - abort_clients(); - errexit("Error accepting from one of the clients: %s", neterrstr()); - } else - { - /* - * SET THE FD IN THE MASK - */ - FD_SET(socknum[cnt],fdset); - } - D_PRINTF( "on socket %d\n",socknum[cnt] ); - } - D_PRINTF( "\n" ); - - /* - * WAIT FOR A READY. - */ - sleep(1); - fprintf(stdout,"Waiting for READY from %d clients\n",totalnumclients); - fflush(stdout); - leftfdset = *fdset; -#ifndef WIN32 - while(memcmp(&leftfdset,&zerofdset,sizeof(fd_set))) - { - tmpfdset = leftfdset; - - if(select(FD_SETSIZE,&tmpfdset,NULL,NULL,NULL) < 0) - { - /* - * ERROR SELECTING. ABORT ALL. - */ - abort_clients(); - errexit("Error accepting from one of the clients: %s\n", - neterrstr()); - break; - } -#else - /* I don't see why a select is needed at all--all clients must respond - * and there is no synchronization/timing issue. - */ - tmpfdset = leftfdset; - { -#endif /* WIN32 */ - - for (cnt = 0; cnt < totalnumclients; cnt++) - { - /* - * SEE WHICH SOCKETS HAVE A INPUT ON THEM PENDING - * AND RECEIVE IT. - */ - if(!BADSOCKET(socknum[cnt]) && (FD_ISSET(socknum[cnt],&tmpfdset))) - { - /* - * GET THE READY FROM THIS GUY. - * DON'T FORGET TO CLEAR HIS BIT IN THE tmpfdset - */ - len = NETREAD(socknum[cnt],buffer,READYSTRLEN); - if(len != READYSTRLEN) - { - abort_clients(); - errexit("Error reading from client #%d\n", cnt); - } - if(memcmp(buffer, READYSTR, READYSTRLEN)) - { - abort_clients(); - fprintf(stdout,"Received bad READY string: len %d, value %s\n", - len,buffer); - } - FD_CLR(socknum[cnt],&leftfdset); - } - } - } - sleep(1); - fprintf(stdout,"All READYs received\n"); - fflush(stdout); -} - -/* - Start all the clients by sending them a GO signal - totalnumclients is the total number of clients - socknum is an int array with the filedescriptors for all the - client connections -*/ -void SendGo( totalnumclients, socknum) -int totalnumclients; -int *socknum; -{ - int cnt; - fprintf(stdout,"Sending GO to all clients\n"); - for(cnt = 0; cnt < totalnumclients; cnt++) - { - if(socknum[cnt] > 0) - { - /* - * SEND A GO - */ - if(NETWRITE(socknum[cnt], GOSTR, GOSTRLEN) != GOSTRLEN) - { - abort_clients(); - errexit("Error sending GO to client %d: %s\n", cnt, neterrstr()); - } - } - } -} - -/* - This function gathers statistics from all the clients -*/ - -void GetResults(fdset, page_stats, endtime, timestr, totalnumclients, - statarray) -fd_set *fdset; -page_stats_t **page_stats; -time_t *endtime; -char *timestr; -int totalnumclients; -stats_t statarray[MAXCLIENTS]; -{ - fd_set leftfdset,tmpfdset; - char *stats_as_text; - char *page_stats_as_text; - int returnval; - int cnt,i; - - - /* DOESN'T ACTUALLY PRINT UNTIL THE FIRST CLIENT REPORTS */ - fprintf(stdout,"Reading results "); - - /* - * COPY THE FILE DESCRIPTORS TO A TMP LIST, - * ALLOCATE MEMORY FOR STATS, PAGESTATS IN TEXT FORM - */ - leftfdset = *fdset; - stats_as_text = (char *)mymalloc(SIZEOF_STATSTEXT+1); - page_stats_as_text = (char *)mymalloc(SIZEOF_PAGESTATSTEXT+1); - - /* - * COPY THE FILE DESCRIPTORS TO A TMP LIST, - * PLUS A LIST OF REMAINING FDs - */ - leftfdset = *fdset; - /* - * LOOP UNTIL ALL CLIENTS HAVE REPORTED - * AND tmpfdset IS EMPTY - */ -#ifndef WIN32 - while(memcmp(&leftfdset,&zerofdset,sizeof(fd_set))) - { - tmpfdset = leftfdset; - sleep(1); - returnval = select(FD_SETSIZE,&tmpfdset,NULL,NULL,NULL); - D_PRINTF( "Call to select returned %d, errno %d\n", - returnval, errno ); - if(returnval < 0) - { - /* - * ERROR SELECTING. ABORT ALL. - */ - D_PRINTF( "select() error %s\n", neterrstr() ); - abort_clients(); - errexit("Error selecting from one of the clients\n"); - } -#else - /* I don't see why a select is needed at all */ - tmpfdset = leftfdset; - { -#endif /* WIN32 */ - for(cnt = 0; cnt < totalnumclients; cnt++) - { - /* - * SEE WHICH SOCKETS HAVE A INPUT ON THEM PENDING AND - * RECEIVE IT. - */ - - /* IS THIS A VALID SOCKET? IS IT READY TO READ? */ - if(!BADSOCKET(socknum[cnt]) && (FD_ISSET(socknum[cnt],&tmpfdset))) - { - int len; - - /* - * GET THE TIMING DATA FROM THIS GUY - * THEN REMOVE HIM FROM THE tmpfdset - */ - /* - * READ TIME STATS - * DOES READ() RETURN THE CORRECT LENGTH? - */ - D_PRINTF( "About to read timestats, count %d, errno %d\n", - cnt, errno ); - len = SIZEOF_STATSTEXTBASE + number_of_pages*SIZEOF_DOUBLETEXT; - returnval = recvdata(socknum[cnt], stats_as_text, - len); - D_PRINTF( "Read time stats %d\n", returnval ); - if (returnval != len) /* <= 0) */ - { - D_PRINTF( "Error reading timing stats: %s\n", - neterrstr() ); - fprintf(stderr, "Error reading timing stats: %s\nSocket number %d\n", - neterrstr(),socknum[cnt]); - abort_clients(); - errexit(""); - } /* end if */ - - /* convert text to stats */ - stats_as_text[returnval] = 0; /* add an end marker */ - statarray[cnt] = *text_to_stats(stats_as_text); - - fputc('.', stdout); /* PROGRESS MARKER */ - fflush(stdout); - - if(uil_filelist_f) /* READ PAGE STATS */ - { - for (i = 0; i < number_of_pages; i++) - { - D_PRINTF( "On page_stats[%d][%d]\n", cnt, i ); - returnval = recvdata(socknum[cnt], page_stats_as_text, - SIZEOF_PAGESTATSTEXT); - D_PRINTF( "Read page stats %d\n", returnval ); - - if (returnval != SIZEOF_PAGESTATSTEXT) /* <= 0) */ - { - D_PRINTF( "Error reading page_stats[%d][%d]: %s\n", - cnt, i, neterrstr() ); - fprintf(stderr, "Error reading page_stats[%d][%d]: %s\n", - cnt, i, neterrstr()); - abort_clients(); - errexit(""); - } - D_PRINTF( "Page stats: read %d bytes\n", - returnval ); - - page_stats_as_text[returnval] = 0; /* add an end marker */ - D_PRINTF("strlen(page_stats_as_text) = %d\n", - strlen(page_stats_as_text)); - page_stats[cnt][i] = - *text_to_page_stats(page_stats_as_text); - - } /* end for */ - } /* end if filelist */ - - FD_CLR(socknum[cnt],&leftfdset); - NETCLOSE(socknum[cnt]); - socknum[cnt] = BADSOCKET_VALUE; - } /* end if socknum */ - } /* end for cnt */ - } /* end while memcmp fd */ - - /* - * DONE READING RESULTS FROM CLIENTS - */ - - *endtime = time(NULL); - timestr = asctime(localtime(endtime)); - fprintf(stdout,"\nAll clients ended at %s\n",timestr); - fflush(stdout); - - /* FREE MEMORY ALLOCATED FOR CLIENT STATS, PAGESTATS AS TEXT */ - free(stats_as_text); - free(page_stats_as_text); - -} - -/* - Prints out all the results -*/ -void PrintResults( page_stats, endtime, timestr, totalnumclients, statarray, - page_stats_total) -page_stats_t **page_stats; -time_t endtime; -char *timestr; -int totalnumclients; -stats_t statarray[MAXCLIENTS]; -page_stats_t *page_stats_total; -{ - stats_t masterstat; - int cnt,i,j; - double thruput; - struct timeval dtime; - - /* - * PRINT EVERYTHING OUT - */ - stats_init(&masterstat); - for(cnt = 0; cnt < totalnumclients; cnt++) - { - if((statarray[cnt].rs.totalconnects > 0) && (dumpall)) - { - fprintf(stdout,"----------------------------------\n"); - /* fprintf(stdout,"Test for host: %s\n",statarray[cnt].hostname); */ - fprintf(stdout,"Total number of pages retrieved from server: %u\n", - statarray[cnt].totalpages); - - rqstat_fprint(stdout, &(statarray[cnt].rs)); - - thruput = thruputpersec((double)(statarray[cnt].rs.totalbytes), - &(statarray[cnt].rs.totalresponsetime)); - - fprintf(stdout, "Thruput average per connection: %.0f bytes/sec\n", - thruput); - } - if(statarray[cnt].rs.totalconnects > 0) - { - D_PRINTF( "Summing stats for %d, with %ld total connections\n", - cnt, statarray[cnt].rs.totalconnects ); - rqstat_sum(&masterstat.rs, &(statarray[cnt].rs)); - } - else - { - masterstat.rs.totalerrs += statarray[cnt].rs.totalerrs; - } - } - - for (i=0; i < totalnumclients; i++) - { - for (j=0; j < number_of_pages; j++) - { - D_PRINTF( "Summing page stats for %d, page %d, with %d connects\n", - i, j, statarray[i].page_numbers[j] ); - - if (statarray[i].page_numbers[j] != 0) - { - rqst_stats_t *pst_rs; - rqst_stats_t *ps_rs; - - pst_rs = &(page_stats_total[j].rs); - ps_rs = &(page_stats[i][j].rs); - - rqstat_sum(pst_rs, ps_rs); - - page_stats_total[j].totalpages += page_stats[i][j].totalpages; - masterstat.totalpages += page_stats[i][j].totalpages; - - /* yes, this is assignment, not sum */ - page_stats_total[j].page_size = page_stats[i][j].page_size; - - page_stats_total[j].page_valid = 1; - } - } - } - - /* print page statistics */ - if (verbose) { - for (i = 0; i < number_of_pages; i++) - { - if (page_stats_total[i].page_valid == 1) - { - page_stats_t *pst; - - pst = &(page_stats_total[i]); - - printf ("===============================================================================\n"); - printf ("Page # %d\n\n", i); - printf ("Total number of times page was hit %u\n", - pst->totalpages); - - rqstat_print(&(pst->rs)); - - printf ("Page size %u \n", pst->page_size); - printf ("===============================================================================\n\n"); - } - } - } - - fprintf(stdout,"===============================================================================\n"); - - /* - * Validate run. - */ - masterstat.total_num_of_files = statarray[0].total_num_of_files; - for (i=1; i < totalnumclients; i++) - { - if ((statarray[i].rs.totalconnects > 0) && - (statarray[i].total_num_of_files != masterstat.total_num_of_files)) - { - fprintf(stdout,"**********************************************************************\n"); - fprintf(stdout,"**** ERROR: number of files in each test configuration is not the same\n"); - fprintf(stdout,"**** ERROR: Check configuration file %s on each client\n", configfile); - fprintf(stdout,"**********************************************************************\n"); - break; - } - } - - - /* - * Print summary statistics - */ - fprintf(stdout, "WEBSTONE 2.0 results:\n"); - - fprintf(stdout, "Total number of clients: \t%d\n", totalnumclients); - testtime = sumedh_end.tv_sec - sumedh_start.tv_sec; - fprintf(stdout,"Test time: \t\t\t%d seconds\n", testtime); - - fprintf(stdout, "Server connection rate: \t%3.2f connections/sec\n", - (double)(masterstat.rs.totalconnects)/(testtime)); - - fprintf(stdout, "Server error rate: \t\t%4.4f err/sec\n", - (double)(masterstat.rs.totalerrs)/(testtime)); - - fprintf(stdout, "Server thruput: \t\t%2.2f Mbit/sec\n", - (double)(8*masterstat.rs.totalbytes)/(testtime*1024*1024)); - - fprintf(stdout, "Little's Load Factor: \t\t%3.2f \n", - (double)(masterstat.rs.totalresponsetime.tv_sec) - /(testtime)); - avgtime(&masterstat.rs.totalresponsetime, - masterstat.rs.totalconnects, &dtime); - - fprintf(stdout, "Average response time: \t\t%4.4f millisec\n", - (double)1000*(dtime.tv_sec + (double)dtime.tv_usec / 1000000)); - - fprintf(stdout, "Error Level:\t\t\t%4.4f %%\n", - (double)(100 * masterstat.rs.totalerrs)/(masterstat.rs.totalconnects)); - - /* so much for the key metrics */ - - thruput = 8 * thruputpersec((double)(masterstat.rs.totalbytes), - &(masterstat.rs.totalresponsetime)); - - fprintf(stdout, "Average client thruput: \t%4.4f Mbit/sec\n", - thruput/(1024*1024)); - - fprintf(stdout,"Sum of client response times:\t%u.%u sec\n", - masterstat.rs.totalresponsetime.tv_sec, - masterstat.rs.totalresponsetime.tv_usec); - - fprintf(stdout,"Total number of pages read:\t%u\n\n", - masterstat.totalpages); - - /* Remaining stats are the same as usual */ - - rqstat_fprint(stdout, &(masterstat.rs)); - fflush(stdout); - -} - -#ifdef WIN32 -/* close socket library */ -void sock_cleanup(void) { - - WSACleanup(); -} -#endif /* WIN32 */ - -void -main(const int argc, char *argv[]) -{ - - int sync_sock; - int i; - int j; - char buffer[NCCARGS]; - char commandline[NCCARGS]; - char *timestr; - time_t starttime; - time_t endtime; - fd_set fdset; - /* make the big arrays static to avoid stack overflow */ - static char clienthostname[MAXCLIENTS][MAXHOSTNAMELEN]; - static stats_t statarray[MAXCLIENTS]; - page_stats_t **page_stats; - page_stats_t *page_stats_total; - struct sockaddr_in serveraddr; - - -#ifdef WIN32 - WSADATA WSAData; - COORD dwSize; - - if ((WSAStartup(MAKEWORD(1,1), &WSAData)) != 0) { - errexit("Error in WSAStartup()\n"); - } - atexit(sock_cleanup); - - /* increase size of output window */ - dwSize.X = 80; - dwSize.Y = 500; - SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), dwSize); -#endif /* WIN32 */ - - - /* Initalization of variables. */ - debugfile = stdout; - memset(buffer, 0, NCCARGS); - memset(webserver, 0, MAXHOSTNAMELEN); - memset(configfile, 0, MAXPATHLEN); - FD_ZERO(&zerofdset); - FD_ZERO(&fdset); - - for(i = 0; i < MAXCLIENTS; i++) - { - socknum[i] = BADSOCKET_VALUE; - statarray[i].rs.totalconnects = 0; - } - - signal(SIGINT, sig_int); - - ParseCmdLine( argc, argv); - - sync_sock = SetupSyncSocket( &serveraddr ); - - MakeCmdLine( commandline); - - totalnumclients = RexecClients( commandline, clienthostname, &serveraddr); - - /* Initalization of variables. */ - page_stats = - (page_stats_t **) - mymalloc(totalnumclients*sizeof(page_stats_t *)); - for (i=0; i < totalnumclients; i++) - { - page_stats[i] = (page_stats_t *) - mymalloc(number_of_pages*sizeof(page_stats_t)); - } - page_stats_total = - (page_stats_t *)mymalloc(number_of_pages*sizeof(page_stats_t)); - - for (i=0; i < totalnumclients; i++) { - stats_init(&(statarray[i])); - } - for (i=0; i < totalnumclients; i++) { - for (j=0; j < number_of_pages; j++) { - page_stats_init(&(page_stats[i][j])); - } - } - for (i=0; i < number_of_pages; i++) { - page_stats_init(&(page_stats_total[i])); - } - - for(i = 0; i < totalnumclients; i++) - { - socknum[i] = BADSOCKET_VALUE; - statarray[i].rs.totalconnects = 0; - } - - GetReady( &fdset, totalnumclients, sync_sock ); - NETCLOSE(sync_sock); - - /* - * START ALL OF THE CLIENTS BY SENDING THEM A GO SIGNAL. - */ - - - gettimeofday (&sumedh_start, NULL); - SendGo( totalnumclients, socknum); - - /* - * WAIT FOR ALL OF THE CLIENTS TO COMPLETE. WE SHOULD GET A REPLY - * FOR EACH SOCKET WE HAVE OPEN. THE REPLY WILL BE THE TIMING - * INFORMATION WE USE. - */ - - starttime = time(NULL); - timestr = asctime(localtime(&starttime)); - fprintf(stdout,"All clients started at %s\n",timestr); - fprintf(stdout,"Waiting for clients completion\n"); - fflush(stdout); - - /* IF THIS IS A TIMED TEST, WE MIGHT AS WELL SNOOZE */ - if (testtime) { - sleep(testtime * 60); - } - - GetResults( &fdset, page_stats, &endtime, timestr, totalnumclients, - statarray); - - gettimeofday (&sumedh_end, NULL); - PrintResults( page_stats, endtime, timestr, totalnumclients, statarray, - page_stats_total); - - /* free memory */ - for (i = 0; i < totalnumclients; i++) - { - free(page_stats[i]); - } - free(page_stats); - free(page_stats_total); - - exit(0); -} - -/* Added by Rajesh Shah 5/18/96 */ -void -HostEntCpy(struct hostent *dest, struct hostent *src) -{ - - dest->h_name = (char *)malloc(strlen(src->h_name)+1); - strcpy(dest->h_name, src->h_name); - printf("WebMaster name = %s\n", dest->h_name); - dest->h_aliases = src->h_aliases; - dest->h_addrtype = src->h_addrtype; - dest->h_length = src->h_length; - dest->h_addr_list = src->h_addr_list; -} - |