From: Tim Starling Date: Sun, 1 Jun 2008 03:27:48 +0000 (+0000) Subject: Revert r35478, r35264, r35262: $wgPerLanguageCaching feature. Bug found with $wgPerLa... X-Git-Tag: 1.31.0-rc.0~47265 X-Git-Url: http://git.cyclocoop.org/%22.%28%24lien.?a=commitdiff_plain;h=f3bffd7ca9a05c4090f2d4a46f4f1c20ecf5dc4d;p=lhc%2Fweb%2Fwiklou.git Revert r35478, r35264, r35262: $wgPerLanguageCaching feature. Bug found with $wgPerLanguageCaching=false. Nikerabbit, please see me for a detailed code review. --- diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 3f1512d7b7..8fee2e04f9 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -47,8 +47,6 @@ it from source control: http://www.mediawiki.org/wiki/Download_from_SVN image page already exists * $wgMaximumMovedPages restricts the number of pages that can be moved at once (default 100) with the new subpage-move functionality of Special:Movepage -* New option $wgPerLanguageCaching, for wikies with many translated system - messages in MediaWiki namespace === New features in 1.13 === @@ -126,7 +124,6 @@ it from source control: http://www.mediawiki.org/wiki/Download_from_SVN * (bug 13232) importScript(), importStylesheet() funcs available to custom JS * (bug 13095) Search by first letters or digits in [[Special:Categories]] * Users moving a page can now move all subpages automatically as well -* Sidebar is now cached for all languages * (bug 14259) Localisation message for upload button on Special:Import is now 'import-upload' instead of 'upload' * Add information about user group membership to Special:Preferences diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index 61d6d7abf1..6d24f63f0d 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -720,13 +720,6 @@ $wgLocalMessageCache = false; */ $wgLocalMessageCacheSerialized = true; -/** - * Cache messages in MesssageCache per language, instead of all them together. - * Enable this if you have thousands of messages in MediaWiki namespace in many - * different languages. - */ -$wgPerLanguageCaching = false; - /** * Directory for compiled constant message array databases * WARNING: turning anything on will just break things, aaaaaah!!!! diff --git a/includes/GlobalFunctions.php b/includes/GlobalFunctions.php index 8c05555656..1266bec2dc 100644 --- a/includes/GlobalFunctions.php +++ b/includes/GlobalFunctions.php @@ -2342,14 +2342,6 @@ function wfMemcKey( /*... */ ) { return $key; } -function wfMemcKeyLang( $key, $code ) { - if ( !is_string($code) ) { - return $key; - } else { - return $key . ';L:' . $code; - } -} - /** * Get a cache key for a foreign DB */ diff --git a/includes/MessageCache.php b/includes/MessageCache.php index 5b24aaf527..9bd33214f0 100644 --- a/includes/MessageCache.php +++ b/includes/MessageCache.php @@ -22,7 +22,8 @@ class MessageCache { var $mMemcKey, $mKeys, $mParserOptions, $mParser; var $mExtensionMessages = array(); var $mInitialised = false; - var $mAllMessagesLoaded; // Extension messages + var $mDeferred = true; + var $mAllMessagesLoaded; function __construct( &$memCached, $useDB, $expiry, $memcPrefix) { wfProfileIn( __METHOD__ ); @@ -37,14 +38,15 @@ class MessageCache { $this->mInitialised = true; $this->mParser = null; + # When we first get asked for a message, + # then we'll fill up the cache. If we + # can return a cache hit, this saves + # some extra milliseconds + $this->mDeferred = true; + wfProfileOut( __METHOD__ ); } - - /** - * ParserOptions is lazy initialised. - * Access should probably be protected. - */ function getParserOptions() { if ( !$this->mParserOptions ) { $this->mParserOptions = new ParserOptions; @@ -53,26 +55,22 @@ class MessageCache { } /** - * Try to load the cache from a local file. - * Actual format of the file depends on the $wgLocalMessageCacheSerialized - * setting. - * - * @param $hash String: the hash of contents, to check validity. - * @param $code Mixed: Optional language code, see documenation of load(). - * @return false on failure. + * Try to load the cache from a local file */ - function loadFromLocal( $hash, $code ) { + function loadFromLocal( $hash ) { global $wgLocalMessageCache, $wgLocalMessageCacheSerialized; + if ( $wgLocalMessageCache === false ) { + return; + } + $filename = "$wgLocalMessageCache/messages-" . wfWikiID(); - if ( $code ) $filename .= '-' . $code; - # Check file existence wfSuppressWarnings(); $file = fopen( $filename, 'r' ); wfRestoreWarnings(); if ( !$file ) { - return false; // No cache file + return; } if ( $wgLocalMessageCacheSerialized ) { @@ -84,35 +82,35 @@ class MessageCache { while ( !feof( $file ) ) { $serialized .= fread( $file, 100000 ); } - fclose( $file ); - return $this->setCache( unserialize( $serialized ) ); - } else { - fclose( $file ); - return false; // Wrong hash + $this->setCache( unserialize( $serialized ) ); } + fclose( $file ); } else { $localHash=substr(fread($file,40),8); fclose($file); if ($hash!=$localHash) { - return false; // Wrong hash + return; } - require( $filename ); - return $this->setCache( $this->mCache ); + require("$wgLocalMessageCache/messages-" . wfWikiID()); + $this->setCache( $this->mCache); } } /** * Save the cache to a local file */ - function saveToLocal( $serialized, $hash, $code ) { - global $wgLocalMessageCache; + function saveToLocal( $serialized, $hash ) { + global $wgLocalMessageCache, $wgLocalMessageCacheSerialized; - $filename = "$wgLocalMessageCache/messages-" . wfWikiID(); - if ( $code ) $filename .= '-' . $code; + if ( $wgLocalMessageCache === false ) { + return; + } - # Make sure the directories exist - $this->createCacheDir( $wgLocalMessageCache ); + $filename = "$wgLocalMessageCache/messages-" . wfWikiID(); + $oldUmask = umask( 0 ); + wfMkdirParents( $wgLocalMessageCache, 0777 ); + umask( $oldUmask ); $file = fopen( $filename, 'w' ); if ( !$file ) { @@ -125,39 +123,32 @@ class MessageCache { @chmod( $filename, 0666 ); } - function saveToScript( $array, $hash, $code ) { + function loadFromScript( $hash ) { + wfDeprecated( __METHOD__ ); + $this->loadFromLocal( $hash ); + } + + function saveToScript($array, $hash) { global $wgLocalMessageCache; + if ( $wgLocalMessageCache === false ) { + return; + } $filename = "$wgLocalMessageCache/messages-" . wfWikiID(); - if ( $code ) $filename .= '-' . $code; - $tempFilename = $filename . '.tmp'; - - # Make sure the directories exist - $this->createCacheDir( $wgLocalMessageCache ); - - $file = fopen( $tempFilename, 'w'); + $oldUmask = umask( 0 ); + wfMkdirParents( $wgLocalMessageCache, 0777 ); + umask( $oldUmask ); + $file = fopen( $filename.'.tmp', 'w'); fwrite($file,"mCache = array("); foreach ($array as $key => $message) { - $key = $this->escapeForScript($key); - $messages = $this->escapeForScript($message); - fwrite($file, "'$key' => '$message',\n"); + fwrite($file, "'". $this->escapeForScript($key). + "' => '" . $this->escapeForScript($message). + "',\n"); } - fwrite($file,");\n?>"); fclose($file); - rename($tempFilename, $filename); - } - - /** - * Creates directory with correct permissions. - * - * @param $path String: path that is created if it does not exist. - */ - protected function createCacheDir( $path ) { - $oldUmask = umask( 0 ); - wfMkdirParents( $path, 0777 ); - umask( $oldUmask ); + rename($filename.'.tmp',$filename); } function escapeForScript($string) { @@ -171,321 +162,220 @@ class MessageCache { */ function setCache( $cache ) { if ( isset( $cache['VERSION'] ) && $cache['VERSION'] == MSG_CACHE_VERSION ) { - if ( $this->mCache ) { - $this->mCache = $cache + $this->mCache; - } else { - $this->mCache = $cache; - } - return true; + $this->mCache = $cache; } else { - return false; + $this->mCache = false; } } /** - * Loads messages from caches or from database in this order: - * (1) local message cache (if $wgLocalMessageCache is enabled) - * (2) memcached - * (3) from the database. - * - * When succesfully loading from (2) or (3), all higher level caches are - * updated for the newest version. - * - * Nothing is loaded if member variable mDisabled is true, either manually - * set by calling code or if message loading fails (is this possible?). - * - * Returns true if cache is already populated or it was succesfully populated, - * or false if populating empty cache fails. Also returns true if MessageCache - * is disabled. - * - * @param $code Mixed: if evaluates to false, messages for all languages is - * loaded and stored in cache as one object. If code is provided - * and $wgPerLanguageCaching is true, messages are loaded per - * language and stored individually in caches 1 to 2. + * Loads messages either from memcached or the database, if not disabled + * On error, quietly switches to a fallback mode + * Returns false for a reportable error, true otherwise */ - function load( $code = false ) { - global $wgLocalMessageCache, $wgPerLanguageCaching; - - if ( !$this->mUseCache ) { - return true; - } - - # Keep track of loaded messages. Either array of loaded codes as keys, - # or just true if all languages are loaded. - static $loaded = false; - - if ( !$wgPerLanguageCaching ) { - // Disable language separation for normal use case - $code = false; - } elseif( !is_string( $code ) ) { - # This isn't really nice, so at least make a note about it - wfDebug( __METHOD__ . " called without providing a language code\n" ); - } - - # Don't do double loading... - if ( $loaded === true || ($code && isset($loaded[$code])) ) return true; - - # Adjust cache key if we are handling only single language - $cacheKey = wfMemcKeyLang( $this->mMemcKey, $code ); + function load() { + global $wgLocalMessageCache, $wgLocalMessageCacheSerialized; - # 8 lines of code just to say (once) that message cache is disabled if ( $this->mDisable ) { static $shownDisabled = false; if ( !$shownDisabled ) { - wfDebug( __METHOD__ . ": disabled\n" ); + wfDebug( "MessageCache::load(): disabled\n" ); $shownDisabled = true; } return true; } + if ( !$this->mUseCache ) { + $this->mDeferred = false; + return true; + } - # Loading code starts - wfProfileIn( __METHOD__ ); - $success = false; # Keep track of success - $where = array(); # Debug info, delayed to avoid spamming debug log too much + $fname = 'MessageCache::load'; + wfProfileIn( $fname ); + $success = true; - # (1) local cache - # Hash of the contents is stored in memcache, to detect if local cache goes - # out of date (due to update in other thread?) + $this->mCache = false; + + # Try local cache if ( $wgLocalMessageCache !== false ) { - wfProfileIn( __METHOD__ . '-fromlocal' ); - $hash = $this->mMemc->get( "$cacheKey-hash" ); + wfProfileIn( $fname.'-fromlocal' ); + $hash = $this->mMemc->get( "{$this->mMemcKey}-hash" ); if ( $hash ) { - $success = $this->loadFromLocal( $hash, $code ); - if ( $success ) $where[] = 'got from local cache'; + $this->loadFromLocal( $hash ); + if ( $this->mCache ) { + wfDebug( "MessageCache::load(): got from local cache\n" ); + } } - wfProfileOut( __METHOD__ . '-fromlocal' ); + wfProfileOut( $fname.'-fromlocal' ); } - # (2) memcache - # Fails if nothing in cache, or in the wrong version. - if ( !$success ) { - wfProfileIn( __METHOD__ . '-fromcache' ); - $cache = $this->mMemc->get( $cacheKey ); - $success = $this->setCache( $cache ); - if ( $success ) { - $where[] = 'got from global cache'; - $this->saveToCaches( $cache, $cacheKey, false, $code ); + # Try memcached + if ( !$this->mCache ) { + wfProfileIn( $fname.'-fromcache' ); + $this->setCache( $this->mMemc->get( $this->mMemcKey ) ); + if ( $this->mCache ) { + wfDebug( "MessageCache::load(): got from global cache\n" ); + # Save to local cache + if ( $wgLocalMessageCache !== false ) { + $serialized = serialize( $this->mCache ); + if ( !$hash ) { + $hash = md5( $serialized ); + $this->mMemc->set( "{$this->mMemcKey}-hash", $hash, $this->mExpiry ); + } + if ($wgLocalMessageCacheSerialized) { + $this->saveToLocal( $serialized,$hash ); + } else { + $this->saveToScript( $this->mCache, $hash ); + } + } } - wfProfileOut( __METHOD__ . '-fromcache' ); - } - - - # (3) - # Nothing in caches... so we need create one and store it in caches - if ( !$success ) { - $where[] = 'cache is empty'; - $this->lock($cacheKey); - wfProfileIn( __METHOD__ . '-load' ); - $where[] = 'loading from database'; - # We want to store messages of particular language here, not everything - # from mCache. - $cache = $this->loadFromDB( $code ); - $success = $this->setCache( $cache ); - wfProfileOut( __METHOD__ . '-load' ); + wfProfileOut( $fname.'-fromcache' ); + } + + + # If there's nothing in memcached, load all the messages from the database + if ( !$this->mCache ) { + wfDebug( "MessageCache::load(): cache is empty\n" ); + $this->lock(); + # Other threads don't need to load the messages if another thread is doing it. + $success = $this->mMemc->add( $this->mMemcKey.'-status', "loading", MSG_LOAD_TIMEOUT ); if ( $success ) { - $this->saveToCaches( $cache, $cacheKey, true, $code ); + wfProfileIn( $fname.'-load' ); + wfDebug( "MessageCache::load(): loading all messages from DB\n" ); + $this->loadFromDB(); + wfProfileOut( $fname.'-load' ); + + # Save in memcached + # Keep trying if it fails, this is kind of important + wfProfileIn( $fname.'-save' ); + for ($i=0; $i<20 && + !$this->mMemc->set( $this->mMemcKey, $this->mCache, $this->mExpiry ); + $i++ ) { + usleep(mt_rand(500000,1500000)); + } + + # Save to local cache + if ( $wgLocalMessageCache !== false ) { + $serialized = serialize( $this->mCache ); + $hash = md5( $serialized ); + $this->mMemc->set( "{$this->mMemcKey}-hash", $hash, $this->mExpiry ); + if ($wgLocalMessageCacheSerialized) { + $this->saveToLocal( $serialized,$hash ); + } else { + $this->saveToScript( $this->mCache, $hash ); + } + } + + wfProfileOut( $fname.'-save' ); + if ( $i == 20 ) { + $this->mMemc->set( $this->mMemcKey.'-status', 'error', 60*5 ); + wfDebug( "MemCached set error in MessageCache: restart memcached server!\n" ); + } else { + $this->mMemc->delete( $this->mMemcKey.'-status' ); + } } - $this->unlock($cacheKey); + $this->unlock(); } - if ( !$success ) { - # Bad luck... this should not happen - $where[] = 'loading FAILED - cache is disabled'; - $info = implode( ', ', $where ); - wfDebug( __METHOD__ . ": Loading $code... $info\n" ); + if ( !is_array( $this->mCache ) ) { + wfDebug( "MessageCache::load(): unable to load cache, disabled\n" ); $this->mDisable = true; $this->mCache = false; - } else { - # All good, just record the success - $info = implode( ', ', $where ); - wfDebug( __METHOD__ . ": Loading $code... $info\n" ); - if ( $code ) { - $loaded[$code] = true; - } else { - $loaded = true; - } } - wfProfileOut( __METHOD__ ); + wfProfileOut( $fname ); + $this->mDeferred = false; return $success; } /** - * Loads cacheable messages from the database. Messages bigger than - * $wgMaxMsgCacheEntrySize are assigned a special value, and are loaded - * on-demand from the database later. - * - * @param $code Optional language code, see documenation of load(). - * @return Array: Loaded messages for storing in caches. + * Loads all or main part of cacheable messages from the database */ - function loadFromDB( $code = false ) { + function loadFromDB() { + global $wgMaxMsgCacheEntrySize; + wfProfileIn( __METHOD__ ); - global $wgMaxMsgCacheEntrySize, $wgContLanguageCode; $dbr = wfGetDB( DB_SLAVE ); - $cache = array(); - - # Common conditions - $conds = array( - 'page_is_redirect' => 0, - 'page_namespace' => NS_MEDIAWIKI, - ); - - if ( $code ) { - # Should $code be escaped? - # Is this fast enough. Should not matter if the filtering is done in the - # database or in code. - if ( $code !== $wgContLanguageCode ) { - # Messages for particular language - $conds[] = "page_title like '%%/$code'"; - } else { - # Effectively disallows use of '/' character in NS_MEDIAWIKI for uses - # other than language code. - $conds[] = "page_title not like '%%/%%'"; - } - } - - # Conditions to fetch oversized pages to ignore them - $bigConds = $conds; - $bigConds[] = 'page_len > ' . intval( $wgMaxMsgCacheEntrySize ); + $this->mCache = array(); # Load titles for all oversized pages in the MediaWiki namespace - $res = $dbr->select( 'page', 'page_title', $bigConds, __METHOD__ ); + $res = $dbr->select( 'page', 'page_title', + array( + 'page_len > ' . intval( $wgMaxMsgCacheEntrySize ), + 'page_is_redirect' => 0, + 'page_namespace' => NS_MEDIAWIKI, + ), + __METHOD__ ); while ( $row = $dbr->fetchObject( $res ) ) { - $cache[$row->page_title] = '!TOO BIG'; + $this->mCache[$row->page_title] = '!TOO BIG'; } $dbr->freeResult( $res ); - # Conditions to load the remaining pages with their contents - $smallConds = $conds; - $smallConds[] = 'page_latest=rev_id'; - $smallConds[] = 'rev_text_id=old_id'; - $smallConds[] = 'page_len <= ' . intval( $wgMaxMsgCacheEntrySize ); - + # Load text for the remaining pages $res = $dbr->select( array( 'page', 'revision', 'text' ), array( 'page_title', 'old_text', 'old_flags' ), - $smallConds, __METHOD__ ); + array( + 'page_is_redirect' => 0, + 'page_namespace' => NS_MEDIAWIKI, + 'page_latest=rev_id', + 'rev_text_id=old_id', + 'page_len <= ' . intval( $wgMaxMsgCacheEntrySize ) ), + __METHOD__ ); for ( $row = $dbr->fetchObject( $res ); $row; $row = $dbr->fetchObject( $res ) ) { - $cache[$row->page_title] = ' ' . Revision::getRevisionText( $row ); + $this->mCache[$row->page_title] = ' ' . Revision::getRevisionText( $row ); } + $this->mCache['VERSION'] = MSG_CACHE_VERSION; $dbr->freeResult( $res ); - - $cache['VERSION'] = MSG_CACHE_VERSION; wfProfileOut( __METHOD__ ); - return $cache; } - /** - * Updates cache as necessary when message page is changed - * - * @param $title String: name of the page changed. - * @param $text Mixed: new contents of the page. - */ - public function replace( $title, $text ) { - global $wgMaxMsgCacheEntrySize, $wgPerLanguageCaching; - - list( $message, $code ) = $this->figureMessage( $title ); - - # TODO: Should we define the sidebar key name somewhere? - $sidebarKey = wfMemcKeyLang( 'sidebar' , $code ); - - # Load only messages for affected language, if possible - if ( !$wgPerLanguageCaching ) $code = false; - $cacheKey = wfMemcKeyLang( $this->mMemcKey, $code ); + function replace( $title, $text ) { + global $wgLocalMessageCache, $wgLocalMessageCacheSerialized, $parserMemc; + global $wgMaxMsgCacheEntrySize; wfProfileIn( __METHOD__ ); - $this->lock($cacheKey); - - $cache = $this->mMemc->get( $cacheKey ); - if ( is_array( $cache ) ) { + $this->lock(); + $this->load(); + if ( is_array( $this->mCache ) ) { if ( $text === false ) { # Article was deleted unset( $this->mCache[$title] ); $this->mMemc->delete( "$this->mMemcKey:{$title}" ); } elseif ( strlen( $text ) > $wgMaxMsgCacheEntrySize ) { - $cache[$title] = $this->mCache[$title] = '!TOO BIG'; + $this->mCache[$title] = '!TOO BIG'; $this->mMemc->set( "$this->mMemcKey:{$title}", ' '.$text, $this->mExpiry ); } else { - $cache[$title] = $this->mCache[$title] = ' ' . $text; + $this->mCache[$title] = ' ' . $text; $this->mMemc->delete( "$this->mMemcKey:{$title}" ); } - - # Update per-request cache - $success = $this->setCache( $cache, $cacheKey ); - if ( $success ) { - # And then all caches - $this->saveToCaches( $cache, $cacheKey, true, $code ); - } - } - $this->unlock($cacheKey); - - // Also delete cached sidebar... just in case it is affected - global $parserMemc; - $parserMemc->delete( $sidebarKey ); - wfProfileOut( __METHOD__ ); - } - - /** - * Shortcut to update caches. - * - * @param $cache Array: cached messages with a version. - * @param $cacheKey String: Identifier for the cache. - * @param $memc Bool: Wether to update or not memcache. - * @param $code String: Language code. - * @return False on somekind of error. - */ - protected function saveToCaches( $cache, $cacheKey, $memc = true, $code = false ) { - wfProfileIn( __METHOD__ ); - global $wgLocalMessageCache, $wgLocalMessageCacheSerialized; - - $success = $this->mMemc->add( $cacheKey.'-status', "loading", MSG_LOAD_TIMEOUT ); - if ( !$success ) return true; # Other process should be updating them now - - $i = 0; - if ( $memc ) { - # Save in memcached - # Keep trying if it fails, this is kind of important - - for ($i=0; $i<20 && - !$this->mMemc->set( $cacheKey, $cache, $this->mExpiry ); - $i++ ) { - usleep(mt_rand(500000,1500000)); - } - } - - # Save to local cache - if ( $wgLocalMessageCache !== false ) { - $serialized = serialize( $cache ); - $hash = md5( $serialized ); - $this->mMemc->set( "$cacheKey-hash", $hash, $this->mExpiry ); - if ($wgLocalMessageCacheSerialized) { - $this->saveToLocal( $serialized, $hash, $code ); - } else { - $this->saveToScript( $cache, $hash, $code ); + $this->mMemc->set( $this->mMemcKey, $this->mCache, $this->mExpiry ); + + # Save to local cache + if ( $wgLocalMessageCache !== false ) { + $serialized = serialize( $this->mCache ); + $hash = md5( $serialized ); + $this->mMemc->set( "{$this->mMemcKey}-hash", $hash, $this->mExpiry ); + if ($wgLocalMessageCacheSerialized) { + $this->saveToLocal( $serialized,$hash ); + } else { + $this->saveToScript( $this->mCache, $hash ); + } } } - - if ( $i == 20 ) { - $this->mMemc->set( $cacheKey.'-status', 'error', 60*5 ); - wfDebug( "MemCached set error in MessageCache: restart memcached server!\n" ); - $success = false; - } else { - $this->mMemc->delete( $cacheKey.'-status' ); - $success = true; - } + $this->unlock(); + $parserMemc->delete(wfMemcKey('sidebar')); wfProfileOut( __METHOD__ ); - return $success; } /** * Returns success * Represents a write lock on the messages key */ - function lock($key) { + function lock() { if ( !$this->mUseCache ) { return true; } - $lockKey = $key . 'lock'; + $lockKey = $this->mMemcKey . 'lock'; for ($i=0; $i < MSG_WAIT_TIMEOUT && !$this->mMemc->add( $lockKey, 1, MSG_LOCK_TIMEOUT ); $i++ ) { sleep(1); } @@ -493,12 +383,12 @@ class MessageCache { return $i >= MSG_WAIT_TIMEOUT; } - function unlock($key) { + function unlock() { if ( !$this->mUseCache ) { return; } - $lockKey = $key . 'lock'; + $lockKey = $this->mMemcKey . 'lock'; $this->mMemc->delete( $lockKey ); } @@ -548,6 +438,10 @@ class MessageCache { if( !$this->mInitialised ) { return '<' . htmlspecialchars($key) . '>'; } + # If cache initialization was deferred, start it now. + if( $this->mDeferred && !$this->mDisable && $useDB ) { + $this->load(); + } $message = false; @@ -561,11 +455,10 @@ class MessageCache { if(!$isFullKey && ($langcode != $wgContLanguageCode) ) { $title .= '/' . $langcode; } - $message = $this->getMsgFromNamespace( $title, $langcode ); + $message = $this->getMsgFromNamespace( $title ); } - # Try the extension array - if ( $message === false && isset( $this->mExtensionMessages[$langcode][$lckey] ) ) { + if( $message === false && isset( $this->mExtensionMessages[$langcode][$lckey] ) ) { $message = $this->mExtensionMessages[$langcode][$lckey]; } if ( $message === false && isset( $this->mExtensionMessages['en'][$lckey] ) ) { @@ -573,8 +466,11 @@ class MessageCache { } # Try the array in the language object - if ( $message === false ) { + if( $message === false ) { + #wfDebug( "Trying language object for message $key\n" ); + wfSuppressWarnings(); $message = $lang->getMessage( $lckey ); + wfRestoreWarnings(); if ( is_null( $message ) ) { $message = false; } @@ -602,7 +498,7 @@ class MessageCache { if( ($message === false || $message === '-' ) && !$this->mDisable && $useDB && !$isFullKey && ($langcode != $wgContLanguageCode) ) { - $message = $this->getMsgFromNamespace( $wgContLang->ucfirst( $lckey ), $wgContLanguageCode ); + $message = $this->getMsgFromNamespace( $wgContLang->ucfirst( $lckey ) ); } # Final fallback @@ -616,25 +512,18 @@ class MessageCache { * Get a message from the MediaWiki namespace, with caching. The key must * first be converted to two-part lang/msg form if necessary. * - * @param $title String: Message cache key with initial uppercase letter. - * @param $code String: code denoting the language to try. + * @param string $title Message cache key with initial uppercase letter */ - function getMsgFromNamespace( $title, $code ) { + function getMsgFromNamespace( $title ) { $message = false; $type = false; - if ( $this->mUseCache ) { - if ( !isset($this->mCache[$title]) ) { - # Delay loading as far as possible, and only load messages for requested - # language. - $this->load( $code ); - } - if (isset( $this->mCache[$title] ) ) { - $entry = $this->mCache[$title]; - $type = substr( $entry, 0, 1 ); - if ( $type == ' ' ) { - return substr( $entry, 1 ); - } + # Try the cache + if( $this->mUseCache && isset( $this->mCache[$title] ) ) { + $entry = $this->mCache[$title]; + $type = substr( $entry, 0, 1 ); + if ( $type == ' ' ) { + return substr( $entry, 1 ); } } @@ -658,7 +547,6 @@ class MessageCache { $type = substr( $entry, 0, 1 ); if ( $type == ' ' ) { - # Ok! $message = substr( $entry, 1 ); $this->mCache[$title] = $entry; return $message; @@ -686,6 +574,7 @@ class MessageCache { $this->mMemc->set( $memcKey, '!NONEXISTENT', $this->mExpiry ); $this->mCache[$title] = false; } + return $message; } @@ -709,7 +598,7 @@ class MessageCache { function disable() { $this->mDisable = true; } function enable() { $this->mDisable = false; } - + /** @deprecated */ function disableTransform(){ wfDeprecated( __METHOD__ ); @@ -872,15 +761,4 @@ class MessageCache { $this->addMessages( $mergedMessages, $langcode ); } - public function figureMessage( $key ) { - global $wgContLanguageCode; - $pieces = explode('/', $key, 2); - - $key = $pieces[0]; - - # Language the user is translating to - $langCode = isset($pieces[1]) ? $pieces[1] : $wgContLanguageCode; - return array( $key, $langCode ); - } - } diff --git a/includes/Skin.php b/includes/Skin.php index c5399e5f00..e2e9a3235a 100644 --- a/includes/Skin.php +++ b/includes/Skin.php @@ -1650,18 +1650,24 @@ END; * Build an array that represents the sidebar(s), the navigation bar among them * * @return array + * @private */ function buildSidebar() { global $parserMemc, $wgEnableSidebarCache, $wgSidebarCacheExpiry; - global $wgLang; - wfProfileIn( __METHOD__ ); + global $wgLang, $wgContLang; + + $fname = 'SkinTemplate::buildSidebar'; + + wfProfileIn( $fname ); - $key = wfMemcKeyLang( wfMemcKey( 'sidebar' ), $wgLang->getCode() ); + $key = wfMemcKey( 'sidebar' ); + $cacheSidebar = $wgEnableSidebarCache && + ($wgLang->getCode() == $wgContLang->getCode()); - if ( $wgEnableSidebarCache ) { + if ($cacheSidebar) { $cachedsidebar = $parserMemc->get( $key ); - if ( $cachedsidebar ) { - wfProfileOut( __METHOD__ ); + if ($cachedsidebar!="") { + wfProfileOut($fname); return $cachedsidebar; } } @@ -1677,7 +1683,7 @@ END; $heading = $line; } else { if (strpos($line, '|') !== false) { // sanity check - $line = array_map('trim', explode( '|' , trim($line, '* '), 2 ) ); + $line = explode( '|' , trim($line, '* '), 2 ); $link = wfMsgForContent( $line[0] ); if ($link == '-') continue; @@ -1707,9 +1713,9 @@ END; } else { continue; } } } - if ( $wgEnableSidebarCache ) $parserMemc->set( $key, $bar, $wgSidebarCacheExpiry ); - wfProfileOut( __METHOD__ ); + if ($cacheSidebar) + $parserMemc->set( $key, $bar, $wgSidebarCacheExpiry ); + wfProfileOut( $fname ); return $bar; } } - diff --git a/languages/Language.php b/languages/Language.php index 4a2b886d49..8288e80f0f 100644 --- a/languages/Language.php +++ b/languages/Language.php @@ -2093,9 +2093,8 @@ class Language { } # Try the global cache - - $memcKey = wfMemcKeyLang( wfMemcKey('localisation'), $code ); - $fbMemcKey = wfMemcKeyLang( wfMemcKey('fallback'), $cache['fallback'] ); + $memcKey = wfMemcKey('localisation', $code ); + $fbMemcKey = wfMemcKey('fallback', $cache['fallback'] ); $cache = $wgMemc->get( $memcKey ); if ( $cache ) { if ( self::isLocalisationOutOfDate( $cache ) ) { @@ -2233,7 +2232,7 @@ class Language { // Try memcache global $wgMemc; - $memcKey = wfMemcKeyLang( wfMemcKey('fallback'), $code ); + $memcKey = wfMemcKey( 'fallback', $code ); $fbcode = $wgMemc->get( $memcKey ); if ( is_string($fbcode) ) {