More phd stuff.
This commit is contained in:
		@@ -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 <<<EOHELP
 | 
			
		||||
phd - phabricator daemon launcher
 | 
			
		||||
 | 
			
		||||
launch <daemon>
 | 
			
		||||
  Start a daemon.
 | 
			
		||||
 | 
			
		||||
list
 | 
			
		||||
  List available daemons.
 | 
			
		||||
 | 
			
		||||
stop
 | 
			
		||||
  Stop all daemons.
 | 
			
		||||
 | 
			
		||||
status
 | 
			
		||||
  List running daemons.
 | 
			
		||||
 | 
			
		||||
stop
 | 
			
		||||
  Stop all running daemons.
 | 
			
		||||
 | 
			
		||||
parse-commit <rXnnnn>
 | 
			
		||||
  Parse a single commit.
 | 
			
		||||
 | 
			
		||||
EOHELP;
 | 
			
		||||
    exit(1);
 | 
			
		||||
    $err = $control->executeHelpCommand();
 | 
			
		||||
    exit($err);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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',
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										192
									
								
								src/infrastructure/daemon/control/PhabricatorDaemonControl.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										192
									
								
								src/infrastructure/daemon/control/PhabricatorDaemonControl.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,192 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright 2011 Facebook, Inc.
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *   http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
final class PhabricatorDaemonControl {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  public function executeListCommand() {
 | 
			
		||||
    $symbols = $this->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(<<<EOHELP
 | 
			
		||||
**NAME**
 | 
			
		||||
        **phd** - phabricator daemon launcher
 | 
			
		||||
 | 
			
		||||
**COMMAND REFERENCE**
 | 
			
		||||
 | 
			
		||||
        **launch** [__n__] __daemon__
 | 
			
		||||
            Start a daemon (or n copies of a daemon).
 | 
			
		||||
 | 
			
		||||
        **list**
 | 
			
		||||
            List available daemons.
 | 
			
		||||
 | 
			
		||||
        **stop**
 | 
			
		||||
            Stop all daemons.
 | 
			
		||||
 | 
			
		||||
        **status**
 | 
			
		||||
            List running daemons.
 | 
			
		||||
 | 
			
		||||
        **stop**
 | 
			
		||||
            Stop all running daemons.
 | 
			
		||||
 | 
			
		||||
        **help**
 | 
			
		||||
            Show this help.
 | 
			
		||||
 | 
			
		||||
        **parse-commit** __rXnnnn__
 | 
			
		||||
            Parse a single commit.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
EOHELP
 | 
			
		||||
    );
 | 
			
		||||
    return 1;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  protected function getControlDirectory($dir) {
 | 
			
		||||
    return PhabricatorEnv::getEnvConfig('phd.pid-directory').'/'.$dir;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  protected function loadAvailableDaemonClasses() {
 | 
			
		||||
    $loader = new PhutilSymbolLoader();
 | 
			
		||||
    return $loader
 | 
			
		||||
      ->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) {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										18
									
								
								src/infrastructure/daemon/control/__init__.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/infrastructure/daemon/control/__init__.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
<?php
 | 
			
		||||
/**
 | 
			
		||||
 * This file is automatically generated. Lint this module to rebuild it.
 | 
			
		||||
 * @generated
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
phutil_require_module('phabricator', 'infrastructure/daemon/control/reference');
 | 
			
		||||
phutil_require_module('phabricator', 'infrastructure/env');
 | 
			
		||||
 | 
			
		||||
phutil_require_module('phutil', 'console');
 | 
			
		||||
phutil_require_module('phutil', 'filesystem');
 | 
			
		||||
phutil_require_module('phutil', 'symbols');
 | 
			
		||||
phutil_require_module('phutil', 'utils');
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
phutil_require_source('PhabricatorDaemonControl.php');
 | 
			
		||||
@@ -0,0 +1,76 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright 2011 Facebook, Inc.
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *   http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
final class PhabricatorDaemonReference {
 | 
			
		||||
 | 
			
		||||
  private $name;
 | 
			
		||||
  private $pid;
 | 
			
		||||
  private $start;
 | 
			
		||||
  private $pidFile;
 | 
			
		||||
 | 
			
		||||
  public static function newFromDictionary(array $dict) {
 | 
			
		||||
    $ref = new PhabricatorDaemonReference();
 | 
			
		||||
 | 
			
		||||
    $ref->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();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										12
									
								
								src/infrastructure/daemon/control/reference/__init__.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/infrastructure/daemon/control/reference/__init__.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
<?php
 | 
			
		||||
/**
 | 
			
		||||
 * This file is automatically generated. Lint this module to rebuild it.
 | 
			
		||||
 * @generated
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
phutil_require_module('phutil', 'utils');
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
phutil_require_source('PhabricatorDaemonReference.php');
 | 
			
		||||
		Reference in New Issue
	
	Block a user