PageRenderTime 55ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/BRI_RNAseq_Nextera_optimized/trinity/v2.0.6/util/deprecated/cmd_process_forker.pl

https://gitlab.com/pooja043/Globus_Docker_1
Perl | 222 lines | 140 code | 57 blank | 25 comment | 22 complexity | e4112ccde16617c78b14ae9139ab59cf MD5 | raw file
  1. #!/usr/bin/env perl
  2. use strict;
  3. use warnings;
  4. use FindBin;
  5. use Getopt::Long qw(:config no_ignore_case bundling);
  6. use List::Util qw (shuffle);
  7. my $usage = <<_EOUSAGE_;
  8. #################################################################################
  9. #
  10. # -c <string> filename containing a list of commands to execute, one cmd per line.
  11. #
  12. # --CPU Default: 1
  13. #
  14. # --shuffle randomly orders the commands before executing them.
  15. #
  16. ###################################################################################
  17. _EOUSAGE_
  18. ;
  19. my $cmds_file = "";
  20. my $CPU = 1;
  21. my $shuffle_flag = 0;
  22. &GetOptions (
  23. "c=s" => \$cmds_file,
  24. "CPU=i" => \$CPU,
  25. "shuffle" => \$shuffle_flag,
  26. );
  27. unless ($cmds_file) {
  28. die $usage;
  29. }
  30. my $log_dir = "cmds_log.$$";
  31. mkdir($log_dir) or die "Error, cannot mkdir $log_dir";
  32. ## This is very cheap 'parallel-computing' !!! :)
  33. my $uname = `uname -n`;
  34. chomp $uname;
  35. print "SERVER: $uname, PID: $$\n";
  36. my $ENCOUNTERED_FAILURE = 0;
  37. main: {
  38. my %job_tracker;
  39. my @failed_jobs;
  40. my $num_running = 0;
  41. my @unix_cmds; # just command strings such as you would launch directly from a bash shell.
  42. my %completed_cmds = (); # list of completed commands
  43. my $completed_file_name = $cmds_file.".completed";
  44. {
  45. ## process list of completed commands
  46. if(-f ($completed_file_name)){
  47. open (my $fh, "<", $completed_file_name) or die "Error, cannot open completion file for reading $completed_file_name";
  48. while (<$fh>) {
  49. chomp;
  50. $completed_cmds{$_} = 1;
  51. }
  52. }
  53. ## load all commands in memory... filesystem glitches can otherwise result in premature termination with inadvertent success status.
  54. open (my $fh, $cmds_file) or die "Error, cannot open file $cmds_file";
  55. while (my $cmd = <$fh>) {
  56. chomp $cmd;
  57. if(!$completed_cmds{$cmd}){
  58. push (@unix_cmds, $cmd);
  59. }
  60. }
  61. close $fh;
  62. }
  63. if ($shuffle_flag) {
  64. @unix_cmds = shuffle(@unix_cmds);
  65. }
  66. my $cmd_counter = 0;
  67. foreach my $cmd (@unix_cmds) {
  68. $cmd_counter++;
  69. $num_running++;
  70. my $child = fork();
  71. if ($child) {
  72. # parent
  73. $job_tracker{$cmd_counter} = $cmd;
  74. }
  75. else {
  76. # child:
  77. my $ret = &run_cmd($cmd_counter, $cmd);
  78. exit($ret);
  79. }
  80. if ($num_running >= $CPU) {
  81. wait();
  82. my $num_finished = &collect_jobs(\%job_tracker, \@failed_jobs, $completed_file_name);
  83. $num_running -= $num_finished;
  84. ## collect the other finished children to avoid build-up of zombie processes.
  85. for (1..$num_finished-1) {
  86. wait();
  87. }
  88. }
  89. }
  90. ## collect remaining processes.
  91. while (wait() != -1) { };
  92. &collect_jobs(\%job_tracker, \@failed_jobs, $completed_file_name);
  93. # purge log directory
  94. `rm -rf $log_dir`;
  95. my $num_failed_jobs = scalar @failed_jobs;
  96. if (! $ENCOUNTERED_FAILURE) {
  97. print "\n\nAll $cmd_counter jobs completed successfully! :) \n\n";
  98. exit(0);
  99. }
  100. else {
  101. unless ($num_failed_jobs == $ENCOUNTERED_FAILURE) {
  102. print "\n\nError, $ENCOUNTERED_FAILURE jobs failed, but only have recorded $num_failed_jobs ... very strange and unexplained.\n\n";
  103. # I haven't seen this in my testing, but it's clear that others have, and I haven't figured out why or how yet... bhaas
  104. }
  105. # write all failed commands to a file.
  106. my $failed_cmd_file = "failed_cmds.$$.txt";
  107. open (my $ofh, ">$failed_cmd_file") or die "Error, cannot write to $failed_cmd_file";
  108. @failed_jobs = sort {$a->{index}<=>$b->{index}} @failed_jobs;
  109. foreach my $failed_job (@failed_jobs) {
  110. print $ofh $failed_job->{cmd} . "\n";
  111. }
  112. close $ofh;
  113. print "\n\nSorry, $num_failed_jobs of $cmd_counter jobs failed.\n\n"
  114. . "Failed commands written to file: $failed_cmd_file\n\n";
  115. exit(1);
  116. }
  117. }
  118. ####
  119. sub run_cmd {
  120. my ($index, $cmd) = @_;
  121. print "\nRUNNING: $cmd\n";
  122. my $ret = system($cmd);
  123. if ($ret) {
  124. print STDERR "Error, command: $cmd died with ret $ret";
  125. }
  126. open (my $log_fh, ">$log_dir/$index.ret") or die "Error, cannot write to log file for $index.ret";
  127. print $log_fh $ret;
  128. close $log_fh;
  129. return($ret);
  130. }
  131. ####
  132. sub collect_jobs {
  133. my ($job_tracker_href, $failed_jobs_aref, $completed_file) = @_;
  134. my @job_indices = keys %$job_tracker_href;
  135. my $num_finished = 0;
  136. foreach my $index (@job_indices) {
  137. my $log_file = "$log_dir/$index.ret";
  138. if (-s $log_file) {
  139. my $ret_val = `cat $log_file`;
  140. chomp $ret_val;
  141. my $job = $job_tracker_href->{$index};
  142. if ($ret_val == 0) {
  143. # hurray, job succeded.
  144. print "SUCCESS[$index]: $job\n";
  145. # write completed jobs to file
  146. if(open (my $fh, ">>", $completed_file)){
  147. print($fh $job."\n");
  148. close($fh);
  149. }
  150. }
  151. else {
  152. # job failed.
  153. print "FAILED[$index]: $job\n";
  154. $ENCOUNTERED_FAILURE++;
  155. push (@$failed_jobs_aref, {index => $index,
  156. cmd => $job_tracker_href->{$index},
  157. });
  158. }
  159. unlink $log_file;
  160. $num_finished++;
  161. delete $job_tracker_href->{$index}; # job done, no need to continue tracking it. (thanks Raj!)
  162. }
  163. }
  164. return($num_finished);
  165. }