summaryrefslogtreecommitdiff
path: root/includes/parser/ParserCache.php
diff options
context:
space:
mode:
Diffstat (limited to 'includes/parser/ParserCache.php')
-rw-r--r--includes/parser/ParserCache.php108
1 files changed, 69 insertions, 39 deletions
diff --git a/includes/parser/ParserCache.php b/includes/parser/ParserCache.php
index 7053f134..79523003 100644
--- a/includes/parser/ParserCache.php
+++ b/includes/parser/ParserCache.php
@@ -26,9 +26,8 @@
* @todo document
*/
class ParserCache {
+ /** @var MWMemcached */
private $mMemc;
- const try116cache = false; /* Only useful $wgParserCacheExpireTime after updating to 1.17 */
-
/**
* Get an instance of this object
*
@@ -47,7 +46,7 @@ class ParserCache {
* Setup a cache pathway with a given back-end storage mechanism.
* May be a memcached client or a BagOStuff derivative.
*
- * @param $memCached Object
+ * @param MWMemcached $memCached
* @throws MWException
*/
protected function __construct( $memCached ) {
@@ -58,8 +57,8 @@ class ParserCache {
}
/**
- * @param $article Article
- * @param $hash string
+ * @param Article $article
+ * @param string $hash
* @return mixed|string
*/
protected function getParserOutputKey( $article, $hash ) {
@@ -74,7 +73,7 @@ class ParserCache {
}
/**
- * @param $article Article
+ * @param Article $article
* @return mixed|string
*/
protected function getOptionsKey( $article ) {
@@ -92,11 +91,11 @@ class ParserCache {
* English preferences. That's why we take into account *all* user
* options. (r70809 CR)
*
- * @param $article Article
- * @param $popts ParserOptions
+ * @param Article $article
+ * @param ParserOptions $popts
* @return string
*/
- function getETag( $article, $popts ) {
+ public function getETag( $article, $popts ) {
return 'W/"' . $this->getParserOutputKey( $article,
$popts->optionsHash( ParserOptions::legacyOptions(), $article->getTitle() ) ) .
"--" . $article->getTouched() . '"';
@@ -104,8 +103,8 @@ class ParserCache {
/**
* Retrieve the ParserOutput from ParserCache, even if it's outdated.
- * @param $article Article
- * @param $popts ParserOptions
+ * @param Article $article
+ * @param ParserOptions $popts
* @return ParserOutput|bool False on failure
*/
public function getDirty( $article, $popts ) {
@@ -114,15 +113,22 @@ class ParserCache {
}
/**
- * Used to provide a unique id for the PoolCounter.
+ * Generates a key for caching the given article considering
+ * the given parser options.
+ *
+ * @note Which parser options influence the cache key
+ * is controlled via ParserOutput::recordOption() or
+ * ParserOptions::addExtraKey().
+ *
+ * @note Used by Article to provide a unique id for the PoolCounter.
* It would be preferable to have this code in get()
* instead of having Article looking in our internals.
*
* @todo Document parameter $useOutdated
*
- * @param $article Article
- * @param $popts ParserOptions
- * @param $useOutdated Boolean (default true)
+ * @param Article $article
+ * @param ParserOptions $popts
+ * @param bool $useOutdated (default true)
* @return bool|mixed|string
*/
public function getKey( $article, $popts, $useOutdated = true ) {
@@ -139,29 +145,40 @@ class ParserCache {
if ( !$useOutdated && $optionsKey->expired( $article->getTouched() ) ) {
wfIncrStats( "pcache_miss_expired" );
$cacheTime = $optionsKey->getCacheTime();
- wfDebug( "Parser options key expired, touched " . $article->getTouched() . ", epoch $wgCacheEpoch, cached $cacheTime\n" );
+ wfDebug( "Parser options key expired, touched " . $article->getTouched()
+ . ", epoch $wgCacheEpoch, cached $cacheTime\n" );
+ return false;
+ } elseif ( $optionsKey->isDifferentRevision( $article->getLatest() ) ) {
+ wfIncrStats( "pcache_miss_revid" );
+ $revId = $article->getLatest();
+ $cachedRevId = $optionsKey->getCacheRevisionId();
+ wfDebug( "ParserOutput key is for an old revision, latest $revId, cached $cachedRevId\n" );
return false;
}
+ // $optionsKey->mUsedOptions is set by save() by calling ParserOutput::getUsedOptions()
$usedOptions = $optionsKey->mUsedOptions;
wfDebug( "Parser cache options found.\n" );
} else {
- if ( !$useOutdated && !self::try116cache ) {
+ if ( !$useOutdated ) {
return false;
}
$usedOptions = ParserOptions::legacyOptions();
}
- return $this->getParserOutputKey( $article, $popts->optionsHash( $usedOptions, $article->getTitle() ) );
+ return $this->getParserOutputKey(
+ $article,
+ $popts->optionsHash( $usedOptions, $article->getTitle() )
+ );
}
/**
* Retrieve the ParserOutput from ParserCache.
* false if not found or outdated.
*
- * @param $article Article
- * @param $popts ParserOptions
- * @param $useOutdated Boolean (default false)
+ * @param Article $article
+ * @param ParserOptions $popts
+ * @param bool $useOutdated (default false)
*
* @return ParserOutput|bool False on failure
*/
@@ -186,12 +203,6 @@ class ParserCache {
}
$value = $this->mMemc->get( $parserOutputKey );
- if ( self::try116cache && !$value && strpos( $value, '*' ) !== -1 ) {
- wfDebug( "New format parser cache miss.\n" );
- $parserOutputKey = $this->getParserOutputKey( $article,
- $popts->optionsHash( ParserOptions::legacyOptions(), $article->getTitle() ) );
- $value = $this->mMemc->get( $parserOutputKey );
- }
if ( !$value ) {
wfDebug( "ParserOutput cache miss.\n" );
wfIncrStats( "pcache_miss_absent" );
@@ -209,7 +220,14 @@ class ParserCache {
if ( !$useOutdated && $value->expired( $touched ) ) {
wfIncrStats( "pcache_miss_expired" );
$cacheTime = $value->getCacheTime();
- wfDebug( "ParserOutput key expired, touched $touched, epoch $wgCacheEpoch, cached $cacheTime\n" );
+ wfDebug( "ParserOutput key expired, touched $touched, "
+ . "epoch $wgCacheEpoch, cached $cacheTime\n" );
+ $value = false;
+ } elseif ( $value->isDifferentRevision( $article->getLatest() ) ) {
+ wfIncrStats( "pcache_miss_revid" );
+ $revId = $article->getLatest();
+ $cachedRevId = $value->getCacheRevisionId();
+ wfDebug( "ParserOutput key is for an old revision, latest $revId, cached $cachedRevId\n" );
$value = false;
} else {
wfIncrStats( "pcache_hit" );
@@ -220,15 +238,20 @@ class ParserCache {
}
/**
- * @param $parserOutput ParserOutput
- * @param $article Article
- * @param $popts ParserOptions
- * @param $cacheTime Time when the cache was generated
+ * @param ParserOutput $parserOutput
+ * @param WikiPage $page
+ * @param ParserOptions $popts
+ * @param string $cacheTime Time when the cache was generated
+ * @param int $revId Revision ID that was parsed
*/
- public function save( $parserOutput, $article, $popts, $cacheTime = null ) {
+ public function save( $parserOutput, $page, $popts, $cacheTime = null, $revId = null ) {
$expire = $parserOutput->getCacheExpiry();
if ( $expire > 0 ) {
$cacheTime = $cacheTime ?: wfTimestampNow();
+ if ( !$revId ) {
+ $revision = $page->getRevision();
+ $revId = $revision ? $revision->getId() : null;
+ }
$optionsKey = new CacheTime;
$optionsKey->mUsedOptions = $parserOutput->getUsedOptions();
@@ -236,23 +259,30 @@ class ParserCache {
$optionsKey->setCacheTime( $cacheTime );
$parserOutput->setCacheTime( $cacheTime );
+ $optionsKey->setCacheRevisionId( $revId );
+ $parserOutput->setCacheRevisionId( $revId );
$optionsKey->setContainsOldMagic( $parserOutput->containsOldMagic() );
- $parserOutputKey = $this->getParserOutputKey( $article,
- $popts->optionsHash( $optionsKey->mUsedOptions, $article->getTitle() ) );
+ $parserOutputKey = $this->getParserOutputKey( $page,
+ $popts->optionsHash( $optionsKey->mUsedOptions, $page->getTitle() ) );
// Save the timestamp so that we don't have to load the revision row on view
- $parserOutput->setTimestamp( $article->getTimestamp() );
+ $parserOutput->setTimestamp( $page->getTimestamp() );
+
+ $msg = "Saved in parser cache with key $parserOutputKey" .
+ " and timestamp $cacheTime" .
+ " and revision id $revId" .
+ "\n";
- $parserOutput->mText .= "\n<!-- Saved in parser cache with key $parserOutputKey and timestamp $cacheTime\n -->\n";
- wfDebug( "Saved in parser cache with key $parserOutputKey and timestamp $cacheTime\n" );
+ $parserOutput->mText .= "\n<!-- $msg -->\n";
+ wfDebug( $msg );
// Save the parser output
$this->mMemc->set( $parserOutputKey, $parserOutput, $expire );
// ...and its pointer
- $this->mMemc->set( $this->getOptionsKey( $article ), $optionsKey, $expire );
+ $this->mMemc->set( $this->getOptionsKey( $page ), $optionsKey, $expire );
} else {
wfDebug( "Parser output was marked as uncacheable and has not been saved.\n" );
}