'bkgSearch-treeRootNode', 'request' => 'bkgPlot-treeRootNode', 'download' => 'bkgDown-treeRootNode', 'statistics' => 'bkgStatistics-treeRootNode'); protected $resRootNode = array('condition' => 'resSearch-treeRootNode', 'request' => 'resPlot-treeRootNode', 'download' => 'resDown-treeRootNode', 'statistics' => 'resStatistics-treeRootNode'); /* * @brief Constructor */ function __construct() { } /* * @brief Load jobs file and create it if needed */ protected function init() { $this->jobXmlName = IHMConfigClass::getUserJobsFile(); $this->jobXml = new DomDocument("1.0"); if (!file_exists($this->jobXmlName)) { $res = $this->createJobsFile(); if (!$res['success']) return $res; } $res = $this->jobXml->load($this->jobXmlName); if (!$res) return array( "success" => false, "message" => "Cannot load jobs file"); return array("success" => true); } /* * @brief Create a new jobs file */ protected function createJobsFile() { $rootElement = $this->jobXml->createElement('jobs'); $jobsInProgress = $this->jobXml->createElement('jobsInProgress'); foreach ($this->bkgRootNode as $key => $value) { $element = $this->jobXml->createElement("$key"); $element->setAttribute('xml:id',$value); $jobsInProgress->appendChild($element); } $jobsFinished = $this->jobXml->createElement('jobsFinished'); foreach ($this->resRootNode as $key => $value) { $element = $this->jobXml->createElement("$key"); $element->setAttribute('xml:id',"$value"); $jobsFinished->appendChild($element); } $rootElement->appendChild($jobsInProgress); $rootElement->appendChild($jobsFinished); $this->jobXml->appendChild($rootElement); $res = $this->jobXml->save($this->jobXmlName); if (!$res) return array( "success" => false, "message" => "Cannot create new jobs file"); return array("success" => true); } /* * @brief Get the path of the request object file */ protected function getRequestObjectFilePath($id) { return IHMConfigClass::getUserJobsPath().$id.".request"; } /* * @brief Save a request object file */ protected function saveRequestObjectFile($obj, $id) { $file = fopen($this->getRequestObjectFilePath($id), 'w'); fwrite($file, json_encode($obj)); fclose($file); } /* * @brief Decode a request object file */ public function getRequestObjectFile($id) { if (!file_exists($this->getRequestObjectFilePath($id))) return NULL; return json_decode(file_get_contents($this->getRequestObjectFilePath($id))); } /* * @brief Delete a request object file */ protected function deleteRequestObjectFile($id) { if (file_exists($this->getRequestObjectFilePath($id))) unlink($this->getRequestObjectFilePath($id)); } /* * @brief get a job status from process info */ protected function getJobStatus($running,$exitcode) { if ($running) return 'in_progress'; if ($exitcode == 0) return 'done'; return 'error'; } /* * @brief delete a job */ public function deleteJob($id) { $res = $this->init(); if (!$res['success']) return $res; $job = $this->jobXml->getElementById($id); //delete job if (!$job) return array('success' => false, 'message' => "Job not reachable"); $folder = $job->getAttribute('folder'); //be sure that it's an AMDA working dir before deletion... $fullFolderPath = IHMConfigClass::getRequestPath().$folder.'/'; if ((isset($folder)) && ($folder != "") && is_dir($fullFolderPath) && (preg_match("/DD[0-9A-Za-z]*_/",$folder) || preg_match("/Plot[0-9]*_/",$folder))) { foreach (glob($fullFolderPath.'*') as $filename) { if (is_dir($filename) && (basename($filename) == 'params')) { //recursive deletion only for "params" dir (a full recursive deletion is probably too dangerous...) foreach (glob($filename.'/*') as $paramname) unlink($paramname); rmdir($filename); } else unlink($filename); } rmdir($fullFolderPath); } $this->deleteRequestObjectFile($id); $job->parentNode->removeChild($job); $res = $this->jobXml->save($this->jobXmlName); if (!$res) return array( 'success' => false, 'message' => "Cannot save jobs file"); return array('success' => true, 'id' => $id); } /* * @brief get job info about a job */ public function getJobInfo($id) { $res = $this->init(); if (!$res['success']) return $res; $job = $this->jobXml->getElementById($id); $attributes = []; foreach( $job->attributes as $attrName => $attrNode) { $attributes[$attrName] = $attrNode->nodeValue; } $format = 'unknown'; $compression = 'unknown'; if($job) { $name = $job->getAttribute('name'); $status = $job->getAttribute('status'); $jobType = $job->getAttribute('jobType'); $info = $job->getAttribute('info'); $start = $job->getAttribute('start'); $stop = $job->getAttribute('stop'); $result = $job->getAttribute('result'); $folder = $job->getAttribute('folder'); $request_obj = $this->getRequestObjectFile($id); if (isset($request_obj)) { if (isset($request_obj->format)) { $format = strtolower($request_obj->format); if (($format == "pdf") || ($format == "ps")) //auto compression for plot request $compression = ".tar.gz"; } if (isset($request_obj->compression)) $compression = strtolower($request_obj->compression); } $sendToSamp = $job->getAttribute('sendToSamp'); if (empty($sendToSamp)) { $sendToSamp = false; } else { $sendToSamp = ($sendToSamp == "true"); } } return array( 'success' => true, 'id' => $id, 'name' => $name, 'status' => $status, 'jobType' => $jobType, 'info' => $info, 'start' => $start, 'stop' => $stop, 'folder' => $folder, 'result' => $result, 'format' => $format, 'compression' => $compression, 'sendToSamp' => $sendToSamp, ); } /* * @brief Add a new job */ public function addJob($obj, $id, $folder, $running, $start, $result, $exitcode) { $obj = get_object_vars($obj); // Allow access to elements where the key is in dash-separated form. $res = $this->init(); if (!$res['success']) return $res; $infos = []; switch ($obj['nodeType']) { // Data mining case 'condition': $name = 'datamining_'.time(); if($obj['name'] != '') { $infos['Name'] = $obj['name']; } $infos['Condition'] = $obj['expression']; $infos['Start date'] = $obj['startDate']; $infos['Stop date'] = $obj['stopDate']; break; case 'statistics': $name = 'statistics_'.time(); $infos['Name'] = $obj['name']; // TODO: name toujours égal à 'test' (?) // TODO : lire data/user/TT/tt_0.xml -> trouver ttname + nbIntervals if(array_key_exists('timeTables', $obj)) { $ttXml = new DomDocument(); $ttXml->load(USERWSDIR . 'Tt.xml'); $ttIntervals = []; foreach ($ttXml->getElementsByTagName('timetab') as $tt) { $ttIntervals[$tt->getAttribute('name')] = $tt->getAttribute('intervals'); } if(count($obj['timeTables']) == 1) { $infos['Time table'] = $obj['timeTables'][0]->timeTableName; $infos['Nb Intervals'] = $ttIntervals[$infos['Time table']]; } else { foreach ($obj['timeTables'] as $tt) { if($tt === reset($obj['timeTables'])) { $infos['Time tables'] = $tt->timeTableName . '(' . $ttIntervals[$tt->timeTableName] . ' int.)'; } else { $infos['Time tables'] .= ', ' . $tt->timeTableName . '(' . $ttIntervals[$tt->timeTableName] . ' int.)'; } } } } else { $infos['Start date'] = $obj['startDate']; $infos['Stop date'] = $obj['stopDate']; } if(array_key_exists('expression', $obj)) { $infos['Expression'] = $obj['expression']; } $params = []; foreach ($obj['parameter'] as $param) { $params[] = $param->function . '(' . $param->paramid . ')'; } if(count($params) == 1) { $infos['Parameter'] = $params[0]; } else { $infos['Parameters'] = ''; } break; case 'download': $name = $obj['downloadSrc'] == '2' ? "download_fits_".time() : "download_data_".time(); $params = []; foreach ($obj['list'] as $param) { $params[] = $param->paramid; } if(count($params) == 1) { $infos['Parameter'] = $params[0]; } else { $infos['Parameters'] = join(', ', $params); } $infos['Start date'] = $obj['startDate']; $infos['Stop date'] = $obj['stopDate']; break; // Plot case 'request': $name = "request_".time(); $infos['Output'] = strtolower($obj['file-format']) . ' (' . strtolower($obj['file-output']) . ')'; foreach ($obj['tabs'] as $tab) { if($tab->id == $obj['last-plotted-tab']) { $infos['Start date'] = $tab->startDate; $infos['Stop date'] = $tab->stopDate; $strPanels = []; foreach ($tab->panels as $panel) { $strParams = ''; foreach ($panel->params as $param) { $strParams .= $param->paramid . ($param === end($panel->params) ? '' : ', '); } $infos['• Panel ' . $panel->id] = $strParams; } continue; } } break; default: $name = "unknown_".time(); } $infos['Started at'] = gmdate("Y-m-d H:i:s", $start); $strInfo = ''; foreach ($infos as $key => $info) { $strInfo .= ($key == 'Started at' ? '
' : '') . '' . $key . ': ' . $info . '
'; } $newJob = $this->jobXml->createElement('job'); $newJob->setAttribute('xml:id', $id); $newJob->setAttribute('jobType', $obj['nodeType']); $newJob->setAttribute('name', $name); $newJob->setAttribute('info', $strInfo); $newJob->setAttribute('folder', $folder); $newJob->setAttribute('result', $result); $newJob->setAttribute('start', date('d-m-Y H:i:s', $start)); //to know if know if it's an immediate job or not $newJob->setAttribute('immediate', !$running); $sendToSamp = isset($obj['sendToSamp']) ? $obj['sendToSamp'] : FALSE; if ($sendToSamp) { $newJob->setAttribute('sendToSamp', "true"); } $key = $obj['nodeType']; if ($running) { $rootJobNode = $this->jobXml->getElementById($this->bkgRootNode[$key]); if (!$rootJobNode) { $rootJobNode = $this->jobXml->createElement("$key"); $rootJobNode->setAttribute('xml:id', $this->bkgRootNode[$key]); $jobsInProgress = $this->jobXml->getElementsByTagName('jobsInProgress')->item(0); $jobsInProgress->appendChild($rootJobNode); } } else { $rootJobNode = $this->jobXml->getElementById($this->resRootNode[$key]); if (!$rootJobNode) { $rootJobNode = $this->jobXml->createElement("$key"); $rootJobNode->setAttribute('xml:id', $this->resRootNode[$key]); $jobsFinished = $this->jobXml->getElementsByTagName('jobsFinished')->item(0); $jobsFinished->appendChild($rootJobNode); } } $rootJobNode->appendChild($newJob); if (!$this->jobXml->save($this->jobXmlName)) return array("success" => false, "message" => "Cannot save job manager file"); $this->saveRequestObjectFile($obj, $id); $this->updateJobStatus($id, $running, $exitcode); return $this->getJobInfo($id); } /* * @brief Update the status of a job */ public function updateJobStatus($id, $running, $exitcode) { $res = $this->init(); if (!$res['success']) return $res; $job = $this->jobXml->getElementById($id); if (!isset($job)) { return array("success" => false, "message" => "Cannot found job"); } $jobstatus = $this->getJobStatus($running,$exitcode); $job->setAttribute('status', $jobstatus); $infos = []; if ($running) { $job->setAttribute('stop', 'unknown'); } else if ($job->getAttribute('stop') == '' || $job->getAttribute('stop') == 'unknown') { $job->setAttribute('stop', date('d-m-Y H:i:s', time())); $start = new DateTime($job->getAttribute('start')); $interval = (new DateTime('now'))->diff($start); $infos['Job duration'] = $interval->format('%Hh %Im %Ss'); $resPath = glob(USERWORKINGDIR . $job->getAttribute('folder') . '/' . $job->getAttribute('result') . '*')[0]; if($job->getAttribute('jobType') == 'condition') { error_log('resPath: ' . $resPath); $resXml = new DomDocument(); $resXml->load($resPath); $infos['nb intervals'] = $resXml->getElementsByTagName('nbIntervals')->item(0)->nodeValue; } $fileSize = filesize($resPath); if ($fileSize < 1024) { $strSize = number_format($fileSize, 2, '.', ' ') . 'b'; } else if($fileSize < 1024*1024) { $strSize = number_format($fileSize/1024, 2, '.', ' ') . 'kb'; } else if($fileSize < 1024*1024*1024) { $strSize = number_format($fileSize/(1024*1024), 2, '.', ' ') . 'mb'; } else { $strSize = number_format($fileSize/(1024*1024*1024), 2, '.', ' ') . 'gb'; } $infos['File size'] = $strSize; $this->jobXml->getElementById($this->resRootNode[$job->getAttribute('jobType')])->appendChild($job); } if($exitcode != 0) { $infos['Error code'] = $exitcode; } $strInfo = $job->getAttribute('info'); foreach ($infos as $key => $info) { $strInfo .= '' . $key . ': ' . $info . '
'; } $job->setAttribute('info', $strInfo); $res = $this->jobXml->save($this->jobXmlName); if (!$res) return array( 'success' => false, 'message' => "Cannot save jobs status file"); return $this->getJobInfo($id); } /* * @brief Get the list of jobs with a specific status */ public function getJobsByStatus($status) { $res = $this->init(); if (!$res['success']) return $res; $xp = new domxpath($this->jobXml); $jobs = $xp->query("//job[@status='".$status."']"); $jobsId = array(); foreach ($jobs as $job) $jobsId[] = $job->getAttribute('xml:id'); return array('success' => true, 'jobs' => $jobsId); } /* * @brief Get jobs that use a specific working dir */ public function getJobsByWorkingDir($folder) { $res = $this->init(); if (!$res['success']) return $res; $xp = new domxpath($this->jobXml); $jobs = $xp->query("//job[@folder='".$folder."']"); $jobsId = array(); foreach ($jobs as $job) $jobsId[] = $job->getAttribute('xml:id'); return array('success' => true, 'jobs' => $jobsId); } /* * @brief Get all jobs to clean (immediate result jobs) */ public function getJobsToClean() { $res = $this->init(); if (!$res['success']) return $res; // Get immediate jobs $xp = new domxpath($this->jobXml); $jobs = $xp->query("//job[@immediate='1']"); $jobsId = array(); foreach ($jobs as $job) $jobsId[] = $job->getAttribute('xml:id'); return array("success" => true, "jobs" => $jobsId); } } ?>