MediaWiki  master
rebuildLocalisationCache.php
Go to the documentation of this file.
1 <?php
2 
35 
36 require_once __DIR__ . '/Maintenance.php';
37 
44  public function __construct() {
45  parent::__construct();
46  $this->addDescription( 'Rebuild the localisation cache' );
47  $this->addOption( 'force', 'Rebuild all files, even ones not out of date' );
48  $this->addOption( 'threads', 'Fork more than one thread', false, true );
49  $this->addOption( 'outdir', 'Override the output directory (normally $wgCacheDirectory)',
50  false, true );
51  $this->addOption( 'lang', 'Only rebuild these languages, comma separated.',
52  false, true );
53  $this->addOption(
54  'store-class',
55  'Override the LC store class (normally $wgLocalisationCacheConf[\'storeClass\'])',
56  false,
57  true
58  );
59  $this->addOption(
60  'no-clear-message-blob-store', "Don't clear the MessageBlobStore global cache" );
61  }
62 
63  public function finalSetup() {
64  # This script needs to be run to build the inital l10n cache. But if
65  # $wgLanguageCode is not 'en', it won't be able to run because there is
66  # no l10n cache. Break the cycle by forcing $wgLanguageCode = 'en'.
67  global $wgLanguageCode;
68  $wgLanguageCode = 'en';
69  parent::finalSetup();
70  }
71 
72  public function execute() {
74 
75  $force = $this->hasOption( 'force' );
76  $threads = $this->getOption( 'threads', 1 );
77  if ( $threads < 1 || $threads != intval( $threads ) ) {
78  $this->output( "Invalid thread count specified; running single-threaded.\n" );
79  $threads = 1;
80  }
81  if ( $threads > 1 && wfIsWindows() ) {
82  $this->output( "Threaded rebuild is not supported on Windows; running single-threaded.\n" );
83  $threads = 1;
84  }
85  if ( $threads > 1 && !function_exists( 'pcntl_fork' ) ) {
86  $this->output( "PHP pcntl extension is not present; running single-threaded.\n" );
87  $threads = 1;
88  }
89 
91  // Allow fallbacks to create CDB files
92  $conf['manualRecache'] = false;
93  $conf['forceRecache'] = $force || !empty( $conf['forceRecache'] );
94  if ( $this->hasOption( 'outdir' ) ) {
95  $conf['storeDirectory'] = $this->getOption( 'outdir' );
96  }
97 
98  if ( $this->hasOption( 'store-class' ) ) {
99  $conf['storeClass'] = $this->getOption( 'store-class' );
100  }
101  // XXX Copy-pasted from ServiceWiring.php. Do we need a factory for this one caller?
102  $services = MediaWikiServices::getInstance();
103  $lc = new LocalisationCacheBulkLoad(
104  new ServiceOptions(
106  $conf,
107  $services->getMainConfig()
108  ),
110  LoggerFactory::getInstance( 'localisation' ),
111  $this->hasOption( 'no-clear-message-blob-store' ) ? [] :
112  [ static function () use ( $services ) {
113  MessageBlobStore::clearGlobalCacheEntry( $services->getMainWANObjectCache() );
114  } ],
115  $services->getLanguageNameUtils(),
116  $services->getHookContainer()
117  );
118 
119  $allCodes = array_keys( $services
120  ->getLanguageNameUtils()
121  ->getLanguageNames( null, 'mwfile' ) );
122  if ( $this->hasOption( 'lang' ) ) {
123  # Validate requested languages
124  $codes = array_intersect( $allCodes,
125  explode( ',', $this->getOption( 'lang' ) ) );
126  # Bailed out if nothing is left
127  if ( count( $codes ) == 0 ) {
128  $this->fatalError( 'None of the languages specified exists.' );
129  }
130  } else {
131  # By default get all languages
132  $codes = $allCodes;
133  }
134  sort( $codes );
135 
136  // Initialise and split into chunks
137  $numRebuilt = 0;
138  $total = count( $codes );
139  $chunks = array_chunk( $codes, ceil( count( $codes ) / $threads ) );
140  $pids = [];
141  $parentStatus = 0;
142  foreach ( $chunks as $codes ) {
143  // Do not fork for only one thread
144  $pid = ( $threads > 1 ) ? pcntl_fork() : -1;
145 
146  if ( $pid === 0 ) {
147  // Child, reseed because there is no bug in PHP:
148  // https://bugs.php.net/bug.php?id=42465
149  mt_srand( getmypid() );
150 
151  $this->doRebuild( $codes, $lc, $force );
152  exit( 0 );
153  } elseif ( $pid === -1 ) {
154  // Fork failed or one thread, do it serialized
155  $numRebuilt += $this->doRebuild( $codes, $lc, $force );
156  } else {
157  // Main thread
158  $pids[] = $pid;
159  }
160  }
161  // Wait for all children
162  foreach ( $pids as $pid ) {
163  $status = 0;
164  pcntl_waitpid( $pid, $status );
165 
166  if ( pcntl_wifexited( $status ) ) {
167  $code = pcntl_wexitstatus( $status );
168  if ( $code ) {
169  $this->output( "Pid $pid exited with status $code !!\n" );
170  }
171  // Mush all child statuses into a single value in the parent.
172  $parentStatus |= $code;
173  } elseif ( pcntl_wifsignaled( $status ) ) {
174  $signum = pcntl_wtermsig( $status );
175  $this->output( "Pid $pid terminated by signal $signum !!\n" );
176  $parentStatus |= 1;
177  }
178  }
179 
180  if ( !$pids ) {
181  $this->output( "$numRebuilt languages rebuilt out of $total\n" );
182  if ( $numRebuilt === 0 ) {
183  $this->output( "Use --force to rebuild the caches which are still fresh.\n" );
184  }
185  }
186  if ( $parentStatus ) {
187  exit( $parentStatus );
188  }
189  }
190 
199  private function doRebuild( $codes, $lc, $force ) {
200  $numRebuilt = 0;
201  foreach ( $codes as $code ) {
202  if ( $force || $lc->isExpired( $code ) ) {
203  $this->output( "Rebuilding $code...\n" );
204  $lc->recache( $code );
205  $numRebuilt++;
206  }
207  }
208 
209  return $numRebuilt;
210  }
211 
217  public function setForce( $forced = true ) {
218  $this->mOptions['force'] = $forced;
219  }
220 }
221 
222 $maintClass = RebuildLocalisationCache::class;
223 require_once RUN_MAINTENANCE_IF_MAIN;
LocalisationCache\CONSTRUCTOR_OPTIONS
const CONSTRUCTOR_OPTIONS
Definition: LocalisationCache.php:235
RebuildLocalisationCache\setForce
setForce( $forced=true)
Sets whether a run of this maintenance script has the force parameter set.
Definition: rebuildLocalisationCache.php:217
RebuildLocalisationCache\__construct
__construct()
Default constructor.
Definition: rebuildLocalisationCache.php:44
MessageBlobStore\clearGlobalCacheEntry
static clearGlobalCacheEntry(WANObjectCache $cache)
Invalidate cache keys for all known modules.
Definition: MessageBlobStore.php:189
RebuildLocalisationCache\execute
execute()
Do the actual work.
Definition: rebuildLocalisationCache.php:72
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:172
Maintenance\fatalError
fatalError( $msg, $exitCode=1)
Output a message and terminate the current script.
Definition: Maintenance.php:486
Maintenance\addDescription
addDescription( $text)
Set the description text.
Definition: Maintenance.php:327
RebuildLocalisationCache\finalSetup
finalSetup()
Handle some last-minute setup here.
Definition: rebuildLocalisationCache.php:63
Maintenance
Abstract maintenance class for quickly writing and churning out maintenance scripts with minimal effo...
Definition: Maintenance.php:55
$wgCacheDirectory
$wgCacheDirectory
Directory for caching data in the local filesystem.
Definition: DefaultSettings.php:2510
LocalisationCacheBulkLoad
A localisation cache optimised for loading large amounts of data for many languages.
Definition: LocalisationCacheBulkLoad.php:25
MediaWiki\Config\ServiceOptions
A class for passing options to services.
Definition: ServiceOptions.php:27
MediaWiki\Logger\LoggerFactory
PSR-3 logger instance factory.
Definition: LoggerFactory.php:45
LocalisationCache\getStoreFromConf
static getStoreFromConf(array $conf, $fallbackCacheDir)
Return a suitable LCStore as specified by the given configuration.
Definition: LocalisationCache.php:207
Maintenance\addOption
addOption( $name, $description, $required=false, $withArg=false, $shortName=false, $multiOccurrence=false)
Add a parameter to the script.
Definition: Maintenance.php:245
$wgLocalisationCacheConf
$wgLocalisationCacheConf
Localisation cache configuration.
Definition: DefaultSettings.php:2848
$maintClass
$maintClass
Definition: rebuildLocalisationCache.php:222
RebuildLocalisationCache
Maintenance script to rebuild the localisation cache.
Definition: rebuildLocalisationCache.php:43
wfIsWindows
wfIsWindows()
Check if the operating system is Windows.
Definition: GlobalFunctions.php:1870
$wgLanguageCode
$wgLanguageCode
Site language code.
Definition: DefaultSettings.php:3194
Maintenance\getOption
getOption( $name, $default=null)
Get an option, or return the default.
Definition: Maintenance.php:281
RebuildLocalisationCache\doRebuild
doRebuild( $codes, $lc, $force)
Helper function to rebuild list of languages codes.
Definition: rebuildLocalisationCache.php:199
Maintenance\output
output( $out, $channel=null)
Throw some output to the user.
Definition: Maintenance.php:433
Maintenance\hasOption
hasOption( $name)
Checks to see if a particular option exists.
Definition: Maintenance.php:266