diff --git a/lib/classes/module/console/schedulerStart.class.php b/lib/classes/module/console/schedulerStart.class.php index 52afd000be..8dd81c9ca4 100644 --- a/lib/classes/module/console/schedulerStart.class.php +++ b/lib/classes/module/console/schedulerStart.class.php @@ -29,6 +29,20 @@ class module_console_schedulerStart extends Command parent::__construct($name); $this->setDescription('Start the scheduler'); + $this->addOption( + 'nolog' + , NULL + , 1 | InputOption::VALUE_NONE + , 'do not log (scheduler) to logfile' + , NULL + ); + $this->addOption( + 'notasklog' + , NULL + , 1 | InputOption::VALUE_NONE + , 'do not log (tasks) to logfiles' + , NULL + ); $this->setHelp( "You should use launch the command and finish it with `&`" . " to return to the console\n\n" @@ -38,7 +52,7 @@ class module_console_schedulerStart extends Command return $this; } - public function execute(InputInterface $input, OutputInterface $output) + public function execute(InputInterface $zinput, OutputInterface $output) { if(!setup::is_installed()) { @@ -48,7 +62,7 @@ class module_console_schedulerStart extends Command require_once dirname(__FILE__) . '/../../../../lib/bootstrap.php'; $scheduler = new task_Scheduler(); - $scheduler->run($output, true); + $scheduler->run($zinput, $output); //, !$input->getOption('nolog'), !$input->getOption('notasklog')); return; } diff --git a/lib/classes/module/console/taskrun.class.php b/lib/classes/module/console/taskrun.class.php index fe7da52197..31714db34a 100644 --- a/lib/classes/module/console/taskrun.class.php +++ b/lib/classes/module/console/taskrun.class.php @@ -43,10 +43,27 @@ class module_console_taskrun extends Command , 'The name of the runner (manual, scheduler...)' , task_abstract::RUNNER_MANUAL ); + $this->addOption( + 'nolog' + , NULL + , 1 | InputOption::VALUE_NONE + , 'do not log to logfile' + , NULL + ); $this->setDescription('Run task'); return $this; } + + function sig_handler($signo) + { + if($this->task) + { + $this->task->log(sprintf("signal %s received", $signo)); + if($signo == SIGTERM) + $this->task->set_running(false); + } + } public function execute(InputInterface $input, OutputInterface $output) { @@ -81,9 +98,12 @@ class module_console_taskrun extends Command register_tick_function(array($this, 'tick_handler'), true); declare(ticks=1); + pcntl_signal(SIGTERM, array($this, 'sig_handler')); + + $this->task->run($runner, $input, $output); + +$this->task->log(sprintf("%s [%d] taskrun : returned from 'run()', get_status()=%s \n", __FILE__, __LINE__, $this->task->get_status())); - $this->task->run($runner); - printf("TASK QUIT\n"); return $this; } diff --git a/lib/classes/task/Scheduler.class.php b/lib/classes/task/Scheduler.class.php index deae331966..b70dfe0258 100644 --- a/lib/classes/task/Scheduler.class.php +++ b/lib/classes/task/Scheduler.class.php @@ -26,6 +26,7 @@ class task_Scheduler const METHOD_PROC_OPEN = 'METHOD_PROC_OPEN'; private $method; + private $input; protected $output; protected function log($message) @@ -33,18 +34,21 @@ class task_Scheduler $registry = registry::get_instance(); $logdir = $registry->get('GV_RootPath') . 'logs/'; - logs::rotate($logdir . "scheduler.log"); + logs::rotate($logdir . "scheduler_l.log"); + logs::rotate($logdir . "scheduler_o.log"); + logs::rotate($logdir . "scheduler_e.log"); $date_obj = new DateTime(); $message = sprintf("%s\t%s", $date_obj->format(DATE_ATOM), $message); if($this->output instanceof OutputInterface) { - $this->output->writeln($message); +// $this->output->writeln($message); } - // else +// $this->output->writeln($this->input->getOption('nolog')); + if($this->input && !($this->input->getOption('nolog'))) { - file_put_contents($logdir . "scheduler.log", $message."\n", FILE_APPEND); + file_put_contents($logdir . "scheduler_l.log", $message . "\n", FILE_APPEND); } return $this; } @@ -52,20 +56,32 @@ class task_Scheduler protected static function get_connection() { require dirname(__FILE__) . '/../../../config/connexion.inc'; - - return new connection_pdo('appbox', $hostname, $port, $user, $password, $dbname); + return(appbox::get_instance()->get_connection()); } - public function run(OutputInterface $output = null, $log_tasks = true) + public function run($input=null, OutputInterface $output = null) //, $log = true, $log_tasks = true) { $this->method = self::METHOD_FORK; require_once dirname(__FILE__) . '/../../bootstrap.php'; + $this->input = $input; $this->output = $output; $appbox = appbox::get_instance(); $registry = $appbox->get_registry(); + $nullfile = ''; $system = system_server::get_platform(); + switch($system) + { + case "WINDOWS": + $nullfile = 'NUL'; + break; + default: + case "DARWIN": + case "LINUX": + $nullfile = '/dev/null'; + break; + } $lockdir = $registry->get('GV_RootPath') . 'tmp/locks/'; @@ -98,16 +114,15 @@ class task_Scheduler } } } - + $this->log(sprintf("running scheduler with method %s", $this->method)); - if($this->method == self::METHOD_FORK) pcntl_signal(SIGCHLD, SIG_IGN); $logdir = $registry->get('GV_RootPath') . 'logs/'; - $conn = self::get_connection(); + $conn = appbox::get_instance()->get_connection(); $taskPoll = array(); // the poll of tasks @@ -146,15 +161,36 @@ class task_Scheduler while($schedstatus == 'started' || $runningtask > 0) { - while(!$conn->ping()) + while(1) { + try + { + assert(is_object($conn)); + $ping = @$conn->ping(); + } + catch(ErrorException $e) + { + $ping = false; + } + if($ping) + break; + unset($conn); if(!$connwaslost) { $this->log(sprintf("Warning : abox connection lost, restarting in 10 min.")); } - sleep(60 * 10); - $conn = self::get_connection(); + for($i = 0; $i < 60 * 10; $i++) + sleep(1); + try + { + $conn = appbox::get_instance()->get_connection(); + } + catch(ErrorException $e) + { + $ping = false; + } + $connwaslost = true; } if($connwaslost) @@ -168,13 +204,21 @@ class task_Scheduler $connwaslost = false; } - +// printf("%d \n", __LINE__); $schedstatus = ''; - $sql = "SELECT schedstatus FROM sitepreff"; - $stmt = $conn->prepare($sql); - $stmt->execute(); - $row = $stmt->fetch(PDO::FETCH_ASSOC); - $stmt->closeCursor(); + $row = NULL; + try + { + $sql = "SELECT schedstatus FROM sitepreff"; + $stmt = $conn->prepare($sql); + $stmt->execute(); + $row = $stmt->fetch(PDO::FETCH_ASSOC); + $stmt->closeCursor(); + } + catch(ErrorException $e) + { + continue; + } if($row) { @@ -193,14 +237,14 @@ class task_Scheduler $stmt = $conn->prepare($sql); $stmt->execute(); $stmt->closeCursor(); - $this->log("schedstatus == 'stopping', waiting tasks to end"); } - logs::rotate($logdir . "scheduler.log"); - logs::rotate($logdir . "scheduler.error.log"); - + logs::rotate($logdir . "scheduler_t.log"); + logs::rotate($logdir . "scheduler_o.log"); + logs::rotate($logdir . "scheduler_e.log"); +// printf("%d \n", __LINE__); // initialy, all tasks are supposed to be removed from the poll foreach($taskPoll as $tkey => $task) $taskPoll[$tkey]["todel"] = true; @@ -208,32 +252,41 @@ class task_Scheduler foreach($task_manager->get_tasks(true) as $task) { $tkey = "t_" . $task->get_task_id(); + $status = $task->get_status(); - logs::rotate($logdir . "task_$tkey.log"); - logs::rotate($logdir . "task_$tkey.error.log"); + logs::rotate($logdir . "task_t_" . $task->get_task_id() . ".log"); + logs::rotate($logdir . "task_o_" . $task->get_task_id() . ".log"); + logs::rotate($logdir . "task_e_" . $task->get_task_id() . ".log"); if(!isset($taskPoll[$tkey])) { // the task is not in the poll, add it $phpcli = $registry->get('GV_cli'); - switch($system) { + case "WINDOWS": + $cmd = $phpcli; + $args = array('-f', $registry->get('GV_RootPath') . 'bin/console', '--', '-q', 'task:run', $task->get_task_id(), '--runner=scheduler'); + if($this->input && ($this->input->getOption('notasklog'))) + $args[] = 'notasklog'; + break; default: case "DARWIN": - case "WINDOWS": case "LINUX": $cmd = $phpcli; - $args = array('-f', $registry->get('GV_RootPath') . 'bin/console', 'task:run', $task->get_task_id(), '--runner=scheduler'); + $args = array('-f', $registry->get('GV_RootPath') . 'bin/console', '--', '-q', 'task:run', $task->get_task_id(), '--runner=scheduler'); + if($this->input && ($this->input->getOption('notasklog'))) + $args[] = 'notasklog'; break; } $taskPoll[$tkey] = array( "task" => $task, - "current_status" => $task->get_status(), + "current_status" => $status, "cmd" => $cmd, "args" => $args, - "killat" => null + "killat" => null, + "sigterm_sent" => false ); if($this->method == self::METHOD_PROC_OPEN) { @@ -245,24 +298,24 @@ class task_Scheduler sprintf( "new Task %s, status=%s" , $taskPoll[$tkey]["task"]->get_task_id() - , $task->get_status() + , $status ) ); } else { // the task is already in the poll, update its status - if($taskPoll[$tkey]["current_status"] != $task->get_status()) + if($taskPoll[$tkey]["current_status"] != $status) { $this->log( sprintf( "Task %s, oldstatus=%s, newstatus=%s" , $taskPoll[$tkey]["task"]->get_task_id() , $taskPoll[$tkey]["current_status"] - , $task->get_status() + , $status ) ); - $taskPoll[$tkey]["current_status"] = $task->get_status(); + $taskPoll[$tkey]["current_status"] = $status; } // update the whole task object unset($taskPoll[$tkey]["task"]); @@ -284,18 +337,16 @@ class task_Scheduler } } - - /** - * Launch task that are not yet launched - */ + // Launch task that are not yet launched $runningtask = 0; foreach($taskPoll as $tkey => $tv) { - switch($tv['task']->get_status()) + $status = $tv['task']->get_status(); + switch($status) { default: - $this->log(sprintf('Unknow status `%s`', $tv['task']->get_status())); + $this->log(sprintf('Unknow status `%s`', $status)); break; case task_abstract::RETURNSTATUS_TORESTART: @@ -332,24 +383,8 @@ class task_Scheduler { if(!$taskPoll[$tkey]["process"]) { - $descriptors = array( - 1 => array("pipe", "w"), - 2 => array("pipe", "w") - ); - - if($log_tasks === true) - { - $descriptors[1] = array( - "file" - , $logdir . "task_$tkey.log" - , "a+" - ); - $descriptors[2] = array( - "file" - , $logdir . "task_$tkey.error.log" - , "a+" - ); - } + $descriptors[1] = array('file', $logdir . "task_o_" . $task->get_task_id() . ".log", 'a+'); + $descriptors[2] = array('file', $logdir . "task_e_" . $task->get_task_id() . ".log", 'a+'); $taskPoll[$tkey]["process"] = proc_open( $taskPoll[$tkey]["cmd"] . ' ' . implode(' ', $taskPoll[$tkey]["args"]) @@ -415,27 +450,25 @@ class task_Scheduler // child // printf("hello i am child pid=%d\n", getmypid()); // printf("%s %s \n", $taskPoll[$tkey]["cmd"], implode(' ', $taskPoll[$tkey]["args"])); - // ; umask(0); - openlog('MyLog', LOG_PID | LOG_PERROR, LOG_LOCAL0); if(posix_setsid() < 0) die("Forked process could not detach from terminal\n"); - //chdir(dirname(__FILE__)); + fclose(STDIN); fclose(STDOUT); fclose(STDERR); - $fdIN = fopen('/dev/null', 'r'); - $fdOUT = fopen($logdir . "task_$tkey.log", 'a+'); - $fdERR = fopen($logdir . "task_$tkey.error.log", 'a+'); + $fdIN = fopen($nullfile, 'r'); + $fdOUT = fopen($logdir . "task_o_" . $taskPoll[$tkey]["task"]->get_task_id() . ".log", 'a+'); + $fdERR = fopen($logdir . "task_e_" . $taskPoll[$tkey]["task"]->get_task_id() . ".log", 'a+'); + $this->log(sprintf("exec('%s %s')", $taskPoll[$tkey]["cmd"], implode(' ', $taskPoll[$tkey]["args"]))); pcntl_exec($taskPoll[$tkey]["cmd"], $taskPoll[$tkey]["args"]); - sleep(2); } else { // parent - // printf("hello i am parent pid=%d\n", getmypid()); + // sleep(2); } } break; @@ -506,33 +539,30 @@ class task_Scheduler if($taskPoll[$tkey]["killat"] === NULL) $taskPoll[$tkey]["killat"] = time() + self::TASKDELAYTOQUIT; - $tpid = $taskPoll[$tkey]['task']->get_pid(); - if($tpid) + $pid = $taskPoll[$tkey]['task']->get_pid(); + if($pid) { + if(!$taskPoll[$tkey]['sigterm_sent']) + { + posix_kill($pid, SIGTERM); + $this->log( + sprintf( + "SIGTERM sent to task %s (pid=%s)" + , $taskPoll[$tkey]["task"]->get_task_id() + , $pid + ) + ); + } + if(($dt = $taskPoll[$tkey]["killat"] - time()) < 0) { - if($this->method == self::METHOD_PROC_OPEN) - { - $pids = preg_split('/\s+/', `ps -o pid --no-heading --ppid $tpid`); - foreach($pids as $pid) - { - if(is_numeric($pid)) - { - $this->log("Killing pid %d", $pid); - posix_kill($pid, 9); - } - } - } - elseif($this->method == self::METHOD_FORK) - { - posix_kill($tpid, 9); - } + posix_kill($pid, 9); $this->log( sprintf( "SIGKILL sent to task %s (pid=%s)" , $taskPoll[$tkey]["task"]->get_task_id() - , $tpid + , $pid ) ); @@ -569,6 +599,7 @@ class task_Scheduler , $taskPoll[$tkey]["task"]->get_task_id() ) ); + $taskPoll[$tkey]["task"]->set_status(task_abstract::RETURNSTATUS_STOPPED); } break; @@ -590,290 +621,8 @@ class task_Scheduler } } - - /* - - - $common_status = array( - task_abstract::STATUS_STARTED - , task_abstract::RETURNSTATUS_STOPPED - ); - - - foreach($taskPoll as $tkey => $tv) - { - // if (!in_array($taskPoll[$tkey]["task"]->get_status(), $common_status)) - // { - // $this->log( - // sprintf( - // 'task %s has status %s' - // , $taskPoll[$tkey]["task"]->get_task_id() - // , $taskPoll[$tkey]["task"]->get_status() - // ) - // ); - // } - switch($tv['task']->get_status()) - { - default: - $this->log(sprintf('Unknow status `%s`', $tv['task']->get_status())); - break; - - case task_abstract::RETURNSTATUS_TORESTART: - if(!$taskPoll[$tkey]['task']->get_pid()) - { - @fclose($taskPoll[$tkey]["pipes"][1]); - @fclose($taskPoll[$tkey]["pipes"][2]); - @proc_close($taskPoll[$tkey]["process"]); - - $taskPoll[$tkey]["process"] = null; - if($schedstatus == 'started') - { - $taskPoll[$tkey]["task"]->set_status(task_abstract::STATUS_TOSTART); - } - // trick to start the task immediatly : DON'T break if ending with 'tostart' - // so it will continue with 'tostart' case ! - } - else - { - break; - } - - case task_abstract::STATUS_TOSTART: - // if scheduler is 'tostop', don't launch a new task ! - if($schedstatus != 'started') - break; - - $taskPoll[$tkey]["killat"] = NULL; - if(!$taskPoll[$tkey]["process"]) - { - $descriptors = array( - 1 => array("pipe", "w"), - 2 => array("pipe", "w") - ); - - if($log_tasks === true) - { - $descriptors[1] = array( - "file" - , $logdir . "task_$tkey.log" - , "a+" - ); - $descriptors[2] = array( - "file" - , $logdir . "task_$tkey.error.log" - , "a+" - ); - } - - $taskPoll[$tkey]["process"] = proc_open( - $taskPoll[$tkey]["cmd"].' '.implode(' ', $taskPoll[$tkey]["args"]) - , $descriptors - , $taskPoll[$tkey]["pipes"] - , $registry->get('GV_RootPath') . "bin/" - , null - , array('bypass_shell' => true) - ); - - if(is_resource($taskPoll[$tkey]["process"])) - { - sleep(2); // let the process lock and write it's pid - } - - if(is_resource($taskPoll[$tkey]["process"]) && $taskPoll[$tkey]['task']->get_pid() !== null) - { - - // ************************************************ - // file_put_contents("/tmp/scheduler2.log", sprintf("%s [%d] : RUNNING ? : pid=%s \n", __FILE__, __LINE__, $taskPoll[$tkey]['task']->get_pid()), FILE_APPEND); - - $this->log( - sprintf( - "Task %s '%s' started (pid=%s)" - , $taskPoll[$tkey]['task']->get_task_id() - , $taskPoll[$tkey]["cmd"] - , $taskPoll[$tkey]['task']->get_pid() - ) - ); - $runningtask++; - } - else - { - // ************************************************ - // file_put_contents("/tmp/scheduler2.log", sprintf("%s [%d] : NOT RUNNING ? : pid=%s \n", __FILE__, __LINE__, $taskPoll[$tkey]['task']->get_pid()), FILE_APPEND); - $taskPoll[$tkey]["task"]->increment_crash_counter(); - - @fclose($taskPoll[$tkey]["pipes"][1]); - @fclose($taskPoll[$tkey]["pipes"][2]); - @proc_close($taskPoll[$tkey]["process"]); - $taskPoll[$tkey]["process"] = null; - - $this->log( - sprintf( - "Task %s '%s' failed to start %d times" - , $taskPoll[$tkey]["task"]->get_task_id() - , $taskPoll[$tkey]["cmd"] - , $taskPoll[$tkey]["task"]->get_crash_counter() - ) - ); - - if($taskPoll[$tkey]["task"]->get_crash_counter() > 5) - { - $taskPoll[$tkey]["task"]->set_status(task_abstract::RETURNSTATUS_STOPPED); - } - else - { - $taskPoll[$tkey]["task"]->set_status(task_abstract::STATUS_TOSTART); - } - } - } - break; - - case task_abstract::STATUS_STARTED: - $crashed = false; - // If no process, the task is probably manually ran - if($taskPoll[$tkey]["process"]) - { - $taskPoll[$tkey]["killat"] = NULL; - - // if(is_resource($taskPoll[$tkey]["process"])) - // { - // $proc_status = proc_get_status($taskPoll[$tkey]["process"]); - // if($proc_status['running']) - // $runningtask++; - // else - // $crashed = true; - // } - // else - // { - // $crashed = true; - // } - - if($taskPoll[$tkey]['task']->get_pid()) - $runningtask++; - else - $crashed = true; - } - - if($crashed === true && $taskPoll[$tkey]["task"]->get_status() === task_abstract::RETURNSTATUS_TORESTART) - { - $crashed = false; - } - if($crashed) - { - $taskPoll[$tkey]["task"]->increment_crash_counter(); - - @fclose($taskPoll[$tkey]["pipes"][1]); - @fclose($taskPoll[$tkey]["pipes"][2]); - @proc_close($taskPoll[$tkey]["process"]); - $taskPoll[$tkey]["process"] = null; - - $this->log( - sprintf( - "Task %s crashed %d times" - , $taskPoll[$tkey]["task"]->get_task_id() - , $taskPoll[$tkey]["task"]->get_crash_counter() - ) - ); - - - if($taskPoll[$tkey]["task"]->get_crash_counter() > 5) - { - $taskPoll[$tkey]["task"]->set_status(task_abstract::RETURNSTATUS_STOPPED); - } - else - { - $taskPoll[$tkey]["task"]->set_status(task_abstract::STATUS_TOSTART); - } - } - break; - - case task_abstract::STATUS_TOSTOP: - if($taskPoll[$tkey]["process"]) - { - if($taskPoll[$tkey]["killat"] === NULL) - $taskPoll[$tkey]["killat"] = time() + self::TASKDELAYTOQUIT; - - if(($dt = $taskPoll[$tkey]["killat"] - time()) < 0) - { - $ppid = $taskPoll[$tkey]['task']->get_pid(); - $pids = preg_split('/\s+/', `ps -o pid --no-heading --ppid $ppid`); - foreach($pids as $pid) - { - if(is_numeric($pid)) - { - $this->log("Killing pid %d", $pid); - posix_kill($pid, 9); - } - } - - $this->log( - sprintf( - "SIGKILL sent to task %s (pid=%s)" - , $taskPoll[$tkey]["task"]->get_task_id() - , $taskPoll[$tkey]["task"]->get_pid() - ) - ); - - proc_terminate($taskPoll[$tkey]["process"], 9); - @fclose($taskPoll[$tkey]["pipes"][1]); - @fclose($taskPoll[$tkey]["pipes"][2]); - proc_close($taskPoll[$tkey]["process"]); - unlink($lockdir . 'task_' . $taskPoll[$tkey]['task']->get_task_id() . '.lock'); - - $taskPoll[$tkey]["task"]->increment_crash_counter(); - // $taskPoll[$tkey]["task"]->set_pid(null); - $taskPoll[$tkey]["task"]->set_status(task_abstract::RETURNSTATUS_STOPPED); - } - else - { - $this->log( - sprintf( - "waiting task %s to quit (kill in %d seconds)" - , $taskPoll[$tkey]["task"]->get_task_id() - , $dt - ) - ); - $runningtask++; - } - } - break; - - case task_abstract::RETURNSTATUS_STOPPED: - case task_abstract::RETURNSTATUS_TODELETE: - if($taskPoll[$tkey]["process"]) - { - @fclose($taskPoll[$tkey]["pipes"][1]); - @fclose($taskPoll[$tkey]["pipes"][2]); - @proc_close($taskPoll[$tkey]["process"]); - - $taskPoll[$tkey]["process"] = null; - } - break; - } - } - - */ - - - - - - - - - - - $to_reopen = false; - if($conn->ping()) - { - $conn->close(); - unset($conn); - $to_reopen = true; - } - sleep($sleeptime); - if($to_reopen) - { - $conn = self::get_connection(); - } + for($i=0; $i<$sleeptime; $i++) + sleep(1); } $sql = "UPDATE sitepreff SET schedstatus='stopped', schedpid='0'"; diff --git a/lib/classes/task/abstract.class.php b/lib/classes/task/abstract.class.php index 801696d992..8662d1d456 100644 --- a/lib/classes/task/abstract.class.php +++ b/lib/classes/task/abstract.class.php @@ -89,6 +89,9 @@ abstract class task_abstract */ protected $return_value; protected $runner; + + private $input; + private $output; /** * delay between two loops @@ -104,7 +107,15 @@ abstract class task_abstract public function get_status() { - return $this->task_status; + $conn = connection::getPDOConnection(); + $sql = 'SELECT status FROM task2 WHERE task_id = :taskid'; + $stmt = $conn->prepare($sql); + $stmt->execute(array(':taskid' => $this->taskid)); + $row = $stmt->fetch(PDO::FETCH_ASSOC); + $stmt->closeCursor(); + if(!$row) + throw new Exception('Unknown task id'); + return $row['status']; } public function printInterfaceHEAD() @@ -141,7 +152,7 @@ abstract class task_abstract $stmt = $conn->prepare($sql); $stmt->execute(array(':status' => $status, ':taskid' => $this->get_task_id())); $stmt->closeCursor(); - +$this->log(sprintf("task %d <- %s", $this->get_task_id(), $status)); $this->task_status = $status; return $this->task_status; @@ -265,6 +276,7 @@ abstract class task_abstract function __construct($taskid) { $this->taskid = $taskid; + phrasea::use_i18n(Session_Handler::get_locale()); $this->system = system_server::get_platform(); @@ -296,7 +308,7 @@ abstract class task_abstract $this->log($e->getMessage()); $this->log(("Warning : abox connection lost, restarting in 10 min.")); - for($t = 60 * 10; $t > 0; $t--) // DON'T do sleep(600) because it prevents ticks ! + for($t = 60 * 10; $this->running && $t > 0; $t--) // DON'T do sleep(600) because it prevents ticks ! sleep(1); $this->running = false; @@ -354,18 +366,18 @@ abstract class task_abstract public function delete() { - $conn = connection::getPDOConnection(); - $registry = registry::get_instance(); - $sql = "DELETE FROM task2 WHERE task_id = :task_id"; - $stmt = $conn->prepare($sql); - $stmt->execute(array(':task_id' => $this->get_task_id())); - $stmt->closeCursor(); + if(!$this->get_pid()) // do not delete a running task + { + $conn = connection::getPDOConnection(); + $registry = registry::get_instance(); + $sql = "DELETE FROM task2 WHERE task_id = :task_id"; + $stmt = $conn->prepare($sql); + $stmt->execute(array(':task_id' => $this->get_task_id())); + $stmt->closeCursor(); - $lock_file = $registry->get('GV_RootPath') . 'tmp/locks/task_' . $this->get_task_id() . '.lock'; - if(is_writable($lock_file)) - unlink($lock_file); - - return; + $lock_file = $registry->get('GV_RootPath') . 'tmp/locks/task_' . $this->get_task_id() . '.lock'; + @unlink($lock_file); + } } protected function check_memory_usage() @@ -520,6 +532,11 @@ abstract class task_abstract return $this; } + + public function set_running($stat) + { + $this->running = $stat; + } protected function pause($when_started=0) { @@ -532,15 +549,16 @@ abstract class task_abstract $conn = connection::getPDOConnection(); $conn->close(); unset($conn); -// sleep($this->period - $when_started); - for($t = $this->period - $when_started; $t > 0; $t--) // DON'T do sleep($this->period - $when_started) because it prevents ticks ! + for($t = $this->period - $when_started; $this->running && $t > 0; $t--) // DON'T do sleep($this->period - $when_started) because it prevents ticks ! sleep(1); } } } - final public function run($runner) + final public function run($runner, $input=null, $output = null) { + $this->input = $input; + $this->output = $output; // ************************************************ // file_put_contents("/tmp/scheduler2.log", sprintf("%s [%d] : LAUNCHING : tid=%s \n", __FILE__, __LINE__, $this->get_task_id()), FILE_APPEND); @@ -555,7 +573,7 @@ abstract class task_abstract { // ************************************************ // file_put_contents("/tmp/scheduler2.log", sprintf("%s [%d] : LAUNCH OPENED AND CANT LOCK : pid=%s \n", __FILE__, __LINE__, getmypid()), FILE_APPEND); - printf(("runtask::ERROR : task already running.\n"), $taskid); + $this->log("runtask::ERROR : task already running."); fclose($tasklock); return; @@ -574,8 +592,8 @@ abstract class task_abstract $this->set_status(self::STATUS_STARTED); $this->running = true; + $this->run2(); -// $this->set_pid(0); flock($tasklock, LOCK_UN | LOCK_NB); ftruncate($tasklock, 0); @@ -586,7 +604,6 @@ abstract class task_abstract $this->delete(); else $this->set_status($this->return_value); - return $this; } @@ -651,13 +668,31 @@ abstract class task_abstract // print($s); } - function log($msg = '') + public function log($message) { - // $d = debug_backtrace(false); - // printf("%s\t[%s]\t%s\r\n", date('r'), $d[0]['line'], $msg); - printf("%s\t%s\r\n", date('r'), $msg); - } + $registry = registry::get_instance(); + $logdir = $registry->get('GV_RootPath') . 'logs/'; + logs::rotate($logdir . 'task_l_'.$this->taskid.'.log'); + logs::rotate($logdir . 'task_o_'.$this->taskid.'.log'); + logs::rotate($logdir . 'task_e_'.$this->taskid.'.log'); + + $date_obj = new DateTime(); + $message = sprintf("%s\t%s", $date_obj->format(DATE_ATOM), $message); + + if($this->output) + { + $this->output->writeln($message); + } + if( $this->input && !($this->input->getOption('nolog')) ) + { + file_put_contents($logdir . 'task_l_'.$this->taskid.'.log', $message."\n", FILE_APPEND); + } + + return $this; + } + + public static function interfaceAvailable() { return true; diff --git a/lib/classes/task/databoxAbstract.class.php b/lib/classes/task/databoxAbstract.class.php index 0079a092a2..580bdeca41 100644 --- a/lib/classes/task/databoxAbstract.class.php +++ b/lib/classes/task/databoxAbstract.class.php @@ -33,27 +33,32 @@ abstract class task_databoxAbstract extends task_abstract protected function run2() { +$this->log(sprintf("%s [%d] rv=%s \n", __FILE__, __LINE__, $this->return_value)); while($this->running) { +$this->log(sprintf("%s [%d] rv=%s \n", __FILE__, __LINE__, $this->return_value)); try { $conn = connection::getPDOConnection(); } catch(Exception $e) { +$this->log(sprintf("%s [%d] rv=%s \n", __FILE__, __LINE__, $this->return_value)); $this->log($e->getMessage()); $this->log(("Warning : abox connection lost, restarting in 10 min.")); - for($t = 60 * 10; $t; $t--) // DON'T do sleep(600) because it prevents ticks ! + for($t = 60 * 10; $this->running && $t; $t--) // DON'T do sleep(600) because it prevents ticks ! sleep(1); $this->running = false; $this->return_value = self::RETURNSTATUS_TORESTART; +$this->log(sprintf("%s [%d] returning from 'run2()' rv=%s \n", __FILE__, __LINE__, $this->return_value)); return; } $this->set_last_exec_time(); +$this->log(sprintf("%s [%d] rv=%s \n", __FILE__, __LINE__, $this->return_value)); try { @@ -67,12 +72,14 @@ abstract class task_databoxAbstract extends task_abstract } catch(Exception $e) { +$this->log(sprintf("%s [%d] rv=%s \n", __FILE__, __LINE__, $this->return_value)); $this->task_status = self::STATUS_TOSTOP; $this->return_value = self::RETURNSTATUS_STOPPED; $rs = array(); } foreach($rs as $row) { +$this->log(sprintf("%s [%d] rv=%s \n", __FILE__, __LINE__, $this->return_value)); if(!$this->running) break; @@ -89,6 +96,7 @@ abstract class task_databoxAbstract extends task_abstract try { +$this->log(sprintf("%s [%d] rv=%s \n", __FILE__, __LINE__, $this->return_value)); $this->load_settings(simplexml_load_string($row['settings'])); } catch(Exception $e) @@ -98,14 +106,26 @@ abstract class task_databoxAbstract extends task_abstract } $this->current_state = self::STATE_OK; - $this->process_sbas() - ->check_current_state() - ->flush_records_sbas(); +$this->log(sprintf("%s [%d] rv=%s \n", __FILE__, __LINE__, $this->return_value)); + $this->process_sbas()->check_current_state(); +$this->log(sprintf("%s [%d] rv=%s \n", __FILE__, __LINE__, $this->return_value)); + $this->process_sbas()->flush_records_sbas(); +$this->log(sprintf("%s [%d] rv=%s \n", __FILE__, __LINE__, $this->return_value)); } +$this->log(sprintf("%s [%d] rv=%s \n", __FILE__, __LINE__, $this->return_value)); $this->increment_loops(); +$this->log(sprintf("%s [%d] rv=%s \n", __FILE__, __LINE__, $this->return_value)); $this->pause($duration); } +$this->log(sprintf("%s [%d] rv=%s \n", __FILE__, __LINE__, $this->return_value)); + $this->process_sbas()->check_current_state(); +$this->log(sprintf("%s [%d] rv=%s \n", __FILE__, __LINE__, $this->return_value)); + $this->process_sbas()->flush_records_sbas(); + + $this->set_status($this->return_value); + +$this->log(sprintf("%s [%d] returning from 'run2()' rv=%s \n", __FILE__, __LINE__, $this->return_value)); return; } diff --git a/lib/classes/task/manager.class.php b/lib/classes/task/manager.class.php index 8812c00783..9c428549db 100644 --- a/lib/classes/task/manager.class.php +++ b/lib/classes/task/manager.class.php @@ -167,13 +167,7 @@ class task_manager public function get_scheduler_state2() { - $sql = "SELECT UNIX_TIMESTAMP()-UNIX_TIMESTAMP(schedqtime) AS qdelay, schedstatus AS status FROM sitepreff"; - $stmt = $this->appbox->get_connection()->prepare($sql); - $stmt->execute(); - $ret = $stmt->fetch(PDO::FETCH_ASSOC); - $stmt->closeCursor(); - $ret['pid'] = NULL; - + $pid = NULL; $appbox = appbox::get_instance(); $lockdir = $appbox->get_registry()->get('GV_RootPath') . 'tmp/locks/'; if( ($schedlock = fopen( $lockdir . 'scheduler.lock', 'a+')) ) @@ -181,7 +175,7 @@ class task_manager if (flock($schedlock, LOCK_SH | LOCK_NB) === FALSE) { // already locked : running ! - $ret['pid'] = fgets($schedlock, 512); + $pid = trim(fgets($schedlock, 512)); } else { @@ -190,6 +184,20 @@ class task_manager } fclose($schedlock); } + + $sql = "SELECT UNIX_TIMESTAMP()-UNIX_TIMESTAMP(schedqtime) AS qdelay, schedstatus AS status FROM sitepreff"; + $stmt = $this->appbox->get_connection()->prepare($sql); + $stmt->execute(); + $ret = $stmt->fetch(PDO::FETCH_ASSOC); + $stmt->closeCursor(); + + if($pid === NULL && $ret['status'] !== 'stopped') + { + // auto fix + $this->appbox->get_connection()->exec('UPDATE sitepreff SET schedstatus=\'stopped\''); + $ret['status'] = 'stopped'; + } + $ret['pid'] = $pid; return($ret); } diff --git a/lib/classes/task/period/archive.class.php b/lib/classes/task/period/archive.class.php index 4299bbebd1..bac2aa8b3c 100644 --- a/lib/classes/task/period/archive.class.php +++ b/lib/classes/task/period/archive.class.php @@ -16,7 +16,6 @@ */ class task_period_archive extends task_abstract { - /** * command line args specifics * @@ -96,19 +95,19 @@ class task_period_archive extends task_abstract $dom = new DOMDocument(); $dom->formatOutput = true; $dom->preserveWhiteSpace = false; - if ($dom->loadXML($oldxml)) + if($dom->loadXML($oldxml)) { $xmlchanged = false; // foreach($parm2 as $pname=>$pvalue) - foreach (array("str:base_id", "str:hotfolder", "str:period", "boo:move_archived", "boo:move_error", "boo:delfolder", 'boo:copy_spe', 'str:cold') as $pname) + foreach(array("str:base_id", "str:hotfolder", "str:period", "boo:move_archived", "boo:move_error", "boo:delfolder", 'boo:copy_spe', 'str:cold') as $pname) { $ptype = substr($pname, 0, 3); $pname = substr($pname, 4); $pvalue = $parm2[$pname]; - if ($ns = $dom->getElementsByTagName($pname)->item(0)) + if($ns = $dom->getElementsByTagName($pname)->item(0)) { // le champ existait dans le xml, on supprime son ancienne valeur (tout le contenu) - while (($n = $ns->firstChild)) + while(($n = $ns->firstChild)) $ns->removeChild($n); } else @@ -117,7 +116,7 @@ class task_period_archive extends task_abstract $ns = $dom->documentElement->appendChild($dom->createElement($pname)); } // on fixe sa valeur - switch ($ptype) + switch($ptype) { case "str": $ns->appendChild($dom->createTextNode($pvalue)); @@ -142,16 +141,16 @@ class task_period_archive extends task_abstract */ public function xml2graphic($xml, $form) { - if (($sxml = simplexml_load_string($xml))) // in fact XML IS always valid here... + if(($sxml = simplexml_load_string($xml))) // in fact XML IS always valid here... { // ... but we could check for safe values (ex. 0 < period < 3600) - if ((int) ($sxml->period) < 10) + if((int) ($sxml->period) < 10) $sxml->period = 10; - elseif ((int) ($sxml->period) > 300) + elseif((int) ($sxml->period) > 300) $sxml->period = 300; - if ((int) ($sxml->cold) < 5) + if((int) ($sxml->cold) < 5) $sxml->cold = 5; - elseif ((int) ($sxml->cold) > 3600) + elseif((int) ($sxml->cold) > 3600) $sxml->cold = 3600; ?>
- : + :

- +

-  :  +  :   

-  :  +  :   

  @@ -295,7 +292,7 @@ class task_period_archive extends task_abstract $base_id = (int) ($this->sxTaskSettings->base_id); $this->sbas_id = phrasea::sbasFromBas($base_id); - if (!$this->sbas_id) + if(!$this->sbas_id) { $this->log('base_id unknown'); @@ -307,10 +304,10 @@ class task_period_archive extends task_abstract $this->TColls = array(); $collection = null; - foreach ($databox->get_collections() as $coll) + foreach($databox->get_collections() as $coll) { $this->TColls['c' . $coll->get_coll_id()] = $coll->get_coll_id(); - if ($base_id == $coll->get_base_id()) + if($base_id == $coll->get_base_id()) $collection = $coll; } $server_coll_id = $collection->get_coll_id(); @@ -329,7 +326,7 @@ class task_period_archive extends task_abstract $this->cold = 60; - if (($this->sxBasePrefs = simplexml_load_string($collection->get_prefs()))) + if(($this->sxBasePrefs = simplexml_load_string($collection->get_prefs()))) { $this->sxBasePrefs["id"] = $base_id; // info utile @@ -337,21 +334,21 @@ class task_period_archive extends task_abstract $do_it = true; $this->period = (int) ($this->sxTaskSettings->period); - if ($this->period <= 0 || $this->period >= 60 * 60) + if($this->period <= 0 || $this->period >= 60 * 60) $this->period = 60; $this->cold = (int) ($this->sxTaskSettings->cold); - if ($this->cold <= 0 || $this->cold >= 60 * 60) + if($this->cold <= 0 || $this->cold >= 60 * 60) $this->cold = 60; // si on doit copier le doc dans la base, on verifie que le dossier existe $copyhd = true; $pathhd = (string) ($this->sxBasePrefs->path); - if ($copyhd && $pathhd) + if($copyhd && $pathhd) { system_file::mkdir($pathhd); - if (!is_dir($pathhd)) + if(!is_dir($pathhd)) { $this->log(sprintf(_('task::archive:Can\'t create or go to folder \'%s\''), $pathhd)); $this->running = false; @@ -359,18 +356,18 @@ class task_period_archive extends task_abstract } // on charge les masques de fichiers - if ($this->sxTaskSettings->files && $this->sxTaskSettings->files->file) + if($this->sxTaskSettings->files && $this->sxTaskSettings->files->file) { - foreach ($this->sxTaskSettings->files->file as $ft) + foreach($this->sxTaskSettings->files->file as $ft) $this->tmask[] = array( "mask" => (string) $ft["mask"] , "caption" => (string) $ft["caption"] , "accept" => (string) $ft["accept"] ); } - if ($this->sxTaskSettings->files && $this->sxTaskSettings->files->grouping) + if($this->sxTaskSettings->files && $this->sxTaskSettings->files->grouping) { - foreach ($this->sxTaskSettings->files->grouping as $ft) + foreach($this->sxTaskSettings->files->grouping as $ft) $this->tmaskgrp[] = array( "mask" => (string) $ft["mask"] , "caption" => (string) $ft["caption"] @@ -378,7 +375,7 @@ class task_period_archive extends task_abstract , "accept" => (string) $ft["accept"] ); } - if (count($this->tmask) == 0) + if(count($this->tmask) == 0) { // pas de masque defini : on accepte tout $this->tmask[] = array("mask" => ".*", "caption" => "", "accept" => ""); @@ -386,9 +383,9 @@ class task_period_archive extends task_abstract // ici la teche tourne tant qu'elle est active $loop = 0; - while ($this->running) + while($this->running) { - if (!$conn->ping()) + if(!$conn->ping()) { $this->log(("Warning : abox connection lost, restarting in 10 min.")); sleep(60 * 10); @@ -400,23 +397,25 @@ class task_period_archive extends task_abstract try { $connbas = connection::getPDOConnection($this->sbas_id); - if (!$connbas->ping()) + if(!$connbas->ping()) throw new Exception('Mysql has gone away'); } - catch (Exception $e) + catch(Exception $e) { $this->log(("dbox connection lost, restarting in 10 min.")); - sleep(60 * 10); + for($i = 0; $i < 60 * 10 && $this->running; $i++) + sleep(1); $this->running = false; return(self::RETURNSTATUS_TORESTART); } $path_in = (string) ($this->sxTaskSettings->hotfolder); - if (!@is_dir($path_in)) + if(!@is_dir($path_in)) { $this->log(sprintf(('missing hotfolder \'%s\', restarting in 10 min.'), $path_in)); - sleep(60 * 10); + for($i = 0; $i < 60 * 10 && $this->running; $i++) + sleep(1); $this->running = false; return(self::RETURNSTATUS_TORESTART); @@ -432,9 +431,9 @@ class task_period_archive extends task_abstract $row = $stmt->fetch(PDO::FETCH_ASSOC); $stmt->closeCursor(); - if ($row) + if($row) { - if ($row['status'] == 'tostop') + if($row['status'] == 'tostop') { $ret = self::RETURNSTATUS_STOPPED; $this->running = false; @@ -442,17 +441,17 @@ class task_period_archive extends task_abstract else { - if ($this->sxTaskSettings = simplexml_load_string($row['settings'])) + if($this->sxTaskSettings = simplexml_load_string($row['settings'])) { // copy settings to task, so it's easier to get later $this->move_archived = p4field::isyes($this->sxTaskSettings->move_archived); $this->move_error = p4field::isyes($this->sxTaskSettings->move_error); $period = (int) ($this->sxTaskSettings->period); - if ($period <= 0 || $period >= 60 * 60) + if($period <= 0 || $period >= 60 * 60) $period = 60; $cold = (int) ($this->sxTaskSettings->cold); - if ($cold <= 0 || $cold >= 60 * 60) + if($cold <= 0 || $cold >= 60 * 60) $cold = 60; } else @@ -464,10 +463,10 @@ class task_period_archive extends task_abstract $duration = time(); $r = $this->archiveHotFolder($server_coll_id); - if ($loop > 10) + if($loop > 10) $r = 'MAXLOOP'; - switch ($r) + switch($r) { case 'WAIT': $ret = self::RETURNSTATUS_STOPPED; @@ -479,10 +478,11 @@ class task_period_archive extends task_abstract break; case 'NORECSTODO': $duration = time() - $duration; - if ($duration < ($period + $cold)) + if($duration < ($period + $cold)) { $conn->close(); - sleep(($period + $cold) - $duration); + for($i = 0; $i < (($period + $cold) - $duration) && $this->running; $i++) + sleep(1); unset($conn); $conn = connection::getPDOConnection(); } @@ -490,14 +490,14 @@ class task_period_archive extends task_abstract case 'MAXRECSDONE': case 'MAXMEMORY': case 'MAXLOOP': - if ($row['status'] == self::STATUS_STARTED && $this->get_runner() !== self::RUNNER_MANUAL) + if($row['status'] == self::STATUS_STARTED && $this->get_runner() !== self::RUNNER_MANUAL) { $ret = self::RETURNSTATUS_TORESTART; $this->running = false; } break; default: - if ($row['status'] == self::STATUS_STARTED) + if($row['status'] == self::STATUS_STARTED) { $ret = self::RETURNSTATUS_STOPPED; $this->running = false; @@ -514,7 +514,6 @@ class task_period_archive extends task_abstract } } $this->return_value = $ret; - return($ret); } @@ -532,7 +531,7 @@ class task_period_archive extends task_abstract $conn = connection::getPDOConnection(); $path_in = p4string::delEndSlash(trim((string) ($this->sxTaskSettings->hotfolder))); - if (!@is_file($path_in . "/.phrasea.xml")) + if(!@is_file($path_in . "/.phrasea.xml")) { $this->log(sprintf(('NO .phrasea.xml AT ROOT v2 \'%s\' !'), $path_in)); @@ -540,22 +539,22 @@ class task_period_archive extends task_abstract } $path_archived = $path_error = null; - if ($this->move_archived) + if($this->move_archived) { $path_archived = $path_in . '_archived'; @mkdir($path_archived, 0755, true); - if (!file_exists($path_archived)) + if(!file_exists($path_archived)) { $this->log(sprintf(('Can\'t create folder \'%s\' !'), $path_archived)); return('BAD'); } } - if ($this->move_error) + if($this->move_error) { $path_error = $path_in . '_error'; @mkdir($path_error, 0755, true); - if (!file_exists($path_error)) + if(!file_exists($path_error)) { $this->log(sprintf(('archive:Can\'t create folder \'%s\' !'), $path_error)); @@ -574,14 +573,14 @@ class task_period_archive extends task_abstract $nnew = $this->listFilesPhase1($dom, $root, $path_in, $server_coll_id); - if ($this->debug) + if($this->debug) $this->log("=========== listFilesPhase1 ========== (returned " . $nnew . ")\n" . $dom->saveXML()); $cold = (int) ($this->sxTaskSettings->cold); - if ($cold <= 0 || $cold >= 60 * 60) + if($cold <= 0 || $cold >= 60 * 60) $cold = 60; - while ($cold > 0) + while($cold > 0) { $sql = "SELECT status FROM task2 WHERE task_id=" . $this->get_task_id(); $stmt = $conn->prepare($sql); @@ -589,8 +588,7 @@ class task_period_archive extends task_abstract $row = $stmt->fetch(PDO::FETCH_ASSOC); $stmt->closeCursor(); - if ($row && $row['status'] == 'tostop') - + if($row && $row['status'] == 'tostop') return('NORECSTODO'); sleep(2); $cold -= 2; @@ -598,45 +596,45 @@ class task_period_archive extends task_abstract $this->listFilesPhase2($dom, $root, $path_in); - if ($this->debug) + if($this->debug) $this->log("=========== listFilesPhase2 ========== : \n" . $dom->saveXML()); $this->makePairs($dom, $root, $path_in, $path_archived, $path_error); - if ($this->debug) + if($this->debug) $this->log("=========== makePairs ========== : \n" . $dom->saveXML()); $r = $this->removeBadGroups($dom, $root, $path_in, $path_archived, $path_error); - if ($this->debug) + if($this->debug) $this->log("=========== removeBadGroups ========== (returned " . ($r ? 'true' : 'false') . ") : \n" . $dom->saveXML()); $this->archive($dom, $root, $path_in, $path_archived, $path_error); - if ($this->debug) + if($this->debug) $this->log("=========== archive ========== : \n" . $dom->saveXML()); $this->bubbleResults($dom, $root, $path_in); - if ($this->debug) + if($this->debug) $this->log("=========== bubbleResults ========== : \n" . $dom->saveXML()); $r = $this->moveFiles($dom, $root, $path_in, $path_archived, $path_error); - if ($this->debug) + if($this->debug) $this->log("=========== moveFiles ========== (returned " . ($r ? 'true' : 'false') . ") : \n" . $dom->saveXML()); - if ($this->movedFiles) + if($this->movedFiles) { // something happened : a least one file has moved return('MAXRECSDONE'); } - elseif (memory_get_usage() >> 20 > 15) + elseif(memory_get_usage() >> 20 > 15) { return('MAXMEMORY'); } @@ -674,18 +672,18 @@ class task_period_archive extends task_abstract { $file = $node->getAttribute('name'); - foreach ($this->tmask as $mask) + foreach($this->tmask as $mask) { $preg_mask = '/' . $mask['mask'] . '/'; - if (preg_match($preg_mask, $file)) + if(preg_match($preg_mask, $file)) { - if ($mask['caption']) + if($mask['caption']) { // caption in a linked file ? $captionFileName = @preg_replace($preg_mask, $mask['caption'], $file); $xpath = new DOMXPath($dom); $dnl = $xpath->query('./file[@name="' . $captionFileName . '"]', $node->parentNode); - if ($dnl->length == 1) + if($dnl->length == 1) { // the caption file exists $node->setAttribute('match', $captionFileName); @@ -731,24 +729,22 @@ class task_period_archive extends task_abstract { $listFolder = new CListFolder($path); - if (($sxDotPhrasea = @simplexml_load_file($path . '/.phrasea.xml'))) + if(($sxDotPhrasea = @simplexml_load_file($path . '/.phrasea.xml'))) { // on gere le magicfile - if (($magicfile = trim((string) ($sxDotPhrasea->magicfile))) != '') + if(($magicfile = trim((string) ($sxDotPhrasea->magicfile))) != '') { $magicmethod = strtoupper($sxDotPhrasea->magicfile['method']); - if ($magicmethod == 'LOCK' && file_exists($path . '/' . $magicfile)) - + if($magicmethod == 'LOCK' && file_exists($path . '/' . $magicfile)) return; - elseif ($magicmethod == 'UNLOCK' && !file_exists($path . '/' . $magicfile)) - + elseif($magicmethod == 'UNLOCK' && !file_exists($path . '/' . $magicfile)) return; } // on gere le changement de collection - if (($new_cid = $sxDotPhrasea['collection']) != '') + if(($new_cid = $sxDotPhrasea['collection']) != '') { - if (isset($this->TColls['c' . $new_cid])) + if(isset($this->TColls['c' . $new_cid])) { $server_coll_id = $new_cid; } @@ -762,15 +758,15 @@ class task_period_archive extends task_abstract } $iloop = 0; - while (($file = $listFolder->read()) !== NULL) + while(($file = $listFolder->read()) !== NULL) { - if ($this->isIgnoredFile($file)) + if($this->isIgnoredFile($file)) continue; - if (($iloop++ % 100) == 0) + if(($iloop++ % 100) == 0) usleep(1000); - if (is_dir($path . '/' . $file)) + if(is_dir($path . '/' . $file)) { $n = $node->appendChild($dom->createElement('file')); $n->setAttribute('isdir', '1'); @@ -783,7 +779,7 @@ class task_period_archive extends task_abstract $n = $node->appendChild($dom->createElement('file')); $n->setAttribute('name', $file); $stat = stat($path . '/' . $file); - foreach (array("size", "ctime", "mtime") as $k) + foreach(array("size", "ctime", "mtime") as $k) $n->setAttribute($k, $stat[$k]); $nnew++; } @@ -792,9 +788,9 @@ class task_period_archive extends task_abstract $n->setAttribute('temperature', 'hot'); } } - catch (Exception $e) + catch(Exception $e) { - + } return($nnew); @@ -814,7 +810,7 @@ class task_period_archive extends task_abstract function listFilesPhase2($dom, $node, $path, $depth=0) { static $iloop = 0; - if ($depth == 0) + if($depth == 0) $iloop = 0; $nnew = 0; @@ -825,20 +821,31 @@ class task_period_archive extends task_abstract $xp = new DOMXPath($dom); - while (($file = $listFolder->read()) !== NULL) + if(($sxDotPhrasea = @simplexml_load_file($path . '/.phrasea.xml'))) { - if ($this->isIgnoredFile($file)) + // on gere le magicfile + if(($magicfile = trim((string) ($sxDotPhrasea->magicfile))) != '') + { + $magicmethod = strtoupper($sxDotPhrasea->magicfile['method']); + if($magicmethod == 'LOCK' && file_exists($path . '/' . $magicfile)) + return; + elseif($magicmethod == 'UNLOCK' && !file_exists($path . '/' . $magicfile)) + return; + } + } + + while(($file = $listFolder->read()) !== NULL) + { + if($this->isIgnoredFile($file)) continue; - if (($iloop++ % 100) == 0) + if(($iloop++ % 100) == 0) usleep(500); $dnl = @$xp->query('./file[@name="' . $file . '"]', $node); -// if(!$dnl) -// printf("%s \n", './file[@name="'.$file.'"]'); - if ($dnl && $dnl->length == 0) + if($dnl && $dnl->length == 0) { - if (is_dir($path . '/' . $file)) + if(is_dir($path . '/' . $file)) { $n = $node->appendChild($dom->createElement('file')); $n->setAttribute('isdir', '1'); @@ -859,20 +866,20 @@ class task_period_archive extends task_abstract // $n->setAttribute('temperature', 'hot'); $this->setBranchHot($dom, $n); } - elseif ($dnl && $dnl->length == 1) + elseif($dnl && $dnl->length == 1) { $dnl->item(0)->setAttribute('temperature', 'cold'); // $dnl->item(0)->removeAttribute('hot'); - if (is_dir($path . '/' . $file)) + if(is_dir($path . '/' . $file)) { $this->listFilesPhase2($dom, $dnl->item(0), $path . '/' . $file, $depth + 1); } else { $stat = stat($path . '/' . $file); - foreach (array("size", "ctime", "mtime") as $k) + foreach(array("size", "ctime", "mtime") as $k) { - if ($dnl->item(0)->getAttribute($k) != $stat[$k]) + if($dnl->item(0)->getAttribute($k) != $stat[$k]) { $this->setBranchHot($dom, $dnl->item(0)); break; @@ -882,9 +889,9 @@ class task_period_archive extends task_abstract } } } - catch (Exception $e) + catch(Exception $e) { - + } return; @@ -909,36 +916,35 @@ class task_period_archive extends task_abstract function makePairs($dom, $node, $path, $path_archived, $path_error, $inGrp=false, $depth=0) { static $iloop = 0; - if ($depth == 0) + if($depth == 0) $iloop = 0; - if ($depth == 0 && ($node->getAttribute('temperature') == 'hot' || $node->getAttribute('cid') == '-1')) - + if($depth == 0 && ($node->getAttribute('temperature') == 'hot' || $node->getAttribute('cid') == '-1')) return; $xpath = new DOMXPath($dom); // useful - for ($n = $node->firstChild; $n; $n = $n->nextSibling) + for($n = $node->firstChild; $n; $n = $n->nextSibling) { - if (($iloop++ % 100) == 0) + if(($iloop++ % 100) == 0) usleep(1000); // make xml lighter (free ram) - foreach (array("size", "ctime", "mtime") as $k) + foreach(array("size", "ctime", "mtime") as $k) $n->removeAttribute($k); - if ($n->getAttribute('temperature') == 'hot' || $n->getAttribute('cid') == '-1') + if($n->getAttribute('temperature') == 'hot' || $n->getAttribute('cid') == '-1') continue; $name = $n->getAttribute('name'); - if ($n->getAttribute('isdir') == '1') + if($n->getAttribute('isdir') == '1') { - if (($grpSettings = $this->getGrpSettings($name)) !== FALSE) // get 'caption', 'representation' + if(($grpSettings = $this->getGrpSettings($name)) !== FALSE) // get 'caption', 'representation' { // this is a grp folder, we check it $dnl = $xpath->query('./file[@name=".grouping.xml"]', $n); - if ($dnl->length == 1) + if($dnl->length == 1) { // this group is old (don't care about any linked files), just flag it $n->setAttribute('grp', 'tocomplete'); @@ -953,15 +959,15 @@ class task_period_archive extends task_abstract $err = false; $flink = array('caption' => null, 'representation' => null); - foreach ($flink as $linkName => $v) + foreach($flink as $linkName => $v) { - if (isset($grpSettings[$linkName]) && $grpSettings[$linkName] != '') + if(isset($grpSettings[$linkName]) && $grpSettings[$linkName] != '') { // we need this linked file, calc his real name $f = preg_replace('/' . $grpSettings['mask'] . '/i', $grpSettings[$linkName], $name); $dnl = $xpath->query('./file[@name="' . $f . '"]', $node); - if ($dnl->length == 1) + if($dnl->length == 1) { $flink[$linkName] = $dnl->item(0); // it's here } @@ -973,15 +979,15 @@ class task_period_archive extends task_abstract } } - if (!$err) + if(!$err) { // the group is ok, flag it ... $n->setAttribute('grp', 'tocreate'); // ... as the existing linked file(s) ... - foreach ($flink as $linkName => $v) + foreach($flink as $linkName => $v) { - if ($v) // this linked file exists + if($v) // this linked file exists { // $v->setAttribute('grp', '1'); $v->setAttribute('match', '*'); @@ -1002,13 +1008,13 @@ class task_period_archive extends task_abstract $this->setAllChildren($dom, $n, array('error' => '1')); // bubble to the top - for ($nn = $n; $nn && $nn->nodeType == XML_ELEMENT_NODE; $nn = $nn->parentNode) + for($nn = $n; $nn && $nn->nodeType == XML_ELEMENT_NODE; $nn = $nn->parentNode) $nn->setAttribute('error', '1'); // ... as the existing linked file(s) ... - foreach ($flink as $linkName => $v) + foreach($flink as $linkName => $v) { - if ($v) // this linked file exists, it goes error also + if($v) // this linked file exists, it goes error also $v->setAttribute('error', '1'); } } @@ -1026,9 +1032,9 @@ class task_period_archive extends task_abstract else { // this is a file - if (!$n->getAttribute('match')) // because match can be set before + if(!$n->getAttribute('match')) // because match can be set before { - if ($name == '.phrasea.xml') + if($name == '.phrasea.xml') $n->setAttribute('match', '*'); // special file(s) always ok else $this->checkMatch($dom, $n); @@ -1037,12 +1043,12 @@ class task_period_archive extends task_abstract } // scan again for unmatched files - for ($n = $node->firstChild; $n; $n = $n->nextSibling) + for($n = $node->firstChild; $n; $n = $n->nextSibling) { - if (!$n->getAttribute('isdir') == '1' && !$n->getAttribute('match')) + if(!$n->getAttribute('isdir') == '1' && !$n->getAttribute('match')) { // still no match, now it's an error (bubble to the top) - for ($nn = $n; $nn && $nn->nodeType == XML_ELEMENT_NODE; $nn = $nn->parentNode) + for($nn = $n; $nn && $nn->nodeType == XML_ELEMENT_NODE; $nn = $nn->parentNode) $nn->setAttribute('error', '1'); } } @@ -1066,33 +1072,26 @@ class task_period_archive extends task_abstract function removeBadGroups($dom, $node, $path, $path_archived, $path_error, $depth=0) { static $iloop = 0; - if ($depth == 0) + if($depth == 0) $iloop = 0; $ret = false; - if ($depth == 0 && $node->getAttribute('temperature') == 'hot') // if root of hotfolder if hot, die... - + if($depth == 0 && $node->getAttribute('temperature') == 'hot') // if root of hotfolder if hot, die... return($ret); -//printf("%s : \n", __LINE__); $nodesToDel = array(); - for ($n = $node->firstChild; $n; $n = $n->nextSibling) + for($n = $node->firstChild; $n; $n = $n->nextSibling) { - if (($iloop++ % 20) == 0) + if(($iloop++ % 20) == 0) usleep(1000); - if ($n->getAttribute('temperature') == 'hot') // do not move hotfiles + if($n->getAttribute('temperature') == 'hot') // do not move hotfiles continue; -//printf("%s : \n", __LINE__); $name = $n->getAttribute('name'); -//printf("----------------\n file %s : \n ", $path.'/'.$name); -//$fp = fopen('php://stdin', 'r'); -//fgets($fp); -//fclose($fp); - if ($n->getAttribute('isdir')) + if($n->getAttribute('isdir')) { // a dir // if($n->getAttribute('error') && $this->move_error) @@ -1104,7 +1103,7 @@ class task_period_archive extends task_abstract , $path_archived . '/' . $name , $path_error . '/' . $name , $depth + 1); - if ($n->getAttribute('grp') == 'todelete') + if($n->getAttribute('grp') == 'todelete') { $nodesToDel[] = $n; @unlink($path . '/' . $name); @@ -1113,10 +1112,9 @@ class task_period_archive extends task_abstract else { // a file - if ($n->getAttribute('error')) + if($n->getAttribute('error')) { -// printf("%s : \n", __LINE__); - if ($this->move_error) + if($this->move_error) { $rootpath = p4string::delEndSlash(trim((string) ($this->sxTaskSettings->hotfolder))); $subpath = substr($path, strlen($rootpath)); @@ -1134,7 +1132,7 @@ class task_period_archive extends task_abstract } } - foreach ($nodesToDel as $n) + foreach($nodesToDel as $n) $n->parentNode->removeChild($n); return; @@ -1157,31 +1155,30 @@ class task_period_archive extends task_abstract function archive($dom, $node, $path, $path_archived, $path_error, $depth=0) { static $iloop = 0; - if ($depth == 0) + if($depth == 0) $iloop = 0; - if ($node->getAttribute('temperature') == 'hot') - + if($node->getAttribute('temperature') == 'hot') return; $nodesToDel = array(); - for ($n = $node->firstChild; $n; $n = $n->nextSibling) + for($n = $node->firstChild; $n; $n = $n->nextSibling) { - if (($iloop++ % 20) == 0) + if(($iloop++ % 20) == 0) usleep(1000); - if ($n->getAttribute('temperature') == 'hot') + if($n->getAttribute('temperature') == 'hot') continue; - if ($n->getAttribute('cid') == '-1') + if($n->getAttribute('cid') == '-1') { $n->setAttribute('error', '1'); continue; } - if ($n->getAttribute('isdir') == '1') + if($n->getAttribute('isdir') == '1') { - if ($n->getAttribute('grp')) + if($n->getAttribute('grp')) { // a grp folder : special work $this->ArchiveGrp($dom, $n, $path, $path_archived, $path_error, $nodesToDel); @@ -1203,16 +1200,16 @@ class task_period_archive extends task_abstract } } // printf("========== %s === %s ====== \n", __LINE__, var_export($nodesToDel, true)); - foreach ($nodesToDel as $n) + foreach($nodesToDel as $n) $n->parentNode->removeChild($n); // at the end of recursion, restore the magic file (create or delete it) - if (($magicfile = $node->getAttribute('magicfile')) != '') + if(($magicfile = $node->getAttribute('magicfile')) != '') { $magicmethod = $node->getAttribute('magicmethod'); - if ($magicmethod == 'LOCK') + if($magicmethod == 'LOCK') file_put_contents($path . '/' . $magicfile, ''); - elseif ($magicmethod == 'UNLOCK') + elseif($magicmethod == 'UNLOCK') unlink($path . '/' . $magicfile); } @@ -1234,24 +1231,23 @@ class task_period_archive extends task_abstract function bubbleResults($dom, $node, $path, $depth=0) { static $iloop = 0; - if ($depth == 0) + if($depth == 0) $iloop = 0; - if ($node->getAttribute('temperature') == 'hot') - + if($node->getAttribute('temperature') == 'hot') return; $ret = 0; - for ($n = $node->firstChild; $n; $n = $n->nextSibling) + for($n = $node->firstChild; $n; $n = $n->nextSibling) { - if (($iloop++ % 20) == 0) + if(($iloop++ % 20) == 0) usleep(1000); - if ($n->getAttribute('name') == '.phrasea.xml' || $n->getAttribute('name') == '.grouping.xml') + if($n->getAttribute('name') == '.phrasea.xml' || $n->getAttribute('name') == '.grouping.xml') { // special files stay in place AND are copied into 'archived' $n->setAttribute('keep', '1'); - if (p4field::isyes($this->sxTaskSettings->copy_spe)) + if(p4field::isyes($this->sxTaskSettings->copy_spe)) $n->setAttribute('archived', '1'); } // else @@ -1261,20 +1257,20 @@ class task_period_archive extends task_abstract // $n->setAttribute('error', '1'); // } // } - if ($n->getAttribute('keep') == '1') + if($n->getAttribute('keep') == '1') $ret |= 1; - if ($n->getAttribute('archived') == '1') + if($n->getAttribute('archived') == '1') $ret |= 2; - if ($n->getAttribute('error') == '1') + if($n->getAttribute('error') == '1') $ret |= 4; - if ($n->getAttribute('isdir') == '1') + if($n->getAttribute('isdir') == '1') $ret |= $this->bubbleResults($dom, $n, $path . '/' . $n->getAttribute('name'), $depth + 1); } - if ($ret & 1) + if($ret & 1) $node->setAttribute('keep', '1'); - if ($ret & 2) + if($ret & 2) $node->setAttribute('archived', '1'); - if ($ret & 4) + if($ret & 4) $node->setAttribute('error', '1'); return($ret); @@ -1296,23 +1292,22 @@ class task_period_archive extends task_abstract function moveFiles($dom, $node, $path, $path_archived, $path_error, $depth=0) { static $iloop = 0; - if ($depth == 0) + if($depth == 0) $iloop = 0; $ret = false; - if ($depth == 0 && $node->getAttribute('temperature') == 'hot') // if root of hotfolder if hot, die... - + if($depth == 0 && $node->getAttribute('temperature') == 'hot') // if root of hotfolder if hot, die... return($ret); //printf("%s : \n", __LINE__); $nodesToDel = array(); - for ($n = $node->firstChild; $n; $n = $n->nextSibling) + for($n = $node->firstChild; $n; $n = $n->nextSibling) { - if (($iloop++ % 20) == 0) + if(($iloop++ % 20) == 0) usleep(1000); - if ($n->getAttribute('temperature') == 'hot') // do not move hotfiles + if($n->getAttribute('temperature') == 'hot') // do not move hotfiles continue; //printf("%s : \n", __LINE__); @@ -1322,7 +1317,7 @@ class task_period_archive extends task_abstract //fgets($fp); //fclose($fp); - if ($n->getAttribute('isdir')) + if($n->getAttribute('isdir')) { // printf("%s : ('%s', '%s')\n", __LINE__, $path_archived, $path_error); // $new_path_archived = $new_path_error = null; @@ -1355,7 +1350,7 @@ class task_period_archive extends task_abstract , $path_error . '/' . $name , $depth + 1); - if (!$n->firstChild) + if(!$n->firstChild) $nodesToDel[] = $n; // ----- JY 20100318 : DO NOT DELETE EMPTY FOLDERS ANYMORE, AS THEY MAY DISAPEAR TOO SOON ----- // if(!$n->getAttribute('keep')) @@ -1368,27 +1363,27 @@ class task_period_archive extends task_abstract $rootpath = p4string::delEndSlash(trim((string) ($this->sxTaskSettings->hotfolder))); $subpath = substr($path, strlen($rootpath)); - if ($n->getAttribute('archived') && $this->move_archived) + if($n->getAttribute('archived') && $this->move_archived) { $this->log(sprintf(('copy \'%s\' to \'archived\''), $subpath . '/' . $name)); @mkdir($path_archived, 0755, true); @copy($path . '/' . $name, $path_archived . '/' . $name); - if (!$n->getAttribute('keep')) // do not count copy of special files as a real event + if(!$n->getAttribute('keep')) // do not count copy of special files as a real event { $nodesToDel[] = $n; $ret = true; } } - if ($n->getAttribute('error') && $this->move_error) + if($n->getAttribute('error') && $this->move_error) { // printf("%s : \n", __LINE__); $this->log(sprintf(('copy \'%s\' to \'error\''), $subpath . '/' . $name)); @mkdir($path_error, 0755, true); @copy($path . '/' . $name, $path_error . '/' . $name); - if (!$n->getAttribute('keep')) // do not count copy of special files as a real event + if(!$n->getAttribute('keep')) // do not count copy of special files as a real event { $nodesToDel[] = $n; $ret = true; @@ -1396,11 +1391,11 @@ class task_period_archive extends task_abstract //printf("-> copy to %s \n", $path_error.'/'.$name); } - if (!$n->getAttribute('keep')) + if(!$n->getAttribute('keep')) { //printf("-> unlink %s \n", $path.'/'.$name); $this->log(sprintf(('delete \'%s\''), $subpath . '/' . $name)); - if (@unlink($path . '/' . $name)) + if(@unlink($path . '/' . $name)) { // $n->parentNode->removeChild($n); $this->movedFiles++; @@ -1413,7 +1408,7 @@ class task_period_archive extends task_abstract } } - foreach ($nodesToDel as $n) + foreach($nodesToDel as $n) $n->parentNode->removeChild($n); return($ret); @@ -1427,12 +1422,12 @@ class task_period_archive extends task_abstract */ function setBranchHot($dom, $node) { - for ($n = $node; $n; $n = $n->parentNode) + for($n = $node; $n; $n = $n->parentNode) { - if ($n->nodeType == XML_ELEMENT_NODE) + if($n->nodeType == XML_ELEMENT_NODE) { $n->setAttribute('temperature', 'hot'); - if ($n->hasAttribute('pxml')) + if($n->hasAttribute('pxml')) break; } } @@ -1463,7 +1458,7 @@ class task_period_archive extends task_abstract $groupingFile = $path . '/' . $grpFolder . '/.grouping.xml'; - if ($node->getAttribute('grp') == 'tocreate') + if($node->getAttribute('grp') == 'tocreate') { $representationFileName = null; $representationFileNode = null; @@ -1478,7 +1473,7 @@ class task_period_archive extends task_abstract $this->log(sprintf(('created story \'%s\''), $subpath . '/' . $grpFolder)); // if the .grp does not have a representative doc, let's use a generic file - if (!($rep = $node->getAttribute('grp_representation'))) + if(!($rep = $node->getAttribute('grp_representation'))) { $registry = registry::get_instance(); @@ -1495,7 +1490,7 @@ class task_period_archive extends task_abstract $this->log(sprintf(('representation from \'%s\''), $representationFileName)); } - if (($cap = $node->getAttribute('grp_caption'))) + if(($cap = $node->getAttribute('grp_caption'))) { $dnl = $xpath->query('./file[@name="' . $cap . '"]', $node->parentNode); $captionFileNode = $dnl->item(0); @@ -1509,7 +1504,7 @@ class task_period_archive extends task_abstract $pi = pathinfo($subpath); $caption_file = null; - if (file_exists($path . '/' . $captionFileName)) + if(file_exists($path . '/' . $captionFileName)) { $caption_file = new system_file($path . '/' . $captionFileName); } @@ -1522,14 +1517,14 @@ class task_period_archive extends task_abstract $meta = $system_file->extract_metadatas($databox->get_meta_structure(), $caption_file); $stat0 = $stat1 = "0"; - if ($this->sxBasePrefs->status) + if($this->sxBasePrefs->status) $stat0 = (string) ($this->sxBasePrefs->status); - if ($this->sxTaskSettings->status) + if($this->sxTaskSettings->status) $stat1 = (string) ($this->sxTaskSettings->status); - if (!$stat0) + if(!$stat0) $stat0 = '0'; - if (!$stat1) + if(!$stat1) $stat1 = '0'; @@ -1551,7 +1546,7 @@ class task_period_archive extends task_abstract - if ($genericdoc) + if($genericdoc) unlink($genericdoc); file_put_contents($groupingFile, ''); @@ -1561,7 +1556,7 @@ class task_period_archive extends task_abstract $n->setAttribute('grp', '1'); // $n->setAttribute('archived', '1'); $n->setAttribute('match', '*'); - if ($this->move_archived) + if($this->move_archived) { $this->log(sprintf(('copy \'%s\' to \'archived\''), $subpath . '/' . $grpFolder . '/.grouping.xml')); @mkdir($path_archived . '/' . $grpFolder, 0755, true); @@ -1569,14 +1564,14 @@ class task_period_archive extends task_abstract } // - if ($captionFileNode) + if($captionFileNode) { $captionFileNode->setAttribute('archived', '1'); - if ($this->move_archived) + if($this->move_archived) { $this->log(sprintf(('copy \'%s\' to \'archived\''), $subpath . '/' . $captionFileName)); - if (!is_dir($path_archived)) + if(!is_dir($path_archived)) @mkdir($path_archived, 0755, true); @copy($path . '/' . $captionFileName, $path_archived . '/' . $captionFileName); } @@ -1585,14 +1580,14 @@ class task_period_archive extends task_abstract $this->movedFiles++; } - if ($representationFileNode) + if($representationFileNode) { $representationFileNode->setAttribute('archived', '1'); - if ($this->move_archived) + if($this->move_archived) { $this->log(sprintf(('copy \'%s\' to \'archived\''), $subpath . '/' . $representationFileName)); - if (!is_dir($path_archived)) + if(!is_dir($path_archived)) @mkdir($path_archived, 0755, true); @copy($path . '/' . $representationFileName, $path_archived . '/' . $representationFileName); } @@ -1604,14 +1599,14 @@ class task_period_archive extends task_abstract // $node->setAttribute('grp', 'tocomplete'); } - catch (Exception $e) + catch(Exception $e) { echo $e->getMessage(); } } // here the .grouping.xml should exists - if (file_exists($groupingFile)) + if(file_exists($groupingFile)) { // a .grouping.xml must stay in place // -- don't do, done in phase4 @@ -1646,9 +1641,9 @@ class task_period_archive extends task_abstract { //usleep(1000); $nodesToDel = array(); - for ($n = $node->firstChild; $n; $n = $n->nextSibling) + for($n = $node->firstChild; $n; $n = $n->nextSibling) { - if ($n->getAttribute('isdir') == '1') + if($n->getAttribute('isdir') == '1') { // in a grp, all levels goes in the same grp $node->setAttribute('archived', '1'); // the main grp folder is 'keep'ed, but not subfolders @@ -1664,7 +1659,7 @@ class task_period_archive extends task_abstract } } // printf("======== %s %s \n", __LINE__, var_export($nodesToDel, true)); - foreach ($nodesToDel as $n) + foreach($nodesToDel as $n) $n->parentNode->removeChild($n); return; @@ -1685,8 +1680,7 @@ class task_period_archive extends task_abstract function archiveFile($dom, $node, $path, $path_archived, $path_error, &$nodesToDel, $grp_rid=0) { $match = $node->getAttribute('match'); - if ($match == '*') - + if($match == '*') return; $file = $node->getAttribute('name'); @@ -1697,7 +1691,7 @@ class task_period_archive extends task_abstract $subpath = substr($path, strlen($rootpath)); - if (!$match) + if(!$match) { // the file does not match on any mask $this->log(sprintf(("File '%s' does not match any mask"), $subpath . '/' . $file)); @@ -1705,7 +1699,7 @@ class task_period_archive extends task_abstract return; } - elseif ($match == '?') + elseif($match == '?') { // the caption file is missing $this->log(sprintf(("Caption of file '%s' is missing"), $subpath . '/' . $file)); @@ -1713,12 +1707,12 @@ class task_period_archive extends task_abstract return; } - elseif (($match != '.')) // match='.' : the file does not have a separate caption + elseif(($match != '.')) // match='.' : the file does not have a separate caption { $xpath = new DOMXPath($dom); $dnl = $xpath->query('./file[@name="' . $match . '"]', $node->parentNode); // in fact, xquery has been done in checkMatch, setting match='?' if caption does not exists... - if ($dnl->length == 1) + if($dnl->length == 1) { // ...so we ALWAYS come here $captionFileNode = $dnl->item(0); @@ -1758,26 +1752,26 @@ class task_period_archive extends task_abstract $subpath = substr($path, strlen($rootpath)); $this->log(sprintf(("Archiving file '%s'"), $subpath . '/' . $file)); - if ($captionFileName !== NULL) + if($captionFileName !== NULL) $this->log(sprintf(' ' . (" (caption in '%s')"), $captionFileName)); - if ($grp_rid !== 0) + if($grp_rid !== 0) $this->log(sprintf(' ' . (" into GRP rid=%s"), $grp_rid)); $stat0 = $stat1 = "0"; - if ($this->sxBasePrefs->status) + if($this->sxBasePrefs->status) $stat0 = (string) ($this->sxBasePrefs->status); - if ($this->sxTaskSettings->status) + if($this->sxTaskSettings->status) $stat1 = (string) ($this->sxTaskSettings->status); - if (!$stat0) + if(!$stat0) $stat0 = '0'; - if (!$stat1) + if(!$stat1) $stat1 = '0'; $system_file = new system_file($path . '/' . $file); $caption_file = null; - if ($captionFileName != $file) + if($captionFileName != $file) { $caption_file = new system_file($path . '/' . $captionFileName); } @@ -1794,10 +1788,10 @@ class task_period_archive extends task_abstract unset($databox); $hexstat = ''; - if ($meta['status'] !== NULL) + if($meta['status'] !== NULL) { $s = strrev($meta['status']) . str_repeat('0', 64); - for ($a = 0; $a < 4; $a++) + for($a = 0; $a < 4; $a++) $hexstat = substr('0000' . base_convert(strrev(substr($s, $a << 4, 16)), 2, 16), -4) . $hexstat; } else @@ -1807,7 +1801,7 @@ class task_period_archive extends task_abstract $lazaret = false; $uuid = false; - if ($grp_rid == 0 && $captionFileName == NULL) + if($grp_rid == 0 && $captionFileName == NULL) { $this->log(sprintf(("Checkin for lazaret"))); try @@ -1818,7 +1812,7 @@ class task_period_archive extends task_abstract $sha256 = $system_file->get_sha256(); $uuid = false; - if (!$system_file->has_uuid()) + if(!$system_file->has_uuid()) { try { @@ -1829,12 +1823,12 @@ class task_period_archive extends task_abstract $row = $stmt->fetch(PDO::FETCH_ASSOC); $stmt->closeCursor(); - if ($row && uuid::is_valid($row['uuid'])) + if($row && uuid::is_valid($row['uuid'])) $uuid = $row['uuid']; } - catch (Exception $e) + catch(Exception $e) { - + } } @@ -1843,13 +1837,13 @@ class task_period_archive extends task_abstract $error_file = p4file::check_file_error($system_file->getPathname(), $sbas_id, $file); $status = databox_status::operation_or($stat0, $stat1); - if ($meta['status']) + if($meta['status']) $status = databox_status::operation_or($status, $meta['status']); - if (!$system_file->is_new_in_base(phrasea::sbasFromBas($base_id)) || count($error_file) > 0) + if(!$system_file->is_new_in_base(phrasea::sbasFromBas($base_id)) || count($error_file) > 0) { $this->log(sprintf(("Trying to move to lazaret"))); - if (lazaretFile::move_uploaded_to_lazaret($system_file, $base_id, $file, implode("\n", $error_file), $status)) + if(lazaretFile::move_uploaded_to_lazaret($system_file, $base_id, $file, implode("\n", $error_file), $status)) { $this->log("File %s moved to lazaret"); $lazaret = true; @@ -1862,13 +1856,13 @@ class task_period_archive extends task_abstract $this->log("No need to lazaret"); } } - catch (Exception $e) + catch(Exception $e) { $this->log(sprintf(("Error while checking for lazaret : %s"), $e->getMessage())); } } - if (!$lazaret) + if(!$lazaret) { $cid = $node->getAttribute('cid'); @@ -1885,7 +1879,7 @@ class task_period_archive extends task_abstract $record->reindex(); $rid = $record->get_record_id(); - if ($grp_rid !== NULL) + if($grp_rid !== NULL) { $connbas = connection::getPDOConnection($this->sbas_id); $sql = "INSERT INTO regroup (id, rid_parent, rid_child, dateadd, ord) @@ -1903,49 +1897,49 @@ class task_period_archive extends task_abstract $this->archivedFiles++; $node->setAttribute('archived', '1'); - if ($captionFileNode) + if($captionFileNode) $captionFileNode->setAttribute('archived', '1'); } - catch (Exception $e) + catch(Exception $e) { $this->log(("Error : can't insert record : " . $e->getMessage())); $node->setAttribute('error', '1'); - if ($captionFileNode) + if($captionFileNode) $captionFileNode->setAttribute('error', '1'); } } - if ($node->getAttribute('archived') && $this->move_archived) + if($node->getAttribute('archived') && $this->move_archived) { $this->log(sprintf(('copy \'%s\' to \'archived\''), $subpath . '/' . $file)); @mkdir($path_archived, 0755, true); @copy($path . '/' . $file, $path_archived . '/' . $file); - if ($captionFileName != $file) + if($captionFileName != $file) { $this->log(sprintf(('copy \'%s\' to \'archived\''), $subpath . '/' . $captionFileName)); @copy($path . '/' . $captionFileName, $path_archived . '/' . $captionFileName); } - if (!$node->getAttribute('keep')) // do not count copy of special files as a real event + if(!$node->getAttribute('keep')) // do not count copy of special files as a real event $ret = true; } - if ($node->getAttribute('error') && $this->move_error) + if($node->getAttribute('error') && $this->move_error) { $this->log(sprintf(('copy \'%s\' to \'error\''), $subpath . '/' . $file)); @mkdir($path_error, 0755, true); @copy($path . '/' . $file, $path_error . '/' . $file); - if ($captionFileName != $file) + if($captionFileName != $file) { $this->log(sprintf(('copy \'%s\' to \'error\''), $subpath . '/' . $captionFileName)); @copy($path . '/' . $captionFileName, $path_error . '/' . $captionFileName); } - if (!$node->getAttribute('keep')) // do not count copy of special files as a real event + if(!$node->getAttribute('keep')) // do not count copy of special files as a real event $ret = true; } - if (!$node->getAttribute('keep')) + if(!$node->getAttribute('keep')) { $file = $node->getAttribute('name'); @unlink($path . '/' . $file); @@ -1954,7 +1948,7 @@ class task_period_archive extends task_abstract $this->movedFiles++; } - if ($captionFileNode && !$captionFileNode->getAttribute('keep')) + if($captionFileNode && !$captionFileNode->getAttribute('keep')) { $file = $captionFileNode->getAttribute('name'); @unlink($path . '/' . $file); @@ -1978,16 +1972,16 @@ class task_period_archive extends task_abstract function setAllChildren($dom, $node, $attributes, $depth=0) { static $iloop = 0; - if ($depth == 0) + if($depth == 0) $iloop = 0; - foreach ($attributes as $a => $v) + foreach($attributes as $a => $v) $node->setAttribute($a, $v); - if (($iloop++ % 100) == 0) + if(($iloop++ % 100) == 0) usleep(1000); - for ($n = $node->firstChild; $n; $n = $n->nextSibling) + for($n = $node->firstChild; $n; $n = $n->nextSibling) $this->setAllChildren($dom, $n, $attributes, $depth + 1); } @@ -1999,18 +1993,18 @@ class task_period_archive extends task_abstract function getGrpSettings($file) { $matched = FALSE; - foreach ($this->tmaskgrp as $maskgrp) + foreach($this->tmaskgrp as $maskgrp) { //$attachments = null; //$attachments["representation"] = null; //$attachments["caption"] = null; $preg_maskgrp = "/" . $maskgrp["mask"] . "/"; - if (preg_match($preg_maskgrp, $file)) + if(preg_match($preg_maskgrp, $file)) { $matched = $maskgrp; } - if ($matched) + if($matched) break; } @@ -2021,7 +2015,6 @@ class task_period_archive extends task_abstract class CListFolder { - /** * * @var Array @@ -2036,12 +2029,12 @@ class CListFolder function __construct($path, $sorted = true) { $this->list = array(); - if ($hdir = opendir($path)) + if($hdir = opendir($path)) { - while (false !== ($file = readdir($hdir))) + while(false !== ($file = readdir($hdir))) $this->list[] = $file; closedir($hdir); - if ($sorted) + if($sorted) natcasesort($this->list); } } @@ -2065,4 +2058,3 @@ class CListFolder } } - diff --git a/lib/classes/task/period/cindexer.class.php b/lib/classes/task/period/cindexer.class.php index 15d9ff17de..3cedab138d 100644 --- a/lib/classes/task/period/cindexer.class.php +++ b/lib/classes/task/period/cindexer.class.php @@ -16,6 +16,11 @@ */ class task_period_cindexer extends task_abstract { + // how to execute indexer (choose in 'run2' method) + private $method; + const METHOD_FORK = 'METHOD_FORK'; + const METHOD_EXEC = 'METHOD_EXEC'; + const METHOD_PROC_OPEN = 'METHOD_PROC_OPEN'; /** * @@ -115,18 +120,18 @@ class task_period_cindexer extends task_abstract ); $dom = new DOMDocument(); $dom->formatOutput = true; - if ($dom->loadXML($oldxml)) + if($dom->loadXML($oldxml)) { $xmlchanged = false; - foreach (array("str:binpath", "str:host", "str:port", "str:base", "str:user", "str:password", "str:socket", "boo:use_sbas", "boo:nolog", "str:clng", "boo:winsvc_run", "str:charset") as $pname) + foreach(array("str:binpath", "str:host", "str:port", "str:base", "str:user", "str:password", "str:socket", "boo:use_sbas", "boo:nolog", "str:clng", "boo:winsvc_run", "str:charset") as $pname) { $ptype = substr($pname, 0, 3); $pname = substr($pname, 4); $pvalue = $parm2[$pname]; - if ($ns = $dom->getElementsByTagName($pname)->item(0)) + if($ns = $dom->getElementsByTagName($pname)->item(0)) { // le champ existait dans le xml, on supprime son ancienne valeur (tout le contenu) - while (($n = $ns->firstChild)) + while(($n = $ns->firstChild)) $ns->removeChild($n); } else @@ -135,7 +140,7 @@ class task_period_cindexer extends task_abstract $ns = $dom->documentElement->appendChild($dom->createElement($pname)); } // on fixe sa valeur - switch ($ptype) + switch($ptype) { case "str": $ns->appendChild($dom->createTextNode($pvalue)); @@ -159,7 +164,7 @@ class task_period_cindexer extends task_abstract */ public function xml2graphic($xml, $form) { - if (($sxml = simplexml_load_string($xml))) // in fact XML IS always valid here... + if(($sxml = simplexml_load_string($xml))) // in fact XML IS always valid here... { ?> system == 'WINDOWS') + if($this->system == 'WINDOWS') $appname .= '.exe'; ?> system == 'WINDOWS') + if($this->system == 'WINDOWS') $appname .= '.exe'; ob_start(); ?> @@ -276,19 +279,19 @@ class task_period_cindexer extends task_abstract  :   / 
-  :  +  : 
 : 
-  :  +  : 
-  :  +  : 
-  :  +  : 

-  :  +  : 

@@ -297,21 +300,21 @@ class task_period_cindexer extends task_abstract
-  :  +  : 

 
-  :  +  : 



-  :
+  :
 
@@ -356,128 +359,281 @@ class task_period_cindexer extends task_abstract */ protected function run2() { - $cmd = $this->binpath . 'phraseanet_indexer'; - $nulfile = '/dev/null'; + $this->method = self::METHOD_PROC_OPEN; + $this->method = self::METHOD_FORK; + $this->method = self::METHOD_EXEC; - if ($this->system == 'WINDOWS') + $cmd = $this->binpath . 'phraseanet_indexer'; + $nullfile = '/dev/null'; + + if($this->system == 'WINDOWS') { $cmd .= '.exe'; - $nulfile = 'nul'; + $nullfile = 'NULL'; } - if (!file_exists($cmd) || !is_executable($cmd)) + if(!file_exists($cmd) || !is_executable($cmd)) { $this->log(sprintf(_('task::cindexer:file \'%s\' does not exists'), $cmd)); return; } - $cmd .= $this->host ? " -h=" . $this->host : ''; - $cmd .= $this->port ? " -P=" . $this->port : ''; - $cmd .= $this->base ? " -b=" . $this->base : ''; - $cmd .= $this->user ? " -u=" . $this->user : ''; - $cmd .= $this->password ? " -p=" . $this->password : ''; - $cmd .= $this->socket ? " --socket=" . $this->socket : ''; - $cmd .= $this->use_sbas ? " -o" : ''; - $cmd .= $this->charset ? " --default-character-set=" . $this->charset : ''; - $cmd .= $this->nolog ? " -n" : ''; - $cmd .= $this->winsvc_run ? " --run" : ''; +// $cmd .= $this->host ? " -h=" . $this->host : ''; +// $cmd .= $this->port ? " -P=" . $this->port : ''; +// $cmd .= $this->base ? " -b=" . $this->base : ''; +// $cmd .= $this->user ? " -u=" . $this->user : ''; +// $cmd .= $this->password ? " -p=" . $this->password : ''; +// $cmd .= $this->socket ? " --socket=" . $this->socket : ''; +// $cmd .= $this->use_sbas ? " -o" : ''; +// $cmd .= $this->charset ? " --default-character-set=" . $this->charset : ''; +// $cmd .= $this->nolog ? " -n" : ''; +// $cmd .= $this->winsvc_run ? " --run" : ''; + + $args = array(); + if($this->host) + $args[] = '-h=' . $this->host; + if($this->port) + ; + $args[] = '-P=' . $this->port; + if($this->base) + $args[] = '-b=' . $this->base; + if($this->user) + $args[] = '-u=' . $this->user; + if($this->password) + $args[] = '-p=' . $this->password; + if($this->socket) + $args[] = '--socket=' . $this->socket; + if($this->use_sbas) + $args[] = '-o'; + if($this->charset) + $args[] = '--default-character-set=' . $this->charset; + if($this->nolog) + $args[] = '-n'; + if($this->winsvc_run) + $args[] = '--run'; $registry = registry::get_instance(); $logdir = p4string::addEndSlash($registry->get('GV_RootPath') . 'logs'); - $descriptors = array(); - $descriptors[1] = array("file", $logdir . "/phraseanet_indexer_" . $this->get_task_id() . ".log", "a+"); - $descriptors[2] = array("file", $logdir . "/phraseanet_indexer_" . $this->get_task_id() . ".error.log", "a+"); - - $pipes = array(); - - $this->log(sprintf('cmd=\'%s\'', $cmd)); - $process = proc_open($cmd, $descriptors, $pipes, $this->binpath, null, array('bypass_shell' => true)); - - $pid = NULL; - if (is_resource($process)) + $this->return_value = self::RETURNSTATUS_STOPPED; // will be normal ending + + if($this->method == self::METHOD_PROC_OPEN) { - $proc_status = proc_get_status($process); - if ($proc_status['running']) - $pid = $proc_status['pid']; - } + $descriptors = array(); +// $descriptors[1] = array("file", $logdir . "/phraseanet_indexer_" . $this->get_task_id() . ".log", "a+"); +// $descriptors[2] = array("file", $logdir . "/phraseanet_indexer_" . $this->get_task_id() . ".error.log", "a+"); + $descriptors[1] = array("file", $nullfile, "a+"); + $descriptors[2] = array("file", $nullfile, "a+"); - $qsent = ''; - $timetokill = NULL; - $sock = NULL; + $pipes = array(); - $this->running = true; + $this->log(sprintf('cmd=\'%s %s\'', $cmd, implode(' ', $args))); + $process = proc_open($cmd . ' ' . implode(' ', $args), $descriptors, $pipes, $this->binpath, null, array('bypass_shell' => true)); - while ($this->running) - { - $this->check_task_status(); - - if ($this->task_status == self::STATUS_TOSTOP && $this->socket > 0) + $pid = NULL; + if(is_resource($process)) { - // must quit task, so send 'Q' to port 127.0.0.1:XXXX to cindexer - if (!$qsent && (($sock = socket_create(AF_INET, SOCK_STREAM, 0)) !== false)) + $proc_status = proc_get_status($process); + if($proc_status['running']) + $pid = $proc_status['pid']; + } + + $qsent = ''; + $timetokill = NULL; + $sock = NULL; + + $this->running = true; + + while($this->running) + { + $this->check_task_status(); + + if($this->task_status == self::STATUS_TOSTOP && $this->socket > 0) { - if (socket_connect($sock, '127.0.0.1', $this->socket) === true) + // must quit task, so send 'Q' to port 127.0.0.1:XXXX to cindexer + if(!$qsent && (($sock = socket_create(AF_INET, SOCK_STREAM, 0)) !== false)) { - socket_write($sock, 'Q', 1); - socket_write($sock, "\r\n", strlen("\r\n")); - sleep(5); - $qsent = 'Q'; - $timetokill = time() + 10; + if(socket_connect($sock, '127.0.0.1', $this->socket) === true) + { + socket_write($sock, 'Q', 1); + socket_write($sock, "\r\n", strlen("\r\n")); + sleep(5); + $qsent = 'Q'; + $timetokill = time() + 10; + } + else + { + socket_close($sock); + $sock = NULL; + } + } + } + + $proc_status = proc_get_status($process); + if(!$proc_status['running']) + { + // the cindexer died + if($qsent == 'Q') + { + $this->log(_('task::cindexer:the cindexer clean-quit')); + } + elseif($qsent == 'K') + { + $this->log(_('task::cindexer:the cindexer has been killed')); } else { - socket_close($sock); - $sock = NULL; + $this->log(_('task::cindexer:the cindexer crashed')); + $this->return_value = NULL; // NOT normal ending will enforce restart from scheduler + } + $this->running = false; + } + else + { + if($qsent == 'Q') + { + if(time() > $timetokill) + { + // must kill cindexer + $this->log(_('task::cindexer:killing the cindexer')); + $qsent = 'K'; + proc_terminate($process); // sigint + } } } + sleep(5); } - $proc_status = proc_get_status($process); - if (!$proc_status['running']) + if($sock) { - // the cindexer died - if ($qsent == 'Q') - $this->log(_('task::cindexer:the cindexer clean-quit')); - elseif ($qsent == 'K') - $this->log(_('task::cindexer:the cindexer has been killed')); - else - $this->log(_('task::cindexer:the cindexer crashed')); - $this->running = false; + socket_close($sock); + $sock = NULL; + } + + foreach(array_keys($pipes) as $offset) + { + if(is_resource($pipes[$offset])) + fclose($pipes[$offset]); + } + + proc_terminate($process); // sigint + proc_close($process); + } + elseif($this->method == self::METHOD_FORK) + { + $pid = pcntl_fork(); + if($pid == -1) + { + die("failed to fork"); + } + elseif($pid == 0) + { + // child + umask(0); + // openlog('MyLog', LOG_PID | LOG_PERROR, LOG_LOCAL0); + if(posix_setsid() < 0) + die("Forked process could not detach from terminal\n"); + //chdir(dirname(__FILE__)); + fclose(STDIN); + fclose(STDOUT); + fclose(STDERR); + $fdIN = fopen($nullfile, 'r'); +// $fdOUT = fopen($nullfile, 'a+'); +// $fdERR = fopen($nullfile, 'a+'); + $fdOUT = fopen($logdir . "/task_o_" . $this->get_task_id() . ".log", "a+"); + $fdERR = fopen($logdir . "/task_e_" . $this->get_task_id() . ".log", "a+"); + + pcntl_exec($cmd, $args); + + sleep(2); } else { - if ($qsent == 'Q') + // parent + $this->running = true; + + $sigsent = NULL; + while($this->running) { - if (time() > $timetokill) + // is the cindexer alive ? + if(!posix_kill($pid, 0)) { - // must kill cindexer - $this->log(_('task::cindexer:killing the cindexer')); - $qsent = 'K'; - proc_terminate($process); // sigint +printf("%d \n", __LINE__); + // dead... + if($sigsent === NULL) + { +printf("%d \n", __LINE__); + // but it's not my fault + $this->log(_('task::cindexer:the cindexer crashed')); + $this->running = false; + // return self::RETURNSTATUS_STOPPED; + break; + } } - } + +printf("%d \n", __LINE__); + $this->check_task_status(); + + if($this->task_status == self::STATUS_TOSTOP) + { +printf("%d \n", __LINE__); + posix_kill($pid, ($sigsent=SIGINT)); + sleep(2); + } + + $status = NULL; + if(pcntl_wait($status, WNOHANG) == $pid) + { +printf("%d \n", __LINE__); + // child (indexer) has exited + if($sigsent == SIGINT) + { + $this->log(_('task::cindexer:the cindexer clean-quit')); + } + elseif($sigsent == SIGKILL) + { + $this->log(_('task::cindexer:the cindexer has been killed')); + } + else + { + $this->log(_('task::cindexer:the cindexer crashed')); + $this->return_value = NULL; // NOT normal ending will enforce restart from scheduler + } + $this->running = false; + } + else + { +printf("%d \n", __LINE__); + if($sigsent == SIGINT && time() > $timetokill) + { +printf("%d \n", __LINE__); + // must kill cindexer + $this->log(_('task::cindexer:killing the cindexer')); + $qsent = 'K'; + posix_kill($pid, ($sigsent=SIGKILL)); + } + sleep(2); + } + } // while running (method fork) } - sleep(5); } - - if ($sock) + elseif($this->method == self::METHOD_EXEC) { - socket_close($sock); - $sock = NULL; + umask(0); + fclose(STDIN); + fclose(STDOUT); + fclose(STDERR); + $fdIN = fopen($nullfile, 'r'); + $fdOUT = fopen($logdir . "/task_o_" . $this->get_task_id() . ".log", "a+"); + $fdERR = fopen($logdir . "/task_e_" . $this->get_task_id() . ".log", "a+"); + + pcntl_exec($cmd, $args); + + sleep(2); } - - foreach (array_keys($pipes) as $offset) - { - if (is_resource($pipes[$offset])) - fclose($pipes[$offset]); - } - - proc_terminate($process); // sigint - proc_close($process); - - return self::RETURNSTATUS_STOPPED; + + return($this->return_value); } } diff --git a/lib/classes/task/period/outofdate.class.php b/lib/classes/task/period/outofdate.class.php index 58eaef71f0..ece2a5ab21 100644 --- a/lib/classes/task/period/outofdate.class.php +++ b/lib/classes/task/period/outofdate.class.php @@ -551,7 +551,8 @@ class task_period_outofdate extends task_abstract if(!$conn->ping()) { $this->log(("Warning : abox connection lost, restarting in 10 min.")); - sleep(60 * 10); + for($i=0; $i<60 * 10; $i++) + sleep(1); $this->running = false; return(self::RETURNSTATUS_TORESTART); @@ -566,13 +567,13 @@ class task_period_outofdate extends task_abstract catch(Exception $e) { $this->log(("dbox connection lost, restarting in 10 min.")); - sleep(60 * 10); + for($i=0; $i<60 * 10; $i++) + sleep(1); $this->running = false; return(self::RETURNSTATUS_TORESTART); } - $this->set_last_exec_time(); $databox = databox::get_instance($this->sbas_id); @@ -671,242 +672,33 @@ class task_period_outofdate extends task_abstract $nchanged = 0; foreach($tsql as $xsql) { - $stmt = $this->connbas->prepare($xsql['sql']); - $stmt->execute($xsql['params']); - $n = $stmt->rowCount(); - $stmt->closeCursor(); + try + { + $stmt = $this->connbas->prepare($xsql['sql']); + if($stmt->execute($xsql['params'])) + { + $n = $stmt->rowCount(); + $stmt->closeCursor(); - $nchanged += $n; - if($n > 0) - $this->log(sprintf(("SQL=%s\n - %s changes"), $xsql['sql'], $n)); + $nchanged += $n; + if($n > 0) + $this->log(sprintf("SQL='%s' ; parms=%s - %s changes", $xsql['sql'], var_export($xsql['params']), $n)); + } + else + { + $this->log(sprintf("ERROR SQL='%s' ; parms=%s", $xsql['sql'], var_export($xsql['params'], true))); + } + } + catch (ErrorException $e) + { + $this->log(sprintf("ERROR SQL='%s' ; parms=%s", $xsql['sql'], var_export($xsql['params'], true))); + } } $ret = ($nchanged > 0 ? $nchanged : 'NORECSTODO'); return($ret); } - - - - /* - function doRecords() - { - $ndone = 0; - $ret = 'NORECSTODO'; - - $date1 = $date2 = NULL; - $field1 = $field2 = ''; - - // test : DATE 1 - if(($field1 = trim($this->sxTaskSettings->field1)) != '') - { - $date1 = time(); - if(($delta = (int) ($this->sxTaskSettings->fieldDv1)) > 0) - { - if($this->sxTaskSettings->fieldDs1 == '-') - $date1 += 86400 * $delta; - else - $date1 -= 86400 * $delta; - } - $date1 = date("YmdHis", $date1); - } - // test : DATE 2 - if(($field2 = trim($this->sxTaskSettings->field2)) != '') - { - $date2 = time(); - if(($delta = (int) ($this->sxTaskSettings->fieldDv2)) > 0) - { - if($this->sxTaskSettings->fieldDs2 == '-') - $date2 += 86400 * $delta; - else - $date2 -= 86400 * $delta; - } - $date2 = date("YmdHis", $date2); - } - - - $sqlset = $params = $tmp_params = array(); - for($i = 0; $i <= 2; $i++) - { - $sqlwhere[$i] = ''; - $sqlset[$i] = ''; - $x = 'status' . $i; - @list($tostat, $statval) = explode('_', (string) ($this->sxTaskSettings->{$x})); - if($tostat >= 4 && $tostat <= 63) - { - if($statval == '0') - { - $sqlset[$i] = 'status=status & ~(1<<' . $tostat . ')'; - $sqlwhere[$i] .= '(status & (1<<' . $tostat . ') = 0)'; - } - elseif($statval == '1') - { - $sqlset[$i] = 'status=status|(1<<' . $tostat . ')'; - $sqlwhere[$i] .= '(status & (1<<' . $tostat . ') != 0)'; - } - } - $x = 'coll' . $i; - if(($tocoll = (string) ($this->sxTaskSettings->{$x})) != '') - { - $sqlset[$i] .= ( $sqlset[$i] ? ', ' : '') . ('coll_id = :coll_id_set' . $i); - $sqlwhere[$i] .= ( $sqlwhere[$i] ? ' AND ' : '') . '(coll_id = :coll_id_where' . $i . ')'; - $tmp_params[':coll_id_set' . $i] = $tocoll; - $tmp_params[':coll_id_where' . $i] = $tocoll; - } - } - for($i = 0; $i <= 2; $i++) - { - // if(!$sqlwhere[$i]) - // $sqlwhere[$i] = '1'; - } - - $nchanged = 0; - // $sqlupd = 'UPDATE record INNER JOIN prop ON prop.record_id=record.record_id'; - - if($date1) - { - $params = array(); - $params[':name1'] = $field1; - $params[':date1'] = $date1; - $params[':coll_id_set0'] = $tmp_params[':coll_id_set0']; - - $w = 'p1.name = :name1 AND :date1 <= p1.value'; - if($sqlwhere[1] && $sqlwhere[2]) - { - $w .= ' AND ((' . $sqlwhere[1] . ') OR (' . $sqlwhere[2] . '))'; - $params[':coll_id_where1'] = $tmp_params[':coll_id_where1']; - $params[':coll_id_where2'] = $tmp_params[':coll_id_where2']; - } - else - { - if($sqlwhere[1]) - { - $w .= ' AND ' . $sqlwhere[1]; - $params[':coll_id_where1'] = $tmp_params[':coll_id_where1']; - } - elseif($sqlwhere[2]) - { - $w .= ' AND ' . $sqlwhere[2]; - $params[':coll_id_where2'] = $tmp_params[':coll_id_where2']; - } - } - - $sql = "UPDATE prop AS p1 INNER JOIN record USING(record_id) - SET " . $sqlset[0] . - " WHERE " . $w; - printf("%d : %s \n%s", __LINE__, $sql, var_export($params, true)); - - $stmt = $this->connbas->prepare($sql); - $stmt->execute($params); - $n = $stmt->rowCount(); - $stmt->closeCursor(); - - $nchanged += $n; - if($n > 0) - $this->log(sprintf(("SQL=%s\n - %s changes"), $sql, $n)); - } - - - - - - if($date2 && $date1) - { - $params = array(); - $params[':name1'] = $field1; - $params[':name2'] = $field2; - $params[':date1'] = $date1; - $params[':date2'] = $date2; - $params[':coll_id_set1'] = $tmp_params[':coll_id_set1']; - - $w = 'p1.name = :name1 AND p2.name = :name2 AND :date1 > p1.value AND :date2 <= p2.value'; - if($sqlwhere[0] && $sqlwhere[2]) - { - $w .= ' AND ((' . $sqlwhere[0] . ') OR (' . $sqlwhere[2] . '))'; - $params[':coll_id_where0'] = $tmp_params[':coll_id_where0']; - $params[':coll_id_where2'] = $tmp_params[':coll_id_where2']; - } - else - { - if($sqlwhere[0]) - { - $w .= ' AND ' . $sqlwhere[0]; - $params[':coll_id_where0'] = $tmp_params[':coll_id_where0']; - } - elseif($sqlwhere[2]) - { - $w .= ' AND ' . $sqlwhere[2]; - $params[':coll_id_where2'] = $tmp_params[':coll_id_where2']; - } - } - - $sql = "UPDATE (prop AS p1 INNER JOIN prop AS p2 USING(record_id)) - INNER JOIN record USING(record_id) - SET " . $sqlset[1] . - " WHERE " . $w; - printf("%d : %s \n%s", __LINE__, $sql, var_export($params, true)); - - $stmt = $this->connbas->prepare($sql); - $stmt->execute($params); - $n = $stmt->rowCount(); - $stmt->closeCursor(); - - $nchanged += $n; - if($n > 0) - $this->log(sprintf(("SQL=%s\n - %s changes"), $sql, $n)); - } - - - - if($date2) - { - $params = array(); - $params[':name2'] = $field2; - $params[':date2'] = $date2; - $params[':coll_id_set2'] = $tmp_params[':coll_id_set2']; - - $w = 'p2.name = :name2 AND :date2 > p2.value'; - if($sqlwhere[0] && $sqlwhere[1]) - { - $w .= ' AND ((' . $sqlwhere[0] . ') OR (' . $sqlwhere[2] . '))'; - $params[':coll_id_where0'] = $tmp_params[':coll_id_where0']; - $params[':coll_id_where1'] = $tmp_params[':coll_id_where1']; - } - else - { - if($sqlwhere[0]) - { - $w .= ' AND ' . $sqlwhere[0]; - $params[':coll_id_where0'] = $tmp_params[':coll_id_where0']; - } - elseif($sqlwhere[1]) - { - $w .= ' AND ' . $sqlwhere[1]; - $params[':coll_id_where1'] = $tmp_params[':coll_id_where1']; - } - } - - $sql = "UPDATE prop AS p2 INNER JOIN record USING(record_id) - SET " . $sqlset[2] . - " WHERE " . $w; - - printf("%d : %s \n%s", __LINE__, $sql, var_export($params, true)); - - $stmt = $this->connbas->prepare($sql); - $stmt->execute($params); - $n = $stmt->rowCount(); - $stmt->closeCursor(); - - $nchanged += $n; - if($n > 0) - $this->log(sprintf(("SQL=%s\n - %s changes"), $sql, $n)); - } - - $ret = ($nchanged > 0 ? $nchanged : 'NORECSTODO'); - - return($ret); - } - */ private function calcSQL($sxTaskSettings) { @@ -1006,24 +798,11 @@ class task_period_outofdate extends task_abstract $sql = "UPDATE prop AS p1 INNER JOIN record USING(record_id) SET " . $sqlset[0] . " WHERE " . $w; -// printf("%d : %s \n%s", __LINE__, $sql, var_export($params, true)); $ret[] = array('sql'=>$sql, 'params'=>$params); - -// $stmt = $this->connbas->prepare($sql); -// $stmt->execute($params); -// $n = $stmt->rowCount(); -// $stmt->closeCursor(); -// -// $nchanged += $n; -// if($n > 0) -// $this->log(sprintf(("SQL=%s\n - %s changes"), $sql, $n)); } - - - if($date1 && $date2) { $params = array(); @@ -1058,22 +837,11 @@ class task_period_outofdate extends task_abstract INNER JOIN record USING(record_id) SET " . $sqlset[1] . " WHERE " . $w; -// printf("%d : %s \n%s", __LINE__, $sql, var_export($params, true)); $ret[] = array('sql'=>$sql, 'params'=>$params); - -// $stmt = $this->connbas->prepare($sql); -// $stmt->execute($params); -// $n = $stmt->rowCount(); -// $stmt->closeCursor(); -// -// $nchanged += $n; -// if($n > 0) -// $this->log(sprintf(("SQL=%s\n - %s changes"), $sql, $n)); } - if($date2 && $sqlset[2]) { $params = array(); @@ -1084,7 +852,7 @@ class task_period_outofdate extends task_abstract $w = 'p2.name = :name2 AND :date2 > p2.value'; if($sqlwhere[0] && $sqlwhere[1]) { - $w .= ' AND ((' . $sqlwhere[0] . ') OR (' . $sqlwhere[2] . '))'; + $w .= ' AND ((' . $sqlwhere[0] . ') OR (' . $sqlwhere[1] . '))'; $params[':coll_id_where0'] = $tmp_params[':coll_id_where0']; $params[':coll_id_where1'] = $tmp_params[':coll_id_where1']; } @@ -1106,122 +874,14 @@ class task_period_outofdate extends task_abstract SET " . $sqlset[2] . " WHERE " . $w; -// printf("%d : %s \n%s", __LINE__, $sql, var_export($params, true)); - $ret[] = array('sql'=>$sql, 'params'=>$params); - -// $stmt = $this->connbas->prepare($sql); -// $stmt->execute($params); -// $n = $stmt->rowCount(); -// $stmt->closeCursor(); -// -// $nchanged += $n; -// if($n > 0) -// $this->log(sprintf(("SQL=%s\n - %s changes"), $sql, $n)); } return($ret); } - private function no_calcSQL($sxTaskSettings) - { - $ret = array(); - - $date1 = $date2 = time(); - $field1 = $field2 = ''; - - // test : DATE 1 - if(($field1 = trim($sxTaskSettings->field1)) != '') - { - if(($delta = (int) ($sxTaskSettings->fieldDv1)) > 0) - { - if($sxTaskSettings->fieldDs1 == '-') - $date1 += 86400 * $delta; - else - $date1 -= 86400 * $delta; - } - } - // test : DATE 2 - if(($field2 = trim($sxTaskSettings->field2)) != '') - { - if(($delta = (int) ($sxTaskSettings->fieldDv2)) > 0) - { - if($sxTaskSettings->fieldDs2 == '-') - $date2 += 86400 * $delta; - else - $date2 -= 86400 * $delta; - } - } - - $date1 = date("YmdHis", $date1); - $date2 = date("YmdHis", $date2); - - $sqlset = array(); - for($i = 0; $i <= 2; $i++) - { - $sqlset[$i] = ''; - $x = 'status' . $i; - @list($tostat, $statval) = explode('_', (string) ($sxTaskSettings->{$x})); - if($tostat >= 4 && $tostat <= 63) - { - if($statval == '0') - $sqlset[$i] = 'status=status&~(1<<' . $tostat . ')'; - elseif($statval == '1') - $sqlset[$i] = 'status=status|(1<<' . $tostat . ')'; - } - $x = 'coll' . $i; - if(($tocoll = (string) ($sxTaskSettings->{$x})) != '') - $sqlset[$i] .= ($sqlset[$i] ? ', ' : '') . ('coll_id=\'' . $tocoll . '\''); - } - - // $sqlupd = 'UPDATE record INNER JOIN prop ON prop.record_id=record.record_id'; - - if($sqlset[0] && $field1) - { - $sql = 'UPDATE prop AS p1 INNER JOIN record USING(record_id)' . - ' SET ' . $sqlset[0] . - ' WHERE p1.name=\'' . $field1 . '\' AND \'' . $date1 . '\'<=p1.value'; - $ret[] = $sql; - } - - if($sqlset[1]) - { - if($field1 && $field2) - { - $sql = 'UPDATE (prop AS p1 INNER JOIN prop AS p2 USING(record_id))' . - ' INNER JOIN record USING(record_id)' . - ' SET ' . $sqlset[1] . - ' WHERE (p1.name=\'' . $field1 . '\' AND \'' . $date1 . '\'>p1.value)' . - ' AND (p2.name=\'' . $field2 . '\' AND \'' . $date2 . '\'<=p2.value)'; - $ret[] = $sql; - } - elseif($field1) - { - $sql = 'UPDATE prop AS p1 INNER JOIN record USING(record_id)' . - ' SET ' . $sqlset[1] . - ' WHERE p1.name=\'' . $field1 . '\' AND \'' . $date1 . '\'>p1.value'; - $ret[] = $sql; - } - elseif($field2) - { - $sql = 'UPDATE prop AS p2 INNER JOIN record USING(record_id)' . - ' SET ' . $sqlset[1] . - ' WHERE p2.name=\'' . $field2 . '\' AND \'' . $date2 . '\'<=p2.value'; - $ret[] = $sql; - } - } - - if($sqlset[2] && $field2) - { - $sql = 'UPDATE prop AS p2 INNER JOIN record USING(record_id)' . - ' SET ' . $sqlset[2] . - ' WHERE p2.name=\'' . $field2 . '\' AND \'' . $date2 . '\'>p2.value'; - $ret[] = $sql; - } - - return($ret); - } + public function facility() { $ret = NULL; @@ -1232,9 +892,6 @@ class task_period_outofdate extends task_abstract ); phrasea::headers(200, true, 'application/json', 'UTF-8', false); -// return("hello4"); -//var_dump($parm2); -//return; $ret = NULL; switch($parm2['ACT']) { @@ -1281,6 +938,6 @@ class task_period_outofdate extends task_abstract } print(json_encode($ret)); } - } + ?> diff --git a/www/admin/adminFeedback.php b/www/admin/adminFeedback.php index 179e6caac9..244ced2902 100644 --- a/www/admin/adminFeedback.php +++ b/www/admin/adminFeedback.php @@ -107,21 +107,26 @@ switch ($parm['action']) break; case 'SETTASKSTATUS': - $parm = $request->get_parms("task_id", "status"); + $parm = $request->get_parms('task_id', 'status', 'signal'); try { $task_manager = new task_manager($appbox); $task = $task_manager->get_task($parm['task_id']); + $pid = (int)($task->get_pid()); $task->set_status($parm["status"]); + $signal = (int)($parm['signal']); + if( $signal > 0 && $pid ) + posix_kill($pid, $signal); } catch (Exception $e) { } + $output = json_encode($pid); break; case 'SETSCHEDSTATUS': - $parm = $request->get_parms('status'); + $parm = $request->get_parms('status', 'signal'); try { $task_manager = new task_manager($appbox); @@ -132,13 +137,6 @@ switch ($parm['action']) { } - $ret = new DOMDocument("1.0", "UTF-8"); - $ret->standalone = true; - $ret->preserveWhiteSpace = false; - $root = $ret->appendChild($ret->createElement("result")); - $root->appendChild($ret->createCDATASection(var_export($parm, true))); - - $output = $ret->saveXML(); break; case 'RESETTASKCRASHCOUNTER': @@ -267,7 +265,6 @@ switch ($parm['action']) $ret['tasks'] = array(); foreach ($task_manager->get_tasks(true) as $task) { - // var_dump($task); $_t = array( 'id'=>$task->get_task_id() , 'pid' =>$task->get_pid() @@ -277,9 +274,23 @@ switch ($parm['action']) ); $ret['tasks'][$_t['id']] = $_t; } + + if(1) + { + $sql = 'SHOW PROCESSLIST'; + $stmt = $appbox->get_connection()->prepare($sql); + $stmt->execute(); + $rows = $stmt->fetchALL(PDO::FETCH_ASSOC); + $stmt->closeCursor(); + $ret['db_processlist'] = array(); + foreach($rows as $row) + { + if($row['Info'] != $sql) + $ret['db_processlist'][] = $row; + } + } $output = json_encode($ret); - break; case 'UNMOUNTBASE': diff --git a/www/admin/runscheduler.php b/www/admin/runscheduler.php index 2b0c9e83bc..830c3ca48d 100644 --- a/www/admin/runscheduler.php +++ b/www/admin/runscheduler.php @@ -15,6 +15,7 @@ * @license http://opensource.org/licenses/gpl-3.0 GPLv3 * @link www.phraseanet.com */ + require_once dirname(__FILE__) . "/../../lib/bootstrap.php"; $appbox = appbox::get_instance(); @@ -52,31 +53,35 @@ $logdir = p4string::addEndSlash($registry->get('GV_RootPath') . 'logs'); $phpcli = $registry->get('GV_cli'); +$nullfile = ''; switch ($system) { case "DARWIN": $cmd = $phpcli . ' -f ' . $registry->get('GV_RootPath') . "bin/console scheduler:start"; + $nullfile = '/dev/null'; break; case "LINUX": $cmd = $phpcli . ' -f ' . $registry->get('GV_RootPath') . "bin/console scheduler:start"; + $nullfile = '/dev/null'; break; case "WINDOWS": case "WINDOWS NT": $cmd = $phpcli . ' -f ' . $registry->get('GV_RootPath') . "bin/console scheduler:start"; + $nullfile = 'NUL'; break; } -if ($logdir) -{ - $descriptors[1] = array("file", $logdir . "scheduler.log", "a+"); - $descriptors[2] = array("file", $logdir . "scheduler.error.log", "a+"); -} -else -{ - $descriptors[1] = array("file", "NUL", "a+"); - $descriptors[2] = array("file", "NUL", "a+"); -} +//if ($logdir) +//{ +// $descriptors[1] = array("file", $logdir . "scheduler.log", "a+"); +// $descriptors[2] = array("file", $logdir . "scheduler.error.log", "a+"); +//} +//else +//{ + $descriptors[1] = array("file", $nullfile, "a+"); + $descriptors[2] = array("file", $nullfile, "a+"); +//} $pipes = null; $cwd = $registry->get('GV_RootPath') . "bin/"; diff --git a/www/admin/showlogtask.php b/www/admin/showlogtask.php index d9d59e73a2..9d9ef713fa 100644 --- a/www/admin/showlogtask.php +++ b/www/admin/showlogtask.php @@ -1,5 +1,4 @@ get_session(); $request = http_request::getInstance(); -$parm = $request->get_parms('fil', 'act'); - -$registry = $appbox->get_registry(); -$logdir = p4string::addEndSlash($registry->get('GV_RootPath') . 'logs'); -$logfile = $logdir . $parm['fil']; - -if (file_exists($logfile)) +$parm = $request->get_parms('fil', 'log', 'id', 'act'); +?> + + + + + +

+ logfile : + 'log', 'o' => 'stdout', 'e' => 'stderr') as $k => $v) { - if ($parm['act'] == 'CLR') - { - file_put_contents($logfile, ''); - - return phrasea::redirect("/admin/showlogtask.php?fil=" . urlencode($parm['fil'])); - } - else - { - printf("get_I18n() . "\">

%s  effacer

\n", $logfile, urlencode($parm['fil'])); - print("
\n");
-    print(htmlentities(file_get_contents($logfile)));
-    print("
\n"); - } -} -else -{ - printf("file %s does not exists\n", $logfile); + $cls = ''; + if($k == $parm['log']) + $cls = 'current'; + printf("(%s)\n" + , $cls + , urlencode($parm['fil']) + , urlencode($k) + , urlencode($parm['id']) + , $v); } +?> + + get_registry(); + $logdir = p4string::addEndSlash($registry->get('GV_RootPath') . 'logs'); + $logfile = $logdir . $parm['fil']; + if($parm['log']) + $logfile .= '_' . $parm['log']; + if($parm['id']) + $logfile .= '_' . $parm['id']; + $logfile .= '.log'; + if(file_exists($logfile)) + { + if($parm['act'] == 'CLR') + { + file_put_contents($logfile, ''); + return phrasea::redirect(sprintf("/admin/showlogtask.php?fil=%s&log=%s&id=%s" + , urlencode($parm['fil']) + , urlencode($parm['log']) + , urlencode($parm['id'])) + ); + } + else + { + printf("

%s\n", $logfile); + printf(" effacer\n" + , urlencode($parm['fil']) + , urlencode($parm['log']) + , urlencode($parm['id'])); + print("

\n
\n");
+          print(htmlentities(file_get_contents($logfile)));
+          print("
\n"); + } + } + else + { + printf("

file %s does not exists

\n", $logfile); + } + ?> + + diff --git a/www/admin/taskmanager.php b/www/admin/taskmanager.php index a196b7d492..3603a60d36 100644 --- a/www/admin/taskmanager.php +++ b/www/admin/taskmanager.php @@ -30,12 +30,32 @@ if(!$user->ACL()->has_right('taskmanager')) phrasea::headers(); $registry = $appbox->get_registry(); + $task_manager = new task_manager($appbox); + +$refresh_tasklist = false; +if($parm["act"] == "DELETETASK") +{ + try + { + $task = $task_manager->get_task($parm['tid']); + $task->delete(); + $refresh_tasklist = true; + } + catch(Exception $e) + { + + } +} + + + ?> + - + + + + +