
#
# The Cleaner.  The  "-nosave" option will cause all old jobs
# to be deleted.
#



#set no output buffering

$|=1;

#
# Clean the log files -
# limit total size to .5M->1M
#
$LOGSCLEANED=0;
$LOGS = "$ENV{SERVER_VAR}/logs";

chomp(@logs = `ls $LOGS/*`);

foreach $log (@logs)
{
  if(-r ($log) and ($log !~ /cleaner/) and ($log !~ /queues/))
  {
    $corrupt = 0;
    $desired = 1048576; #hardwired!!!
    $room2grow = 524288;
    $filesize = (-s "$log");
    open(FILE, "$log") or (print "Could not open $log\n" and next);
    $first = <FILE>; #keep the first line of the log
    if ($filesize > $desired) {
      if (seek FILE, $filesize-$desired+$room2grow, 1) {
        #move back from the end of the file
        $corrupt = 1;  #if successful, file is too big
        $second = <FILE>;    #throw out any partial sentence
      } else {
        seek FILE, 0, 0;
        $first = "";
      }
    }
    @all = <FILE>;    #this array should not need more than ~4194304 bytes
    @all = ($first, @all);
    close(FILE);
    $all = "";
    if($corrupt != 0)
    {	
      open(WRITE, ">$log.tmp") or (print "Could not open $log.tmp\n" and next);	
      foreach (@all)
      {
        $_ =~ s///g; #should no longer be necessary with improved logging
        print WRITE $_;
      }
      close(WRITE);
      system("mv $log.tmp $log") and  (print "Could not move $log.tmp to $log\n" and die);
      print "cleaner: cleaned log file $log\n";
      $LOGSCLEANED++;
    }	
  }           
}

#
# Restart the server
#

if($LOGSCLEANED > 0) {
  system("$ENV{SERVER_USER_BIN}/restart &> /dev/null") and (print "Could not restart server\n" and die);
  chomp($date = `date`);
  print "cleaner: restarted server $date\n";
} 

#
# Cleaning up after jobs.
#

$JOBS = "$ENV{SERVER_VAR}/jobs";

#
# Parse command line
#

if ($ARGV[0] eq "-nosave") {
  $SAVE = 0; 
} else {
  $SAVE = 1; 
}

if ($SAVE) {
  # Select current archive directory
  chop($date = `date`);
  $date  =~ /(\d\d\d\d)/;
  $year  = $1;
  chop($month = `date +%h`);
  $DIR  = "$month$year";

  # These are the files to be saved within each job directory.
  @FILES = ("job.received", "job.results", "job.out"); 
}

#
# Clean up Web area
#
# changed to remove jobs inactive _more_ than two days,
# as opposed to _exactly_ one day 09/23/1999
#

system("find $ENV{SERVER_WWW_HOME}/jobs -type f -mmin +2280 -exec rm -f {} \\;");

#
# Get a list of all job directories in <SERVER_VAR>/jobs.
#

chdir("$JOBS");
print @DIRS;
chomp(@DIRS = `ls -d job.* 2>/dev/null`);

#
# Iterate through each of the job directories.
#

