Merge "Revert "MessageCache invalidation improvements" (temporary)"
[lhc/web/wiklou.git] / includes / cache / MessageCache.php
index 62fab5f..0c2f9de 100644 (file)
@@ -20,6 +20,8 @@
  * @file
  * @ingroup Cache
  */
+use MediaWiki\MediaWikiServices;
+use Wikimedia\ScopedCallback;
 
 /**
  * MediaWiki message cache structure version.
@@ -142,21 +144,17 @@ class MessageCache {
         * @param bool $useDB
         * @param int $expiry Lifetime for cache. @see $mExpiry.
         */
-       function __construct( $memCached, $useDB, $expiry ) {
+       function __construct( BagOStuff $memCached, $useDB, $expiry ) {
                global $wgUseLocalMessageCache;
 
-               if ( !$memCached ) {
-                       $memCached = wfGetCache( CACHE_NONE );
-               }
-
                $this->mMemc = $memCached;
                $this->mDisable = !$useDB;
                $this->mExpiry = $expiry;
 
                if ( $wgUseLocalMessageCache ) {
-                       $this->localCache = ObjectCache::getLocalServerInstance( CACHE_NONE );
+                       $this->localCache = MediaWikiServices::getInstance()->getLocalServerObjectCache();
                } else {
-                       $this->localCache = wfGetCache( CACHE_NONE );
+                       $this->localCache = new EmptyBagOStuff();
                }
 
                $this->wanCache = ObjectCache::getMainWANInstance();
@@ -226,17 +224,14 @@ class MessageCache {
         * or false if populating empty cache fails. Also returns true if MessageCache
         * is disabled.
         *
-        * @param bool|string $code Language to which load messages
-        * @param integer $mode Use MessageCache::FOR_UPDATE to skip process cache
+        * @param string $code Language to which load messages
+        * @param integer $mode Use MessageCache::FOR_UPDATE to skip process cache [optional]
         * @throws MWException
         * @return bool
         */
-       function load( $code = false, $mode = null ) {
+       protected function load( $code, $mode = null ) {
                if ( !is_string( $code ) ) {
-                       # This isn't really nice, so at least make a note about it and try to
-                       # fall back
-                       wfDebug( __METHOD__ . " called without providing a language code\n" );
-                       $code = 'en';
+                       throw new InvalidArgumentException( "Missing language code" );
                }
 
                # Don't do double loading...
@@ -302,7 +297,7 @@ class MessageCache {
                                                $where[] = 'global cache is expired';
                                                $staleCache = $cache;
                                        } elseif ( $hashVolatile ) {
-                                               # DB results are slave lag prone until the holdoff TTL passes.
+                                               # DB results are replica DB lag prone until the holdoff TTL passes.
                                                # By then, updates should be reflected in loadFromDBWithLock().
                                                # One thread renerates the cache while others use old values.
                                                $where[] = 'global cache is expired/volatile';
@@ -442,7 +437,7 @@ class MessageCache {
        function loadFromDB( $code, $mode = null ) {
                global $wgMaxMsgCacheEntrySize, $wgLanguageCode, $wgAdaptiveMessageCache;
 
-               $dbr = wfGetDB( ( $mode == self::FOR_UPDATE ) ? DB_MASTER : DB_SLAVE );
+               $dbr = wfGetDB( ( $mode == self::FOR_UPDATE ) ? DB_MASTER : DB_REPLICA );
 
                $cache = [];
 
@@ -564,7 +559,7 @@ class MessageCache {
                }
 
                // Mark this cache as definitely "latest" (non-volatile) so
-               // load() calls do try to refresh the cache with slave data
+               // load() calls do try to refresh the cache with replica DB data
                $this->mCache[$code]['LATEST'] = time();
 
                // Update caches if the lock was acquired
@@ -630,11 +625,11 @@ class MessageCache {
                if ( $dest === 'all' ) {
                        $cacheKey = wfMemcKey( 'messages', $code );
                        $success = $this->mMemc->set( $cacheKey, $cache );
+                       $this->setValidationHash( $code, $cache );
                } else {
                        $success = true;
                }
 
-               $this->setValidationHash( $code, $cache );
                $this->saveToLocalCache( $code, $cache );
 
                return $success;
@@ -863,6 +858,8 @@ class MessageCache {
                                }
                                $alreadyTried[ $langcode ] = true;
                        }
+               } else {
+                       $uckey = null;
                }
 
                // Check the CDB cache
@@ -880,7 +877,8 @@ class MessageCache {
                                        continue;
                                }
 
-                               $message = $this->getMsgFromNamespace( $this->getMessagePageName( $code, $uckey ), $code );
+                               $message = $this->getMsgFromNamespace(
+                                       $this->getMessagePageName( $code, $uckey ), $code );
 
                                if ( $message !== false ) {
                                        return $message;
@@ -945,28 +943,47 @@ class MessageCache {
                        return false;
                }
 
-               # Try the individual message cache
+               // Try the individual message cache
                $titleKey = wfMemcKey( 'messages', 'individual', $title );
-               $entry = $this->wanCache->get( $titleKey );
+
+               $curTTL = null;
+               $entry = $this->wanCache->get(
+                       $titleKey,
+                       $curTTL,
+                       [ wfMemcKey( 'messages', $code ) ]
+               );
+               $entry = ( $curTTL >= 0 ) ? $entry : false;
+
                if ( $entry ) {
                        if ( substr( $entry, 0, 1 ) === ' ' ) {
                                $this->mCache[$code][$title] = $entry;
-
-                               // The message exists, so make sure a string
-                               // is returned.
+                               // The message exists, so make sure a string is returned
                                return (string)substr( $entry, 1 );
                        } elseif ( $entry === '!NONEXISTENT' ) {
                                $this->mCache[$code][$title] = '!NONEXISTENT';
 
                                return false;
                        } else {
-                               # Corrupt/obsolete entry, delete it
+                               // Corrupt/obsolete entry, delete it
                                $this->wanCache->delete( $titleKey );
                        }
                }
 
-               # Try loading it from the database
-               $revision = Revision::newFromTitle( Title::makeTitle( NS_MEDIAWIKI, $title ) );
+               // Try loading it from the database
+               $dbr = wfGetDB( DB_REPLICA );
+               $cacheOpts = Database::getCacheSetOptions( $dbr );
+               // Use newKnownCurrent() to avoid querying revision/user tables
+               $titleObj = Title::makeTitle( NS_MEDIAWIKI, $title );
+               if ( $titleObj->getLatestRevID() ) {
+                       $revision = Revision::newKnownCurrent(
+                               $dbr,
+                               $titleObj->getArticleID(),
+                               $titleObj->getLatestRevID()
+                       );
+               } else {
+                       $revision = false;
+               }
+
                if ( $revision ) {
                        $content = $revision->getContent();
                        if ( !$content ) {
@@ -993,7 +1010,7 @@ class MessageCache {
                                        $message = false; // negative caching
                                } else {
                                        $this->mCache[$code][$title] = ' ' . $message;
-                                       $this->wanCache->set( $titleKey, ' ' . $message, $this->mExpiry );
+                                       $this->wanCache->set( $titleKey, ' ' . $message, $this->mExpiry, $cacheOpts );
                                }
                        }
                } else {
@@ -1002,7 +1019,7 @@ class MessageCache {
 
                if ( $message === false ) { // negative caching
                        $this->mCache[$code][$title] = '!NONEXISTENT';
-                       $this->wanCache->set( $titleKey, '!NONEXISTENT', $this->mExpiry );
+                       $this->wanCache->set( $titleKey, '!NONEXISTENT', $this->mExpiry, $cacheOpts );
                }
 
                return $message;
@@ -1089,7 +1106,7 @@ class MessageCache {
                if ( !$title || !$title instanceof Title ) {
                        global $wgTitle;
                        wfDebugLog( 'GlobalTitleFail', __METHOD__ . ' called by ' .
-                               wfGetAllCallers( 5 ) . ' with no title set.' );
+                               wfGetAllCallers( 6 ) . ' with no title set.' );
                        $title = $wgTitle;
                }
                // Sometimes $wgTitle isn't set either...