#!/usr/bin/perl -w

use Getopt::Long;
use POSIX "sys_wait_h";
use File::Basename;

#globals
my $config_file;
my %config;
my $rc = 0;
my $prog_name;
my $pid;
my $retry;
				
if (init()) {
    exit 1;
}

# Set to one to enable retry if nodes are bad, experimental so turned off by default
$retry = 0;

my $prog_root = $config{"PROGROOT"};
my $working_dir = $config{"WORKINGDIR"};
my $ionodecount = $config{"IONCOUNT"};
my $metacount = $config{"METACOUNT"};

@commands = ("$prog_root/pav_create -c $config_file -n $ionodecount -e $metacount",
	"$prog_root/pav_check -ping -one-all -sd $working_dir", 
	"$prog_root/pav_dist -sd $working_dir", 
	"$prog_root/pav_init -sd $working_dir");
    
mainloop:
my $done = 0;
while(!$done) {
    my $stage = 0;
    foreach $cmd (@commands) {
	print "PAV: stage $stage running command: $cmd\n";
	$rc = system("$cmd");
	$rc = $rc >> 8;
	print "--------------------------------------------------------------------------------\n";
#	print "PAV: stage $stage command complete: $rc\n";

	if ($rc == 1) {
	    if ($retry) {
		print STDERR "WARNING: recoverable error encountered, cleaning up and trying again...\n";
	    
		@stop_commands = ("$prog_root/pav_uninit -sd $working_dir", "$prog_root/pav_clean -sd $working_dir");
		foreach $stop_cmd (@stop_commands) {
		    print "PAV: cleaning up: $stop_cmd\n";
		    $rc = system("$stop_cmd");
		    print "--------------------------------------------------------------------------------\n";
		    
		}

		@commands = ("$prog_root/pav_create -sd $working_dir", "$prog_root/pav_dist -sd $working_dir", "$prog_root/pav_init -sd $working_dir");

		goto mainloop;
	    } else {
		print "ERROR: recoverable error encountered, retry turned off: please check node list and make sure all nodes are available/healthy!\n";
		exit(1);
	    }
	} elsif ($rc == 2) {
	    print STDERR "ERROR: unrecoverable error running command: $cmd\n";
	    exit(1);
	}
	$stage++;
    }
    $done++;
}

exit(0);

sub usage {

    print<<EOF;
Usage: $prog_name [option]
-c -config        configuration file for PAV to use
-r -root          path to program root (default ./)
-m -machinefile   file with list of available nodes
-n -ionodecount   number of nodes to use for IO
-e -metanodecount number of nodes to use as metadata servers
-h -help          display this message
EOF
}

sub init {
    GetOptions(\%args,
	       'c|config:s',
	       'r|root:s',
	       'm|machinefile:s',
	       'n|ionodecount:i',
	       'e|metanodecount:i',
	       'h|help'
	       );

    $prog_name = $0;
    $pid = $$;
 
    if ($args{'h'}) {
	usage();
	return(1);
    }

    $config_file = $args{'c'} || "~/auto_pvfsvol.conf";
    if (!-f $config_file) {
	print STDERR "ERROR: cannot find config file: $config_file\n";
	usage();
	return(1);
    }
    
    %config = ('PVFSPORT' => 3334,
	       'WORKINGDIR' => "/tmp",
	       'IONCOUNT' => 4,
	       'METACOUNT' => 1,
	       'NODEFILE' => "machine_file",
	       'PROTOCOL' => 0,
	       'UNIQUEMETA' => 0,
	       'STORAGE' => "/tmp/data",
	       'SERVERLOG' => "/tmp/log",
	       'MOUNTPOINT' => "/pvfs_auto",
	       'BINDIR' => "/tmp/bin",
	       'PROG' => "pvfs2-server",
	       'PINGPROG' => "pvfs2-ping",
	       'GENCONFIG' => "pvfs2-genconfig",
	       'TROVESYNC' => 1,
	       'TROVEMETHOD' => "dbpf",
	       'COMPUTENODES_LAST' => 1,
	       'PROGROOT' => "./"
	       );
 
    $config{'PROGROOT'} = real_dir($0) || $config{'PROGROOT'};
    ($config{'USERNAME'}) = getpwuid($>);
    my ($gid) = split(/\s*/, $();
    ($config{'GROUPNAME'}) = getgrgid($gid);

    $config{'PROGROOT'} = $args{'r'} || $config{'PROGROOT'};
    my $prog_root = $config{'PROGROOT'};
    require "$prog_root/pav_lib.pl";
    
    $rc = read_configfile($config_file, \%config);
    if ($rc) {
	print STDERR "ERROR: reading config file\n";
	return($rc);
    }

    $config{'PROGROOT'} = $args{'r'} || $config{'PROGROOT'};
    $config{'NODEFILE'} = $args{'m'} || $config{'NODEFILE'};
    $config{'IONCOUNT'} = $args{'n'} || $config{'IONCOUNT'};
    $config{'METACOUNT'} = $args{'e'} || $config{'METACOUNT'};
    
    return(0);
}

sub real_dir {
   my ($file, $reldir, $suffix) = fileparse(shift);
   my ($realdir, $envpwd);

   if ($reldir =~ /^\//) {
      $realdir = $reldir;
   } else {
      if (!$ENV{PWD}) {
         chomp($envpwd = `pwd`);
      } else {
         $envpwd = $ENV{PWD};
      }
      $realdir = $envpwd . "/$reldir";
   }
   $realdir .= '/';
   $realdir =~ s#/./#/#g;
   $realdir =~ s#//#/#g;
   return($realdir);
}
