#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/wait.h>
#include <stdint.h>
#include <fcntl.h>
#include "../lve-ctl.h"
#define DIFF_T(a,b) ( (a.tv_sec - b.tv_sec) + (double)(a.tv_usec - b.tv_usec)/1000000 )

struct liblve *lve;

execLS() {
  int out_fd = open("/dev/null", O_RDWR);
  dup2(out_fd, 1);
  execlp("/bin/ls", "-l", "/etc", NULL);
}

execlsInLVE(int id) {
      uint32_t p_cookie;
      if (lve_enter(lve, 900+id, -1, -1, &p_cookie)) {
	exit(-1);
      }
      execLS();
      /* I will never get there 
      if (lve_leave(lve, &p_cookie)) {
	printf("lve_leave failed");
	exit(-1);
      }
      */
}

forkLVE(int id) {
  pid_t pid;
  pid = fork();
  if (pid == 0) {
    execlsInLVE(id);
  } else if (pid < 0) {
    printf("Failed to fork\n");
    exit(1);
  }
}

forkLS() {
  pid_t pid;
  pid = fork();
  if (pid == 0) {
    execLS();
  } else if (pid < 0) {
    printf("Failed to fork\n");
    exit(1);
  }
}

main() 
{
  const char* strId;
  int i,j;
  pid_t pID;
  struct timeval start, end;  
  double a,b,c,d;
  int rc;
  rc = lve_instance_init(NULL);
//  printf("LVE data size %d\n", rc);
  lve = malloc(rc);
  rc = lve_instance_init(lve);
  if (rc != 0) {
    printf("Can't init lve instance %d\n", rc);
    _exit(-1);
  }
//  printf("Successfull init lve instance %d - %d\n", rc, getpid());
  
  gettimeofday(&start, NULL);
  for (i = 0; i < 100; i++) {
    forkLVE(i);
  }

  int status;
  for (i = 0; i < 20000; i++) { //as soon as one finished, start another one
      wait(&status);
      forkLVE(i%10000);
  }
  gettimeofday(&end, NULL);

//  printf("lve fork exec - time took %.6f sec, avg: %.6f\n", 
	   a=DIFF_T(end, start); b=DIFF_T(end, start)/1020;
  lve_instance_destroy(lve);


  gettimeofday(&start, NULL);
  for (i = 0; i < 100; i++) {
    forkLS();
  }

  for (i = 0; i < 20000; i++) { //as soon as one finished, start another one
      wait(&status);
      forkLS();
  }
  gettimeofday(&end, NULL);
//  printf("no lve fork exec - time took %.6f sec, avg: %.6f\n", 
	   c=DIFF_T(end, start); d=DIFF_T(end, start)/1020;
    printf("With LVE\tWithout LVE\n");
    printf("%.6f\t%.6f\n%.6f\t%.6f\n",a,c,b,d);
  return 0;
}
