From bf196910b0247317fce5f9393d6508dadbb03e58 Mon Sep 17 00:00:00 2001 From: epriestley Date: Mon, 14 Mar 2011 15:43:56 -0700 Subject: [PATCH] More phd stuff. --- .../daemon/phabricator_daemon_launcher.php | 97 +++------ src/__phutil_library_map__.php | 2 + .../control/PhabricatorDaemonControl.php | 192 ++++++++++++++++++ .../daemon/control/__init__.php | 18 ++ .../reference/PhabricatorDaemonReference.php | 76 +++++++ .../daemon/control/reference/__init__.php | 12 ++ 6 files changed, 328 insertions(+), 69 deletions(-) create mode 100644 src/infrastructure/daemon/control/PhabricatorDaemonControl.php create mode 100644 src/infrastructure/daemon/control/__init__.php create mode 100644 src/infrastructure/daemon/control/reference/PhabricatorDaemonReference.php create mode 100644 src/infrastructure/daemon/control/reference/__init__.php diff --git a/scripts/daemon/phabricator_daemon_launcher.php b/scripts/daemon/phabricator_daemon_launcher.php index 6b9a11e776..fbd36ab2bb 100755 --- a/scripts/daemon/phabricator_daemon_launcher.php +++ b/scripts/daemon/phabricator_daemon_launcher.php @@ -21,58 +21,24 @@ $root = dirname(dirname(dirname(__FILE__))); require_once $root.'/scripts/__init_script__.php'; require_once $root.'/scripts/__init_env__.php'; +phutil_require_module('phabricator', 'infrastructure/daemon/control'); +$control = new PhabricatorDaemonControl(); + $phd_dir = PhabricatorEnv::getEnvConfig('phd.pid-directory'); $pid_dir = $phd_dir.'/pid'; switch (isset($argv[1]) ? $argv[1] : 'help') { case 'list': - phutil_require_module('phutil', 'console'); - - $loader = new PhutilSymbolLoader(); - $symbols = $loader - ->setAncestorClass('PhutilDaemon') - ->selectSymbolsWithoutLoading(); - - $symbols = igroup($symbols, 'library'); - foreach ($symbols as $library => $symbol_list) { - echo phutil_console_format("Daemons in library __%s__:\n", $library); - foreach ($symbol_list as $symbol) { - echo " ".$symbol['name']."\n"; - } - echo "\n"; - } - - break; + $err = $control->executeListCommand(); + exit($err); case 'status': - $pid_descs = Filesystem::listDirectory($pid_dir); - if (!$pid_descs) { - echo "There are no running Phabricator daemons.\n"; - } else { - printf( - "%-5s\t%-24s\t%s\n", - "PID", - "Started", - "Daemon"); - foreach ($pid_descs as $pid_file) { - $data = Filesystem::readFile($pid_dir.'/'.$pid_file); - $data = json_decode($data, true); + $err = $control->executeStatusCommand(); + exit($err); - $pid = idx($data, 'pid', '?'); - $name = idx($data, 'name', '?'); - $since = idx($data, 'start') - ? date('M j Y, g:i:s A', $data['start']) - : '?'; - - printf( - "%5s\t%-24s\t%s\n", - $pid, - $since, - $name); - } - } - - break; + case 'stop': + $err = $control->executeStopCommand(); + exit($err); case 'launch': phutil_require_module('phutil', 'moduleutils'); @@ -82,6 +48,8 @@ switch (isset($argv[1]) ? $argv[1] : 'help') { throw new Exception("Daemon name required!"); } + $pass = array_slice($argv, 3); + $n = 1; if (is_numeric($daemon)) { $n = $daemon; @@ -92,6 +60,7 @@ switch (isset($argv[1]) ? $argv[1] : 'help') { if (!$daemon) { throw new Exception("Daemon name required!"); } + $pass = array_slice($argv, 4); } $loader = new PhutilSymbolLoader(); @@ -131,12 +100,23 @@ switch (isset($argv[1]) ? $argv[1] : 'help') { Filesystem::assertIsDirectory($pid_dir); Filesystem::assertWritable($pid_dir); + foreach ($pass as $key => $arg) { + $pass[$key] = escapeshellarg($arg); + } + echo "Starting {$n} x {$daemon}"; + + chdir($launch_daemon); for ($ii = 0; $ii < $n; $ii++) { list($stdout, $stderr) = execx( - "(cd %s && ./launch_daemon.php %s --daemonize --phd=%s)", - $launch_daemon, + "./launch_daemon.php ". + "%s ". + "--load-phutil-library=%s ". + "--daemonize ". + "--phd=%s ". + implode(' ', $pass), $daemon, + phutil_get_library_root('phabricator'), $pid_dir); echo "."; } @@ -191,27 +171,6 @@ switch (isset($argv[1]) ? $argv[1] : 'help') { case '--help': case 'help': default: - echo << - Start a daemon. - -list - List available daemons. - -stop - Stop all daemons. - -status - List running daemons. - -stop - Stop all running daemons. - -parse-commit - Parse a single commit. - -EOHELP; - exit(1); + $err = $control->executeHelpCommand(); + exit($err); } diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index de7a69bca1..a6eff10bb5 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -205,7 +205,9 @@ phutil_register_library_map(array( 'PhabricatorController' => 'applications/base/controller/base', 'PhabricatorDaemon' => 'infrastructure/daemon/base', 'PhabricatorDaemonConsoleController' => 'applications/daemon/controller/console', + 'PhabricatorDaemonControl' => 'infrastructure/daemon/control', 'PhabricatorDaemonController' => 'applications/daemon/controller/base', + 'PhabricatorDaemonReference' => 'infrastructure/daemon/control/reference', 'PhabricatorDaemonTimelineConsoleController' => 'applications/daemon/controller/timeline', 'PhabricatorDaemonTimelineEventController' => 'applications/daemon/controller/timelineevent', 'PhabricatorDirectoryCategory' => 'applications/directory/storage/category', diff --git a/src/infrastructure/daemon/control/PhabricatorDaemonControl.php b/src/infrastructure/daemon/control/PhabricatorDaemonControl.php new file mode 100644 index 0000000000..f5812498d8 --- /dev/null +++ b/src/infrastructure/daemon/control/PhabricatorDaemonControl.php @@ -0,0 +1,192 @@ +loadAvailableDaemonClasses(); + + $symbols = igroup($symbols, 'library'); + + echo "\n"; + foreach ($symbols as $library => $symbol_list) { + echo phutil_console_format("Daemons in library __%s__:\n", $library); + foreach ($symbol_list as $symbol) { + echo " ".$symbol['name']."\n"; + } + echo "\n"; + } + + return 0; + } + + public function executeStatusCommand() { + $daemons = $this->loadRunningDaemons(); + + if (!$daemons) { + echo "There are no running Phabricator daemons.\n"; + return 0; + } + + printf( + "%-5s\t%-24s\t%s\n", + "PID", + "Started", + "Daemon"); + foreach ($daemons as $daemon) { + printf( + "%5s\t%-24s\t%s\n", + $daemon->getPID(), + $daemon->getEpochStarted() + ? date('M j Y, g:i:s A', $daemon->getEpochStarted()) + : null, + $daemon->getName()); + } + + return 0; + } + + public function executeStopCommand() { + $daemons = $this->loadRunningDaemons(); + if (!$daemons) { + echo "There are no running Phabricator daemons.\n"; + return 0; + } + + $running = $daemons; + + foreach ($running as $key => $daemon) { + $pid = $daemon->getPID(); + $name = $daemon->getName(); + + echo "Stopping daemon '{$name}' ({$pid})...\n"; + if (!$daemon->isRunning()) { + echo "Daemon is not running.\n"; + unset($running[$key]); + } else { + posix_kill($pid, SIGINT); + } + } + + $start = time(); + do { + foreach ($running as $key => $daemon) { + $pid = $daemon->getPID(); + if (!$daemon->isRunning()) { + echo "Daemon {$pid} exited normally.\n"; + unset($running[$key]); + } + } + if (empty($running)) { + break; + } + usleep(100000); + } while (time() < $start + 15); + + foreach ($running as $key => $daemon) { + $pid = $daemon->getPID(); + echo "KILLing daemon {$pid}.\n"; + posix_kill($pid, SIGKILL); + } + + foreach ($daemons as $daemon) { + if ($daemon->getPIDFile()) { + Filesystem::remove($daemon->getPIDFile()); + } + } + + } + + public function executeHelpCommand() { + echo phutil_console_format(<<setAncestorClass('PhutilDaemon') + ->selectSymbolsWithoutLoading(); + } + + protected function loadRunningDaemons() { + $results = array(); + + $pid_dir = $this->getControlDirectory('pid'); + $pid_files = Filesystem::listDirectory($pid_dir); + if (!$pid_files) { + return $results; + } + + foreach ($pid_files as $pid_file) { + $pid_data = Filesystem::readFile($pid_dir.'/'.$pid_file); + $dict = json_decode($pid_data, true); + if (!is_array($dict)) { + // Just return a hanging reference, since control code needs to be + // robust against unusual system states. + $dict = array(); + } + $ref = PhabricatorDaemonReference::newFromDictionary($dict); + $ref->setPIDFile($pid_dir.'/'.$pid_file); + $results[] = $ref; + } + + return $results; + } + + protected function killDaemon(PhabricatorDaemonReference $ref) { + } + + + +} diff --git a/src/infrastructure/daemon/control/__init__.php b/src/infrastructure/daemon/control/__init__.php new file mode 100644 index 0000000000..b1c5285ecd --- /dev/null +++ b/src/infrastructure/daemon/control/__init__.php @@ -0,0 +1,18 @@ +name = idx($dict, 'name', 'Unknown'); + $ref->pid = idx($dict, 'pid'); + $ref->start = idx($dict, 'start'); + + return $ref; + } + + public function getPID() { + return $this->pid; + } + + public function getName() { + return $this->name; + } + + public function getEpochStarted() { + return $this->start; + } + + public function setPIDFile($pid_file) { + $this->pidFile = $pid_file; + return $this; + } + + public function getPIDFile() { + return $this->pidFile; + } + + public function isRunning() { + $pid = $this->getPID(); + if (!$pid) { + return false; + } + return posix_kill($pid, 0); + } + + public function waitForExit($seconds) { + $start = time(); + while (time() < $start + $seconds) { + usleep(100000); + if (!$this->isRunning()) { + return true; + } + } + return !$this->isRunning(); + } + +} diff --git a/src/infrastructure/daemon/control/reference/__init__.php b/src/infrastructure/daemon/control/reference/__init__.php new file mode 100644 index 0000000000..66e65b55fe --- /dev/null +++ b/src/infrastructure/daemon/control/reference/__init__.php @@ -0,0 +1,12 @@ +