/** * @covers WANObjectCache::delete() */ public function testDelete() { $key = wfRandomString(); $value = wfRandomString(); $this->cache->set($key, $value); $curTTL = null; $v = $this->cache->get($key, $curTTL); $this->assertEquals($value, $v, "Key was created with value"); $this->assertGreaterThan(0, $curTTL, "Existing key has current TTL > 0"); $this->cache->delete($key); $curTTL = null; $v = $this->cache->get($key, $curTTL); $this->assertFalse($v, "Deleted key has false value"); $this->assertLessThan(0, $curTTL, "Deleted key has current TTL < 0"); $this->cache->set($key, $value . 'more'); $v = $this->cache->get($key, $curTTL); $this->assertFalse($v, "Deleted key is tombstoned and has false value"); $this->assertLessThan(0, $curTTL, "Deleted key is tombstoned and has current TTL < 0"); $this->cache->set($key, $value); $this->cache->delete($key, WANObjectCache::HOLDOFF_NONE); $curTTL = null; $v = $this->cache->get($key, $curTTL); $this->assertFalse($v, "Deleted key has false value"); $this->assertNull($curTTL, "Deleted key has null current TTL"); $this->cache->set($key, $value); $v = $this->cache->get($key, $curTTL); $this->assertEquals($value, $v, "Key was created with value"); $this->assertGreaterThan(0, $curTTL, "Existing key has current TTL > 0"); }
/** * Delete the cached stat info for a file path. * The cache key is salted for a while to prevent race conditions. * Since negatives (404s) are not cached, this does not need to be called when * a file is created at a path were there was none before. * * @param string $path Storage path */ protected final function deleteFileCache($path) { $path = FileBackend::normalizeStoragePath($path); if ($path === null) { return; // invalid storage path } if (!$this->memCache->delete($this->fileCacheKey($path), 300)) { trigger_error("Unable to delete stat cache for file {$path}."); } }
/** * Get a message from the MediaWiki namespace, with caching. The key must * first be converted to two-part lang/msg form if necessary. * * Unlike self::get(), this function doesn't resolve fallback chains, and * some callers require this behavior. LanguageConverter::parseCachedTable() * and self::get() are some examples in core. * * @param string $title Message cache key with initial uppercase letter. * @param string $code Code denoting the language to try. * @return string|bool The message, or false if it does not exist or on error */ function getMsgFromNamespace($title, $code) { $this->load($code); if (isset($this->mCache[$code][$title])) { $entry = $this->mCache[$code][$title]; if (substr($entry, 0, 1) === ' ') { // The message exists, so make sure a string // is returned. return (string) substr($entry, 1); } elseif ($entry === '!NONEXISTENT') { return false; } elseif ($entry === '!TOO BIG') { // Fall through and try invididual message cache below } } else { // XXX: This is not cached in process cache, should it? $message = false; Hooks::run('MessagesPreLoad', array($title, &$message)); if ($message !== false) { return $message; } return false; } # Try the individual message cache $titleKey = wfMemcKey('messages', 'individual', $title); $entry = $this->wanCache->get($titleKey); if ($entry) { if (substr($entry, 0, 1) === ' ') { $this->mCache[$code][$title] = $entry; // 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 $this->wanCache->delete($titleKey); } } # Try loading it from the database $revision = Revision::newFromTitle(Title::makeTitle(NS_MEDIAWIKI, $title)); if ($revision) { $content = $revision->getContent(); if (!$content) { // A possibly temporary loading failure. wfDebugLog('MessageCache', __METHOD__ . ": failed to load message page text for {$title} ({$code})"); $message = null; // no negative caching } else { // XXX: Is this the right way to turn a Content object into a message? // NOTE: $content is typically either WikitextContent, JavaScriptContent or // CssContent. MessageContent is *not* used for storing messages, it's // only used for wrapping them when needed. $message = $content->getWikitextForTransclusion(); if ($message === false || $message === null) { wfDebugLog('MessageCache', __METHOD__ . ": message content doesn't provide wikitext " . "(content model: " . $content->getModel() . ")"); $message = false; // negative caching } else { $this->mCache[$code][$title] = ' ' . $message; $this->wanCache->set($titleKey, ' ' . $message, $this->mExpiry); } } } else { $message = false; // negative caching } if ($message === false) { // negative caching $this->mCache[$code][$title] = '!NONEXISTENT'; $this->wanCache->set($titleKey, '!NONEXISTENT', $this->mExpiry); } return $message; }
/** * @return void */ protected function doFlushCaches() { foreach (array('size', 'acquiredcount') as $type) { $this->cache->delete($this->getCacheKey($type)); } }
/** * Updates cache as necessary when message page is changed * * @param string $title Name of the page changed. * @param mixed $text New contents of the page. */ public function replace($title, $text) { global $wgMaxMsgCacheEntrySize, $wgContLang, $wgLanguageCode; if ($this->mDisable) { return; } list($msg, $code) = $this->figureMessage($title); if (strpos($title, '/') !== false && $code === $wgLanguageCode) { # Content language overrides do not use the /<code> suffix return; } $cacheKey = wfMemcKey('messages', $code); $this->lock($cacheKey); $this->load($code, self::FOR_UPDATE); $titleKey = wfMemcKey('messages', 'individual', $title); if ($text === false) { # Article was deleted $this->mCache[$code][$title] = '!NONEXISTENT'; $this->mMemc->delete($titleKey); } elseif (strlen($text) > $wgMaxMsgCacheEntrySize) { # Check for size $this->mCache[$code][$title] = '!TOO BIG'; $this->mMemc->set($titleKey, ' ' . $text, $this->mExpiry); } else { $this->mCache[$code][$title] = ' ' . $text; $this->mMemc->delete($titleKey); } # Update caches $this->saveToCaches($this->mCache[$code], 'all', $code); $this->unlock($cacheKey); $this->wanCache->touchCheckKey(wfMemcKey('messages', $code)); // Also delete cached sidebar... just in case it is affected $codes = array($code); if ($code === 'en') { // Delete all sidebars, like for example on action=purge on the // sidebar messages $codes = array_keys(Language::fetchLanguageNames()); } foreach ($codes as $code) { $sidebarKey = wfMemcKey('sidebar', $code); $this->wanCache->delete($sidebarKey, 5); } // Update the message in the message blob store $blobStore = new MessageBlobStore(); $blobStore->updateMessage($wgContLang->lcfirst($msg)); Hooks::run('MessageCacheReplace', array($title, $text)); }