r35667 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r35666‎ | r35667 | r35668 >
Date:03:27, 1 June 2008
Author:tstarling
Status:old
Tags:
Comment:
Revert r35478, r35264, r35262: $wgPerLanguageCaching feature. Bug found with $wgPerLanguageCaching=false. Nikerabbit, please see me for a detailed code review.
Modified paths:
  • /trunk/phase3/RELEASE-NOTES (modified) (history)
  • /trunk/phase3/includes/DefaultSettings.php (modified) (history)
  • /trunk/phase3/includes/GlobalFunctions.php (modified) (history)
  • /trunk/phase3/includes/MessageCache.php (modified) (history)
  • /trunk/phase3/includes/Skin.php (modified) (history)
  • /trunk/phase3/languages/Language.php (modified) (history)

Diff [purge]

Index: trunk/phase3/includes/GlobalFunctions.php
@@ -2342,14 +2342,6 @@
23432343 return $key;
23442344 }
23452345
2346 -function wfMemcKeyLang( $key, $code ) {
2347 - if ( !is_string($code) ) {
2348 - return $key;
2349 - } else {
2350 - return $key . ';L:' . $code;
2351 - }
2352 -}
2353 -
23542346 /**
23552347 * Get a cache key for a foreign DB
23562348 */
Index: trunk/phase3/includes/MessageCache.php
@@ -22,7 +22,8 @@
2323 var $mMemcKey, $mKeys, $mParserOptions, $mParser;
2424 var $mExtensionMessages = array();
2525 var $mInitialised = false;
26 - var $mAllMessagesLoaded; // Extension messages
 26+ var $mDeferred = true;
 27+ var $mAllMessagesLoaded;
