#!/bin/perl
#
# ParallelRunner: A generic program which reads a file with (commands probabily)
# and runs at most MAX_PROCESS's in parallel. It makes sure that at any instant 
# there are atmost MAX_PROCESS's in the system.
#
# There are several applications of this simple program, for example regression running
# I'm currently using for my parallel crawling program.
#
# April 27, 2008 , vamsik@engr.uconn.edu
#
# lines with '#' in the begining are ignored
#

$#ARGV == 1 or die("USAGE: perl parallel_runner.pl <file_with_commands> <no.of.process's>");
$command_file = $ARGV[0];
open(CMD_FILE,$command_file) or die("$!");
$max_process = $ARGV[1];
($max_process < 256) or die("Too many process's....use less number");

%child_hash;
$process_count = 0;

while(<CMD_FILE>){
	$cmd = $_;
	if($cmd =~ /^\#/){
		next;
	}
	if($process_count < $max_process){
		$pid = fork();
		if($pid < 0 ){
			die("$! : RESOURCE ERRORS");
		}elsif($pid == 0){
#Child
			system("$cmd");
			exit(0);
		}else{
#Parent
			$child_hash{$pid} = 1;
			$process_count++;
		}
	}

	if($process_count==$max_process){
		#print "Process's in the system are now $max_process \n";
		#print "The scheduler will wait until some die's.......\n";
		$pid = wait();
		if($child_hash{$pid} == 1){
			#print "Valid Child\n";
			$child_hash{$pid} = 0;
		}elsif($pid == -1){
			#print "No childs to wait?? Confused...quitting\n";
			last;
		} 
		#print "CHILD finished $pid \n";
		$process_count--;
	}
}
#print "Done creating process's...now waiting for childs...\n";
#
# Wait for all the guys to complete. Avoiding while(1)
#

$i = 0;
while($i < $max_process){
	$pid = wait();
	if($pid == -1){
		#print "....I'm Done......\n";
		last;
	}
	$i++;
}

