/*
* wrbench
*
* SYNOPSIS      A simple write-random benchmark application.
* USAGE         wrbench [-d device] [-s device-size] [-b io-size]
* EXAMPLE       wrbench -d /dev/rdsk/c1t6d0s0 -b 512 -s 9000000000
*               (For a Sun 9GB disk, 512 byte IO size)
*
* Written by G. D. Musumeci <gdm@oreilly.com> for O'Reilly &
          * Associates. This source code is released under the terms of
          * the BSD License.
*/

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>


int
main(int argc, char **argv)
{
    extern char *optarg;
    int c, r, FD;
    char *device, *buf;
    uint64_t deviceSize = 0;
    int ioSize = 512, iter = 512;
    hrtime_t st, ft;
    long double t;
    off64_t s, e;

/* Parse command-line options */
    while ((c = getopt(argc, argv, "d:s:b:i:")) != -1) {
        switch(c) {
             case 'd':
                 device = (char *)strdup(optarg);
                 break;
             case 's':
                 deviceSize = atoll(optarg);
                 break;
             case 'b':
                 ioSize = atoi(optarg);
                 break;
             case 'i':
                 iter = atoi(optarg);
                 break;
             case '?':
                 if (isprint(optopt)) {
                     fprintf(stderr, "Unknown option `-%c'.\n", getopt);
                 } else {
                     fprintf(stderr, "Unknown option character `\\s%xc'.\n",
                             optopt);
                 }
                 return 1;
         }
     }

     /* Quick sanity check */
     if (device == NULL) {
         fprintf(stderr, "wrbench: must specify a device to test with -d\n");
         exit(1);
     }

     fprintf(stderr, "wrbench: Testing %s (%lld bytes) with %d-byte 
writes\n", device, deviceSize, ioSize);

     /* Allocate space for *buf */
     buf = (char *)malloc(ioSize * sizeof(char));

     /* Seed the random number generator */
     st = gethrtime();
     srand48((long) st);

     /* Open the device */
     if ((FD = open(device, O_WRONLY | O_LARGEFILE | O_SYNC)) < 0) {
         fprintf(stderr, "wrbench: unable to open %s: %d\n",
                 device, FD);
         exit(1);
     }

     /* Start timing */
     st = gethrtime();


     /* Seek and write -- lather, rinse, repeat */
     for (c = 0; c < iter; c++) {
         /* Insert a random seek */
         s = (((deviceSize - 2048) * drand48()) + 512) / 512;
         e = lseek64(FD, (s * 512), SEEK_SET);
         if (e < 0)
             perror("wrbench: lseek64() error");

         /* Perform the write */
         r = write(FD, buf, (size_t)ioSize);
     }

     /* Stop timing */
     ft = gethrtime();

     close(FD);

     t = ((long double)ft - (long double)st) / 1000000000;
     /* Output the result */
     fprintf(stderr, "wrbench: %0.Lf %d-byte IOs/sec\n",
             (iter / t), ioSize);
     }