#include <stdio.h>
#include <stdlib.h>
#include <sys/file.h>
#include <strings.h>
#include <iostream.h>
#include <fstream.h>
#include <string>

#include "iotrace.h"

#define InputFileNum 64
#define SPARCECONSTANT 1000000

FILE *fp[InputFileNum];
unsigned servermap[InputFileNum];
char tracename[InputFileNum][64];
unsigned tickets[InputFileNum];
unsigned char flag[InputFileNum];
unsigned clientnum;    
unsigned servernum;

int readconf(char * confname)
{
  char tmp[256];

  fstream input;

  int inputleft = 0;

  input.open(confname, ios::in);
  if (!input) {
    cout << "File Open Failed ! " << endl;
    exit(1);
  }

  input.seekg(0, ios::beg);
  if (input.getline(tmp, 256, '\n') == 0)
    return 0;

  servernum = atoi(strtok(tmp, " \n"));
  //  clientnum = atoi(strtok(tmp, " \n"));

  while (input.getline(tmp, 256, '\n')) {
    if ((tmp[0] == 0)||(tmp[0] == ' ')||(tmp[0] == '\n')||(tmp[0] == '\r'))
      break;
  
    // open input file
    strcpy(tracename[inputleft], strtok(tmp, " "));
    fp[inputleft] = fopen(tracename[inputleft], "rb");
    if (fp[inputleft] == NULL) {
      cout << "File " << inputleft + 1 << "  Open Error" << endl;
      exit(1);
    }

    tickets[inputleft] =  atoi(strtok(NULL, " "));
    servermap[inputleft] = atoi(strtok(NULL, " \n"));
    flag[inputleft] = 1;
    inputleft++;
    
    if (inputleft > InputFileNum) {
      cout << "cannot have more than " << InputFileNum << " files " << endl;
      exit(1);
    }
  } // end of while

  clientnum = inputleft;

  input.close();

  srandom(731419); // initialize the seed

  return 1;
}

int outputconf(FILE * out)
{
  fwrite((const void *)&servernum, sizeof(unsigned), 1, out);
  fwrite((const void *)&clientnum, sizeof(unsigned), 1, out);

  for (int i = 0 ; i < clientnum ; i ++)
    {
      fwrite((const void *)tracename[i], sizeof(char), 64, out);
      fwrite((const void *)&tickets[i], sizeof(unsigned), 1, out);
      fwrite((const void *)&servermap[i], sizeof(unsigned), 1, out);
    } // end of for

  return 0;
}

int NextTrace()
{
  unsigned alltickets = 0;

  for (int i = 0; i < clientnum; i++)
    if (flag[i])
      alltickets += tickets[i];

  int chooseticket = random() % alltickets;

  for (int i = 0; i < clientnum; i++)
    if (flag[i]) {
      chooseticket -= tickets[i]; 
      if (chooseticket < 0) 
	return i;
    }
  
  return 0; // never be here
}

void ModTraceRec(struct tracerecord &record, int index)
{
  record.pid = index; // user id;

  record.i_dev =  servermap[index];
  record.i_num = (index * SPARCECONSTANT) + record.i_num;
}

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

  // open output file
  if (argc < 3) {
    printf("usage: %s configfile outputfilename\n", argv[0]);
    exit(1);
  }

  if (readconf(argv[1]) == 0)
    return 0;

  FILE *outfp = fopen(argv[2], "wb");

  if (outfp == NULL) {
    printf("output file open error\n");
    exit(1);
  }

  outputconf(outfp);

  int inputleft = clientnum;

  struct tracerecord record;

  int size;

  while (inputleft > 0) {

    // decide where does next trace come from
    int index = NextTrace();

    if ((size = fread(&record, sizeof(struct tracerecord), 1, fp[index])) != 0) 
      {
      
	if ((record.op >= MYTRACE_READ) && (record.op <= MYTRACE_EXIT) 
	    && ((record.i_dev == 5382) || (record.i_dev == 5418))) 
	  {
	    ModTraceRec(record, index);
		
	    fwrite(&record, sizeof(struct tracerecord), 1, outfp);
	  }
      }
    else
      {  
	inputleft--;
	flag[index] = 0;
      }

  } // end of while

  // close file
  fclose(outfp);

  for (int i = 0; i < clientnum; i++)
    fclose(fp[i]);
}