2728
2829 function __construct( &$memCached, $useDB, $expiry, $memcPrefix) {
2930 wfProfileIn( __METHOD__ );
@@ -37,14 +38,15 @@
3839 $this->mInitialised = true;
3940 $this->mParser = null;
4041
 42+ # When we first get asked for a message,
 43+ # then we'll fill up the cache. If we
 44+ # can return a cache hit, this saves
 45+ # some extra milliseconds
 46+ $this->mDeferred = true;
 47+
4148 wfProfileOut( __METHOD__ );
4249 }
4350
44 -
45 - /**
46 - * ParserOptions is lazy initialised.
47 - * Access should probably be protected.
48 - */
4951 function getParserOptions() {
5052 if ( !$this->mParserOptions ) {
5153 $this->mParserOptions = new ParserOptions;
@@ -53,26 +55,22 @@
5456 }
5557
5658 /**
57 - * Try to load the cache from a local file.
58 - * Actual format of the file depends on the $wgLocalMessageCacheSerialized
59 - * setting.
60 - *
61 - * @param $hash String: the hash of contents, to check validity.
62 - * @param $code Mixed: Optional language code, see documenation of load().
63 - * @return false on failure.
 59+ * Try to load the cache from a local file
6460 */
65 - function loadFromLocal( $hash, $code ) {
 61+ function loadFromLocal( $hash ) {
6662 global $wgLocalMessageCache, $wgLocalMessageCacheSerialized;
6763
 64+ if ( $wgLocalMessageCache === false ) {
 65+ return;
 66+ }
 67+
6868 $filename = "$wgLocalMessageCache/messages-" . wfWikiID();
69 - if ( $code ) $filename .= '-' . $code;
7069
71 - # Check file existence
7270 wfSuppressWarnings();
7371 $file = fopen( $filename, 'r' );
7472 wfRestoreWarnings();
7573 if ( !$file ) {
76 - return false; // No cache file
 74+ return;
7775 }
7876
7977 if ( $wgLocalMessageCacheSerialized ) {
@@ -84,36 +82,36 @@
8583 while ( !feof( $file ) ) {
8684 $serialized .= fread( $file, 100000 );
8785 }
88 - fclose( $file );
89 - return $this->setCache( unserialize( $serialized ) );
90 - } else {
91 - fclose( $file );
92 - return false; // Wrong hash
 86+ $this->setCache( unserialize( $serialized ) );
9387 }
 88+ fclose( $file );
9489 } else {
9590 $localHash=substr(fread($file,40),8);
9691 fclose($file);
9792 if ($hash!=$localHash) {
98 - return false; // Wrong hash
 93+ return;
9994 }
10095
101 - require( $filename );
102 - return $this->setCache( $this->mCache );
 96+ require("$wgLocalMessageCache/messages-" . wfWikiID());
 97+ $this->setCache( $this->mCache);
10398 }
10499 }
105100
106101 /**
107102 * Save the cache to a local file
108103 */
109 - function saveToLocal( $serialized, $hash, $code ) {
110 - global $wgLocalMessageCache;
 104+ function saveToLocal( $serialized, $hash ) {
 105+ global $wgLocalMessageCache, $wgLocalMessageCacheSerialized;
111106
 107+ if ( $wgLocalMessageCache === false ) {
 108+ return;
 109+ }
 110+
112111 $filename = "$wgLocalMessageCache/messages-" . wfWikiID();
113 - if ( $code ) $filename .= '-' . $code;
 112+ $oldUmask = umask( 0 );
 113+ wfMkdirParents( $wgLocalMessageCache, 0777 );
 114+ umask( $oldUmask );
114115
115 - # Make sure the directories exist
116 - $this->createCacheDir( $wgLocalMessageCache );
117 -
118116 $file = fopen( $filename, 'w' );
119117 if ( !$file ) {
120118 wfDebug( "Unable to open local cache file for writing\n" );
@@ -125,41 +123,34 @@
126124 @chmod( $filename, 0666 );
127125 }
128126
129 - function saveToScript( $array, $hash, $code ) {
 127+ function loadFromScript( $hash ) {
 128+ wfDeprecated( __METHOD__ );
 129+ $this->loadFromLocal( $hash );
 130+ }
 131+
 132+ function saveToScript($array, $hash) {
130133 global $wgLocalMessageCache;
 134+ if ( $wgLocalMessageCache === false ) {
 135+ return;
 136+ }
131137
132138 $filename = "$wgLocalMessageCache/messages-" . wfWikiID();
133 - if ( $code ) $filename .= '-' . $code;
134 - $tempFilename = $filename . '.tmp';
135 -
136 - # Make sure the directories exist
137 - $this->createCacheDir( $wgLocalMessageCache );
138 -
139 - $file = fopen( $tempFilename, 'w');
 139+ $oldUmask = umask( 0 );
 140+ wfMkdirParents( $wgLocalMessageCache, 0777 );
 141+ umask( $oldUmask );
 142+ $file = fopen( $filename.'.tmp', 'w');
140143 fwrite($file,"<?php\n//$hash\n\n \$this->mCache = array(");
141144
142145 foreach ($array as $key => $message) {
143 - $key = $this->escapeForScript($key);
144 - $messages = $this->escapeForScript($message);
145 - fwrite($file, "'$key' => '$message',\n");
 146+ fwrite($file, "'". $this->escapeForScript($key).
 147+ "' => '" . $this->escapeForScript($message).
 148+ "',\n");
146149 }
147 -
148150 fwrite($file,");\n?>");
149151 fclose($file);
150 - rename($tempFilename, $filename);
 152+ rename($filename.'.tmp',$filename);
151153 }
152154
153 - /**
154 - * Creates directory with correct permissions.
155 - *
156 - * @param $path String: path that is created if it does not exist.
157 - */
158 - protected function createCacheDir( $path ) {
159 - $oldUmask = umask( 0 );
160 - wfMkdirParents( $path, 0777 );
161 - umask( $oldUmask );
162 - }
163 -
164155 function escapeForScript($string) {
165156 $string = str_replace( '\\', '\\\\', $string );
166157 $string = str_replace( '\'', '\\\'', $string );
@@ -171,321 +162,220 @@
172163 */
173164 function setCache( $cache ) {
174165 if ( isset( $cache['VERSION'] ) && $cache['VERSION'] == MSG_CACHE_VERSION ) {
175 - if ( $this->mCache ) {
176 - $this->mCache = $cache + $this->mCache;
177 - } else {
178 - $this->mCache = $cache;
179 - }
180 - return true;
 166+ $this->mCache = $cache;
181167 } else {
182 - return false;
 168+ $this->mCache = false;
183169 }
184170 }
185171
186172 /**
187 - * Loads messages from caches or from database in this order:
188 - * (1) local message cache (if $wgLocalMessageCache is enabled)
189 - * (2) memcached
190 - * (3) from the database.
191 - *
192 - * When succesfully loading from (2) or (3), all higher level caches are
193 - * updated for the newest version.
194 - *
195 - * Nothing is loaded if member variable mDisabled is true, either manually
196 - * set by calling code or if message loading fails (is this possible?).
197 - *
198 - * Returns true if cache is already populated or it was succesfully populated,
199 - * or false if populating empty cache fails. Also returns true if MessageCache
200 - * is disabled.
201 - *
202 - * @param $code Mixed: if evaluates to false, messages for all languages is
203 - * loaded and stored in cache as one object. If code is provided
204 - * and $wgPerLanguageCaching is true, messages are loaded per
205 - * language and stored individually in caches 1 to 2.
 173+ * Loads messages either from memcached or the database, if not disabled
 174+ * On error, quietly switches to a fallback mode
 175+ * Returns false for a reportable error, true otherwise
206176 */
207 - function load( $code = false ) {
208 - global $wgLocalMessageCache, $wgPerLanguageCaching;
 177+ function load() {
 178+ global $wgLocalMessageCache, $wgLocalMessageCacheSerialized;
209179
210 - if ( !$this->mUseCache ) {
211 - return true;
212 - }
213 -
214 - # Keep track of loaded messages. Either array of loaded codes as keys,
215 - # or just true if all languages are loaded.
216 - static $loaded = false;
217 -
218 - if ( !$wgPerLanguageCaching ) {
219 - // Disable language separation for normal use case
220 - $code = false;
221 - } elseif( !is_string( $code ) ) {
222 - # This isn't really nice, so at least make a note about it
223 - wfDebug( __METHOD__ . " called without providing a language code\n" );
224 - }
225 -
226 - # Don't do double loading...
227 - if ( $loaded === true || ($code && isset($loaded[$code])) ) return true;
228 -
229 - # Adjust cache key if we are handling only single language
230 - $cacheKey = wfMemcKeyLang( $this->mMemcKey, $code );
231 -
232 - # 8 lines of code just to say (once) that message cache is disabled
233180 if ( $this->mDisable ) {
234181 static $shownDisabled = false;
235182 if ( !$shownDisabled ) {
236 - wfDebug( __METHOD__ . ": disabled\n" );
 183+ wfDebug( "MessageCache::load(): disabled\n" );
237184 $shownDisabled = true;
238185 }
239186 return true;
240187 }
 188+ if ( !$this->mUseCache ) {
 189+ $this->mDeferred = false;
 190+ return true;
 191+ }
241192
242 - # Loading code starts
243 - wfProfileIn( __METHOD__ );
244 - $success = false; # Keep track of success
245 - $where = array(); # Debug info, delayed to avoid spamming debug log too much
 193+ $fname = 'MessageCache::load';
 194+ wfProfileIn( $fname );
 195+ $success = true;
246196
247 - # (1) local cache
248 - # Hash of the contents is stored in memcache, to detect if local cache goes
249 - # out of date (due to update in other thread?)
 197+ $this->mCache = false;
 198+
 199+ # Try local cache
250200 if ( $wgLocalMessageCache !== false ) {
251 - wfProfileIn( __METHOD__ . '-fromlocal' );
252 - $hash = $this->mMemc->get( "$cacheKey-hash" );
 201+ wfProfileIn( $fname.'-fromlocal' );
 202+ $hash = $this->mMemc->get( "{$this->mMemcKey}-hash" );
253203 if ( $hash ) {
254 - $success = $this->loadFromLocal( $hash, $code );
255 - if ( $success ) $where[] = 'got from local cache';
 204+ $this->loadFromLocal( $hash );
 205+ if ( $this->mCache ) {
 206+ wfDebug( "MessageCache::load(): got from local cache\n" );
 207+ }
256208 }
257 - wfProfileOut( __METHOD__ . '-fromlocal' );
 209+ wfProfileOut( $fname.'-fromlocal' );
258210 }
259211
260 - # (2) memcache
261 - # Fails if nothing in cache, or in the wrong version.
262 - if ( !$success ) {
263 - wfProfileIn( __METHOD__ . '-fromcache' );
264 - $cache = $this->mMemc->get( $cacheKey );
265 - $success = $this->setCache( $cache );
266 - if ( $success ) {
267 - $where[] = 'got from global cache';
268 - $this->saveToCaches( $cache, $cacheKey, false, $code );
 212+ # Try memcached
 213+ if ( !$this->mCache ) {
 214+ wfProfileIn( $fname.'-fromcache' );
 215+ $this->setCache( $this->mMemc->get( $this->mMemcKey ) );
 216+ if ( $this->mCache ) {
 217+ wfDebug( "MessageCache::load(): got from global cache\n" );
 218+ # Save to local cache
 219+ if ( $wgLocalMessageCache !== false ) {
 220+ $serialized = serialize( $this->mCache );
 221+ if ( !$hash ) {
 222+ $hash = md5( $serialized );
 223+ $this->mMemc->set( "{$this->mMemcKey}-hash", $hash, $this->mExpiry );
 224+ }
 225+ if ($wgLocalMessageCacheSerialized) {
 226+ $this->saveToLocal( $serialized,$hash );
 227+ } else {
 228+ $this->saveToScript( $this->mCache, $hash );
 229+ }
 230+ }
269231 }
270 - wfProfileOut( __METHOD__ . '-fromcache' );
 232+ wfProfileOut( $fname.'-fromcache' );
271233 }
272234
273235
274 - # (3)
275 - # Nothing in caches... so we need create one and store it in caches
276 - if ( !$success ) {
277 - $where[] = 'cache is empty';
278 - $this->lock($cacheKey);
279 - wfProfileIn( __METHOD__ . '-load' );
280 - $where[] = 'loading from database';
281 - # We want to store messages of particular language here, not everything
282 - # from mCache.
283 - $cache = $this->loadFromDB( $code );
284 - $success = $this->setCache( $cache );
285 - wfProfileOut( __METHOD__ . '-load' );
 236+ # If there's nothing in memcached, load all the messages from the database
 237+ if ( !$this->mCache ) {
 238+ wfDebug( "MessageCache::load(): cache is empty\n" );
 239+ $this->lock();
 240+ # Other threads don't need to load the messages if another thread is doing it.
 241+ $success = $this->mMemc->add( $this->mMemcKey.'-status', "loading", MSG_LOAD_TIMEOUT );
286242 if ( $success ) {
287 - $this->saveToCaches( $cache, $cacheKey, true, $code );
 243+ wfProfileIn( $fname.'-load' );
 244+ wfDebug( "MessageCache::load(): loading all messages from DB\n" );
 245+ $this->loadFromDB();
 246+ wfProfileOut( $fname.'-load' );
 247+
 248+ # Save in memcached
 249+ # Keep trying if it fails, this is kind of important
 250+ wfProfileIn( $fname.'-save' );
 251+ for ($i=0; $i<20 &&
 252+ !$this->mMemc->set( $this->mMemcKey, $this->mCache, $this->mExpiry );
 253+ $i++ ) {
 254+ usleep(mt_rand(500000,1500000));
 255+ }
 256+
 257+ # Save to local cache
 258+ if ( $wgLocalMessageCache !== false ) {
 259+ $serialized = serialize( $this->mCache );
 260+ $hash = md5( $serialized );
 261+ $this->mMemc->set( "{$this->mMemcKey}-hash", $hash, $this->mExpiry );
 262+ if ($wgLocalMessageCacheSerialized) {
 263+ $this->saveToLocal( $serialized,$hash );
 264+ } else {
 265+ $this->saveToScript( $this->mCache, $hash );
 266+ }
 267+ }
 268+
 269+ wfProfileOut( $fname.'-save' );
 270+ if ( $i == 20 ) {
 271+ $this->mMemc->set( $this->mMemcKey.'-status', 'error', 60*5 );
 272+ wfDebug( "MemCached set error in MessageCache: restart memcached server!\n" );
 273+ } else {
 274+ $this->mMemc->delete( $this->mMemcKey.'-status' );
 275+ }
288276 }
289 - $this->unlock($cacheKey);
 277+ $this->unlock();
290278 }
291279
292 - if ( !$success ) {
293 - # Bad luck... this should not happen
294 - $where[] = 'loading FAILED - cache is disabled';
295 - $info = implode( ', ', $where );
296 - wfDebug( __METHOD__ . ": Loading $code... $info\n" );
 280+ if ( !is_array( $this->mCache ) ) {
 281+ wfDebug( "MessageCache::load(): unable to load cache, disabled\n" );
297282 $this->mDisable = true;
298283 $this->mCache = false;
299 - } else {
300 - # All good, just record the success
301 - $info = implode( ', ', $where );
302 - wfDebug( __METHOD__ . ": Loading $code... $info\n" );
303 - if ( $code ) {
304 - $loaded[$code] = true;
305 - } else {
306 - $loaded = true;
307 - }
308284 }
309 - wfProfileOut( __METHOD__ );
 285+ wfProfileOut( $fname );
 286+ $this->mDeferred = false;
310287 return $success;
311288 }
312289
313290 /**
314 - * Loads cacheable messages from the database. Messages bigger than
315 - * $wgMaxMsgCacheEntrySize are assigned a special value, and are loaded
316 - * on-demand from the database later.
317 - *
318 - * @param $code Optional language code, see documenation of load().
319 - * @return Array: Loaded messages for storing in caches.
 291+ * Loads all or main part of cacheable messages from the database
320292 */
321 - function loadFromDB( $code = false ) {
 293+ function loadFromDB() {
 294+ global $wgMaxMsgCacheEntrySize;
 295+
322296 wfProfileIn( __METHOD__ );
323 - global $wgMaxMsgCacheEntrySize, $wgContLanguageCode;
324297 $dbr = wfGetDB( DB_SLAVE );
325 - $cache = array();
 298+ $this->mCache = array();
326299
327 - # Common conditions
328 - $conds = array(
329 - 'page_is_redirect' => 0,
330 - 'page_namespace' => NS_MEDIAWIKI,
331 - );
332 -
333 - if ( $code ) {
334 - # Should $code be escaped?
335 - # Is this fast enough. Should not matter if the filtering is done in the
336 - # database or in code.
337 - if ( $code !== $wgContLanguageCode ) {
338 - # Messages for particular language
339 - $conds[] = "page_title like '%%/$code'";
340 - } else {
341 - # Effectively disallows use of '/' character in NS_MEDIAWIKI for uses
342 - # other than language code.
343 - $conds[] = "page_title not like '%%/%%'";
344 - }
345 - }
346 -
347 - # Conditions to fetch oversized pages to ignore them
348 - $bigConds = $conds;
349 - $bigConds[] = 'page_len > ' . intval( $wgMaxMsgCacheEntrySize );
350 -
351300 # Load titles for all oversized pages in the MediaWiki namespace
352 - $res = $dbr->select( 'page', 'page_title', $bigConds, __METHOD__ );
 301+ $res = $dbr->select( 'page', 'page_title',
 302+ array(
 303+ 'page_len > ' . intval( $wgMaxMsgCacheEntrySize ),
 304+ 'page_is_redirect' => 0,
 305+ 'page_namespace' => NS_MEDIAWIKI,
 306+ ),
 307+ __METHOD__ );
353308 while ( $row = $dbr->fetchObject( $res ) ) {
354 - $cache[$row->page_title] = '!TOO BIG';
 309+ $this->mCache[$row->page_title] = '!TOO BIG';
355310 }
356311 $dbr->freeResult( $res );
357312
358 - # Conditions to load the remaining pages with their contents
359 - $smallConds = $conds;
360 - $smallConds[] = 'page_latest=rev_id';
361 - $smallConds[] = 'rev_text_id=old_id';
362 - $smallConds[] = 'page_len <= ' . intval( $wgMaxMsgCacheEntrySize );
363 -
 313+ # Load text for the remaining pages
364314 $res = $dbr->select( array( 'page', 'revision', 'text' ),
365315 array( 'page_title', 'old_text', 'old_flags' ),
366 - $smallConds, __METHOD__ );
 316+ array(
 317+ 'page_is_redirect' => 0,
 318+ 'page_namespace' => NS_MEDIAWIKI,
 319+ 'page_latest=rev_id',
 320+ 'rev_text_id=old_id',
 321+ 'page_len <= ' . intval( $wgMaxMsgCacheEntrySize ) ),
 322+ __METHOD__ );
367323
368324 for ( $row = $dbr->fetchObject( $res ); $row; $row = $dbr->fetchObject( $res ) ) {
369 - $cache[$row->page_title] = ' ' . Revision::getRevisionText( $row );
 325+ $this->mCache[$row->page_title] = ' ' . Revision::getRevisionText( $row );
370326 }
 327+ $this->mCache['VERSION'] = MSG_CACHE_VERSION;
371328 $dbr->freeResult( $res );
372 -
373 - $cache['VERSION'] = MSG_CACHE_VERSION;
374329 wfProfileOut( __METHOD__ );
375 - return $cache;
376330 }
377331
378 - /**
379 - * Updates cache as necessary when message page is changed
380 - *
381 - * @param $title String: name of the page changed.
382 - * @param $text Mixed: new contents of the page.
383 - */
384 - public function replace( $title, $text ) {
385 - global $wgMaxMsgCacheEntrySize, $wgPerLanguageCaching;
 332+ function replace( $title, $text ) {
 333+ global $wgLocalMessageCache, $wgLocalMessageCacheSerialized, $parserMemc;
 334+ global $wgMaxMsgCacheEntrySize;
386335
387 - list( $message, $code ) = $this->figureMessage( $title );
388 -
389 - # TODO: Should we define the sidebar key name somewhere?
390 - $sidebarKey = wfMemcKeyLang( 'sidebar' , $code );
391 -
392 - # Load only messages for affected language, if possible
393 - if ( !$wgPerLanguageCaching ) $code = false;
394 - $cacheKey = wfMemcKeyLang( $this->mMemcKey, $code );
395 -
396336 wfProfileIn( __METHOD__ );
397 - $this->lock($cacheKey);
398 -
399 - $cache = $this->mMemc->get( $cacheKey );
400 - if ( is_array( $cache ) ) {
 337+ $this->lock();
 338+ $this->load();
 339+ if ( is_array( $this->mCache ) ) {
401340 if ( $text === false ) {
402341 # Article was deleted
403342 unset( $this->mCache[$title] );
404343 $this->mMemc->delete( "$this->mMemcKey:{$title}" );
405344 } elseif ( strlen( $text ) > $wgMaxMsgCacheEntrySize ) {
406 - $cache[$title] = $this->mCache[$title] = '!TOO BIG';
 345+ $this->mCache[$title] = '!TOO BIG';
407346 $this->mMemc->set( "$this->mMemcKey:{$title}", ' '.$text, $this->mExpiry );
408347 } else {
409 - $cache[$title] = $this->mCache[$title] = ' ' . $text;
 348+ $this->mCache[$title] = ' ' . $text;
410349 $this->mMemc->delete( "$this->mMemcKey:{$title}" );
411350 }
 351+ $this->mMemc->set( $this->mMemcKey, $this->mCache, $this->mExpiry );
412352
413 - # Update per-request cache
414 - $success = $this->setCache( $cache, $cacheKey );
415 - if ( $success ) {
416 - # And then all caches
417 - $this->saveToCaches( $cache, $cacheKey, true, $code );
 353+ # Save to local cache
 354+ if ( $wgLocalMessageCache !== false ) {
 355+ $serialized = serialize( $this->mCache );
 356+ $hash = md5( $serialized );
 357+ $this->mMemc->set( "{$this->mMemcKey}-hash", $hash, $this->mExpiry );
 358+ if ($wgLocalMessageCacheSerialized) {
 359+ $this->saveToLocal( $serialized,$hash );
 360+ } else {
 361+ $this->saveToScript( $this->mCache, $hash );
 362+ }
418363 }
419364 }
420 - $this->unlock($cacheKey);
421 -
422 - // Also delete cached sidebar... just in case it is affected
423 - global $parserMemc;
424 - $parserMemc->delete( $sidebarKey );
 365+ $this->unlock();
 366+ $parserMemc->delete(wfMemcKey('sidebar'));
425367 wfProfileOut( __METHOD__ );
426368 }
427369
428370 /**
429 - * Shortcut to update caches.
430 - *
431 - * @param $cache Array: cached messages with a version.
432 - * @param $cacheKey String: Identifier for the cache.
433 - * @param $memc Bool: Wether to update or not memcache.
434 - * @param $code String: Language code.
435 - * @return False on somekind of error.
436 - */
437 - protected function saveToCaches( $cache, $cacheKey, $memc = true, $code = false ) {
438 - wfProfileIn( __METHOD__ );
439 - global $wgLocalMessageCache, $wgLocalMessageCacheSerialized;
440 -
441 - $success = $this->mMemc->add( $cacheKey.'-status', "loading", MSG_LOAD_TIMEOUT );
442 - if ( !$success ) return true; # Other process should be updating them now
443 -
444 - $i = 0;
445 - if ( $memc ) {
446 - # Save in memcached
447 - # Keep trying if it fails, this is kind of important
448 -
449 - for ($i=0; $i<20 &&
450 - !$this->mMemc->set( $cacheKey, $cache, $this->mExpiry );
451 - $i++ ) {
452 - usleep(mt_rand(500000,1500000));
453 - }
454 - }
455 -
456 - # Save to local cache
457 - if ( $wgLocalMessageCache !== false ) {
458 - $serialized = serialize( $cache );
459 - $hash = md5( $serialized );
460 - $this->mMemc->set( "$cacheKey-hash", $hash, $this->mExpiry );
461 - if ($wgLocalMessageCacheSerialized) {
462 - $this->saveToLocal( $serialized, $hash, $code );
463 - } else {
464 - $this->saveToScript( $cache, $hash, $code );
465 - }
466 - }
467 -
468 - if ( $i == 20 ) {
469 - $this->mMemc->set( $cacheKey.'-status', 'error', 60*5 );
470 - wfDebug( "MemCached set error in MessageCache: restart memcached server!\n" );
471 - $success = false;
472 - } else {
473 - $this->mMemc->delete( $cacheKey.'-status' );
474 - $success = true;
475 - }
476 - wfProfileOut( __METHOD__ );
477 - return $success;
478 - }
479 -
480 - /**
481371 * Returns success
482372 * Represents a write lock on the messages key
483373 */
484 - function lock($key) {
 374+ function lock() {
485375 if ( !$this->mUseCache ) {
486376 return true;
487377 }
488378
489 - $lockKey = $key . 'lock';
 379+ $lockKey = $this->mMemcKey . 'lock';
490380 for ($i=0; $i < MSG_WAIT_TIMEOUT && !$this->mMemc->add( $lockKey, 1, MSG_LOCK_TIMEOUT ); $i++ ) {
491381 sleep(1);
492382 }
@@ -493,12 +383,12 @@
494384 return $i >= MSG_WAIT_TIMEOUT;
495385 }
496386
497 - function unlock($key) {
 387+ function unlock() {
498388 if ( !$this->mUseCache ) {
499389 return;
500390 }
501391
502 - $lockKey = $key . 'lock';
 392+ $lockKey = $this->mMemcKey . 'lock';
503393 $this->mMemc->delete( $lockKey );
504394 }
505395
@@ -548,6 +438,10 @@
549439 if( !$this->mInitialised ) {
550440 return '&lt;' . htmlspecialchars($key) . '&gt;';
551441 }
 442+ # If cache initialization was deferred, start it now.
 443+ if( $this->mDeferred && !$this->mDisable && $useDB ) {
 444+ $this->load();
 445+ }
552446
553447 $message = false;
554448
@@ -561,11 +455,10 @@
562456 if(!$isFullKey && ($langcode != $wgContLanguageCode) ) {
563457 $title .= '/' . $langcode;
564458 }
565 - $message = $this->getMsgFromNamespace( $title, $langcode );
 459+ $message = $this->getMsgFromNamespace( $title );
566460 }
567 -
568461 # Try the extension array
569 - if ( $message === false && isset( $this->mExtensionMessages[$langcode][$lckey] ) ) {
 462+ if( $message === false && isset( $this->mExtensionMessages[$langcode][$lckey] ) ) {
570463 $message = $this->mExtensionMessages[$langcode][$lckey];
571464 }
572465 if ( $message === false && isset( $this->mExtensionMessages['en'][$lckey] ) ) {
@@ -573,8 +466,11 @@
574467 }
575468
576469 # Try the array in the language object
577 - if ( $message === false ) {
 470+ if( $message === false ) {
 471+ #wfDebug( "Trying language object for message $key\n" );
 472+ wfSuppressWarnings();
578473 $message = $lang->getMessage( $lckey );
 474+ wfRestoreWarnings();
579475 if ( is_null( $message ) ) {
580476 $message = false;
581477 }
@@ -602,7 +498,7 @@
603499 if( ($message === false || $message === '-' ) &&
604500 !$this->mDisable && $useDB &&
605501 !$isFullKey && ($langcode != $wgContLanguageCode) ) {
606 - $message = $this->getMsgFromNamespace( $wgContLang->ucfirst( $lckey ), $wgContLanguageCode );
 502+ $message = $this->getMsgFromNamespace( $wgContLang->ucfirst( $lckey ) );
607503 }
608504
609505 # Final fallback
@@ -616,26 +512,19 @@
617513 * Get a message from the MediaWiki namespace, with caching. The key must
618514 * first be converted to two-part lang/msg form if necessary.
619515 *
620 - * @param $title String: Message cache key with initial uppercase letter.
621 - * @param $code String: code denoting the language to try.
 516+ * @param string $title Message cache key with initial uppercase letter
622517 */
623 - function getMsgFromNamespace( $title, $code ) {
 518+ function getMsgFromNamespace( $title ) {
624519 $message = false;
625520 $type = false;
626521
627 - if ( $this->mUseCache ) {
628 - if ( !isset($this->mCache[$title]) ) {
629 - # Delay loading as far as possible, and only load messages for requested
630 - # language.
631 - $this->load( $code );
 522+ # Try the cache
 523+ if( $this->mUseCache && isset( $this->mCache[$title] ) ) {
 524+ $entry = $this->mCache[$title];
 525+ $type = substr( $entry, 0, 1 );
 526+ if ( $type == ' ' ) {
 527+ return substr( $entry, 1 );
632528 }
633 - if (isset( $this->mCache[$title] ) ) {
634 - $entry = $this->mCache[$title];
635 - $type = substr( $entry, 0, 1 );
636 - if ( $type == ' ' ) {
637 - return substr( $entry, 1 );
638 - }
639 - }
640529 }
641530
642531 # Call message hooks, in case they are defined
@@ -658,7 +547,6 @@
659548 $type = substr( $entry, 0, 1 );
660549
661550 if ( $type == ' ' ) {
662 - # Ok!
663551 $message = substr( $entry, 1 );
664552 $this->mCache[$title] = $entry;
665553 return $message;
@@ -686,6 +574,7 @@
687575 $this->mMemc->set( $memcKey, '!NONEXISTENT', $this->mExpiry );
688576 $this->mCache[$title] = false;
689577 }
 578+
690579 return $message;
691580 }
692581
@@ -709,7 +598,7 @@
710599
711600 function disable() { $this->mDisable = true; }
712601 function enable() { $this->mDisable = false; }
713 -
 602+
714603 /** @deprecated */
715604 function disableTransform(){
716605 wfDeprecated( __METHOD__ );
@@ -872,15 +761,4 @@
873762 $this->addMessages( $mergedMessages, $langcode );
874763 }
875764
876 - public function figureMessage( $key ) {
877 - global $wgContLanguageCode;
878 - $pieces = explode('/', $key, 2);
879 -
880 - $key = $pieces[0];
881 -
882 - # Language the user is translating to
883 - $langCode = isset($pieces[1]) ? $pieces[1] : $wgContLanguageCode;
884 - return array( $key, $langCode );
885 - }
886 -
887765 }
Index: trunk/phase3/includes/DefaultSettings.php
@@ -721,13 +721,6 @@
722722 $wgLocalMessageCacheSerialized = true;
723723
724724 /**
725 - * Cache messages in MesssageCache per language, instead of all them together.
726 - * Enable this if you have thousands of messages in MediaWiki namespace in many
727 - * different languages.
728 - */
729 -$wgPerLanguageCaching = false;
730 -
731 -/**
732725 * Directory for compiled constant message array databases
733726 * WARNING: turning anything on will just break things, aaaaaah!!!!
734727 */
Index: trunk/phase3/includes/Skin.php
@@ -1650,18 +1650,24 @@
16511651 * Build an array that represents the sidebar(s), the navigation bar among them
16521652 *
16531653 * @return array
 1654+ * @private
16541655 */
16551656 function buildSidebar() {
16561657 global $parserMemc, $wgEnableSidebarCache, $wgSidebarCacheExpiry;
1657 - global $wgLang;
1658 - wfProfileIn( __METHOD__ );
 1658+ global $wgLang, $wgContLang;
16591659
1660 - $key = wfMemcKeyLang( wfMemcKey( 'sidebar' ), $wgLang->getCode() );
 1660+ $fname = 'SkinTemplate::buildSidebar';
16611661
1662 - if ( $wgEnableSidebarCache ) {
 1662+ wfProfileIn( $fname );
 1663+
 1664+ $key = wfMemcKey( 'sidebar' );
 1665+ $cacheSidebar = $wgEnableSidebarCache &&
 1666+ ($wgLang->getCode() == $wgContLang->getCode());
 1667+
 1668+ if ($cacheSidebar) {
16631669 $cachedsidebar = $parserMemc->get( $key );
1664 - if ( $cachedsidebar ) {
1665 - wfProfileOut( __METHOD__ );
 1670+ if ($cachedsidebar!="") {
 1671+ wfProfileOut($fname);
16661672 return $cachedsidebar;
16671673 }
16681674 }
@@ -1677,7 +1683,7 @@
16781684 $heading = $line;
16791685 } else {
16801686 if (strpos($line, '|') !== false) { // sanity check
1681 - $line = array_map('trim', explode( '|' , trim($line, '* '), 2 ) );
 1687+ $line = explode( '|' , trim($line, '* '), 2 );
16821688 $link = wfMsgForContent( $line[0] );
16831689 if ($link == '-')
16841690 continue;
@@ -1707,9 +1713,9 @@
17081714 } else { continue; }
17091715 }
17101716 }
1711 - if ( $wgEnableSidebarCache ) $parserMemc->set( $key, $bar, $wgSidebarCacheExpiry );
1712 - wfProfileOut( __METHOD__ );
 1717+ if ($cacheSidebar)
 1718+ $parserMemc->set( $key, $bar, $wgSidebarCacheExpiry );
 1719+ wfProfileOut( $fname );
17131720 return $bar;
17141721 }
17151722 }
1716 -
Index: trunk/phase3/languages/Language.php
@@ -2093,9 +2093,8 @@
20942094 }
20952095
20962096 # Try the global cache
2097 -
2098 - $memcKey = wfMemcKeyLang( wfMemcKey('localisation'), $code );
2099 - $fbMemcKey = wfMemcKeyLang( wfMemcKey('fallback'), $cache['fallback'] );
 2097+ $memcKey = wfMemcKey('localisation', $code );
 2098+ $fbMemcKey = wfMemcKey('fallback', $cache['fallback'] );
21002099 $cache = $wgMemc->get( $memcKey );
21012100 if ( $cache ) {
21022101 if ( self::isLocalisationOutOfDate( $cache ) ) {
@@ -2233,7 +2232,7 @@
22342233
22352234 // Try memcache
22362235 global $wgMemc;
2237 - $memcKey = wfMemcKeyLang( wfMemcKey('fallback'), $code );
 2236+ $memcKey = wfMemcKey( 'fallback', $code );
22382237 $fbcode = $wgMemc->get( $memcKey );
22392238
22402239 if ( is_string($fbcode) ) {
Index: trunk/phase3/RELEASE-NOTES
@@ -47,8 +47,6 @@
4848 image page already exists
4949 * $wgMaximumMovedPages restricts the number of pages that can be moved at once
5050 (default 100) with the new subpage-move functionality of Special:Movepage
51 -* New option $wgPerLanguageCaching, for wikies with many translated system
52 - messages in MediaWiki namespace
5351
5452 === New features in 1.13 ===
5553
@@ -126,7 +124,6 @@
127125 * (bug 13232) importScript(), importStylesheet() funcs available to custom JS
128126 * (bug 13095) Search by first letters or digits in [[Special:Categories]]
129127 * Users moving a page can now move all subpages automatically as well
130 -* Sidebar is now cached for all languages
131128 * (bug 14259) Localisation message for upload button on Special:Import is now
132129 'import-upload' instead of 'upload'
133130 * Add information about user group membership to Special:Preferences

Past revisions this follows-up on

RevisionCommit summaryAuthorDate
r35262* New option $wgPerLanguageCaching, for wikies with many translated system me...nikerabbit22:14, 23 May 2008
r35264* And the variable definition for my previous commitnikerabbit22:17, 23 May 2008
r35478E_NOTICE: undefined variable $code in MessageCache::saveToCaches()ialex12:17, 28 May 2008

Status & tagging log