home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / TP1.ZIP / BENCHW.C < prev    next >
Text File  |  1989-06-29  |  16KB  |  600 lines

  1. /***************************************************************************/
  2. /* Copyright (C) 1989 Microsoft Corporation                                */
  3. /* Copyright (C) 1989 Sybase, Inc.                                         */
  4. /* Program: BENCHW.C                                                       */
  5. /* Description:  The program acts as client for the TP/1 benchmark.        */
  6. /*               BENCHW reads mail sent by the controlling program,        */
  7. /*               SQLQUEEN.  SQLQUEEN tells BENCHW to connect to the        */
  8. /*               server under test and to a tracking server to log the     */
  9. /*               test results.  BENCHW then waits for a mail message       */
  10. /*               to start testing.  After the tests are completed,         */
  11. /*               BENCHW logs the test results to the tracking server.      */
  12. /*                                                                         */
  13. /* Inputs:  Workstation Number, Computer Description                       */
  14. /*                                                                         */
  15. /* Created:   Trish Millines 1/24/89                                       */
  16. /* Modified:  Bob Muglia 4/6/89                                            */
  17. /*                                                                         */
  18. /***************************************************************************/
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <time.h>
  22. #include <math.h>
  23. #include <types.h>
  24. #include <fcntl.h>
  25. #include <stat.h>
  26. #include <share.h>
  27. #include <io.h>
  28. #include <timeb.h>
  29. #include <sqlfront.h>
  30. #include <sqldb.h>
  31. #include <netcons.h>
  32. #include <neterr.h>
  33. #include <mailslot.h>
  34. #include <os2def.h>
  35. #include <bse.h>
  36. #include "bench.h"
  37.  
  38. #define MAILPATH "\\mailslot\\sqlbench\\"
  39.  
  40. /* */
  41. /* Forward declaration of SQL Server error handlers */
  42. /* */
  43.  
  44.  int bench_err_handler();
  45.  int bench_msg_handler();
  46.  
  47. /* */
  48. /* SETUP and CONFIGURATION structures */
  49. /* */
  50.  
  51.  struct bench_data bd;                 /* Program setup structure */
  52.  DBPROCESS far *dbproc, *track_proc;
  53.  DBINT CURR_ERROR;
  54.  int PRINT_ERRORS;
  55.  
  56. /* */
  57. /* EXECUTION STATISTICS structures */
  58. /* */
  59.  
  60. struct statistics stats;
  61.  
  62. FILE *outptr;
  63.  
  64. main(argc,argv)
  65. int argc;
  66. char **argv;
  67. {
  68.  char message[100];
  69.  char mailbox[50]; 
  70.  char buffout[80];
  71.  char code;                                  
  72.  int mailtemp, i;
  73.  unsigned mailhandle;           
  74.  unsigned short messagebytes, nextbytes, priority;
  75.  DBINT dummy_seed;              /* truly randomizes the function */
  76.  
  77. /* */
  78. /* Initialize */
  79. /* */
  80.  
  81.  dummy_seed = get_random(500l);         /* just seed the generator */
  82.  mailtemp = 1;
  83.  code = READY;
  84.  
  85. /* */
  86. /* Call routine to parse the arguments */
  87. /* */
  88.  
  89.  if (Check_arguments(argc,argv) == FAIL)
  90.    exit(-1);
  91.  
  92. /* */
  93. /* Open the status log */
  94. /* */
  95.  
  96.  if((outptr = fopen("sqlstat.log","w")) == NULL)
  97.    {
  98.     printf("\nBENCH ERROR: Can't open sqlstat.log");
  99.     exit(FAIL);
  100.    }
  101.  
  102. /* */
  103. /* Install the SQL Server error handlers */
  104. /* */
  105.  
  106.  dberrhandle(bench_err_handler);     /* install DBLIB error handler */
  107.  dbmsghandle(bench_msg_handler);     /* install DBLIB message handler */
  108.  
  109. /* */
  110. /* Create a mailbox to receive information from SQLQUEEN */
  111. /* */
  112.  
  113.  do
  114.  {
  115.   sprintf(mailbox,"%s%d",MAILPATH,mailtemp);                             
  116.   mailtemp++;
  117.  }
  118.  while (DosMakeMailslot(mailbox, 100, 600, &mailhandle) != NERR_Success);
  119.  
  120. /* */
  121. /* Loop to allow multiple tests in sequence */
  122. /* */
  123.  
  124.  while (code != QUIT)
  125.  {
  126.   printf("\nWaiting for server information");
  127.   
  128.   PRINT_ERRORS = TRUE;
  129.  
  130. /* */
  131. /* Wait for a mail message indicating it's time to start testing */
  132. /* */
  133.  
  134.   DosReadMailslot(mailhandle, message, &messagebytes, 
  135.                   &nextbytes, &priority, (long) -1);
  136.   
  137.   code = message[0];
  138.   
  139.   if (code != GET_SERVERS)
  140.   {
  141.    printf("\nBENCH ERROR: Incorrect code, expected GET_SERVERS, received: %c",
  142.           code);
  143.    exit(FAIL);
  144.   }
  145.  
  146. /* */
  147. /* Parse the mail message, connect to servers */
  148. /* */
  149.  
  150.   i = 2;
  151.  
  152.   i = parsebuff(message,i,',',bd.test_server);
  153.   i = parsebuff(message,i,',',bd.track_server);
  154.   i = parsebuff(message,i,',',bd.database);
  155.  
  156.   Connect_to_servers();
  157.  
  158. /* */
  159. /* Get ready to test - Wait for mail to start */
  160. /* */
  161.  
  162.   DosReadMailslot(mailhandle, message, &messagebytes, 
  163.                   &nextbytes, &priority, (long) -1);
  164.   
  165.   code = message[0];
  166.   
  167.   if (code != ALL_START)
  168.   {
  169.    printf("\nBENCH ERROR: Incorrect code, expected ALL_START, received: %c",
  170.           code);
  171.    exit(FAIL);
  172.   }
  173.  
  174.   i = 2;
  175.  
  176.   i = parsebuff(message,i,',',buffout);
  177.   bd.seconds = atol(buffout);
  178.   i = parsebuff(message,i,',',buffout);
  179.   bd.max_accts = atol(buffout);
  180.   i = parsebuff(message,i,',',buffout);
  181.   bd.max_teller = atol(buffout);
  182.   i = parsebuff(message,i,',',buffout);
  183.   bd.max_branch = atol(buffout);
  184.  
  185. /* */
  186. /* Go! */
  187. /* */
  188.  
  189.   printf("\nTesting for %ld seconds",bd.seconds);
  190.   Run_tp1();
  191.  
  192. /* */
  193. /* Finish up the test */
  194. /* */                  
  195.  
  196.   PRINT_ERRORS = FALSE;
  197.   Update_bench_stats();
  198.   dbexit();
  199.  }
  200.  
  201.  exit(0);
  202. }
  203.  
  204. /***************************************************************************/
  205. /*                      FUNCTION TO PARSE THE ARGUMENTS                    */
  206. /***************************************************************************/
  207. int Check_arguments(argc,argv)
  208. int argc;
  209. char **argv;
  210. {
  211.  
  212. /* */
  213. /* See if all the necessary arguments are there */
  214. /* */
  215.  
  216.  if(argc != 2)
  217.   {
  218.    system("cls");
  219.    printf("\nUSAGE: benchw Computer_identifier");
  220.    printf("\n\nEXAMPLE: benchw Compaq-386/20");
  221.    return(FAIL);
  222.   }
  223.  
  224. /* */
  225. /* Initialize variables */
  226. /* */
  227.  
  228.  strcpy(bd.computer,argv[1]);
  229.  return(SUCCEED);
  230. }
  231.  
  232. /***************************************************************************/
  233. /*                      FUNCTION TO MAKE SERVER CONNECTIONS                */
  234. /***************************************************************************/
  235. int Connect_to_servers()
  236. {
  237.  int done;
  238.  LOGINREC far *login;
  239.  
  240. /* */
  241. /* Get the login record */
  242. /* */
  243.  
  244.  if((login = dblogin()) == NULL)
  245.   {
  246.    printf("\nBENCH ERROR: Out of memeory logging on to test server");
  247.    fprintf(outptr,"\nBENCH ERROR: Out of memory logging on to test server");
  248.    return(FAIL);
  249.   }
  250.  
  251.  DBSETLUSER(login,"sa");
  252.  DBSETLPWD(login,"");
  253.  DBSETLAPP(login,"benchmarks");
  254.  
  255. /* */
  256. /* Connect to the server under test.  */
  257. /* */
  258.  
  259.  if((dbproc = dbopen(login,bd.test_server)) == NULL)
  260.   {
  261.    printf("\nBENCH ERROR: Unable to connect to the test server");
  262.    fprintf(outptr,"\nBENCH ERROR: Unable to connect to the test server");
  263.    return(FAIL);
  264.   }
  265.  
  266.  dbfreelogin(login);
  267.  
  268.  if(dbuse(dbproc,bd.database) == FAIL)
  269.   {
  270.    printf("\nBENCH ERROR: Database %s not found",bd.database);
  271.    fprintf(outptr,"\nBENCH ERROR: Database %s not found",bd.database);
  272.    return(FAIL);
  273.   }
  274.  
  275.  printf("\nMade connection to test server %s",bd.test_server);
  276.  fprintf(outptr,"\n\nMade connection to test server %s",bd.test_server);
  277.  fflush(outptr);
  278.  
  279. /* */
  280. /* Make a connection to the performance tracking database */
  281. /* */
  282.  
  283.  if((login = dblogin()) == NULL)
  284.   {
  285.    printf("\nBENCH ERROR: Out of memory logging on to tracking server");
  286.    fprintf(outptr,"\nBENCH ERROR: Out of memory logging on to tracking server");
  287.    return(FAIL);
  288.   }
  289.  
  290.  DBSETLUSER(login,"sa");
  291.  DBSETLPWD(login,"");
  292.  DBSETLAPP(login,"bench_stats");
  293.  
  294.  if((track_proc = dbopen(login,bd.track_server)) == NULL)
  295.   {
  296.    printf("\nBENCH ERROR: Unable to connect to the tracking server");
  297.    fprintf(outptr,"\nBENCH ERROR: Unable to connect to the tracking server");
  298.    return(FAIL);
  299.   }
  300.  
  301.  dbfreelogin(login);
  302.  
  303.  if(dbuse(track_proc,"bench_stat") == FAIL)
  304.   {
  305.    printf("\nBENCH ERROR: Cannot find bench_stat database");
  306.    fprintf(outptr,"\nBENCH ERROR: Cannot find bench_stat database");
  307.    return(FAIL);
  308.   }
  309.  printf("\nMade connection to tracking server %s",bd.track_server);
  310.  fprintf(outptr,"\n\n*** Made connection to tracking server %s ***",\
  311.          bd.track_server);
  312.  fflush(outptr);
  313.  
  314.  return(SUCCEED);
  315. }
  316.  
  317. /***************************************************************************/
  318. /*                      FUNCTION TO START THE TIMER                        */
  319. /***************************************************************************/
  320.  
  321. void Startimer(Start)
  322. struct timeb *Start;
  323. {
  324.  ftime(Start);
  325. }
  326.  
  327. /***************************************************************************/
  328. /*                      FUNCTION TO STOP THE TIMER                        */
  329. /***************************************************************************/
  330.  
  331. void Get_elapsed_time(Start)
  332. struct timeb Start;     /* Start time */
  333. {
  334.  unsigned long result;
  335.  struct timeb Stoptime;
  336.  
  337.  ftime(&Stoptime);
  338.  
  339. /* */
  340. /* If ending milliseconds greater than starting milliseconds, */
  341. /* borrow from seconds. */
  342. /* */
  343.  
  344.  if (Stoptime.millitm < Start.millitm)
  345.   {
  346.    Stoptime.time--;
  347.    Stoptime.millitm += 1000;
  348.   }
  349.  
  350. /* */
  351. /* Since time is represented in seconds since 1970, and */
  352. /* would overflow when converted to milliseconds, simply */
  353. /* take the difference modulo 1 day. */
  354. /* */
  355.  
  356.  result = (((Stoptime.time - Start.time) % (60*60*24L)) * 1000L) +
  357.                   (Stoptime.millitm - Start.millitm);
  358.  
  359. /* */
  360. /* Get the max, min and total (all loops) execution time of the transaction */
  361. /* */
  362.  
  363.  if (stats.Timecnt == 0)
  364.  {
  365.   stats.Timemin = result;
  366.   stats.Timemax = result;
  367.  }
  368.  else
  369.  {
  370.   if (result < stats.Timemin)
  371.      stats.Timemin = result;
  372.   else if (result > stats.Timemax)
  373.           stats.Timemax = result;
  374.  }
  375.  stats.Timetot += result;
  376.  
  377. /* */
  378. /* If under 1 second, add 1 to Timeunder1 */
  379. /* */
  380.  
  381.  if (result < 1000)
  382.    ++stats.Timeunder1;
  383.  
  384. /* */
  385. /* If under 2 seconds, add 1 to Timeunder2 */
  386. /* */
  387.  
  388.  if (result < 2000)
  389.    ++stats.Timeunder2;
  390. }
  391.  
  392. /***************************************************************************/
  393. /*                   FUNCTION TO EXECUTE TP/1 PROCEDURES                   */
  394. /***************************************************************************/
  395. void Run_tp1()
  396. {
  397.  DBINT acct, teller, branch, delta, transid, pid;
  398.  char cmd[240],code;
  399.  struct timeb timein;
  400.  long elapsed,now,Target_time;
  401.  int done,i;
  402.  char tp1message[101];
  403.  
  404.  CURR_ERROR = 0;
  405.  transid = pid = 0;
  406.  stats.Timemin = 0;
  407.  stats.Timemax = 0;
  408.  stats.Timetot = 0;
  409.  stats.Timecnt = 0;
  410.  stats.Errcnt  = 0;
  411.  stats.Timeunder1 = 0;
  412.  stats.Timeunder2 = 0;
  413.  
  414. /* */
  415. /* Initialize a 100 byte string to pass to the server for the TP1 benchmark */
  416. /* */
  417.  
  418.  strcpy(tp1message,"12345678901234567890123456789012345678901234567890");
  419.  strcat(tp1message,"12345678901234567890123456789012345678901234567890");
  420.  
  421. /* */
  422. /* Execute for the specified number of seconds */
  423. /* */
  424.  
  425.  time(&stats.Real_start);
  426.  Target_time = stats.Real_start + bd.seconds;
  427.  
  428.  do
  429.   {
  430.  
  431. /* */
  432. /* Generate random numbers */
  433. /* */
  434.  
  435.    acct = get_random(bd.max_accts);
  436.    teller = get_random(bd.max_teller);
  437.    branch = get_random(bd.max_branch);
  438.    delta = get_random(500l);
  439.    ++transid;
  440.    ++pid;
  441.    sprintf(cmd,"exec tp1 %ld,%ld,%ld,%ld,%ld,%ld,'%s'",acct,teller,branch,
  442.            delta,transid,pid,tp1message);
  443.    dbcmd(dbproc,(char DBDIST *)cmd);
  444.  
  445. /* */
  446. /* Send the script */
  447. /* */
  448.  
  449.    Startimer(&timein);                /* Start exec timing here */
  450.  
  451.    if(dbsqlexec(dbproc) != FAIL)      /* execute it  */
  452.    {
  453.     if(CURR_ERROR != 0)
  454.       CURR_ERROR = 0;
  455.     else
  456.     {
  457.      Get_results(dbproc);             /* Get the results */
  458.      Get_elapsed_time(timein);        /* Stop the res timing here */
  459.      ++stats.Timecnt;
  460.     }
  461.    }
  462.  
  463. /* */
  464. /* Check the elapsed time every 10 iterations*/
  465. /* */
  466.  
  467.    done = Check_time(Target_time);
  468.  
  469.   }
  470.  while(done == FALSE);
  471.  
  472.  time(&stats.Real_end);
  473. }
  474.  
  475. /***************************************************************************/
  476. /*                   FUNCTION TO CHECK TARGET TIME                         */
  477. /***************************************************************************/
  478. int Check_time(Target_time)
  479. long Target_time;
  480. {
  481.  long now;
  482.  
  483.  if(stats.Timecnt%10 == 0)
  484.   {
  485.    time(&now);
  486.    if(now >= Target_time)
  487.      return(TRUE);
  488.   }
  489.  return(FALSE);
  490. }
  491.  
  492. /***************************************************************************/
  493. /*               FUNCTION TO UPDATE THE PERFORMANCE TRACKING DATABASE      */
  494. /***************************************************************************/
  495. void Update_bench_stats()
  496. {
  497.  DBINT run_num;
  498.  char cmd[240],start_time[50],end_time[50];
  499.  struct tm *t;
  500.  
  501.  fprintf(outptr,"\n\nStarted at: %s",ctime(&stats.Real_start));
  502.  fprintf(outptr,"Ended at  : %s",ctime(&stats.Real_end));
  503.  fprintf(outptr,"\nIterations: %ld",stats.Timecnt);
  504.  fprintf(outptr,"\nErrors    : %ld ",stats.Errcnt);
  505.  fflush(outptr);
  506.  
  507.  printf("\nUpdating the performance tracking database");
  508.  
  509.  t = localtime(&stats.Real_start);
  510.  sprintf(start_time,"%d/%d/%d %d:%d:%d",t->tm_mon + 1,t->tm_mday,t->tm_year,\
  511.          t->tm_hour,t->tm_min,t->tm_sec);
  512.  
  513.  t = localtime(&stats.Real_end);
  514.  sprintf(end_time,"%d/%d/%d %d:%d:%d",t->tm_mon + 1,t->tm_mday,t->tm_year,\
  515.          t->tm_hour,t->tm_min,t->tm_sec);
  516.  
  517. /* */
  518. /* Update the RUNS tables */
  519. /* */
  520.  
  521.  CURR_ERROR = SQLDUPROW;
  522.  
  523.  while(CURR_ERROR != SUCCEED)
  524.   {
  525.    run_num = Get_max_value(track_proc,"runs","number");  /* get max run# + 1 */
  526.    ++run_num; 
  527.  
  528.    sprintf(cmd,"insert into runs values "
  529.                "(%ld,'%s','%s','%s',%ld,%ld,%ld,%ld,%ld,%f,%ld,%ld)",
  530.         run_num,bd.computer,start_time,end_time,stats.Timecnt,
  531.         stats.Errcnt,stats.Timetot,stats.Timemin,stats.Timemax,
  532.         (float)stats.Timetot/stats.Timecnt,stats.Timeunder1,stats.Timeunder2);
  533.  
  534.    dbcmd(track_proc,(char DBDIST *)cmd);
  535.    if(dbsqlexec(track_proc) != FAIL)
  536.      CURR_ERROR = SUCCEED;
  537.  
  538.    Get_results(track_proc);
  539.   }
  540.  
  541.  printf("\nSuccessful - Run number: %d\n\n",run_num);
  542.  fprintf(outptr,"\nRun number: %d",run_num);
  543.  fflush(outptr);
  544. }
  545.  
  546. /***************************************************************************/
  547. /*               FUNCTION TO HANDLE DBLIB ERRORS                           */
  548. /***************************************************************************/
  549. int bench_err_handler(dbproc,severity,dberr,oserr,dberrstr,oserrstr)
  550. DBPROCESS   *dbproc;
  551. int         severity;
  552. int         dberr;
  553. int         oserr;
  554. char        *dberrstr;
  555. char        *oserrstr;
  556. {
  557.  long ltoday;
  558.  
  559.  if (PRINT_ERRORS)
  560.  {
  561.   time(<oday);
  562.   printf("\nDB-LIB error: %d=%s\n Time: %s",dberr,dberrstr,
  563.           ctime(<oday));
  564.   fprintf(outptr,"\nDB-LIB error: %d=%s\n Time: %s",dberr,dberrstr,
  565.           ctime(<oday));
  566.   fflush(outptr);
  567.   ++stats.Errcnt;
  568.  }
  569.  return(INT_CANCEL);
  570. }
  571.  
  572. /***************************************************************************/
  573. /*               FUNCTION TO HANDLE SQL SERVER MESSAGES                    */
  574. /***************************************************************************/
  575. int bench_msg_handler(dbproc,msgno,msgstate,severity,msgtext)
  576. DBPROCESS    *dbproc;
  577. DBINT        msgno;
  578. int          msgstate;
  579. int          severity;
  580. char        *msgtext;
  581. {          
  582.  long ltoday;
  583.  
  584.  if (PRINT_ERRORS)
  585.  {
  586.   if (msgno != 5701)
  587.    {
  588.     CURR_ERROR = msgno;
  589.     time(<oday);
  590.     printf("\nMessage number: %ld=%s\n Time: %s",msgno,msgtext,
  591.           ctime(<oday));
  592.     fprintf(outptr,"\nMessage number: %ld=%s\n Time: %s",msgno,msgtext,
  593.           ctime(<oday));
  594.     fflush(outptr);
  595.     ++stats.Errcnt;
  596.    }
  597.   }
  598.   return(0);
  599. }
  600.