98 $force = $this->hasOption(
'force' );
99 $threads = $this->getOption(
'threads', 1 );
100 if ( $threads < 1 || $threads != intval( $threads ) ) {
101 $this->output(
"Invalid thread count specified; running single-threaded.\n" );
105 $this->output(
"Threaded rebuild is not supported on Windows; running single-threaded.\n" );
108 if ( $threads > 1 && ( !extension_loaded(
'sockets' ) || !function_exists(
'pcntl_fork' ) ) ) {
109 $this->output(
"Threaded rebuild requires ext-pcntl and ext-sockets; running single-threaded.\n" );
113 $conf = $this->getConfig()->get( MainConfigNames::LocalisationCacheConf );
115 $conf[
'manualRecache'] =
false;
116 $conf[
'forceRecache'] = $force || !empty( $conf[
'forceRecache'] );
117 if ( $this->hasOption(
'outdir' ) ) {
118 $conf[
'storeDirectory'] = $this->getOption(
'outdir' );
121 if ( $this->hasOption(
'store-class' ) ) {
122 $conf[
'storeClass'] = $this->getOption(
'store-class' );
126 $services = $this->getServiceContainer();
129 LocalisationCache::CONSTRUCTOR_OPTIONS,
131 $services->getMainConfig()
133 LocalisationCache::getStoreFromConf( $conf, $this->getConfig()->get( MainConfigNames::CacheDirectory ) ),
134 LoggerFactory::getInstance(
'localisation' ),
135 $this->hasOption(
'skip-message-purge' ) ? [] :
136 [
static function () use ( $services ) {
137 MessageBlobStore::clearGlobalCacheEntry( $services->getMainWANObjectCache() );
139 $services->getLanguageNameUtils(),
140 $services->getHookContainer()
143 $allCodes = array_keys( $services
144 ->getLanguageNameUtils()
145 ->getLanguageNames( LanguageNameUtils::AUTONYMS, LanguageNameUtils::SUPPORTED ) );
146 if ( $this->hasOption(
'lang' ) ) {
147 # Validate requested languages
148 $codes = array_intersect( $allCodes,
149 explode(
',', $this->getOption(
'lang' ) ) );
150 # Bailed out if nothing is left
151 if ( count( $codes ) == 0 ) {
152 $this->fatalError(
'None of the languages specified exists.' );
155 # By default get all languages
161 $total = count( $codes );
164 if ( $threads <= 1 ) {
166 $numRebuilt += $this->doRebuild( $codes, $lc, $force );
169 $chunks = array_chunk( $codes, ceil( count( $codes ) / $threads ) );
173 foreach ( $chunks as $codes ) {
177 if ( !socket_create_pair( AF_UNIX, SOCK_STREAM, 0, $socketpair ) ) {
178 $this->fatalError(
'socket_create_pair failed' );
184 $this->fatalError(
' pcntl_fork failed' );
185 } elseif ( $pid === 0 ) {
188 mt_srand( getmypid() );
190 $numRebuilt = $this->doRebuild( $codes, $lc, $force );
192 $msg =
"$numRebuilt\n";
193 socket_write( $socketpair[1], $msg, strlen( $msg ) );
198 $sockets[$pid] = $socketpair[0];
203 foreach ( $sockets as $pid => $socket ) {
205 pcntl_waitpid( $pid, $status );
207 if ( pcntl_wifexited( $status ) ) {
208 $code = pcntl_wexitstatus( $status );
210 $this->output(
"Pid $pid exited with status $code !!\n" );
213 $res = socket_read( $socket, 512, PHP_NORMAL_READ );
214 if ( $res ===
false ) {
215 $this->output(
"socket_read failed in parent\n" );
217 $numRebuilt += intval( $res );
222 $parentStatus |= $code;
223 } elseif ( pcntl_wifsignaled( $status ) ) {
224 $signum = pcntl_wtermsig( $status );
225 $this->output(
"Pid $pid terminated by signal $signum !!\n" );
231 $this->output(
"$numRebuilt languages rebuilt out of $total\n" );
232 if ( $numRebuilt === 0 ) {
233 $this->output(
"Use --force to rebuild the caches which are still fresh.\n" );
235 if ( $parentStatus ) {
236 $this->fatalError(
'Failed.', $parentStatus );