#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/time.h>

int main(int argc, char * argv[]) {

    int i, j;

    int filecount;
    int filesize;
    int writesize;

    int files[2048];

    int  writecount;
    
    struct timeval start_time, end_time;

    if (argc < 4) {
        printf("invalid number of arguments: %d\n", argc);
        return 1;
    }

    filecount = atoi(argv[1]);
    filesize  = atoi(argv[2]);
    writesize = atoi(argv[3]);

    printf("files=%d size=%d write=%d\n", filecount, filesize, writesize);

    if (filecount < 1) {
        printf("invalid file count (%d)\n", filecount);
        return 2;
    }

    if (filesize < 1) {
        printf("invalid file size (%d)\n", filesize);
        return 3;
    }

    if ((writesize < 1) || (writesize > 1024)) {
        printf("invalid write size (%d)\n", writesize);
        return 4;
    }

    writecount = (filesize * 1024L * 1024L) / writesize;

    for (i = 0; i < filecount; i++) {

        char filename[1024];
        sprintf(filename, "iotest.%d", i);

        files[i] = creat(filename, S_IRWXU);

        if (files[i] == -1) {
            filecount = (i+1);
            goto cleanup;
        }

    }

    gettimeofday(&start_time, NULL);

    int x = writecount / 10;

    for (j = 0; j < writecount; j++) {

        char data[writesize];

        for (i = 0; i < writesize; i++) {
            data[i] = rand() % 256;
        }

        for (i = 0; i < filecount; i++) {
            ssize_t l = write(files[i], data, writesize);
            if (l != writesize) {
                printf("ERROR writing data (%ld) : %d (file %d) : %s\n", l, errno, files[i], strerror(errno));
                goto cleanup;
            }
        }

        if (j == x) {
                printf("written %.0f %%\n", (100.0 * j) / writecount);
                x += writecount / 10;
        }

    }

    gettimeofday(&end_time, NULL);

    double duration = (end_time.tv_sec - start_time.tv_sec) + (end_time.tv_usec - start_time.tv_usec) / 1000000.0;

    printf("duration = %.2f\n", duration);

    for (i = 0; i < filecount; i++) {
        fsync(files[i]);
    }

    gettimeofday(&end_time, NULL);

    duration = (end_time.tv_sec - start_time.tv_sec) + (end_time.tv_usec - start_time.tv_usec) / 1000000.0;

    printf("duration (with fsync) = %.2f\n", duration);

cleanup:

    for (i = 0; i < filecount; i++) {

        char filename[1024];
        sprintf(filename, "iotest.%d", i);

        close(files[i]);
        unlink(filename);

    }

return 0;

}