/*
 * Copyright 2011 Steven Gribble
 *
 *  This file is part of the UW CSE 333 course project sequence
 *  (333proj).
 *
 *  333proj is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  333proj is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with 333proj.  If not, see .
 */
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
void PrintBandwidth(struct timeval start_t,
                    struct timeval stop_t,
                    int numbytes);
#define BUFSIZE 65536
#define WRITELEN (65536*4096)
#define FILENAME "writefile.bin"
int main(int argc, char **argv) {
  int fd_out;
  char buf[BUFSIZE];
  ssize_t writelen;
  int writecount;
  struct timeval start_t, stop_t;
  // Open the output file
  while (1) {
    fd_out = open(FILENAME,
                  O_WRONLY | O_TRUNC | O_CREAT,
                  S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
    if (fd_out == -1) {
      if ((errno == EINTR) || (errno == EWOULDBLOCK)) {
        // Try again.
        continue;
      }
      // Fail.
      perror("Couldn't open writefile.bin for writing");
      exit(EXIT_FAILURE);
    }
    // The open succeeded, so break out of the loop.
    break;
  }
  // Grab a start timestamp.
  assert(gettimeofday(&start_t, NULL) == 0);
  // Write WRITELEN bytes
  writecount = 0;
  while (writecount < WRITELEN) {
    // Try to write BUFSIZE bytes to the output file.
    writelen = write(fd_out,
                     (void *) buf,
                     (size_t) BUFSIZE);
    if (writelen == -1) {
      if ((errno == EINTR) ||
          (errno == EWOULDBLOCK) ||
          (errno == EAGAIN))
        continue;
      perror("write failed");
      exit(EXIT_FAILURE);
    }
    writecount += writelen;
  }
  // flush the output file
  if (fsync(fd_out) != 0) {
    perror("fsync of output file failed");
    exit(EXIT_FAILURE);
  }
  // Grab a stop timestamp.
  assert(gettimeofday(&stop_t, NULL) == 0);
  // Done!
  PrintBandwidth(start_t, stop_t, WRITELEN);
  // Clean up; close the file descriptor, delete
  // the file we created.
  close(fd_out);
  assert(unlink(FILENAME) == 0);
  return EXIT_SUCCESS;  // defined in stdlib.h
}
void PrintBandwidth(struct timeval start_t,
                    struct timeval stop_t,
                    int numbytes) {
  double total_seconds, bw;
  total_seconds = (stop_t.tv_sec - start_t.tv_sec);
  total_seconds += (stop_t.tv_usec - start_t.tv_usec) / 1000000.0;
  bw = ((double) numbytes) / total_seconds;
  bw = bw / 1000000.0;
  fprintf(stdout, "Bandwidth: %f MB/s\n", bw);
}