Page MenuHomePhabricator

D16847.id40575.diff
No OneTemporary

D16847.id40575.diff

diff --git a/src/applications/config/application/PhabricatorConfigApplication.php b/src/applications/config/application/PhabricatorConfigApplication.php
--- a/src/applications/config/application/PhabricatorConfigApplication.php
+++ b/src/applications/config/application/PhabricatorConfigApplication.php
@@ -45,9 +45,10 @@
'group/(?P<key>[^/]+)/' => 'PhabricatorConfigGroupController',
'version/' => 'PhabricatorConfigVersionController',
'database/'.
+ '(?:(?P<ref>[^/]+)/'.
'(?:(?P<database>[^/]+)/'.
'(?:(?P<table>[^/]+)/'.
- '(?:(?:col/(?P<column>[^/]+)|key/(?P<key>[^/]+))/)?)?)?'
+ '(?:(?:col/(?P<column>[^/]+)|key/(?P<key>[^/]+))/)?)?)?)?'
=> 'PhabricatorConfigDatabaseStatusController',
'dbissue/' => 'PhabricatorConfigDatabaseIssueController',
'(?P<verb>ignore|unignore)/(?P<key>[^/]+)/'
diff --git a/src/applications/config/controller/PhabricatorConfigDatabaseController.php b/src/applications/config/controller/PhabricatorConfigDatabaseController.php
--- a/src/applications/config/controller/PhabricatorConfigDatabaseController.php
+++ b/src/applications/config/controller/PhabricatorConfigDatabaseController.php
@@ -3,22 +3,6 @@
abstract class PhabricatorConfigDatabaseController
extends PhabricatorConfigController {
- protected function buildSchemaQuery() {
- $ref = PhabricatorDatabaseRef::getMasterDatabaseRef();
-
- $api = id(new PhabricatorStorageManagementAPI())
- ->setUser($ref->getUser())
- ->setHost($ref->getHost())
- ->setPort($ref->getPort())
- ->setNamespace(PhabricatorLiskDAO::getDefaultStorageNamespace())
- ->setPassword($ref->getPass());
-
- $query = id(new PhabricatorConfigSchemaQuery())
- ->setAPI($api);
-
- return $query;
- }
-
protected function renderIcon($status) {
switch ($status) {
case PhabricatorConfigStorageSchema::STATUS_OKAY:
diff --git a/src/applications/config/controller/PhabricatorConfigDatabaseIssueController.php b/src/applications/config/controller/PhabricatorConfigDatabaseIssueController.php
--- a/src/applications/config/controller/PhabricatorConfigDatabaseIssueController.php
+++ b/src/applications/config/controller/PhabricatorConfigDatabaseIssueController.php
@@ -6,11 +6,11 @@
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
- $query = $this->buildSchemaQuery();
+ $query = new PhabricatorConfigSchemaQuery();
- $actual = $query->loadActualSchema();
- $expect = $query->loadExpectedSchema();
- $comp = $query->buildComparisonSchema($expect, $actual);
+ $actual = $query->loadActualSchemata();
+ $expect = $query->loadExpectedSchemata();
+ $comp_servers = $query->buildComparisonSchemata($expect, $actual);
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(pht('Database Issues'));
@@ -18,65 +18,70 @@
// Collect all open issues.
$issues = array();
- foreach ($comp->getDatabases() as $database_name => $database) {
- foreach ($database->getLocalIssues() as $issue) {
- $issues[] = array(
- $database_name,
- null,
- null,
- null,
- $issue,
- );
- }
- foreach ($database->getTables() as $table_name => $table) {
- foreach ($table->getLocalIssues() as $issue) {
+ foreach ($comp_servers as $ref_name => $comp) {
+ foreach ($comp->getDatabases() as $database_name => $database) {
+ foreach ($database->getLocalIssues() as $issue) {
$issues[] = array(
+ $ref_name,
$database_name,
- $table_name,
+ null,
null,
null,
$issue,
);
}
- foreach ($table->getColumns() as $column_name => $column) {
- foreach ($column->getLocalIssues() as $issue) {
+ foreach ($database->getTables() as $table_name => $table) {
+ foreach ($table->getLocalIssues() as $issue) {
$issues[] = array(
+ $ref_name,
$database_name,
$table_name,
- 'column',
- $column_name,
+ null,
+ null,
$issue,
);
}
- }
- foreach ($table->getKeys() as $key_name => $key) {
- foreach ($key->getLocalIssues() as $issue) {
- $issues[] = array(
- $database_name,
- $table_name,
- 'key',
- $key_name,
- $issue,
- );
+ foreach ($table->getColumns() as $column_name => $column) {
+ foreach ($column->getLocalIssues() as $issue) {
+ $issues[] = array(
+ $ref_name,
+ $database_name,
+ $table_name,
+ 'column',
+ $column_name,
+ $issue,
+ );
+ }
+ }
+ foreach ($table->getKeys() as $key_name => $key) {
+ foreach ($key->getLocalIssues() as $issue) {
+ $issues[] = array(
+ $ref_name,
+ $database_name,
+ $table_name,
+ 'key',
+ $key_name,
+ $issue,
+ );
+ }
}
}
}
}
-
// Sort all open issues so that the most severe issues appear first.
$order = array();
$counts = array();
foreach ($issues as $key => $issue) {
- $const = $issue[4];
+ $const = $issue[5];
$status = PhabricatorConfigStorageSchema::getIssueStatus($const);
$severity = PhabricatorConfigStorageSchema::getStatusSeverity($status);
$order[$key] = sprintf(
'~%d~%s%s%s',
9 - $severity,
- $issue[0],
$issue[1],
- $issue[3]);
+ $issue[2],
+ $issue[4]);
if (empty($counts[$status])) {
$counts[$status] = 0;
@@ -91,22 +96,25 @@
// Render the issues.
$rows = array();
foreach ($issues as $issue) {
- $const = $issue[4];
+ $const = $issue[5];
+
+ $uri = $this->getApplicationURI('/database/'.$issue[0].'/'.$issue[1].'/');
$database_link = phutil_tag(
'a',
array(
- 'href' => $this->getApplicationURI('/database/'.$issue[0].'/'),
+ 'href' => $uri,
),
- $issue[0]);
+ $issue[1]);
$rows[] = array(
$this->renderIcon(
PhabricatorConfigStorageSchema::getIssueStatus($const)),
+ $issue[0],
$database_link,
- $issue[1],
$issue[2],
$issue[3],
+ $issue[4],
PhabricatorConfigStorageSchema::getIssueDescription($const),
);
}
@@ -117,6 +125,7 @@
->setHeaders(
array(
null,
+ pht('Server'),
pht('Database'),
pht('Table'),
pht('Type'),
@@ -130,6 +139,7 @@
null,
null,
null,
+ null,
'wide',
));
diff --git a/src/applications/config/controller/PhabricatorConfigDatabaseStatusController.php b/src/applications/config/controller/PhabricatorConfigDatabaseStatusController.php
--- a/src/applications/config/controller/PhabricatorConfigDatabaseStatusController.php
+++ b/src/applications/config/controller/PhabricatorConfigDatabaseStatusController.php
@@ -7,6 +7,7 @@
private $table;
private $column;
private $key;
+ private $ref;
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
@@ -14,48 +15,59 @@
$this->table = $request->getURIData('table');
$this->column = $request->getURIData('column');
$this->key = $request->getURIData('key');
+ $this->ref = $request->getURIData('ref');
- $query = $this->buildSchemaQuery();
-
- $actual = $query->loadActualSchema();
- $expect = $query->loadExpectedSchema();
- $comp = $query->buildComparisonSchema($expect, $actual);
-
- if ($this->column) {
- return $this->renderColumn(
- $comp,
- $expect,
- $actual,
- $this->database,
- $this->table,
- $this->column);
- } else if ($this->key) {
- return $this->renderKey(
- $comp,
- $expect,
- $actual,
- $this->database,
- $this->table,
- $this->key);
- } else if ($this->table) {
- return $this->renderTable(
- $comp,
- $expect,
- $actual,
- $this->database,
- $this->table);
- } else if ($this->database) {
- return $this->renderDatabase(
- $comp,
- $expect,
- $actual,
- $this->database);
- } else {
- return $this->renderServer(
- $comp,
- $expect,
- $actual);
+ $query = new PhabricatorConfigSchemaQuery();
+
+ $actual = $query->loadActualSchemata();
+ $expect = $query->loadExpectedSchemata();
+ $comp = $query->buildComparisonSchemata($expect, $actual);
+
+ if ($this->ref !== null) {
+ $server_actual = idx($actual, $this->ref);
+ if (!$server_actual) {
+ return new Aphront404Response();
+ }
+
+ $server_comparison = $comp[$this->ref];
+ $server_expect = $expect[$this->ref];
+
+ if ($this->column) {
+ return $this->renderColumn(
+ $server_comparison,
+ $server_expect,
+ $server_actual,
+ $this->database,
+ $this->table,
+ $this->column);
+ } else if ($this->key) {
+ return $this->renderKey(
+ $server_comparison,
+ $server_expect,
+ $server_actual,
+ $this->database,
+ $this->table,
+ $this->key);
+ } else if ($this->table) {
+ return $this->renderTable(
+ $server_comparison,
+ $server_expect,
+ $server_actual,
+ $this->database,
+ $this->table);
+ } else if ($this->database) {
+ return $this->renderDatabase(
+ $server_comparison,
+ $server_expect,
+ $server_actual,
+ $this->database);
+ }
}
+
+ return $this->renderServers(
+ $comp,
+ $expect,
+ $actual);
}
private function buildResponse($title, $body) {
@@ -66,34 +78,57 @@
$title = pht('Database Status');
}
+ $ref = $this->ref;
+ $database = $this->database;
+ $table = $this->table;
+ $column = $this->column;
+ $key = $this->key;
+
+ $links = array();
+ $links[] = array(
+ pht('Database Status'),
+ 'database/',
+ );
+
+ if ($database) {
+ $links[] = array(
+ $database,
+ "database/{$ref}/{$database}/",
+ );
+ }
+
+ if ($table) {
+ $links[] = array(
+ $table,
+ "database/{$ref}/{$database}/{$table}/",
+ );
+ }
+
+ if ($column) {
+ $links[] = array(
+ $column,
+ "database/{$ref}/{$database}/{$table}/col/{$column}/",
+ );
+ }
+
+ if ($key) {
+ $links[] = array(
+ $key,
+ "database/{$ref}/{$database}/{$table}/key/{$key}/",
+ );
+ }
+
$crumbs = $this->buildApplicationCrumbs();
$crumbs->setBorder(true);
- if ($this->database) {
- $crumbs->addTextCrumb(
- pht('Database Status'),
- $this->getApplicationURI('database/'));
- if ($this->table) {
- $crumbs->addTextCrumb(
- $this->database,
- $this->getApplicationURI('database/'.$this->database.'/'));
- if ($this->column || $this->key) {
- $crumbs->addTextCrumb(
- $this->table,
- $this->getApplicationURI(
- 'database/'.$this->database.'/'.$this->table.'/'));
- if ($this->column) {
- $crumbs->addTextCrumb($this->column);
- } else {
- $crumbs->addTextCrumb($this->key);
- }
- } else {
- $crumbs->addTextCrumb($this->table);
- }
+
+ $last_key = last_key($links);
+ foreach ($links as $link_key => $link) {
+ list($name, $href) = $link;
+ if ($link_key == $last_key) {
+ $crumbs->addTextCrumb($name);
} else {
- $crumbs->addTextCrumb($this->database);
+ $crumbs->addTextCrumb($name, $this->getApplicationURI($href));
}
- } else {
- $crumbs->addTextCrumb(pht('Database Status'));
}
$doc_link = PhabricatorEnv::getDoclink('Managing Storage Adjustments');
@@ -121,46 +156,57 @@
}
- private function renderServer(
- PhabricatorConfigServerSchema $comp,
- PhabricatorConfigServerSchema $expect,
- PhabricatorConfigServerSchema $actual) {
+ private function renderServers(
+ array $comp_servers,
+ array $expect_servers,
+ array $actual_servers) {
$charset_issue = PhabricatorConfigStorageSchema::ISSUE_CHARSET;
$collation_issue = PhabricatorConfigStorageSchema::ISSUE_COLLATION;
$rows = array();
- foreach ($comp->getDatabases() as $database_name => $database) {
- $actual_database = $actual->getDatabase($database_name);
- if ($actual_database) {
- $charset = $actual_database->getCharacterSet();
- $collation = $actual_database->getCollation();
- } else {
- $charset = null;
- $collation = null;
- }
+ foreach ($comp_servers as $ref_key => $comp) {
+ $actual = $actual_servers[$ref_key];
+ $expect = $expect_servers[$ref_key];
+ foreach ($comp->getDatabases() as $database_name => $database) {
+ $actual_database = $actual->getDatabase($database_name);
+ if ($actual_database) {
+ $charset = $actual_database->getCharacterSet();
+ $collation = $actual_database->getCollation();
+ } else {
+ $charset = null;
+ $collation = null;
+ }
- $status = $database->getStatus();
- $issues = $database->getIssues();
+ $status = $database->getStatus();
+ $issues = $database->getIssues();
- $rows[] = array(
- $this->renderIcon($status),
- phutil_tag(
- 'a',
+ $uri = $this->getURI(
array(
- 'href' => $this->getApplicationURI(
- '/database/'.$database_name.'/'),
- ),
- $database_name),
- $this->renderAttr($charset, $database->hasIssue($charset_issue)),
- $this->renderAttr($collation, $database->hasIssue($collation_issue)),
- );
+ 'ref' => $ref_key,
+ 'database' => $database_name,
+ ));
+
+ $rows[] = array(
+ $this->renderIcon($status),
+ $ref_key,
+ phutil_tag(
+ 'a',
+ array(
+ 'href' => $uri,
+ ),
+ $database_name),
+ $this->renderAttr($charset, $database->hasIssue($charset_issue)),
+ $this->renderAttr($collation, $database->hasIssue($collation_issue)),
+ );
+ }
}
$table = id(new AphrontTableView($rows))
->setHeaders(
array(
null,
+ pht('Server'),
pht('Database'),
pht('Charset'),
pht('Collation'),
@@ -168,6 +214,7 @@
->setColumnClasses(
array(
null,
+ null,
'wide pri',
null,
null,
@@ -200,13 +247,17 @@
foreach ($database->getTables() as $table_name => $table) {
$status = $table->getStatus();
+ $uri = $this->getURI(
+ array(
+ 'table' => $table_name,
+ ));
+
$rows[] = array(
$this->renderIcon($status),
phutil_tag(
'a',
array(
- 'href' => $this->getApplicationURI(
- '/database/'.$database_name.'/'.$table_name.'/'),
+ 'href' => $uri,
),
$table_name),
$this->renderAttr(
@@ -252,6 +303,10 @@
$properties = $this->buildProperties(
array(
array(
+ pht('Server'),
+ $this->ref,
+ ),
+ array(
pht('Character Set'),
$actual_charset,
),
@@ -325,17 +380,17 @@
$data_type = $expect_column->getDataType();
}
+ $uri = $this->getURI(
+ array(
+ 'column' => $column_name,
+ ));
+
$rows[] = array(
$this->renderIcon($status),
phutil_tag(
'a',
array(
- 'href' => $this->getApplicationURI(
- 'database/'.
- $database_name.'/'.
- $table_name.'/'.
- 'col/'.
- $column_name.'/'),
+ 'href' => $uri,
),
$column_name),
$data_type,
@@ -407,17 +462,17 @@
$key->hasIssue($longkey_issue));
}
+ $uri = $this->getURI(
+ array(
+ 'key' => $key_name,
+ ));
+
$key_rows[] = array(
$this->renderIcon($status),
phutil_tag(
'a',
array(
- 'href' => $this->getApplicationURI(
- 'database/'.
- $database_name.'/'.
- $table_name.'/'.
- 'key/'.
- $key_name.'/'),
+ 'href' => $uri,
),
$key_name),
$this->renderAttr(
@@ -465,6 +520,10 @@
$properties = $this->buildProperties(
array(
array(
+ pht('Server'),
+ $this->ref,
+ ),
+ array(
pht('Collation'),
$actual_collation,
),
@@ -562,6 +621,10 @@
$properties = $this->buildProperties(
array(
array(
+ pht('Server'),
+ $this->ref,
+ ),
+ array(
pht('Data Type'),
$data_type,
),
@@ -679,6 +742,10 @@
$properties = $this->buildProperties(
array(
array(
+ pht('Server'),
+ $this->ref,
+ ),
+ array(
pht('Unique'),
$this->renderBoolean($actual_unique),
),
@@ -745,4 +812,40 @@
return phutil_tag_div('config-page-property', $view);
}
+ private function getURI(array $properties) {
+ $defaults = array(
+ 'ref' => $this->ref,
+ 'database' => $this->database,
+ 'table' => $this->table,
+ 'column' => $this->column,
+ 'key' => $this->key,
+ );
+
+ $properties = $properties + $defaults;
+ $properties = array_select_keys($properties, array_keys($defaults));
+
+ $parts = array();
+ foreach ($properties as $key => $property) {
+ if (!strlen($property)) {
+ continue;
+ }
+
+ if ($key == 'column') {
+ $parts[] = 'col';
+ } else if ($key == 'key') {
+ $parts[] = 'key';
+ }
+
+ $parts[] = $property;
+ }
+
+ if ($parts) {
+ $parts = implode('/', $parts).'/';
+ } else {
+ $parts = null;
+ }
+
+ return $this->getApplicationURI('/database/'.$parts);
+ }
+
}
diff --git a/src/applications/config/schema/PhabricatorConfigSchemaQuery.php b/src/applications/config/schema/PhabricatorConfigSchemaQuery.php
--- a/src/applications/config/schema/PhabricatorConfigSchemaQuery.php
+++ b/src/applications/config/schema/PhabricatorConfigSchemaQuery.php
@@ -2,36 +2,40 @@
final class PhabricatorConfigSchemaQuery extends Phobject {
- private $api;
+ private function getDatabaseNames(PhabricatorDatabaseRef $ref) {
+ $api = $this->getAPI($ref);
+ $patches = PhabricatorSQLPatchList::buildAllPatches();
+ return $api->getDatabaseList(
+ $patches,
+ $only_living = true);
+ }
- public function setAPI(PhabricatorStorageManagementAPI $api) {
- $this->api = $api;
- return $this;
+ private function getAPI(PhabricatorDatabaseRef $ref) {
+ return id(new PhabricatorStorageManagementAPI())
+ ->setUser($ref->getUser())
+ ->setHost($ref->getHost())
+ ->setPort($ref->getPort())
+ ->setNamespace(PhabricatorLiskDAO::getDefaultStorageNamespace())
+ ->setPassword($ref->getPass());
}
- protected function getAPI() {
- if (!$this->api) {
- throw new PhutilInvalidStateException('setAPI');
+ public function loadActualSchemata() {
+ $refs = PhabricatorDatabaseRef::getMasterDatabaseRefs();
+
+ $schemata = array();
+ foreach ($refs as $ref) {
+ $schema = $this->loadActualSchemaForServer($ref);
+ $schemata[$schema->getRef()->getRefKey()] = $schema;
}
- return $this->api;
- }
- protected function getConn() {
- return $this->getAPI()->getConn(null);
+ return $schemata;
}
- private function getDatabaseNames() {
- $api = $this->getAPI();
- $patches = PhabricatorSQLPatchList::buildAllPatches();
- return $api->getDatabaseList(
- $patches,
- $only_living = true);
- }
+ private function loadActualSchemaForServer(PhabricatorDatabaseRef $ref) {
+ $databases = $this->getDatabaseNames($ref);
- public function loadActualSchema() {
- $databases = $this->getDatabaseNames();
+ $conn = $ref->newManagementConnection();
- $conn = $this->getConn();
$tables = queryfx_all(
$conn,
'SELECT TABLE_SCHEMA, TABLE_NAME, TABLE_COLLATION
@@ -92,7 +96,8 @@
// primary, unique, and foreign keys, so we can't use them here. We pull
// indexes later on using SHOW INDEXES.
- $server_schema = new PhabricatorConfigServerSchema();
+ $server_schema = id(new PhabricatorConfigServerSchema())
+ ->setRef($ref);
$tables = igroup($tables, 'TABLE_SCHEMA');
foreach ($tables as $database_name => $database_tables) {
@@ -177,15 +182,29 @@
return $server_schema;
}
- public function loadExpectedSchema() {
- $databases = $this->getDatabaseNames();
- $info = $this->getAPI()->getCharsetInfo();
+ public function loadExpectedSchemata() {
+ $refs = PhabricatorDatabaseRef::getMasterDatabaseRefs();
+
+ $schemata = array();
+ foreach ($refs as $ref) {
+ $schema = $this->loadExpectedSchemaForServer($ref);
+ $schemata[$schema->getRef()->getRefKey()] = $schema;
+ }
+
+ return $schemata;
+ }
+
+ public function loadExpectedSchemaForServer(PhabricatorDatabaseRef $ref) {
+ $databases = $this->getDatabaseNames($ref);
+ $info = $this->getAPI($ref)->getCharsetInfo();
$specs = id(new PhutilClassMapQuery())
->setAncestorClass('PhabricatorConfigSchemaSpec')
->execute();
- $server_schema = new PhabricatorConfigServerSchema();
+ $server_schema = id(new PhabricatorConfigServerSchema())
+ ->setRef($ref);
+
foreach ($specs as $spec) {
$spec
->setUTF8Charset(
@@ -201,7 +220,21 @@
return $server_schema;
}
- public function buildComparisonSchema(
+ public function buildComparisonSchemata(
+ array $expect_servers,
+ array $actual_servers) {
+
+ $schemata = array();
+ foreach ($actual_servers as $key => $actual_server) {
+ $schemata[$key] = $this->buildComparisonSchemaForServer(
+ $expect_servers[$key],
+ $actual_server);
+ }
+
+ return $schemata;
+ }
+
+ private function buildComparisonSchemaForServer(
PhabricatorConfigServerSchema $expect,
PhabricatorConfigServerSchema $actual) {
diff --git a/src/applications/config/schema/PhabricatorConfigServerSchema.php b/src/applications/config/schema/PhabricatorConfigServerSchema.php
--- a/src/applications/config/schema/PhabricatorConfigServerSchema.php
+++ b/src/applications/config/schema/PhabricatorConfigServerSchema.php
@@ -3,8 +3,18 @@
final class PhabricatorConfigServerSchema
extends PhabricatorConfigStorageSchema {
+ private $ref;
private $databases = array();
+ public function setRef(PhabricatorDatabaseRef $ref) {
+ $this->ref = $ref;
+ return $this;
+ }
+
+ public function getRef() {
+ return $this->ref;
+ }
+
public function addDatabase(PhabricatorConfigDatabaseSchema $database) {
$key = $database->getName();
if (isset($this->databases[$key])) {
diff --git a/src/infrastructure/cluster/PhabricatorDatabaseRef.php b/src/infrastructure/cluster/PhabricatorDatabaseRef.php
--- a/src/infrastructure/cluster/PhabricatorDatabaseRef.php
+++ b/src/infrastructure/cluster/PhabricatorDatabaseRef.php
@@ -157,6 +157,17 @@
return $this->isIndividual;
}
+ public function getRefKey() {
+ $host = $this->getHost();
+
+ $port = $this->getPort();
+ if (strlen($port)) {
+ return "{$host}:{$port}";
+ }
+
+ return $host;
+ }
+
public static function getConnectionStatusMap() {
return array(
self::STATUS_OKAY => array(

File Metadata

Mime Type
text/plain
Expires
Thu, Apr 10, 3:18 AM (2 w, 4 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7223396
Default Alt Text
D16847.id40575.diff (24 KB)

Event Timeline