Location: PHPKode > projects > Huygens Remote Manager > hrm/inc/Job.inc
<?php
// This file is part of the Huygens Remote Manager
// Copyright and license notice: see license.txt

require_once ("Setting.inc");
require_once ("Database.inc");
require_once ("JobDescription.inc");
require_once ("hrm_config.inc");
require_once ("Fileserver.inc");
require_once ("Shell.inc");
require_once ("Mail.inc");

// TODO better manage multiple hosts
function newExternalProcessFor($host, $logfilename, $errfilename) {
	global $imageProcessingIsOnQueueManager;
	$db = new DatabaseConnection();
	$huscript_path = $db->huscriptPathOn($host);
	if ($imageProcessingIsOnQueueManager)
		$shell = new LocalExternalProcess($host, $huscript_path, $logfilename, $errfilename);
	else
		$shell = new ExternalProcess($host, $huscript_path, $logfilename, $errfilename);
	return $shell;
}

Class Job {
	public $script;
	public $jobDescription;
	public $server;
	public $pid;
    public $id;
	public $status;

	function Job($jobDescription) {
		$this->jobDescription = $jobDescription;
		$this->script = '';
	}
	function description() {
		return $this->jobDescription;
	}

	function setServer($server) {
		$this->server = $server;
	}

	function createSubJobsOrScript() {
		$result = True;
		$desc = $this->jobDescription;
                # print "<pre>"; print_r($desc); print "</pre>"; print ($desc->isCompound());
		if ($desc->isCompound()) {
			$result = $result && $desc->createSubJobs();
			if ($result) {
				error_log("created sub jobs");
                                report("created sub jobs", 1);
                        }
			if ($result) {
				$queue = new JobQueue();
				$result = $result && $queue->removeJob($desc);
				if ($result)
					error_log("removed compound job");
				report("removed compound job\n", 1);
				// TODO: check if this does fix compound job processing
				$result = False;
			}
		} else {
			report("Job is elementary", 1);
			$this->createScript();
			report("Created script", 1);
			$result = $result && $this->writeScript();
			/*if ($result) {
			report("Wrote script", 1);
			}*/
		}
		return $result;
	}

	function server() {
		return $this->server;
	}

	function script() {
		return $this->script;
	}

	function pid() {
		return $this->pid;
	}

	function id() {
                $desc = $this->description();
		return $desc->id;
	}

	function setPid($pid) {
		$this->pid = $pid;
	}

	function status() {
		return $this->status;
	}

	function setStatus($status) {
		$this->status = $status;
	}

        function createScript() {
            global $useHuScriptVersion;

            switch ($useHuScriptVersion) {
                case 0: $this->createScriptVersionZero(); break;
                case 1: $this->createScriptVersionOne(); break;
            }

            return;

        }

        // A clearer version of the deconvolution script with fixed procedures
        // and a bunch of input parameters.
        function createScriptVersionOne() {

            # The fixed part of the script:
            $this->script = file_get_contents("../scripts/hrm_job.tcl");

            $desc = $this->description();
            $this->script .= $desc->appendScriptParameters();

        }

        // The original version of the deconvolution script, a linear one, with
        // lines that were written or not depending on the task parameters.

        // This function should be deleted after the new one proves to be
        // stable enough, to make this code clearer. The same applies to all
        // the old script generating subroutines, like putMultiChannelScriptOn,
        // putScriptOn and the like.

	function createScriptVersionZero() {
		global $huscript_call;

		$desc = $this->description();
		$setting = $desc->parameterSetting();
		$this->script = "set id [pid]" . "\n" . 'puts "\npid=$id"' . "\n";
		$this->script = $this->script . "huOpt verb -mode noQs\n";
		$this->script = $this->script . 
                    "if { [ catch {\n# A global catch to report important errors.\n";
		$this->script = $this->script . "huOpt gundo off\n";
		if ($setting->isMultiChannel() && ($setting->numberOfChannels() > 1)) {
			$this->script = $this->script . $desc->putMultiChannelScriptOn('', true);
		} else {
			$this->script = $this->script . $desc->putScriptOn('', true);
		}
		$this->script = $this->script . "} err ] } { \n".
                "huOpt printError \$err }\n";
        $id = $desc->id();
        $finishedMarker = $desc->sourceFolder() . '.finished_' . "$id";
        $this->script = $this->script . "exec touch " . '"' . 
            $finishedMarker . '"' . "\n".
            "file attributes \"$finishedMarker\" -permissions 0666\n".
            "puts \"- DONE --------------------------------\\n\\n\"\n";
		$this->script = $this->script . "exit\n";
	}

	function scriptName() {
		$desc = $this->description();
		$result = ".hrm_" . $desc->id() . ".tcl";
		return $result;
	}

	function writeScript() {
		$result = True;
		$desc = $this->description();
		$scriptName = $this->scriptName();
		$user = $desc->owner();
		$username = $user->name();
		$fileserver = new Fileserver($username);
		$scriptPath = $fileserver->sourceFolder();
		$scriptFile = $scriptPath . "/" . $scriptName;
		$file = fopen($scriptFile, "w");
        if (! $file ) {
            report ("Error opening file $scriptFile, verify permissions!", 0);
            // If permissions fail, introduce some delay not to saturate the
            // log file!
            report ("Waiting 15 seconds...", 1);
            sleep(15);
            return False;
        } else {
            $result = $result && (fwrite($file, $this->script) > 0);
            fclose($file);
            report("Wrote script $scriptFile", 1);
        }
		return $result;
	}
	
	// TODO refactor
	function checkResultImage() {
		global $imageProcessingIsOnQueueManager;
		global $copy_images_to_huygens_server;
		global $huygens_user;
		global $huygens_group;
		global $huygens_server_image_folder;
		global $image_destination;
		
		clearstatcache();
		
		# $queue = new JobQueue();
		
		// Server name without proc number
		$server = $this->server;
		$s = split(" ", $server);
		$server_hostname = $s[0];
		
		$desc = $this->description();
		$user = $desc->owner();
		
		$fileserver = new Fileserver($user->name());
		$path = $fileserver->destinationFolderFor($desc);
		
		// TODO refactor JobDescription
                $destFileName = $desc->destinationImageNameWithoutPath();
                //$resultImage = $desc->sourceImageShortName() . "*" . "_" .
                    //$desc->id() . "*";
		
		// If fileshare is not on the same host as Huygens
		if (!$imageProcessingIsOnQueueManager && $copy_images_to_huygens_server) {
                        $image = $huygens_server_image_folder . $user->name() .
                            "/" . $image_destination . "/" .
                            $desc->relativeSourcePath() . $destFileName .  "*";
                        $previews = $huygens_server_image_folder .
                            $user->name() . "/" . $image_destination . "/" .
                            $desc->relativeSourcePath() . "hrm_previews/".
                            $destFileName. "*";
			// escape special characters in image path
			$image = eregi_replace(" ", "\\ ", $image);
                        $image = str_replace(".ics",".i*s", $image);
			$previews = eregi_replace(" ", "\\ ", $previews);
			//error_log("Retrieving result image...");
			//error_log("sudo mkdir -p " . escapeshellarg($path));
			$result = exec("sudo mkdir -p " . escapeshellarg($path));
			$result = exec("sudo mkdir -p " . escapeshellarg($path)
                        . "/hrm_previews");
			//error_log($result);
			//error_log("(cd " . escapeshellarg($path) . " && scp " . $huygens_user . "@" . $server_hostname . ":" . escapeshellarg($image) . " .)");
			$result = exec("(cd " . escapeshellarg($path) . " && sudo scp " . $huygens_user . "@" . $server_hostname . ":" . escapeshellarg($image) . " .)");
			$result = exec("(cd " . escapeshellarg($path) . 
                        "/hrm_previews && sudo scp " . $huygens_user . "@" . $server_hostname . ":" . escapeshellarg($previews) . " .)");
			//error_log($result);
		}
		
		// TODO is checking for job id only a good idea?
		$fileNameExists = $fileserver->folderContains($path, 
                        $destFileName);
		// TODO is checking for new files a relevant criterion?
		//$newFileWritten = $fileserver->folderContainsNewerFile($path, $queue->startTime($this));
		$result = $fileNameExists/* || $newFileWritten*/;
                if (!$result) { 
                    report("Problem: no result file $destFileName in destination directory $path", 0);
                    } else { report("File $destFileName available", 2); }
		return $result;
	}

        function checkProcessFinished() {
            global $imageProcessingIsOnQueueManager;
            global $huygens_user;
            global $huygens_server_image_folder;
            global $image_source, $image_destination;

            clearstatcache();

            // Server name without proc number
            $server = $this->server;
            $s = split(" ", $server);
            $server_hostname = $s[0];

            $desc = $this->description();
            $user = $desc->owner();

            $fileserver = new Fileserver($user->name());
            $path = $fileserver->sourceFolder();
            $dpath = $fileserver->destinationFolderFor($desc);


            $finishedMarker = ".finished_" . $desc->id();
            $endTimeMarker = ".EstimatedEndTime_" . $desc->id();
            $remarksFile = $desc->sourceImageShortName() . "*" . "_" .
                $desc->id() . "*.remarks.txt";


            // If fileshare is not on the same host as Huygens.
            if (!$imageProcessingIsOnQueueManager) {
                // Copy the finished marker
                $marker = $huygens_server_image_folder . $user->name() . 
                    "/" . $image_source . "/" . $finishedMarker;
                $remoteFile = exec("ssh " . $huygens_user . "@" . 
                        $server_hostname . " ls " . $marker);
                //error_log("ssh " . $huygens_user . "@" . $server_hostname . "
                //ls " . $marker);
                //error_log($result);
                // TODO: is the queue manager a sudoer?

                if ($remoteFile == $marker) {
                    exec("(cd " . $path . " && sudo scp " . $huygens_user . "@"
                            . $server_hostname . ":" . $marker . " .)");

                    // If finished, copy also the remarks file.
                    // Shouldn't this happen only if
                    // $copy_images_to_huygens_server == true ?
                    $marker = $huygens_server_image_folder . $user->name() .
                        "/" . $image_destination . "/" .
                        $desc->relativeSourcePath() . $remarksFile;
                    $marker = $huygens_server_image_folder . 
                        $user->name() . "/" .
                        $image_destination . "/" . $remarksFile;
                    $remoteFile = exec("ssh " . $huygens_user . "@" .
                            $server_hostname . " ls " . $marker);
                    if ($remoteFile == $marker) {
                        exec("(cd " . $dpath . " && sudo scp " . 
                            $huygens_user . "@" . $server_hostname . ":" .
                            $marker . " .)");
                    }
                } else {

                    // Copy the estimated end time little file.
                    $marker = $huygens_server_image_folder . $user->name() 
                        . "/" .  $image_source . "/" . $endTimeMarker;
                    $remoteFile = exec("ssh " . $huygens_user . "@" .
                            $server_hostname . " ls " . $marker);
                    if ($remoteFile == $marker) {
                        exec("(cd " . $path . " && sudo scp " . $huygens_user 
                            . "@" . $server_hostname . ":" . $marker . " .)");
                        // Delete in the remote place, not to transfer again
                        // until it is updated.
                        exec("ssh " . $huygens_user . "@" .
                            $server_hostname . " rm -f " . $marker);
                    }
                }

            }
            $result = file_exists($path . '/' . $finishedMarker);


            if ($imageProcessingIsOnQueueManager) {
                $proc = newExternalProcessFor($this->server(), $this->server().
                        "_" .$this->id() . "_out.txt", $this->server() .  "_"
                        .$this->id(). "_error.txt");
                $result = !$proc->existsHuygensProcess($this->pid());
                if (!$result && $proc->isHuygensProcessSleeping($this->pid())) {
                    $proc->rewakeHuygensProcess($this->pid());
                }
            }

            if ( !$result && file_exists($path . '/' . $endTimeMarker) ) {
                // Tasks may report an estimated end time, whenever they can.
                $estEndTime = file_get_contents($path . '/' . $endTimeMarker);
                report("Estimated end time for ". $desc->id(). ": $estEndTime", 1);
                $queue = new JobQueue();
                $queue->updateEstimatedEndTime($desc->id(), $estEndTime );
                // Delete the end time file, to only look at it when the
                // estimation is updated.
                @unlink($path . '/' . $endTimeMarker);
                # $this->UpdateEstimatedEndTime($estEndTime);
            }


            return $result;
        }

}

?>
Return current item: Huygens Remote Manager