#!/usr/bin/perl -w
# input: directory(contain files to be codeml)
# numberofproceses(how many processes to produce)
# tempDirectoryName(child processes will work under
# directory based on this name)
# output: output files will be in the same directory as input files;
#
# input files must end with .codeml
use strict;
use warnings;
my($dir,$num,$tempDir)=@ARGV;
die ("$0: dir numberOfProcesses tempDirectoryName") unless($dir && $num && $tempDir);
$dir=~s///$//;
# read control file
my $ctlFile;
open(my $f,"<codeml.ctl") or die "cannot find codeml.ctl";
{
local $/;
$ctlFile=<$f>;
}
close($f);
# distribute files
opendir(my $d,$dir) or die $!;
my @files=sort grep {//.codeml$/} readdir($d);
close($d);
my $fileNum=@files;
my $fileno=0;
my @processes;
for(my $i=0;$i<$num;$i++)
{
# assign files
$processes[$i]{'startNo'}=$fileno;
if($fileno+int($fileNum/$num)>$fileNum)
{
$fileno=$fileNum;
}
else
{
$fileno+=int($fileNum/$num);
}
$processes[$i]{'endNo'}=$fileno-1;
# make directories for child processes;
if(-e "${tempDir}_$i")
{
die "${tempDir}_$i exists!! aborted./n";
}
else
{
`mkdir ${tempDir}_$i`;
}
}
# ready to work
my $pid;
my @child_pid;
my $id;
for($id=0;$id<$num;$id++)
{
$pid=fork();
if($pid==0){last;}
else{push(@child_pid,$pid);}
}
# child procese $id
if($pid==0)
{
print STDERR "$id pid=$$ get to work/n";
for(my $fileid=$processes[$id]{'startNo'};$fileid<=$processes[$id]{'endNo'};$fileid++)
{
my $myctlFile=$ctlFile;
`rm ${tempDir}_$id/* 1>>${tempDir}_$id.log`;
open($f,">${tempDir}_$id/codeml.ctl") or die $!;
my $newFileName="$dir/$files[$fileid]";
#$myctlFile=~s/SEQFILE/$newFileName/g;
print $f $myctlFile;
close($f);
my $pwd=`pwd`;
chomp($pwd);
my $exec="cd $pwd/${tempDir}_$id;".
"cp /"$dir/$files[$fileid]/" SEQFILE;".
"codeml codeml.ctl 1>>../${tempDir}_$id.log;".
"mv mlc /"$dir/$files[$fileid].mlc/"";
`$exec`;
}
print STDERR "$id pid=$$ finished./n";
exit(0);
}
# parent process
if($pid!=0)
{
while(wait()!=-1){}
print STDERR "All finished/n";
exit(0);
}