#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <unistd.h>
#include <string.h>


#define SIZE	8192

static char buf[SIZE];
static char *name;
static char *prog_name;


extern int errno;

static char timebuf[512];

time_t ds;
time_t du;
struct timeval s, f;

void start()
{
    gettimeofday(&s, NULL);
}


void stop()
{
    gettimeofday(&f, NULL);
    ds = f.tv_sec - s.tv_sec;
    du = f.tv_usec - s.tv_usec;
    if (du < 0) {
      ds -= 1;
      du += 1000000;
    }
    sprintf(timebuf, "%d.%06d", (unsigned int)ds, (unsigned int)du);
}


#define TRULY_RANDOM


int fff(int i, int n)
{
    return ((i * 11) % n);
}


int g(int i, int n)
{
    if (i % 2 == 0) return(n / 2 + i / 2);
    else return(i / 2);
}


void read_test(int n, int size, int sequential)
{
    int i=0;
    int r;
    int fd;
    long pos;


    if (sequential) {
      printf ("Doing sequential read\n");
    } else {
      printf ("Doing random read\n");
    }
    start();
    
    if((fd = open(name, O_RDONLY)) < 0) {
	printf("%s: open %d failed %d %d\n", prog_name, i, fd, errno);
	exit(1);
    }



    for (i = 0; i < n; i ++) {
	if (!sequential) {

#ifdef TRULY_RANDOM
	    pos = (random() % n) * size;
#else
	    pos = g(i, n) * size;
#endif

	    if ((r = lseek(fd, pos, 0)) < 0) {
		printf("%s: lseek failed %d %d\n", prog_name, r, errno);
	    }
	}

	if ((r = read(fd, buf, size)) < 0) {
	    printf("%s: read failed %d %d\n", prog_name, r, errno);
	    exit(1);
	}
    }
    
    if ((r = close(fd)) < 0) {
	printf("%s: close failed %d %d\n", prog_name, r, errno);
    }
    

    stop();
    printf("%s: read took %s sec\n", prog_name, timebuf);
}


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

    prog_name = argv[0];

    if (argc != 5) {
	printf("%s: %s num size test filename (where test==0 random, test==1 seq)\n", prog_name, prog_name);
	exit(1);
    }

    n = atoi(argv[1]);
    size = atoi(argv[2]);
    name = argv[4];

    printf("%s %d %d\n", prog_name, n, size);

    srandom(getpid());
    

    read_test(n, size, atoi (argv[3]));
    return 0;

}


/*
 *			     Print rusage
 */
/*
#include <sys/time.h>
#include <sys/resource.h>

print_rusage()
{
    struct rusage returnUsage;
    if (getrusage(RUSAGE_SELF, &returnUsage) != 0) return;

    printf("ru_maxrss %d ru_minflt %d ru_majflt %d ru_nswap %d ru_inblock %d "
	   "ru_oublock %d ru_msgsnd %d ru_msgrcv %d ru_nsignals %d "
	   "ru_nvcsw %d ru_nivcsw %d\n",
	   returnUsage.ru_maxrss, returnUsage.ru_minflt, returnUsage.ru_majflt,
	   returnUsage.ru_nswap, returnUsage.ru_inblock,
	   returnUsage.ru_oublock, returnUsage.ru_msgsnd,
	   returnUsage.ru_msgrcv,
	   returnUsage.ru_nsignals, returnUsage.ru_nvcsw,
	   returnUsage.ru_nivcsw);

    printf("user time %ld sec %ld usec system time %ld sec %ld usec\n",
	   returnUsage.ru_utime.tv_sec, returnUsage.ru_utime.tv_usec,
	   returnUsage.ru_stime.tv_sec, returnUsage.ru_stime.tv_usec);
}
*/
