Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F14033895
D15668.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
9 KB
Referenced Files
None
Subscribers
None
D15668.diff
View Options
diff --git a/scripts/sql/manage_storage.php b/scripts/sql/manage_storage.php
--- a/scripts/sql/manage_storage.php
+++ b/scripts/sql/manage_storage.php
@@ -19,13 +19,6 @@
);
$args->parseStandardArguments();
-$conf = PhabricatorEnv::newObjectFromConfig(
- 'mysql.configuration-provider',
- array($dao = null, 'w'));
-
-$default_user = $conf->getUser();
-$default_host = $conf->getHost();
-$default_port = $conf->getPort();
$default_namespace = PhabricatorLiskDAO::getDefaultStorageNamespace();
try {
@@ -41,10 +34,8 @@
'name' => 'user',
'short' => 'u',
'param' => 'username',
- 'default' => $default_user,
'help' => pht(
- "Connect with __username__ instead of the configured default ('%s').",
- $default_user),
+ 'Connect with __username__ instead of the configured default.'),
),
array(
'name' => 'password',
@@ -84,11 +75,21 @@
// First, test that the Phabricator configuration is set up correctly. After
// we know this works we'll test any administrative credentials specifically.
+$ref = PhabricatorDatabaseRef::getMasterDatabaseRef();
+if (!$ref) {
+ throw new Exception(
+ pht('No database master is configured.'));
+}
+
+$default_user = $ref->getUser();
+$default_host = $ref->getHost();
+$default_port = $ref->getPort();
+
$test_api = id(new PhabricatorStorageManagementAPI())
->setUser($default_user)
->setHost($default_host)
->setPort($default_port)
- ->setPassword($conf->getPassword())
+ ->setPassword($ref->getPass())
->setNamespace($args->getArg('namespace'));
try {
@@ -120,15 +121,20 @@
if ($args->getArg('password') === null) {
// This is already a PhutilOpaqueEnvelope.
- $password = $conf->getPassword();
+ $password = $ref->getPass();
} else {
// Put this in a PhutilOpaqueEnvelope.
$password = new PhutilOpaqueEnvelope($args->getArg('password'));
PhabricatorEnv::overrideConfig('mysql.pass', $args->getArg('password'));
}
+$selected_user = $args->getArg('user');
+if ($selected_user === null) {
+ $selected_user = $default_user;
+}
+
$api = id(new PhabricatorStorageManagementAPI())
- ->setUser($args->getArg('user'))
+ ->setUser($selected_user)
->setHost($default_host)
->setPort($default_port)
->setPassword($password)
diff --git a/src/applications/config/check/PhabricatorDatabaseSetupCheck.php b/src/applications/config/check/PhabricatorDatabaseSetupCheck.php
--- a/src/applications/config/check/PhabricatorDatabaseSetupCheck.php
+++ b/src/applications/config/check/PhabricatorDatabaseSetupCheck.php
@@ -12,25 +12,14 @@
}
protected function executeChecks() {
- $conf = PhabricatorEnv::newObjectFromConfig('mysql.configuration-provider');
- $conn_user = $conf->getUser();
- $conn_pass = $conf->getPassword();
- $conn_host = $conf->getHost();
- $conn_port = $conf->getPort();
-
- ini_set('mysql.connect_timeout', 2);
-
- $config = array(
- 'user' => $conn_user,
- 'pass' => $conn_pass,
- 'host' => $conn_host,
- 'port' => $conn_port,
- 'database' => null,
- );
-
- $conn_raw = PhabricatorEnv::newObjectFromConfig(
- 'mysql.implementation',
- array($config));
+ $master = PhabricatorDatabaseRef::getMasterDatabaseRef();
+ if (!$master) {
+ // If we're implicitly in read-only mode during disaster recovery,
+ // don't bother with these setup checks.
+ return;
+ }
+
+ $conn_raw = $master->newManagementConnection();
try {
queryfx($conn_raw, 'SELECT 1');
@@ -88,11 +77,8 @@
->setIsFatal(true)
->addCommand(hsprintf('<tt>phabricator/ $</tt> ./bin/storage upgrade'));
} else {
-
- $config['database'] = $namespace.'_meta_data';
- $conn_meta = PhabricatorEnv::newObjectFromConfig(
- 'mysql.implementation',
- array($config));
+ $conn_meta = $master->newApplicationConnection(
+ $namespace.'_meta_data');
$applied = queryfx_all($conn_meta, 'SELECT patch FROM patch_status');
$applied = ipull($applied, 'patch', 'patch');
@@ -113,7 +99,6 @@
}
}
-
$host = PhabricatorEnv::getEnvConfig('mysql.host');
$matches = null;
if (preg_match('/^([^:]+):(\d+)$/', $host, $matches)) {
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
@@ -239,7 +239,7 @@
continue;
}
- $conn = $ref->newConnection();
+ $conn = $ref->newManagementConnection();
$t_start = microtime(true);
try {
@@ -303,18 +303,69 @@
return $refs;
}
- protected function newConnection() {
+ public function newManagementConnection() {
+ return $this->newConnection(
+ array(
+ 'retries' => 0,
+ 'timeout' => 3,
+ ));
+ }
+
+ public function newApplicationConnection($database) {
+ return $this->newConnection(
+ array(
+ 'database' => $database,
+ ));
+ }
+
+ public static function getMasterDatabaseRef() {
+ $refs = self::loadAll();
+
+ if (!$refs) {
+ $conf = PhabricatorEnv::newObjectFromConfig(
+ 'mysql.configuration-provider',
+ array(null, 'w', null));
+
+ return id(new self())
+ ->setHost($conf->getHost())
+ ->setPort($conf->getPort())
+ ->setUser($conf->getUser())
+ ->setPass($conf->getPassword())
+ ->setIsMaster(true);
+ }
+
+ $master = null;
+ foreach ($refs as $ref) {
+ if ($ref->getDisabled()) {
+ continue;
+ }
+ if ($ref->getIsMaster()) {
+ return $ref;
+ }
+ }
+
+ return null;
+ }
+
+ private function newConnection(array $options) {
+ $spec = $options + array(
+ 'user' => $this->getUser(),
+ 'pass' => $this->getPass(),
+ 'host' => $this->getHost(),
+ 'port' => $this->getPort(),
+ 'database' => null,
+ 'retries' => 3,
+ 'timeout' => 15,
+ );
+
+ // TODO: Remove this once the MySQL connector has proper support
+ // for it, see T6710.
+ ini_set('mysql.connect_timeout', $spec['timeout']);
+
return PhabricatorEnv::newObjectFromConfig(
'mysql.implementation',
array(
- array(
- 'user' => $this->getUser(),
- 'pass' => $this->getPass(),
- 'host' => $this->getHost(),
- 'port' => $this->getPort(),
- 'database' => null,
- 'retries' => 0,
- ),
+ $spec,
));
}
diff --git a/src/infrastructure/storage/lisk/PhabricatorLiskDAO.php b/src/infrastructure/storage/lisk/PhabricatorLiskDAO.php
--- a/src/infrastructure/storage/lisk/PhabricatorLiskDAO.php
+++ b/src/infrastructure/storage/lisk/PhabricatorLiskDAO.php
@@ -52,21 +52,42 @@
*/
protected function establishLiveConnection($mode) {
$namespace = self::getStorageNamespace();
-
- $conf = PhabricatorEnv::newObjectFromConfig(
- 'mysql.configuration-provider',
- array($this, $mode, $namespace));
+ $database = $namespace.'_'.$this->getApplicationName();
$is_readonly = PhabricatorEnv::isReadOnly();
+
if ($is_readonly && ($mode != 'r')) {
throw new Exception(
pht(
'Attempting to establish write-mode connection from a read-only '.
'page (to database "%s").',
- $conf->getDatabase()));
+ $database));
}
- $connection = PhabricatorEnv::newObjectFromConfig(
+ $refs = PhabricatorDatabaseRef::loadAll();
+ if ($refs) {
+ $connection = $this->newClusterConnection($database);
+ } else {
+ $connection = $this->newBasicConnection($database, $mode, $namespace);
+ }
+
+ // TODO: This should be testing if the mode is "r", but that would proably
+ // break a lot of things. Perform a more narrow test for readonly mode
+ // until we have greater certainty that this works correctly most of the
+ // time.
+ if ($is_readonly) {
+ $connection->setReadOnly(true);
+ }
+
+ return $connection;
+ }
+
+ private function newBasicConnection($database, $mode, $namespace) {
+ $conf = PhabricatorEnv::newObjectFromConfig(
+ 'mysql.configuration-provider',
+ array($this, $mode, $namespace));
+
+ return PhabricatorEnv::newObjectFromConfig(
'mysql.implementation',
array(
array(
@@ -74,22 +95,24 @@
'pass' => $conf->getPassword(),
'host' => $conf->getHost(),
'port' => $conf->getPort(),
- 'database' => $conf->getDatabase(),
+ 'database' => $database,
'retries' => 3,
),
));
+ }
- // TODO: This should be testing if the mode is "r", but that would proably
- // break a lot of things. Perform a more narrow test for readonly mode
- // until we have greater certainty that this works correctly most of the
- // time.
- if ($is_readonly) {
- $connection->setReadOnly(true);
+ private function newClusterConnection($database) {
+ $master = PhabricatorDatabaseRef::getMasterDatabaseRef();
+
+ if (!$master) {
+ // TODO: Implicitly degrade to read-only mode.
+ throw new Exception(pht('No master in database cluster config!'));
}
- return $connection;
+ return $master->newApplicationConnection($database);
}
+
/**
* @task config
*/
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Nov 10, 8:37 PM (1 w, 2 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6741359
Default Alt Text
D15668.diff (9 KB)
Attached To
Mode
D15668: When `cluster.databases` is configured, read the master connection from it
Attached
Detach File
Event Timeline
Log In to Comment