foreach $job_num (@DIRS) {
 
  # Clean if "DONE" is in the job's directory. DONE is
  # created by the sender after the job has completed.
  #
  # Alternatively, clean if scheduler has marked job as
  # unschedulable or nothing has been modified in over a week.
  #
  # Only clean if no files have been modified within the last 3 days.
  # 09/23/1999

  chomp(@active = `find $JOBS/$job_num -mtime -8 -type f 2>/dev/null`);

  next unless ((-f "$JOBS/$job_num/DONE") or (-f "$JOBS/$job_num/TIMEOUT") or (-f "$JOBS/$job_num/BAD_PARSE") or (-f "$JOBS/$job_num/QFULL")or (-f "$JOBS/$job_num/LIMIT_REACHED") or (-f "$JOBS/$job_num/job.sockerr") or (-f "$JOBS/$job_num/job.sockdone") or (!@active));

  if(!@active and (!(-f "JOBS/$job_num/job.sockdone"))) {
    open(TOUCH, ">$JOBS/$job_num/job.sockdone");
    close TOUCH;
    print "cleaner: Job $job_num over one week old.\n";
    next;
  }

#
# Check on any unfinished job with a socket problem and no recent activity
#

  if(((-f "$JOBS/$job_num/job.sockdone") or (-f "$JOBS/$job_num/job.sockerr")) and !(-f "$JOBS/$job_num/DONE")) {
    chomp(@active = `find $JOBS/$job_num -mmin -10 -type f 2>/dev/null`);
    next if ($#active >= 0);
    
    #
    # Put off the check a little longer in the case of an error
    # This is in response to Mittelman's drivers going "defunct"
    # Liz 08/2002

    if(-f "$JOBS/$job_num/job.sockerr") {
      chomp(@active = `find $JOBS/$job_num -mmin -240 -type f 2>/dev/null`);
      next if ($#active >= 0);
    }
    $checked = 0;
    undef $solver;
    undef $station;
    undef $port;
    if($job_num =~ /(\d+)/) {
      if(-s "$JOBS/$job_num/job.type") {
        open(FILE, "$JOBS/$job_num/job.type") or die $!;
        chomp($solver = <FILE>); 
        close FILE;
        if($solver =~ /ADMIN/) {
          undef $solver;
        }
        if(-s "$JOBS/$job_num/job.station") {
          open(FILE, "$JOBS/$job_num/job.station") or die $!;
          chomp($station = <FILE>); 
          close FILE;
        } 
      }
      if(defined($station)) {
        open(FILE, "$ENV{SERVER_VAR}/lib/station_type_port") or die $!;
        while (<FILE>) {
          if(/^$station:$solver:(\d+)/) {
            $port = $1;
            last;
          }
        }
        close FILE;
        if(defined($port)) {
          $num = $job_num;
          $num =~ s/job\.//;
          print "cleaner: found all information to check job $job_num.\n";

          $line = `echo \"check job $num\" | $^X $ENV{SERVER_BIN}/client.pl -server $station:$port`;
          $checked = 1;
          if($line =~ /(error)|(ignored)/is) {
            $checked = 0;
          }
          @lines = split '\n', $line;
          $shortline = "";
          foreach $one (@lines) {
            if(($one !~ /^client.pl:/) and ($one !~ /^\s*$/)) {
              $shortline .= "$one\n";
            }
          }
          print "cleaner: check on job $num yields:\n$shortline\n";
        } else {
          print "cleaner: port not defined for job $job_num.\n";
        }
      } else {
        print "cleaner: station not defined for job $job_num.\n";
      }
      unless($checked) {
        open(ERR, ">>$JOBS/$job_num/job.results");
        print ERR "Failure on remote solver with communications handler.  Job lost.\n";
        close ERR;
        system("$^X $ENV{SERVER_BIN}/job_end.pl $1 2>> $ENV{SERVER_VAR}/logs/jobs");
      }
    }
    next;
  }
      
  #
  # Leave any non-troubled jobs around for some time
  #
  chomp(@active = `find $JOBS/$job_num -mtime -3 -type f 2>/dev/null`);
  if($#active > 0) {
    next;
  }

  if ($SAVE) {

    chomp($date = `date`);
    print "cleaner: $date: saving $job_num in $DIR\n";

    #
    # Remove unnecessary files
    #

    chdir("$JOBS/$job_num");
    chomp(@LIST = `ls`);
    foreach $file (@LIST) {
      $needs_saving = 0;
      foreach $one_of_the_files_to_save (@FILES) {
        if ($file eq $one_of_the_files_to_save) {
          $needs_saving = 1; last;
        }
      }
      if($needs_saving) {
        system("gzip $file");
      } else {
        system("rm -f $file");
      }
    }

    #
    # Move the directory into the archive directory
    #

    chdir("$JOBS");
    unless (-d "$DIR") {
      print "cleaner: $date: creating directory $DIR\n";
      system("mkdir $DIR");
    }
    system("mv $job_num $DIR/");
  } else {
    
    # Just delete the directory

    chop($date = `date`);
    print "cleaner: $date: deleting job $job_num\n";
    if (length($job_num)>0) { 
      system("rm -rf $JOBS/$job_num");
    }
  }
  
#
# Clear out kestrel state file
#

  if(defined($ENV{"KESTREL_INSTALL"}) and ($ENV{"KESTREL_INSTALL"}==1) and defined($ENV{"KESTREL_STATE"})) {
    unlink "$ENV{KESTREL_STATE}/$job_num";
  }
  
}

