⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 aldtest.c

📁 linux thread programe
💻 C
字号:
/******************************************************** * An example source module to accompany... * * "Using POSIX Threads: Programming with Pthreads" *     by Brad nichols, Dick Buttlar, Jackie Farrell *     O'Reilly & Associates, Inc. * * aldtest.c * * Performance load test program for atm example program. * * Parent program sets up a number of accounts with the  * atm_server then records the time and spawns a number  * of child processes that make their own connections to  * the server and access the accounts. When the children * have exited the parent records the time. * * Arguments; *  * aldtest [-n|-c]  num_clients accounts_per_client  *         cycles_per_accounts [hot_spot_rate] * * contention flag       - 'n' no contention clients share *                          no accounts. *                         'c' contention, once every cycle *                         through their accounts the clients *                         access a "hot spot" account. * num_clients           - Number of test client processes  * accounts_per_client   - accounts accessed per Client  * cycles_per_accounts   - number of access cycles by a client  *                         on its accounts. * hot_spot_rate         - if contention test, how often *                         to reference the hot spot account. *                         4 means that four every fouth account *                         the client will substitute the hot spot *                         account for one of its own in the test. *                            * For each account accessed the client performs a deposit,  * withdraw and balance. * * When comparing results from tests it is important to maintain  * a equivelent amount of "work" being done in eatm.h case. The  * metric that most closely represents this is total access cycles * delivered by the server; * * access_cycles  *      = num_clients * account_per_client * cycles_per_accounts */#include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <errno.h>#include <string.h>#include <sys/types.h>#include <sys/wait.h>#include <sys/time.h>#include "atm.h"#include "atm_com.h"#include "atm_client_rpc.h"#define NUM_CLIENTS               10#define ACCNTS_PER_CLIENT          5#define CYCLES_PER_ACCNTS          5#define CONTENTION_FLAG          'n'struct accnt {  int id;  int password;} *accnts;/* Test Parameters */char cont = CONTENTION_FLAG;int num_clnts = NUM_CLIENTS;int accnts_per_clnt = ACCNTS_PER_CLIENT;int cycs_per_accnts  = CYCLES_PER_ACCNTS; int hot_rate = 1;int contention = 0;int num_accnts = 0;/* Accomplished "work" Metric */int access_cycs = 0;int accnts_accessed = 0;/* Low level per accnt work parameters */ int deposit_amnt      = 10000; int withdraw_amnt     =  5000; void catchit(int);int atm_load_routine(int);int access_account_wo(int, int);/****************************************************************** * main() *  * Reads command line arguments contacts server and initializes * test accnts. * Forks child processes who wait for a signal to start are go  * into their main routine atm_load_routine. * Parent gets the time, sends signal to children to start then * waits for them to exit. When they have exited the parent * checks the time and prints the result. ****************************************************************/extern int main(int argc, char **argv){  int rtn;  int i, status;  struct sigaction action;  pid_t parent_pg;  pid_t *child_pids;  struct timeval stime, etime;  long    diff_secs, diff_usecs;  double  elapsed_time_sec;  DPRINTF(("LOADTEST, Parent: pid %d, ppid %d, pgrp %d\n", getpid(), getppid(), getpgrp()));   /* move to own new process group so that signals exchanged with     children do not end up hitting anyone else! */  if ((rtn = setpgid(0,getpid())) < 0) {	perror("changing pgrp");	exit(1);	}  DPRINTF(("LOADTEST, Parent: changed pgrp to %d\n", getpgrp()));  if (argc >= 6)  sscanf(argv[5], "%d", &hot_rate);  if (argc >= 5)  sscanf(argv[4], "%d", &cycs_per_accnts);   if (argc >= 4)  sscanf(argv[3], "%d", &accnts_per_clnt);   if (argc >= 3)  sscanf(argv[2], "%d", &num_clnts);   if (argc >= 2)  {    if ((rtn = strcmp(argv[1], "-c")) == 0) contention = 1;    if (((rtn = strcmp(argv[1], "-h")) == 0) || 	((rtn = strcmp(argv[1], "h")) == 0)  ||		((rtn = strcmp(argv[1], "help")) == 0)) {      printf("  %s [-c] [num_clients accnts_per_clnt cycs_per_accnts hot_rate]\n",	     argv[0] );      printf("\t-c\t\tAdd contention for hot spot account.\n");      printf("\tnum_clients\tThe number of child client processes.\n");      printf("\taccnts_per_clnt\tThe number of accounts per child client.\n");      printf("\tcycs_per_accnts\tThe number of times child client will test\n");      printf("\t\t\taccess to its accounts. Eatm.h access to an account\n");      printf("\t\t\tis 4 deposit requests.\n");      printf("\thot_rate\tRate that child client will access hot spot\n");      printf("\t\t\taccount in place of one of its own.\n");      printf("\t\t\t(1 is everytime,.... 4 is 1 out of 4 etc.)\n");      exit(1);    }  }  num_accnts = num_clnts * accnts_per_clnt;  access_cycs = num_clnts * accnts_per_clnt * cycs_per_accnts;  /* Check Boundries on Test Parameters */  if ((num_clnts <= 0) || (accnts_per_clnt <= 0) ||       (cycs_per_accnts <= 0) || (hot_rate <= 0)) {    fprintf(stderr, "Input parameters must be greater than zero\n");    exit (1);  }  accnts = (struct accnt *)malloc(sizeof(struct accnt)*(num_accnts + 							contention));  child_pids = (pid_t *)malloc(sizeof(pid_t)*num_clnts);  printf("Atm load test,\n");  if (contention)    printf("\tContention for one account (flag %c)\n", cont);  else    printf("\tNo contention for no accounts (flag %c)\n", cont);  printf("\tNumber of clients\t\t\t\t%5d\n", num_clnts);   printf("\tNumber of accounts per client\t\t\t%5d\n",	 accnts_per_clnt);   printf("\tAccess cycles per client accounts\t\t%5d\n",	 cycs_per_accnts);  if (contention) printf("\tHot spot hit rate\t\t\t\t1 in %d\n", hot_rate);  printf("\tNumber of accounts\t\t\t\t%5d\n", num_accnts);  if (contention) printf("\t(Plus one hot spot account)\n");   printf("\tNumber of account cycles\t\t\t%5d\n", access_cycs);  /* Initialize communications with server */  client_comm_init();    /* Open test accnts */  for (i = 0; i < num_accnts + contention; i++) {    if ((rtn = accnt_open_rpc(&(accnts[i].id), &(accnts[i].password))) 	< 0) {      fprintf(stderr, "Unable to open test account %d\n", i);      exit(1);    }  }  /* Shutdown communications with server */  client_comm_shutdown();  DPRINTF(("LOAD_TEST, Parent: Starting load test children\n"));  /* Start children */   for (i = 0; i < num_clnts; i++) {    DPRINTF(("LOAD_TEST, Parent: Creating child %d\n",i));    if ((child_pids[i] = fork()) == 0) {      DPRINTF(("LOAD_TEST, Child %d: I'm alive pid %d, ppid %d, pgrp %d\n", i,getpid(),getppid(),getpgrp()));      /* Initialize communications */      client_comm_init();            /* Setup handler and suspend until start signal */      action.sa_handler = catchit;      if (sigaction(SIGUSR1, &action, NULL) < 0)	perror("load test child sigaction"), exit(1);      pause();	      /* Do work */      if (atm_load_routine(i) < 0) {	fprintf(stderr,		"aldtest.c, atm_stress_routine returned failure\n");	exit(1);       }      /* All done */      DPRINTF(("LOAD_TEST, Child %d: complete and exiting\n", i));      exit(0);    }    /* Parent continues */  }  DPRINTF(("LOAD_TEST, Parent: Children Created\n"));  DPRINTF(("LOAD_TEST, Parent: Masking SIGUSR1 from self\n"));  /* setup handler to ignore the signal to be sent to children */  action.sa_handler	= SIG_IGN;  if (sigaction(SIGUSR1, &action, NULL) < 0)    perror("load test parent sigaction"), exit(1);  parent_pg = getpgrp();  DPRINTF(("LOAD_TEST, Parent: Giving children %d secs to get setup\n",1 + (int)(.1*num_clnts)));    sleep(1 + (int)(.1*num_clnts));  /* Record start time */  rtn = gettimeofday(&stime,(void *)0);  /* send start signal */  rtn = kill(-1*parent_pg, SIGUSR1);  DPRINTF(("LOAD_TEST, Parent: Sent start signal SIGUSR1\n"));  for (i = 0; i < num_clnts; i++) {    rtn = waitpid(child_pids[i], &status, 0);    if (rtn != child_pids[i]) {      perror("waitpid");      fprintf(stderr,	      "wait returned something other than the pid\n");    }    if (status != 0) {      fprintf(stderr,	      "LOAD_TEST, Parent, client %d exited with error\n", i);      exit(1);    }    DPRINTF(("LOAD_TEST, Parent: Child %d has finished\n", i));   }  DPRINTF(("LOAD_TEST, Parent: All children have completed\n"));  /* Record finish time */  rtn = gettimeofday(&etime,(void *)0);  /* output results */  diff_secs = (signed long) (etime.tv_sec - stime.tv_sec);  diff_usecs = (signed long) (etime.tv_usec - stime.tv_usec);  DPRINTF(("\nLOAD_TEST, diff_secs %ld, diff_usecs %ld\n",	   diff_secs, diff_usecs));   elapsed_time_sec = (double)diff_secs + (double)diff_usecs*1E-6;  printf("\n\tTest Complete:\n");  printf("\t\tElapsed time\t\t\t\t%5.3f sec\n", elapsed_time_sec);  return 0; }/******************************************************************** * Signal Handler for child processes. * * Does nothing. *******************************************************************/void catchit(int signo){  DPRINTF(("LOAD_TEST, Child in sighandler, %d\n", signo));}/******************************************************************* * Main child process server stress routine * * For the number of accnts the child is responsible for the routine * deposits, withdraws and gets the balanace (dwb) a set number of * times for that accnt.  ******************************************************************/int atm_load_routine(int child_id){  int i = 0,j = 0;  int start_accnt = 0, cur_accnt = 0;    DPRINTF(("LOAD_TEST, Child %d: atm_load_routine\n", child_id));    start_accnt = child_id*accnts_per_clnt;    for (j = 0; j < cycs_per_accnts; j++) {     cur_accnt = start_accnt;    for (i = 0; i < accnts_per_clnt; i++) {          if ((accnts_accessed%hot_rate == 0) && (contention)) {	DPRINTF(("Child %i: hitting hot spot, (skipping %d) accnts_accessed %d\n", 		 child_id, cur_accnt, accnts_accessed));	if (access_account_wo(num_accnts, child_id) < 0)	  return -1;	      } else {	DPRINTF(("Child %i: cur_accnt %d, accnts_accessed %d\n", 		 child_id, cur_accnt, accnts_accessed));	if (access_account_wo(cur_accnt, child_id) < 0)	  return -1;      }         accnts_accessed++;      cur_accnt++;    }  }  return 0;}/************************************************************* * access account - write only - deposit requests *  *************************************************************/int access_account_wo(int accnt, int child_id){  struct accnt *ap;  int i;  ap = &accnts[accnt];  for (i = 0; i < 4; i++) {    if (accnt_deposit_rpc(ap->id, ap->password, deposit_amnt) < 0) {      fprintf(stderr, "Child %d: accnt_deposit_rpc failed\n",	      child_id);      return -1;    }  }}/************************************************************* * access_account  - read and write - balance, deposit, withdraw,  *                                    balance *  *************************************************************/int access_account_rw(int accnt, int child_id){  int b_before, b_after;  struct accnt *ap;    ap = &accnts[accnt];    if (accnt_balance_rpc(ap->id, ap->password, &b_before) < 0 ) {    fprintf(stderr, "Child %d: accnt_balance_rpc failed\n",	    child_id);    return -1;  }  if (accnt_deposit_rpc(ap->id, ap->password, deposit_amnt) < 0) {    fprintf(stderr, "Child %d: accnt_deposit_rpc failed\n",	    child_id);    return -1;  }  if (accnt_withdraw_rpc(ap->id, ap->password, withdraw_amnt) < 0) {    fprintf(stderr, "Child %d: accnt_withdraw_rpc failed\n", 	    child_id);    return -1;  }  if (accnt_balance_rpc(ap->id, ap->password, &b_after) < 0 ) {    fprintf(stderr, "Child %d: accnt_balance_rpc failed\n",	    child_id);    return -1;  }  if (((b_after - b_before) != (deposit_amnt - withdraw_amnt)) &&       (!contention)) {    fprintf(stderr, "Child %d: balance missmatch %d %d, %d %d\n", 	    child_id, b_before, b_after, deposit_amnt, 	    withdraw_amnt);     return -1;  }}/************************************************************* * access account - read only - balance requests *  *************************************************************/int access_account_ro(int accnt, int child_id){  int b_before, b_after;  struct accnt *ap;  int i;  ap = &accnts[accnt];  for (i = 0; i < 4; i++) {    if (accnt_balance_rpc(ap->id, ap->password, &b_before) < 0 ) {      fprintf(stderr, "Child %d: accnt_balance_rpc failed\n",	      child_id);      return -1;    }  }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -