diff --git a/resources/sql/autopatches/20150223.daemon.1.id.sql b/resources/sql/autopatches/20150223.daemon.1.id.sql new file mode 100644 index 0000000000..cd757cb817 --- /dev/null +++ b/resources/sql/autopatches/20150223.daemon.1.id.sql @@ -0,0 +1,2 @@ +ALTER TABLE {$NAMESPACE}_daemon.daemon_log + ADD daemonID VARCHAR(64) NOT NULL COLLATE {$COLLATE_TEXT}; diff --git a/resources/sql/autopatches/20150223.daemon.2.idlegacy.sql b/resources/sql/autopatches/20150223.daemon.2.idlegacy.sql new file mode 100644 index 0000000000..34583ad96f --- /dev/null +++ b/resources/sql/autopatches/20150223.daemon.2.idlegacy.sql @@ -0,0 +1,2 @@ +UPDATE {$NAMESPACE}_daemon.daemon_log + SET daemonID = CONCAT('legacy-', id) WHERE daemonID = ''; diff --git a/resources/sql/autopatches/20150223.daemon.3.idkey.sql b/resources/sql/autopatches/20150223.daemon.3.idkey.sql new file mode 100644 index 0000000000..b9ad068291 --- /dev/null +++ b/resources/sql/autopatches/20150223.daemon.3.idkey.sql @@ -0,0 +1,2 @@ +ALTER TABLE {$NAMESPACE}_daemon.daemon_log + ADD UNIQUE KEY `key_daemonID` (daemonID); diff --git a/src/applications/daemon/event/PhabricatorDaemonEventListener.php b/src/applications/daemon/event/PhabricatorDaemonEventListener.php index ada6ce92d3..db6d9a2eff 100644 --- a/src/applications/daemon/event/PhabricatorDaemonEventListener.php +++ b/src/applications/daemon/event/PhabricatorDaemonEventListener.php @@ -37,6 +37,7 @@ final class PhabricatorDaemonEventListener extends PhabricatorEventListener { $current_user = posix_getpwuid(posix_geteuid()); $daemon = id(new PhabricatorDaemonLog()) + ->setDaemonID($id) ->setDaemon($event->getValue('daemonClass')) ->setHost(php_uname('n')) ->setPID(getmypid()) @@ -114,7 +115,7 @@ final class PhabricatorDaemonEventListener extends PhabricatorEventListener { if (isset($this->daemons[$id])) { return $this->daemons[$id]; } - throw new Exception("No such daemon '{$id}'!"); + throw new Exception(pht('No such daemon "%s"!', $id)); } } diff --git a/src/applications/daemon/management/PhabricatorDaemonManagementStatusWorkflow.php b/src/applications/daemon/management/PhabricatorDaemonManagementStatusWorkflow.php index 5af583b468..9fc3cc016e 100644 --- a/src/applications/daemon/management/PhabricatorDaemonManagementStatusWorkflow.php +++ b/src/applications/daemon/management/PhabricatorDaemonManagementStatusWorkflow.php @@ -37,22 +37,25 @@ final class PhabricatorDaemonManagementStatusWorkflow $table = id(new PhutilConsoleTable()) ->addColumns(array( 'id' => array( - 'title' => 'ID', + 'title' => pht('Log'), + ), + 'daemonID' => array( + 'title' => pht('Daemon'), ), 'host' => array( - 'title' => 'Host', + 'title' => pht('Host'), ), 'pid' => array( - 'title' => 'PID', + 'title' => pht('Overseer'), ), 'started' => array( - 'title' => 'Started', + 'title' => pht('Started'), ), 'daemon' => array( - 'title' => 'Daemon', + 'title' => pht('Class'), ), 'argv' => array( - 'title' => 'Arguments', + 'title' => pht('Arguments'), ), )); @@ -60,6 +63,7 @@ final class PhabricatorDaemonManagementStatusWorkflow if ($daemon instanceof PhabricatorDaemonLog) { $table->addRow(array( 'id' => $daemon->getID(), + 'daemonID' => $daemon->getDaemonID(), 'host' => $daemon->getHost(), 'pid' => $daemon->getPID(), 'started' => date('M j Y, g:i:s A', $daemon->getDateCreated()), @@ -76,12 +80,15 @@ final class PhabricatorDaemonManagementStatusWorkflow $daemon_log = $daemon->getDaemonLog(); $id = null; + $daemon_id = null; if ($daemon_log) { $id = $daemon_log->getID(); + $daemon_id = $daemon_log->getDaemonID(); } $table->addRow(array( 'id' => $id, + 'daemonID' => $daemon_id, 'host' => 'localhost', 'pid' => $daemon->getPID(), 'started' => $daemon->getEpochStarted() diff --git a/src/applications/daemon/management/PhabricatorDaemonManagementWorkflow.php b/src/applications/daemon/management/PhabricatorDaemonManagementWorkflow.php index aa89f9f738..5e719532c1 100644 --- a/src/applications/daemon/management/PhabricatorDaemonManagementWorkflow.php +++ b/src/applications/daemon/management/PhabricatorDaemonManagementWorkflow.php @@ -63,11 +63,15 @@ abstract class PhabricatorDaemonManagementWorkflow } } - $remote_daemons = id(new PhabricatorDaemonLogQuery()) + $daemon_query = id(new PhabricatorDaemonLogQuery()) ->setViewer(PhabricatorUser::getOmnipotentUser()) - ->withoutIDs($local_ids) - ->withStatus(PhabricatorDaemonLogQuery::STATUS_ALIVE) - ->execute(); + ->withStatus(PhabricatorDaemonLogQuery::STATUS_ALIVE); + + if ($local_ids) { + $daemon_query->withoutIDs($local_ids); + } + + $remote_daemons = $daemon_query->execute(); return array_merge($local_daemons, $remote_daemons); } diff --git a/src/applications/daemon/query/PhabricatorDaemonLogQuery.php b/src/applications/daemon/query/PhabricatorDaemonLogQuery.php index 7f411b27db..58e76e3462 100644 --- a/src/applications/daemon/query/PhabricatorDaemonLogQuery.php +++ b/src/applications/daemon/query/PhabricatorDaemonLogQuery.php @@ -11,6 +11,7 @@ final class PhabricatorDaemonLogQuery private $status = self::STATUS_ALL; private $daemonClasses; private $allowStatusWrites; + private $daemonIDs; public static function getTimeUntilUnknown() { return 3 * PhutilDaemonHandle::getHeartbeatEventFrequency(); @@ -45,6 +46,11 @@ final class PhabricatorDaemonLogQuery return $this; } + public function withDaemonIDs(array $daemon_ids) { + $this->daemonIDs = $daemon_ids; + return $this; + } + protected function loadPage() { $table = new PhabricatorDaemonLog(); $conn_r = $table->establishConnection('r'); @@ -120,14 +126,14 @@ final class PhabricatorDaemonLogQuery private function buildWhereClause(AphrontDatabaseConnection $conn_r) { $where = array(); - if ($this->ids) { + if ($this->ids !== null) { $where[] = qsprintf( $conn_r, 'id IN (%Ld)', $this->ids); } - if ($this->notIDs) { + if ($this->notIDs !== null) { $where[] = qsprintf( $conn_r, 'id NOT IN (%Ld)', @@ -141,13 +147,20 @@ final class PhabricatorDaemonLogQuery $this->getStatusConstants()); } - if ($this->daemonClasses) { + if ($this->daemonClasses !== null) { $where[] = qsprintf( $conn_r, 'daemon IN (%Ls)', $this->daemonClasses); } + if ($this->daemonIDs !== null) { + $where[] = qsprintf( + $conn_r, + 'daemonID IN (%Ls)', + $this->daemonIDs); + } + $where[] = $this->buildPagingClause($conn_r); return $this->formatWhereClause($where); } @@ -165,7 +178,7 @@ final class PhabricatorDaemonLogQuery PhabricatorDaemonLog::STATUS_EXITING, ); default: - throw new Exception("Unknown status '{$status}'!"); + throw new Exception(pht('Unknown status "%s"!', $status)); } } diff --git a/src/applications/daemon/storage/PhabricatorDaemonLog.php b/src/applications/daemon/storage/PhabricatorDaemonLog.php index 0e4f1ea838..6573ea8e4c 100644 --- a/src/applications/daemon/storage/PhabricatorDaemonLog.php +++ b/src/applications/daemon/storage/PhabricatorDaemonLog.php @@ -13,6 +13,7 @@ final class PhabricatorDaemonLog extends PhabricatorDaemonDAO protected $daemon; protected $host; protected $pid; + protected $daemonID; protected $runningAsUser; protected $argv; protected $explicitArgv = array(); @@ -34,6 +35,7 @@ final class PhabricatorDaemonLog extends PhabricatorDaemonDAO 'runningAsUser' => 'text255?', 'envHash' => 'bytes40', 'status' => 'text8', + 'daemonID' => 'text64', ), self::CONFIG_KEY_SCHEMA => array( 'status' => array( @@ -42,6 +44,10 @@ final class PhabricatorDaemonLog extends PhabricatorDaemonDAO 'dateCreated' => array( 'columns' => array('dateCreated'), ), + 'key_daemonID' => array( + 'columns' => array('daemonID'), + 'unique' => true, + ), ), ) + parent::getConfiguration(); } diff --git a/src/infrastructure/daemon/control/PhabricatorDaemonReference.php b/src/infrastructure/daemon/control/PhabricatorDaemonReference.php index 89001622ef..4b6fe1182f 100644 --- a/src/infrastructure/daemon/control/PhabricatorDaemonReference.php +++ b/src/infrastructure/daemon/control/PhabricatorDaemonReference.php @@ -22,6 +22,24 @@ final class PhabricatorDaemonReference { $refs = array(); $daemons = idx($dict, 'daemons', array()); + $logs = array(); + + $daemon_ids = ipull($daemons, 'id'); + if ($daemon_ids) { + try { + $logs = id(new PhabricatorDaemonLogQuery()) + ->setViewer(PhabricatorUser::getOmnipotentUser()) + ->withDaemonIDs($daemon_ids) + ->execute(); + } catch (AphrontQueryException $ex) { + // Ignore any issues here; getting this information only allows us + // to provide a more complete picture of daemon status, and we want + // these commands to work if the database is inaccessible. + } + + $logs = mpull($logs, null, 'getDaemonID'); + } + foreach ($daemons as $daemon) { $ref = new PhabricatorDaemonReference(); @@ -33,17 +51,14 @@ final class PhabricatorDaemonReference { $ref->pid = idx($dict, 'pid'); $ref->start = idx($dict, 'start'); - $ref->name = idx($daemon, 'class'); - $ref->argv = idx($daemon, 'argv', array()); + $config = idx($daemon, 'config', array()); + $ref->name = idx($config, 'class'); + $ref->argv = idx($config, 'argv', array()); - - // TODO: We previously identified daemon logs by using a tuple, but now all daemons under a single overseer will share - // that identifier. We can uniquely identify daemons by $daemon['id'], - // but that isn't currently written into the daemon logs. We should - // start writing it, then load the logs here. This would give us a - // slightly greater ability to keep the web UI in sync when daemons - // get killed forcefully and clean up `phd status` a bit. + $log = idx($logs, idx($daemon, 'id')); + if ($log) { + $ref->daemonLog = $log; + } $ref->pidFile = $path; $refs[] = $ref;