MediaWiki  REL1_21
rebuildLocalisationCache.php
Go to the documentation of this file.
00001 <?php
00002 
00032 require_once( __DIR__ . '/Maintenance.php' );
00033 
00039 class RebuildLocalisationCache extends Maintenance {
00040         public function __construct() {
00041                 parent::__construct();
00042                 $this->mDescription = "Rebuild the localisation cache";
00043                 $this->addOption( 'force', 'Rebuild all files, even ones not out of date' );
00044                 $this->addOption( 'threads', 'Fork more than one thread', false, true );
00045                 $this->addOption( 'outdir', 'Override the output directory (normally $wgCacheDirectory)',
00046                         false, true );
00047         }
00048 
00049         public function memoryLimit() {
00050                 if ( $this->hasOption( 'memory-limit' ) ) {
00051                         return parent::memoryLimit();
00052                 }
00053                 return '1000M';
00054         }
00055 
00056         public function finalSetup() {
00057                 # This script needs to be run to build the inital l10n cache. But if
00058                 # $wgLanguageCode is not 'en', it won't be able to run because there is
00059                 # no l10n cache. Break the cycle by forcing $wgLanguageCode = 'en'.
00060                 global $wgLanguageCode;
00061                 $wgLanguageCode = 'en';
00062                 return parent::finalSetup();
00063         }
00064 
00065         public function execute() {
00066                 global $wgLocalisationCacheConf;
00067 
00068                 $force = $this->hasOption( 'force' );
00069                 $threads = $this->getOption( 'threads', 1 );
00070                 if ( $threads < 1 || $threads != intval( $threads ) ) {
00071                         $this->output( "Invalid thread count specified; running single-threaded.\n" );
00072                         $threads = 1;
00073                 }
00074                 if ( $threads > 1 && wfIsWindows() ) {
00075                         $this->output( "Threaded rebuild is not supported on Windows; running single-threaded.\n" );
00076                         $threads = 1;
00077                 }
00078                 if ( $threads > 1 && !function_exists( 'pcntl_fork' ) ) {
00079                         $this->output( "PHP pcntl extension is not present; running single-threaded.\n" );
00080                         $threads = 1;
00081                 }
00082 
00083                 $conf = $wgLocalisationCacheConf;
00084                 $conf['manualRecache'] = false; // Allow fallbacks to create CDB files
00085                 if ( $force ) {
00086                         $conf['forceRecache'] = true;
00087                 }
00088                 if ( $this->hasOption( 'outdir' ) ) {
00089                         $conf['storeDirectory'] = $this->getOption( 'outdir' );
00090                 }
00091                 $lc = new LocalisationCache_BulkLoad( $conf );
00092 
00093                 $codes = array_keys( Language::fetchLanguageNames( null, 'mwfile' ) );
00094                 sort( $codes );
00095 
00096                 // Initialise and split into chunks
00097                 $numRebuilt = 0;
00098                 $total = count( $codes );
00099                 $chunks = array_chunk( $codes, ceil( count( $codes ) / $threads ) );
00100                 $pids = array();
00101                 foreach ( $chunks as $codes ) {
00102                         // Do not fork for only one thread
00103                         $pid = ( $threads > 1 ) ? pcntl_fork() : -1;
00104 
00105                         if ( $pid === 0 ) {
00106                                 // Child, reseed because there is no bug in PHP:
00107                                 // http://bugs.php.net/bug.php?id=42465
00108                                 mt_srand( getmypid() );
00109                                 $numRebuilt = $this->doRebuild( $codes, $lc, $force );
00110                                 // Abuse the exit value for the count of rebuild languages
00111                                 exit( $numRebuilt );
00112                         } elseif ( $pid === -1 ) {
00113                                 // Fork failed or one thread, do it serialized
00114                                 $numRebuilt += $this->doRebuild( $codes, $lc, $force );
00115                         } else {
00116                                 // Main thread
00117                                 $pids[] = $pid;
00118                         }
00119                 }
00120                 // Wait for all children
00121                 foreach ( $pids as $pid ) {
00122                         $status = 0;
00123                         pcntl_waitpid( $pid, $status );
00124                         // Fetch the count from the return value
00125                         $numRebuilt += pcntl_wexitstatus( $status );
00126                 }
00127 
00128                 $this->output( "$numRebuilt languages rebuilt out of $total\n" );
00129                 if ( $numRebuilt === 0 ) {
00130                         $this->output( "Use --force to rebuild the caches which are still fresh.\n" );
00131                 }
00132         }
00133 
00142         private function doRebuild( $codes, $lc, $force ) {
00143                 $numRebuilt = 0;
00144                 foreach ( $codes as $code ) {
00145                         if ( $force || $lc->isExpired( $code ) ) {
00146                                 $this->output( "Rebuilding $code...\n" );
00147                                 $lc->recache( $code );
00148                                 $numRebuilt++;
00149                         }
00150                 }
00151                 return $numRebuilt;
00152         }
00153 
00159         public function setForce( $forced = true ) {
00160                 $this->mOptions['force'] = $forced;
00161         }
00162 }
00163 
00164 $maintClass = "RebuildLocalisationCache";
00165 require_once( RUN_MAINTENANCE_IF_MAIN );