/**
  * @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");
 }
示例#2
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}.");
     }
 }
示例#3
0
 /**
  * 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;
 }
示例#4
0
 /**
  * @return void
  */
 protected function doFlushCaches()
 {
     foreach (array('size', 'acquiredcount') as $type) {
         $this->cache->delete($this->getCacheKey($type));
     }
 }
示例#5
0
 /**
  * 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));
 }