📄 webmaster.c
字号:
{ 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -