

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

const unsigned int KB = 1024;
const unsigned int MB = (1024*1024);
const unsigned int SECTORSIZE = 8*KB;
const unsigned int INITIALSIZE = 50;
const unsigned int INCREMENT = 50;
const unsigned int ENDSIZE = 250;
const unsigned int CHUNK =MB;
const unsigned int SIZE = 100;

//int currentExperiment;

void LogError(int ExpNumber) {
  printf("\nError in Experiment %d\n", ExpNumber);
  printf(strerror(errno));
  printf("\n");
  exit(1);
}

void PrintRate(int exp, struct timeval tvBefore, struct timeval tvAfter, int ReadSize) {
  struct timeval tvDiff;
  float rate, timeInSeconds;

  tvDiff.tv_sec = tvAfter.tv_sec - tvBefore.tv_sec;
  tvDiff.tv_usec = tvAfter.tv_usec - tvBefore.tv_usec;
  if (tvDiff.tv_usec < 0) { //adjust for usecs
    tvDiff.tv_usec += 1000000;
    tvDiff.tv_sec--;
  }
  
  timeInSeconds = tvDiff.tv_sec+(float)tvDiff.tv_usec/1000000;
  rate = ReadSize/MB/timeInSeconds;
  
  //output the results
  if ((exp==1)||(exp==3))	
   printf("%d\t%d\t\t%f\n", exp, ReadSize/MB, rate);    
  else
   fprintf(stderr, "%d\t%d\t\t%f\n", exp, ReadSize/MB, rate);     
}
  


int Experiment1() {

  int StartReadSize = INCREMENT*MB, StepReadSize = INCREMENT*MB, EndReadSize = ENDSIZE*MB;
    
  int pid=fork();
  if (pid==0){	

  int fd, j, k;
  char *buffer, *buf;
  unsigned int offset;
  struct timeval tvBefore, tvAfter;  //will hold the time difference
  bool alternate = true;	
  //allocate buffer
   buffer = new char[CHUNK+SECTORSIZE];
   int  currentExperiment = 1;
  //align buffer
  offset = (unsigned int)buffer;

  if (offset % SECTORSIZE) { //not aligned
    buf = buffer + (SECTORSIZE - offset % SECTORSIZE);
  }    
  else {
    buf = buffer;
  }
  

  //loop incrementing the read size each time
  int ReadSize;
  for (ReadSize = StartReadSize; ReadSize <= EndReadSize; ReadSize += StepReadSize) {
    //open the disk file
    //reopening each time you read will always reset to the begining of the 
    //disk, so you don't have to lseek

    //alternate between openning two big files to diminish the effect of file caching
    //between successive reads.
  //  if (alternate) {
   //   alternate = false;
      fd=open("/mnt/scsi_b/736Project/1000MB", O_RDONLY| O_SYNC);
   // }
   // else {
    //  alternate = true;
    //  fd=open("/mnt/scsi_b/736Project/1000MB1", O_RDONLY| O_SYNC);
    //}
    if (fd < 0) {
      LogError(currentExperiment);
    }
    
    //start the timer
    if (gettimeofday(&tvBefore, NULL) == -1) {
      LogError(currentExperiment);
    }
    
    for(j=0; j< (ReadSize/CHUNK); j++) {
      //read the chunk of data in memory
      k=read(fd, buf, CHUNK);
      if (k < 0) {
	LogError(currentExperiment);
      }
    }
    //stop the timer
    if (gettimeofday(&tvAfter, NULL) == -1) {
      LogError(currentExperiment);
    }

    PrintRate(currentExperiment, tvBefore, tvAfter, ReadSize);

    close(fd);  //close the raw interface 
  }
  
  printf("\nExperiment #%d ended Successfully\n", currentExperiment);
 
  //deallocate the buffer
  delete [] buffer;
  }//end of parent
 else{//for child

 //allocate buffer

   int fd, j, k;
   char *buffer, *buf;
   unsigned int offset;
   struct timeval tvBefore, tvAfter;  //will hold the time difference
   bool alternate = true;
   buffer = new char[CHUNK+SECTORSIZE];
  int currentExperiment = 2;
  //align buffer
  offset = (unsigned int)buffer;

  if (offset % SECTORSIZE) { //not aligned
    buf = buffer + (SECTORSIZE - offset % SECTORSIZE);
  }    
  else {
    buf = buffer;
  }
  
  int ReadSize;
  //loop incrementing the read size each time
  for (ReadSize = StartReadSize; ReadSize <= EndReadSize; ReadSize += StepReadSize) {
    //open the disk file
    //reopening each time you read will always reset to the begining of the 
    //disk, so you don't have to lseek

    //alternate between openning two big files to diminish the effect of file caching
    //between successive reads.
 //   if (alternate) {
   //   alternate = false;
      fd=open("/mnt/scsi_b/736Project/1000MB1", O_RDONLY| O_SYNC);
   // }
   // else {
    //  alternate = true;
    //  fd=open("/mnt/scsi_b/736Project/1000MB3", O_RDONLY| O_SYNC);
   // }
    if (fd < 0) {
      LogError(currentExperiment);
    }
    for(int ij=0; ij<2; ij++){
    //start the timer
    if (gettimeofday(&tvBefore, NULL) == -1) {
      LogError(currentExperiment);
    }
    
    for(j=0; j< (ReadSize/CHUNK); j++) {
      //read the chunk of data in memory
      k=read(fd, buf, CHUNK);
      if (k < 0) {
	LogError(currentExperiment);
      }
    }
    //stop the timer
    if (gettimeofday(&tvAfter, NULL) == -1) {
      LogError(currentExperiment);
    }

    PrintRate(currentExperiment, tvBefore, tvAfter, ReadSize);
    }//end of ij loop 
    close(fd);  //close the raw interface 
  }
  
  printf("\nExperiment #%d ended Successfully\n", currentExperiment);
 
  //deallocate the buffer
  delete [] buffer;


  }


}



