Differential D16848 Diff 40576 src/infrastructure/storage/management/workflow/PhabricatorStorageManagementWorkflow.php
Changeset View
Changeset View
Standalone View
Standalone View
src/infrastructure/storage/management/workflow/PhabricatorStorageManagementWorkflow.php
| <?php | <?php | ||||
| abstract class PhabricatorStorageManagementWorkflow | abstract class PhabricatorStorageManagementWorkflow | ||||
| extends PhabricatorManagementWorkflow { | extends PhabricatorManagementWorkflow { | ||||
| private $api; | private $apis = array(); | ||||
| private $dryRun; | private $dryRun; | ||||
| private $force; | private $force; | ||||
| private $patches; | private $patches; | ||||
| private $didInitialize; | private $didInitialize; | ||||
| final public function getAPI() { | final public function setAPIs(array $apis) { | ||||
| return $this->api; | $this->apis = $apis; | ||||
| return $this; | |||||
| } | } | ||||
| final public function setAPI(PhabricatorStorageManagementAPI $api) { | final public function getAnyAPI() { | ||||
| $this->api = $api; | return head($this->getAPIs()); | ||||
| return $this; | } | ||||
| final public function getMasterAPIs() { | |||||
| $apis = $this->getAPIs(); | |||||
| $results = array(); | |||||
| foreach ($apis as $api) { | |||||
| if ($api->getRef()->getIsMaster()) { | |||||
| $results[] = $api; | |||||
| } | |||||
| } | |||||
| if (!$results) { | |||||
| throw new PhutilArgumentUsageException( | |||||
| pht( | |||||
| 'This command only operates on database masters, but the selected '. | |||||
| 'database hosts do not include any masters.')); | |||||
| } | |||||
| return $results; | |||||
| } | |||||
| final public function getSingleAPI() { | |||||
| $apis = $this->getAPIs(); | |||||
| if (count($apis) == 1) { | |||||
| return head($apis); | |||||
| } | |||||
| throw new PhutilArgumentUsageException( | |||||
| pht( | |||||
| 'Phabricator is configured in cluster mode, with multiple database '. | |||||
| 'hosts. Use "--host" to specify which host you want to operate on.')); | |||||
| } | |||||
| final public function getAPIs() { | |||||
| return $this->apis; | |||||
| } | } | ||||
| final protected function isDryRun() { | final protected function isDryRun() { | ||||
| return $this->dryRun; | return $this->dryRun; | ||||
| } | } | ||||
| final protected function setDryRun($dry_run) { | final protected function setDryRun($dry_run) { | ||||
| $this->dryRun = $dry_run; | $this->dryRun = $dry_run; | ||||
| Show All 40 Lines | if (!$this->isReadOnlyWorkflow()) { | ||||
| } | } | ||||
| } | } | ||||
| return $this->didExecute($args); | return $this->didExecute($args); | ||||
| } | } | ||||
| public function didExecute(PhutilArgumentParser $args) {} | public function didExecute(PhutilArgumentParser $args) {} | ||||
| private function loadSchemata() { | private function loadSchemata(PhabricatorStorageManagementAPI $api) { | ||||
| $query = id(new PhabricatorConfigSchemaQuery()) | $query = id(new PhabricatorConfigSchemaQuery()); | ||||
| ->setAPI($this->getAPI()); | |||||
| $ref = $api->getRef(); | |||||
| $ref_key = $ref->getRefKey(); | |||||
| $actual = $query->loadActualSchema(); | $query->setAPIs(array($api)); | ||||
| $expect = $query->loadExpectedSchema(); | $query->setRefs(array($ref)); | ||||
| $comp = $query->buildComparisonSchema($expect, $actual); | |||||
| return array($comp, $expect, $actual); | $actual = $query->loadActualSchemata(); | ||||
| $expect = $query->loadExpectedSchemata(); | |||||
| $comp = $query->buildComparisonSchemata($expect, $actual); | |||||
| return array( | |||||
| $comp[$ref_key], | |||||
| $expect[$ref_key], | |||||
| $actual[$ref_key], | |||||
| ); | |||||
| } | } | ||||
| final protected function adjustSchemata($unsafe) { | final protected function adjustSchemata( | ||||
| $lock = $this->lock(); | PhabricatorStorageManagementAPI $api, | ||||
| $unsafe) { | |||||
| $lock = $this->lock($api); | |||||
| try { | try { | ||||
| $err = $this->doAdjustSchemata($unsafe); | $err = $this->doAdjustSchemata($api, $unsafe); | ||||
| } catch (Exception $ex) { | } catch (Exception $ex) { | ||||
| $lock->unlock(); | $lock->unlock(); | ||||
| throw $ex; | throw $ex; | ||||
| } | } | ||||
| $lock->unlock(); | $lock->unlock(); | ||||
| return $err; | return $err; | ||||
| } | } | ||||
| final private function doAdjustSchemata($unsafe) { | final private function doAdjustSchemata( | ||||
| PhabricatorStorageManagementAPI $api, | |||||
| $unsafe) { | |||||
| $console = PhutilConsole::getConsole(); | $console = PhutilConsole::getConsole(); | ||||
| $console->writeOut( | $console->writeOut( | ||||
| "%s\n", | "%s\n", | ||||
| pht('Verifying database schemata...')); | pht( | ||||
| 'Verifying database schemata on "%s"...', | |||||
| $api->getRef()->getRefKey())); | |||||
| list($adjustments, $errors) = $this->findAdjustments(); | list($adjustments, $errors) = $this->findAdjustments($api); | ||||
| $api = $this->getAPI(); | |||||
| if (!$adjustments) { | if (!$adjustments) { | ||||
| $console->writeOut( | $console->writeOut( | ||||
| "%s\n", | "%s\n", | ||||
| pht('Found no adjustments for schemata.')); | pht('Found no adjustments for schemata.')); | ||||
| return $this->printErrors($errors, 0); | return $this->printErrors($errors, 0); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 291 Lines • ▼ Show 20 Lines | if (!$failed) { | ||||
| 'Adjustments" in the documentation.')); | 'Adjustments" in the documentation.')); | ||||
| $err = 1; | $err = 1; | ||||
| } | } | ||||
| return $this->printErrors($errors, $err); | return $this->printErrors($errors, $err); | ||||
| } | } | ||||
| private function findAdjustments() { | private function findAdjustments( | ||||
| list($comp, $expect, $actual) = $this->loadSchemata(); | PhabricatorStorageManagementAPI $api) { | ||||
| list($comp, $expect, $actual) = $this->loadSchemata($api); | |||||
| $issue_charset = PhabricatorConfigStorageSchema::ISSUE_CHARSET; | $issue_charset = PhabricatorConfigStorageSchema::ISSUE_CHARSET; | ||||
| $issue_collation = PhabricatorConfigStorageSchema::ISSUE_COLLATION; | $issue_collation = PhabricatorConfigStorageSchema::ISSUE_COLLATION; | ||||
| $issue_columntype = PhabricatorConfigStorageSchema::ISSUE_COLUMNTYPE; | $issue_columntype = PhabricatorConfigStorageSchema::ISSUE_COLUMNTYPE; | ||||
| $issue_surpluskey = PhabricatorConfigStorageSchema::ISSUE_SURPLUSKEY; | $issue_surpluskey = PhabricatorConfigStorageSchema::ISSUE_SURPLUSKEY; | ||||
| $issue_missingkey = PhabricatorConfigStorageSchema::ISSUE_MISSINGKEY; | $issue_missingkey = PhabricatorConfigStorageSchema::ISSUE_MISSINGKEY; | ||||
| $issue_columns = PhabricatorConfigStorageSchema::ISSUE_KEYCOLUMNS; | $issue_columns = PhabricatorConfigStorageSchema::ISSUE_KEYCOLUMNS; | ||||
| $issue_unique = PhabricatorConfigStorageSchema::ISSUE_UNIQUE; | $issue_unique = PhabricatorConfigStorageSchema::ISSUE_UNIQUE; | ||||
| ▲ Show 20 Lines • Show All 333 Lines • ▼ Show 20 Lines | if ($all_surplus) { | ||||
| pht('SCHEMATA ERRORS'), | pht('SCHEMATA ERRORS'), | ||||
| phutil_console_wrap($message)); | phutil_console_wrap($message)); | ||||
| } | } | ||||
| return 2; | return 2; | ||||
| } | } | ||||
| final protected function upgradeSchemata( | final protected function upgradeSchemata( | ||||
| PhabricatorStorageManagementAPI $api, | |||||
| $apply_only = null, | $apply_only = null, | ||||
| $no_quickstart = false, | $no_quickstart = false, | ||||
| $init_only = false) { | $init_only = false) { | ||||
| $lock = $this->lock(); | $lock = $this->lock($api); | ||||
| try { | try { | ||||
| $this->doUpgradeSchemata($apply_only, $no_quickstart, $init_only); | $this->doUpgradeSchemata($api, $apply_only, $no_quickstart, $init_only); | ||||
| } catch (Exception $ex) { | } catch (Exception $ex) { | ||||
| $lock->unlock(); | $lock->unlock(); | ||||
| throw $ex; | throw $ex; | ||||
| } | } | ||||
| $lock->unlock(); | $lock->unlock(); | ||||
| } | } | ||||
| final private function doUpgradeSchemata( | final private function doUpgradeSchemata( | ||||
| PhabricatorStorageManagementAPI $api, | |||||
| $apply_only, | $apply_only, | ||||
| $no_quickstart, | $no_quickstart, | ||||
| $init_only) { | $init_only) { | ||||
| $api = $this->getAPI(); | $applied = $api->getAppliedPatches(); | ||||
| $applied = $this->getApi()->getAppliedPatches(); | |||||
| if ($applied === null) { | if ($applied === null) { | ||||
| if ($this->dryRun) { | if ($this->dryRun) { | ||||
| echo pht( | echo pht( | ||||
| "DRYRUN: Patch metadata storage doesn't exist yet, ". | "DRYRUN: Patch metadata storage doesn't exist yet, ". | ||||
| "it would be created.\n"); | "it would be created.\n"); | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 117 Lines • ▼ Show 20 Lines | while (true) { | ||||
| unset($this->patches[$key]); | unset($this->patches[$key]); | ||||
| $applied[$key] = true; | $applied[$key] = true; | ||||
| } | } | ||||
| if (!$applied_something) { | if (!$applied_something) { | ||||
| if (count($this->patches)) { | if (count($this->patches)) { | ||||
| throw new Exception( | throw new Exception( | ||||
| pht( | pht( | ||||
| 'Some patches could not be applied: %s', | 'Some patches could not be applied to "%s": %s', | ||||
| $api->getRef()->getRefKey(), | |||||
| implode(', ', array_keys($this->patches)))); | implode(', ', array_keys($this->patches)))); | ||||
| } else if (!$this->dryRun && !$apply_only) { | } else if (!$this->dryRun && !$apply_only) { | ||||
| echo pht( | echo pht( | ||||
| "Storage is up to date. Use '%s' for details.", | 'Storage is up to date on "%s". Use "%s" for details.', | ||||
| $api->getRef()->getRefKey(), | |||||
| 'storage status')."\n"; | 'storage status')."\n"; | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| final protected function getBareHostAndPort($host) { | final protected function getBareHostAndPort($host) { | ||||
| Show All 11 Lines | final protected function getBareHostAndPort($host) { | ||||
| return array($bare_hostname, $port); | return array($bare_hostname, $port); | ||||
| } | } | ||||
| /** | /** | ||||
| * Acquires a @{class:PhabricatorGlobalLock}. | * Acquires a @{class:PhabricatorGlobalLock}. | ||||
| * | * | ||||
| * @return PhabricatorGlobalLock | * @return PhabricatorGlobalLock | ||||
| */ | */ | ||||
| final protected function lock() { | final protected function lock(PhabricatorStorageManagementAPI $api) { | ||||
| return PhabricatorGlobalLock::newLock(__CLASS__) | return PhabricatorGlobalLock::newLock(__CLASS__) | ||||
| ->useSpecificConnection($this->getApi()->getConn(null)) | ->useSpecificConnection($api->getConn(null)) | ||||
| ->lock(); | ->lock(); | ||||
| } | } | ||||
| } | } | ||||