X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=maintenance%2FMaintenance.php;h=291920b415e1bda6b61b5a19d7e7f57f0ea4c425;hb=f225fbee535fd784cc0b414cbab019a492034b20;hp=7825ce950dc5293059706404fd0bc8733f2aa000;hpb=18ec10a358b08931e27f0eb44daf8ccd26159b18;p=lhc%2Fweb%2Fwiklou.git diff --git a/maintenance/Maintenance.php b/maintenance/Maintenance.php index 7825ce950d..291920b415 100644 --- a/maintenance/Maintenance.php +++ b/maintenance/Maintenance.php @@ -105,10 +105,13 @@ abstract class Maintenance { /** * Used by getDB() / setDB() - * @var DatabaseBase + * @var IDatabase */ private $mDb = null; + /** @var float UNIX timestamp */ + private $lastSlaveWait = 0.0; + /** * Used when creating separate schema files. * @var resource @@ -122,6 +125,19 @@ abstract class Maintenance { */ private $config; + /** + * Used to read the options in the order they were passed. + * Useful for option chaining (Ex. dumpBackup.php). It will + * be an empty array if the options are passed in through + * loadParamsAndArgs( $self, $opts, $args ). + * + * This is an array of arrays where + * 0 => the option and 1 => parameter value. + * + * @var array + */ + public $orderedOptions = array(); + /** * Default constructor. Children should call this *first* if implementing * their own constructors @@ -184,15 +200,17 @@ abstract class Maintenance { * @param bool $required Is the param required? * @param bool $withArg Is an argument required with this option? * @param string $shortName Character to use as short name + * @param bool $multiOccurrence Can this option be passed multiple times? */ protected function addOption( $name, $description, $required = false, - $withArg = false, $shortName = false + $withArg = false, $shortName = false, $multiOccurrence = false ) { $this->mParams[$name] = array( 'desc' => $description, 'require' => $required, 'withArg' => $withArg, - 'shortName' => $shortName + 'shortName' => $shortName, + 'multiOccurrence' => $multiOccurrence ); if ( $shortName !== false ) { @@ -210,7 +228,11 @@ abstract class Maintenance { } /** - * Get an option, or return the default + * Get an option, or return the default. + * + * If the option was added to support multiple occurrences, + * this will return an array. + * * @param string $name The name of the param * @param mixed $default Anything you want, default null * @return mixed @@ -636,43 +658,16 @@ abstract class Maintenance { } /** - * Process command line arguments - * $mOptions becomes an array with keys set to the option names - * $mArgs becomes a zero-based array containing the non-option arguments + * Load params and arguments from a given array + * of command-line arguments * - * @param string $self The name of the script, if any - * @param array $opts An array of options, in form of key=>value - * @param array $args An array of command line arguments + * @since 1.27 + * @param array $argv */ - public function loadParamsAndArgs( $self = null, $opts = null, $args = null ) { - # If we were given opts or args, set those and return early - if ( $self ) { - $this->mSelf = $self; - $this->mInputLoaded = true; - } - if ( $opts ) { - $this->mOptions = $opts; - $this->mInputLoaded = true; - } - if ( $args ) { - $this->mArgs = $args; - $this->mInputLoaded = true; - } - - # If we've already loaded input (either by user values or from $argv) - # skip on loading it again. The array_shift() will corrupt values if - # it's run again and again - if ( $this->mInputLoaded ) { - $this->loadSpecialVars(); - - return; - } - - global $argv; - $this->mSelf = array_shift( $argv ); - + public function loadWithArgv( $argv ) { $options = array(); $args = array(); + $this->orderedOptions = array(); # Parse arguments for ( $arg = reset( $argv ); $arg !== false; $arg = next( $argv ) ) { @@ -687,17 +682,14 @@ abstract class Maintenance { } elseif ( substr( $arg, 0, 2 ) == '--' ) { # Long options $option = substr( $arg, 2 ); - if ( array_key_exists( $option, $options ) ) { - $this->error( "\nERROR: $option parameter given twice\n" ); - $this->maybeHelp( true ); - } if ( isset( $this->mParams[$option] ) && $this->mParams[$option]['withArg'] ) { $param = next( $argv ); if ( $param === false ) { $this->error( "\nERROR: $option parameter needs a value after it\n" ); $this->maybeHelp( true ); } - $options[$option] = $param; + + $this->setParam( $options, $option, $param ); } else { $bits = explode( '=', $option, 2 ); if ( count( $bits ) > 1 ) { @@ -706,7 +698,8 @@ abstract class Maintenance { } else { $param = 1; } - $options[$option] = $param; + + $this->setParam( $options, $option, $param ); } } elseif ( $arg == '-' ) { # Lonely "-", often used to indicate stdin or stdout. @@ -719,19 +712,16 @@ abstract class Maintenance { if ( !isset( $this->mParams[$option] ) && isset( $this->mShortParamsMap[$option] ) ) { $option = $this->mShortParamsMap[$option]; } - if ( array_key_exists( $option, $options ) ) { - $this->error( "\nERROR: $option parameter given twice\n" ); - $this->maybeHelp( true ); - } + if ( isset( $this->mParams[$option]['withArg'] ) && $this->mParams[$option]['withArg'] ) { $param = next( $argv ); if ( $param === false ) { $this->error( "\nERROR: $option parameter needs a value after it\n" ); $this->maybeHelp( true ); } - $options[$option] = $param; + $this->setParam( $options, $option, $param ); } else { - $options[$option] = 1; + $this->setParam( $options, $option, 1 ); } } } else { @@ -745,6 +735,75 @@ abstract class Maintenance { $this->mInputLoaded = true; } + /** + * Helper function used solely by loadParamsAndArgs + * to prevent code duplication + * + * This sets the param in the options array based on + * whether or not it can be specified multiple times. + * + * @since 1.27 + * @param array $options + * @param string $option + * @param mixed $value + */ + private function setParam( &$options, $option, $value ) { + $this->orderedOptions[] = array( $option, $value ); + + if ( isset( $this->mParams[$option] ) ) { + $multi = $this->mParams[$option]['multiOccurrence']; + $exists = array_key_exists( $option, $options ); + if ( $multi && $exists ) { + $options[$option][] = $value; + } elseif ( $multi ) { + $options[$option] = array( $value ); + } elseif ( !$exists ) { + $options[$option] = $value; + } else { + $this->error( "\nERROR: $option parameter given twice\n" ); + $this->maybeHelp( true ); + } + } + } + + /** + * Process command line arguments + * $mOptions becomes an array with keys set to the option names + * $mArgs becomes a zero-based array containing the non-option arguments + * + * @param string $self The name of the script, if any + * @param array $opts An array of options, in form of key=>value + * @param array $args An array of command line arguments + */ + public function loadParamsAndArgs( $self = null, $opts = null, $args = null ) { + # If we were given opts or args, set those and return early + if ( $self ) { + $this->mSelf = $self; + $this->mInputLoaded = true; + } + if ( $opts ) { + $this->mOptions = $opts; + $this->mInputLoaded = true; + } + if ( $args ) { + $this->mArgs = $args; + $this->mInputLoaded = true; + } + + # If we've already loaded input (either by user values or from $argv) + # skip on loading it again. The array_shift() will corrupt values if + # it's run again and again + if ( $this->mInputLoaded ) { + $this->loadSpecialVars(); + + return; + } + + global $argv; + $this->mSelf = $argv[0]; + $this->loadWithArgv( array_slice( $argv, 1 ) ); + } + /** * Run some validation checks on the params, etc */ @@ -1026,7 +1085,7 @@ abstract class Maintenance { public function purgeRedundantText( $delete = true ) { # Data should come off the master, wrapped in a transaction $dbw = $this->getDB( DB_MASTER ); - $dbw->begin( __METHOD__ ); + $this->beginTransaction( $dbw, __METHOD__ ); # Get "active" text records from the revisions table $this->output( 'Searching for active text records in revisions table...' ); @@ -1069,7 +1128,7 @@ abstract class Maintenance { } # Done - $dbw->commit( __METHOD__ ); + $this->commitTransaction( $dbw, __METHOD__ ); } /** @@ -1085,7 +1144,10 @@ abstract class Maintenance { * If not set, wfGetDB() will be used. * This function has the same parameters as wfGetDB() * - * @return DatabaseBase + * @param integer $db DB index (DB_SLAVE/DB_MASTER) + * @param array $groups; default: empty array + * @param string|bool $wiki; default: current wiki + * @return IDatabase */ protected function getDB( $db, $groups = array(), $wiki = false ) { if ( is_null( $this->mDb ) ) { @@ -1098,12 +1160,60 @@ abstract class Maintenance { /** * Sets database object to be returned by getDB(). * - * @param DatabaseBase $db Database object to be used + * @param IDatabase $db Database object to be used */ - public function setDB( $db ) { + public function setDB( IDatabase $db ) { $this->mDb = $db; } + /** + * Begin a transcation on a DB + * + * This method makes it clear that begin() is called from a maintenance script, + * which has outermost scope. This is safe, unlike $dbw->begin() called in other places. + * + * @param IDatabase $dbw + * @param string $fname Caller name + * @since 1.27 + */ + protected function beginTransaction( IDatabase $dbw, $fname ) { + $dbw->begin( $fname ); + } + + /** + * Commit the transcation on a DB handle and wait for slaves to catch up + * + * This method makes it clear that commit() is called from a maintenance script, + * which has outermost scope. This is safe, unlike $dbw->commit() called in other places. + * + * @param IDatabase $dbw + * @param string $fname Caller name + * @return bool Whether the slave wait succeeded + * @since 1.27 + */ + protected function commitTransaction( IDatabase $dbw, $fname ) { + $dbw->commit( $fname ); + + $ok = wfWaitForSlaves( $this->lastSlaveWait, false, '*', 30 ); + $this->lastSlaveWait = microtime( true ); + + return $ok; + } + + /** + * Rollback the transcation on a DB handle + * + * This method makes it clear that rollback() is called from a maintenance script, + * which has outermost scope. This is safe, unlike $dbw->rollback() called in other places. + * + * @param IDatabase $dbw + * @param string $fname Caller name + * @since 1.27 + */ + protected function rollbackTransaction( IDatabase $dbw, $fname ) { + $dbw->rollback( $fname ); + } + /** * Lock the search index * @param DatabaseBase &$db