int Experiment3() {

  int StartReadSize = INCREMENT*MB, StepReadSize = INCREMENT*MB, EndReadSize = ENDSIZE*MB;
    
  int pid=fork();
  if (pid==0){	

  int fd, j, k;
  char *buffer, *buf;
  unsigned int offset;
  struct timeval tvBefore, tvAfter;  //will hold the time difference
  bool alternate = true;	
  //allocate buffer
   buffer = new char[CHUNK+SECTORSIZE];
   int  currentExperiment = 3;
  //align buffer
  offset = (unsigned int)buffer;

  if (offset % SECTORSIZE) { //not aligned
    buf = buffer + (SECTORSIZE - offset % SECTORSIZE);
  }    
  else {
    buf = buffer;
  }
  

  //loop incrementing the read size each time
  int ReadSize;
  for (ReadSize = StartReadSize; ReadSize <= EndReadSize; ReadSize += StepReadSize) {
    //open the disk file
    //reopening each time you read will always reset to the begining of the 
    //disk, so you don't have to lseek

    //alternate between openning two big files to diminish the effect of file caching
    //between successive reads.
  //  if (alternate) {
   //   alternate = false;
      fd=open("/mnt/scsi_b/736Project/1000MB",O_WRONLY | O_SYNC);
   // }
   // else {
    //  alternate = true;
    //  fd=open("/mnt/scsi_b/736Project/1000MB1", O_RDONLY| O_SYNC);
    //}
    if (fd < 0) {
      LogError(currentExperiment);
    }
    
    //start the timer
    if (gettimeofday(&tvBefore, NULL) == -1) {
      LogError(currentExperiment);
    }
    
    for(j=0; j< (ReadSize/CHUNK); j++) {
      //read the chunk of data in memory
      k=write(fd, buf, CHUNK);
      if (k < 0) {
	LogError(currentExperiment);
      }
    }
    //stop the timer
    if (gettimeofday(&tvAfter, NULL) == -1) {
      LogError(currentExperiment);
    }

    PrintRate(currentExperiment, tvBefore, tvAfter, ReadSize);

    close(fd);  //close the raw interface 
  }
  
  printf("\nExperiment #%d ended Successfully\n", currentExperiment);
 
  //deallocate the buffer
  delete [] buffer;
  }//end of parent
 else{//for child

 //allocate buffer

   int fd, j, k;
   char *buffer, *buf;
   unsigned int offset;
   struct timeval tvBefore, tvAfter;  //will hold the time difference
   bool alternate = true;
   buffer = new char[CHUNK+SECTORSIZE];
  int currentExperiment = 4;
  //align buffer
  offset = (unsigned int)buffer;

  if (offset % SECTORSIZE) { //not aligned
    buf = buffer + (SECTORSIZE - offset % SECTORSIZE);
  }    
  else {
    buf = buffer;
  }
  
  int ReadSize;
  //loop incrementing the read size each time
  for (ReadSize = StartReadSize; ReadSize <= EndReadSize; ReadSize += StepReadSize) {
    //open the disk file
    //reopening each time you read will always reset to the begining of the 
    //disk, so you don't have to lseek

    //alternate between openning two big files to diminish the effect of file caching
    //between successive reads.
 //   if (alternate) {
   //   alternate = false;
      fd=open("/mnt/scsi_b/736Project/1000MB1", O_WRONLY |O_SYNC);
   // }
   // else {
    //  alternate = true;
    //  fd=open("/mnt/scsi_b/736Project/1000MB3", O_RDONLY| O_SYNC);
   // }
    if (fd < 0) {
      LogError(currentExperiment);
    }
    
    //start the timer
    if (gettimeofday(&tvBefore, NULL) == -1) {
      LogError(currentExperiment);
    }
    
    for(j=0; j< (ReadSize/CHUNK); j++) {
      //read the chunk of data in memory
      k=write(fd, buf, CHUNK);
      if (k < 0) {
	LogError(currentExperiment);
      }
    }
    //stop the timer
    if (gettimeofday(&tvAfter, NULL) == -1) {
      LogError(currentExperiment);
    }

    PrintRate(currentExperiment, tvBefore, tvAfter, ReadSize);

    close(fd);  //close the raw interface 
  }
  
  printf("\nExperiment #%d ended Successfully\n", currentExperiment);
 
  //deallocate the buffer
  delete [] buffer;


  }


}






int main(){

 
   Experiment1();
   //Experiment3();

}









