home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / pp / pp-6.0 / Tools / ppbm / ppbm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-18  |  9.0 KB  |  418 lines

  1. /* ppbm.c - measures PP throughput on a filesystem */
  2.  
  3. static char Rcsid[] = "$Header: /xtel/pp/pp-beta/Tools/ppbm/RCS/ppbm.c,v 6.0 1991/12/18 20:32:20 jpo Rel $";
  4.  
  5. /*
  6.  * $Header: /xtel/pp/pp-beta/Tools/ppbm/RCS/ppbm.c,v 6.0 1991/12/18 20:32:20 jpo Rel $
  7.  *
  8.  * $Log: ppbm.c,v $
  9.  * Revision 6.0  1991/12/18  20:32:20  jpo
  10.  * Release 6.0
  11.  *
  12.  */
  13.  
  14. #include <stdio.h>
  15. #include <fcntl.h>
  16. #include <sys/stat.h>
  17. #include <sys/times.h>
  18. #include <sys/wait.h>
  19. #include <sys/time.h>
  20. #include <dirent.h>
  21. #ifndef SYS5
  22. #include <sys/file.h>
  23. #include <sys/resource.h>
  24. #endif
  25. #include <errno.h>
  26.  
  27. #define NOTOK    (-1)
  28. #define MAXPATHLENGTH    1024
  29. #define hertz 60        /* the (times(2/3) manual page says this
  30.                    is a constant but is it really ? */
  31.  
  32. #ifndef SYS5
  33. struct rusage rusage;
  34. #endif
  35. int addr_file_size = 600;    /* how much to put in the address file */
  36. int create_message_sleep = 0;    
  37. int delete_message_sleep = 0;
  38. int batch_sleep = 0;
  39. int usesubdirs = 0;
  40. #ifdef LOCK_EX
  41. int do_flock = 1;        /* should we flock things? */
  42. #else
  43. int do_flock = 0;
  44. #endif
  45. int do_sync = 1;        /* should files be fsync(2)ed ? */
  46. int n_batch = 3;        /* # batches per child */
  47. int message_batch = 10;        /* # messages per batch */
  48. int n_child = 5;
  49. int verbose = 0;
  50. int mypid, childno;
  51.  
  52. char * base_dir  = ".";        /* where to create the test messages */
  53. char buf[60000];
  54.  
  55. /* serror */
  56. serror (routine, what)
  57. char *routine, *what;
  58. {
  59.     extern int errno;
  60.     extern int sys_nerr;
  61.     extern char *sys_errlist[];
  62.     char sbuf[BUFSIZ];
  63.     char *p;
  64.  
  65.     if (errno > 0 && errno < sys_nerr)
  66.         p = sys_errlist[errno];
  67.     else    p = "Unknown error";
  68.     (void) sprintf (sbuf, "%s %s %s\n", routine, what ? what : "", p);
  69.     (void) write (2, sbuf, strlen(sbuf));
  70. }
  71.  
  72. /* main worker function */
  73. child(cno)
  74. int cno;
  75. {
  76.     int i, j;
  77.     mypid = getpid ();
  78.     childno = cno;
  79.  
  80.     for (i = 0; i < n_batch; i++) {
  81.     for (j = 0; j < message_batch; j++) {
  82.         create_message(j);
  83.         if (create_message_sleep) sleep(create_message_sleep);
  84.     }
  85.     for (j = 0; j < message_batch; j++) {
  86.         delete_message(j);
  87.         if (delete_message_sleep) sleep(delete_message_sleep);
  88.     }
  89.     if (batch_sleep) sleep(batch_sleep);
  90.     }
  91. }
  92.  
  93. /* create a message with address file + 1 header + 1 body part */
  94. create_message(i)
  95. int i;
  96. {
  97.     char msg[MAXPATHLENGTH];
  98.     char base[MAXPATHLENGTH];
  99.     char file[MAXPATHLENGTH];
  100.     int adr, fd;
  101.  
  102.     if (usesubdirs)
  103.         (void) sprintf (msg, "%s/%d/msg.%d-%d",
  104.                 base_dir, (childno+i) % usesubdirs, mypid, i);
  105.     else
  106.         (void) sprintf(msg, "%s/msg.%d-%d", base_dir, mypid, i);
  107.     if (mkdir(msg, 0777) == NOTOK) {
  108.         serror ("mkdir", msg);
  109.         return;
  110.     }
  111.     (void) sprintf(file, "%s/addr", msg);
  112.     if ((adr = open(file, O_CREAT | O_WRONLY, 0666)) == NOTOK) {
  113.         serror("open", file);
  114.         return;
  115.     }
  116. #ifdef LOCK_EX
  117.     if (do_flock && flock (adr, LOCK_EX) == NOTOK)
  118.         serror ("flock", file);
  119. #endif
  120.     if (write(adr, buf, addr_file_size) != addr_file_size) {
  121.         serror("write", file);
  122.         (void) close (adr);
  123.         return;
  124.     }
  125.  
  126.     (void) sprintf(base, "%s/base", msg);
  127.     if (mkdir(base, 0777) == NOTOK) {
  128.         serror ("mkdir", base);
  129.         return;
  130.     }
  131.     (void) sprintf(file, "%s/hdr.822", base);
  132.     if ((fd = open(file, O_CREAT | O_WRONLY, 0666)) == NOTOK) {
  133.         serror("open", file);
  134.         (void) close (adr);
  135.         return;
  136.     }
  137.     if (write(fd, buf, header_size(i)) != header_size(i)) {
  138.         serror ("write", file);
  139.         (void) close (fd);
  140.         (void) close (adr);
  141.         return;
  142.     }
  143.         
  144.     if (do_sync && fsync(fd) == NOTOK)
  145.         serror ("fsync", file);
  146.     if (close(fd) == NOTOK)
  147.         serror ("close", file);
  148.     (void) sprintf(file, "%s/1.ia5", base);
  149.     if ((fd = open(file, O_CREAT | O_WRONLY, 0666)) == NOTOK)
  150.         serror ("open", file);
  151.     else {
  152.         if (write(fd, buf, message_size(i)) != message_size(i))
  153.             serror ("write", file);
  154.         if (do_sync && fsync(fd) == NOTOK)
  155.             serror ("fsync", file);
  156.         if (close(fd) == NOTOK)
  157.             serror ("close", file);
  158.     }
  159.     if (do_sync && fsync(adr) == NOTOK)
  160.         serror ("fsync", "addr");
  161.     if (close(adr) == NOTOK)
  162.         serror ("close", "addr");
  163. }
  164.  
  165. header_size(i)
  166. int i;
  167. {
  168.     return(600);
  169. }
  170.  
  171. message_size(i)
  172. int i;
  173. {
  174.     return(6875);    /* average of a couple of days on slough */
  175. }
  176.  
  177. delete_message(i)
  178. int i;
  179. {
  180.     char msg[MAXPATHLENGTH];
  181.     
  182.     if (usesubdirs)
  183.         (void) sprintf(msg, "%s/%d/msg.%d-%d", base_dir,
  184.                (childno + i) % usesubdirs, mypid, i);
  185.     else
  186.         (void) sprintf(msg, "%s/msg.%d-%d", base_dir, mypid, i);
  187.     rm_tree(msg);
  188. }
  189.  
  190. rm_tree(dir)
  191. char * dir;
  192. {
  193.     char file[MAXPATHLENGTH];
  194.     DIR *d = opendir(dir);
  195.     struct dirent * e;
  196.     struct stat st;
  197.  
  198.     if (d == NULL) {
  199.         serror ("opendir", dir);
  200.         return;
  201.     }
  202.  
  203.     while (e = readdir(d)) {
  204.         if (strcmp (e -> d_name, ".") == 0 ||
  205.             strcmp (e -> d_name, "..") == 0)
  206.             continue;
  207.         (void) sprintf(file, "%s/%s", dir, e->d_name);
  208.         if (stat(file, &st) == NOTOK) {
  209.             serror ("stat", file);
  210.             continue;
  211.         }
  212.         if ((st.st_mode&S_IFMT) == S_IFREG) {
  213.             int fd;
  214.             if ((fd = open(file, O_RDONLY, 0)) != NOTOK) {
  215.                 if (read (fd, buf, st.st_size) != st.st_size)
  216.                     serror ("read", file);
  217.                 (void) close(fd);
  218.             }
  219.             else
  220.                 serror ("open", file);
  221.             if (verbose)
  222.                 printf ("Unlink file %s\n", file);
  223.             if (unlink(file) == NOTOK)
  224.                 serror ("unlink", file);
  225.         } else if ((st.st_mode & S_IFMT) == S_IFDIR)
  226.             rm_tree(file);
  227.     }
  228.     if (verbose)
  229.         printf ("rmdir %s\n", dir);
  230.     if (closedir(d) == NOTOK)
  231.         serror ("closedir", dir);
  232.     if (rmdir(dir) == NOTOK)
  233.         serror ("rmdir", dir);
  234. }
  235.  
  236. makesubdirs ()
  237. {
  238.     char buf[BUFSIZ];
  239.     int i;
  240.  
  241.     for (i = 0; i < usesubdirs; i++) {
  242.         (void) sprintf (buf, "%s/%d", base_dir, i);
  243.         if (mkdir (buf, 0777) == NOTOK && errno != EEXIST)
  244.             serror ("mkdir", buf);
  245.     }
  246. }
  247.  
  248. main(argc, argv)
  249. int argc;
  250. char *argv[];
  251. {
  252.     extern char *optarg;
  253.     int i, c;
  254.     struct tms tms;
  255. #ifndef SYS5
  256.     struct timeval startt, endt, tdiff;
  257.     struct rusage rus;
  258.     double mps;
  259. #else
  260.     time_t startt, endt;
  261. #endif
  262.     union wait wt;
  263.  
  264.     while ((c = getopt(argc, argv, "c:d:fFn:m:s:S:v")) != EOF) {
  265.         switch (c) {
  266.  
  267.             case 'c':
  268.             n_child = atoi(optarg);
  269.             break;
  270.  
  271.             case 'd':
  272.             base_dir = optarg;
  273.             break;
  274.  
  275.             case 'f':
  276.             do_sync = 0;
  277.             break;
  278.  
  279.             case 'F':
  280.             do_flock = 0;
  281.             break;
  282.  
  283.             case 'n':
  284.             n_batch = atoi(optarg);
  285.             break;
  286.  
  287.             case 'm':
  288.             message_batch = atoi(optarg);
  289.             break;
  290.  
  291.             case 's':
  292.             batch_sleep = atoi(optarg);
  293.             break;
  294.             case 'S':
  295.             usesubdirs = atoi(optarg);
  296.             break;
  297.             case 'v':
  298.             verbose = 1;
  299.             break;
  300.  
  301.             case '?':
  302.             default:
  303.             fprintf(stderr,
  304. "usage: %s [-vf] [-c children] [-n iterations] [-m messages-per-iterations] [-d base_dir]\n",
  305.                 argv[0]);
  306.             exit(1);
  307.         }
  308.     }
  309.  
  310.     if (usesubdirs)
  311.         makesubdirs ();
  312. #ifndef SYS5
  313.     gettimeofday (&startt, (struct timezone *)0);
  314. #else
  315.     startt = time((time_t *)0);
  316. #endif
  317.     (void) fflush(stdout);
  318.     for (i = 0; i < n_child; i++) {
  319.         switch(fork()) {
  320.  
  321.             case 0:
  322.             child(i);
  323.             exit(0);
  324.     
  325.             case -1:
  326.             perror("fork");
  327.             exit(1);
  328.         }
  329.     }
  330. #ifndef SYS5
  331.     while (wait3(&wt.w_status, 0, &rus) != -1) {
  332.         gettimeofday (&endt, (struct timezone *)0);
  333.         add_ru (&rus);
  334.     }
  335. #else
  336.     while (wait(&wt.w_status) != -1)
  337.         ;
  338.     times(&tms);
  339.     endt = time((time_t *)0);
  340. #endif
  341.     printf ("parameters: flock=%d, fsync=%d, verb=%d\n",
  342.         do_flock, do_sync, verbose);
  343.     printf("  children=%d, iterations=%d, msgs/iterations=%d = %d msgs\n",
  344.            n_child, n_batch, message_batch,
  345.            n_child * n_batch * message_batch);
  346.  
  347. #define ELAPASED    "elapsed time"
  348. #define SYST        "system time"
  349. #define USERT        "user time"
  350. #ifndef SYS5
  351.     tvsub (&tdiff, &endt, &startt);
  352.     printf ("%-14s %d.%06d\n", ELAPASED, tdiff.tv_sec, tdiff.tv_usec);
  353.     printf ("%-14s %d.%06d\n", USERT, rusage.ru_utime.tv_sec,
  354.         rusage.ru_utime.tv_usec);
  355.     printf ("%-14s %d.%06d\n", SYST, rusage.ru_stime.tv_sec,
  356.         rusage.ru_stime.tv_usec);
  357.     printf ("I/O blocks in=%d, blocks out=%d\n", rusage.ru_inblock,
  358.         rusage.ru_oublock);
  359.     mps = tdiff.tv_sec + (double)tdiff.tv_usec / 1000000.0;
  360.     mps = (n_child * n_batch * message_batch) / mps;
  361.     printf ("Gives messages/sec=%.2f\n", mps);
  362. #else
  363.     printf("%-14s %d\n", ELAPASED, endt - startt);
  364.     printf ("%-14s %.2f\n", USERT, (float)tms.tms_cutime / hertz);
  365.     printf ("%-14s %.2f\n", SYST, (float)tms.tms_cstime / hertz);
  366.     printf ("Gives messages-per-sec=%.2f\n", 
  367.         n_child * n_batch * message_batch / (float) (endt - startt));
  368. #endif
  369. }
  370.  
  371.  
  372. #ifndef SYS5
  373. add_ru (ru)
  374. struct rusage *ru;
  375. {
  376.         tvadd(&rusage.ru_utime, &ru->ru_utime);
  377.         tvadd(&rusage.ru_stime, &ru->ru_stime);
  378. #define addru(x) rusage.x += ru -> x;
  379.         addru(ru_maxrss);
  380.         addru(ru_ixrss);
  381.         addru(ru_idrss);
  382.         addru(ru_isrss);
  383.         addru(ru_minflt);
  384.         addru(ru_majflt);
  385.         addru(ru_nswap);
  386.         addru(ru_inblock);
  387.         addru(ru_oublock);
  388.         addru(ru_msgsnd);
  389.         addru(ru_msgrcv);
  390.         addru(ru_nsignals);
  391.         addru(ru_nvcsw);
  392.         addru(ru_nivcsw);
  393. #undef addru
  394. }
  395.  
  396. tvsub (tdiff, t1, t0)
  397. register struct timeval *tdiff,
  398.                         *t1,
  399.                         *t0;
  400. {
  401.  
  402.     tdiff -> tv_sec = t1 -> tv_sec - t0 -> tv_sec;
  403.     tdiff -> tv_usec = t1 -> tv_usec - t0 -> tv_usec;
  404.     if (tdiff -> tv_usec < 0)
  405.         tdiff -> tv_sec--, tdiff -> tv_usec += 1000000;
  406. }
  407.  
  408. tvadd (td, tplus)
  409. struct timeval *td, *tplus;
  410. {
  411.         td -> tv_sec += tplus -> tv_sec;
  412.         td -> tv_usec += tplus -> tv_usec;
  413.         if (td -> tv_usec > 1000000)
  414.                 td -> tv_usec -= 1000000, td -> tv_sec ++;
  415. }
  416.  
  417. #endif
  418.