From: Tim Starling Date: Tue, 8 Nov 2005 11:54:04 +0000 (+0000) Subject: Added local message cache feature ($wgLocalMessageCache), to reduce bandwidth require... X-Git-Tag: 1.6.0~1206 X-Git-Url: https://git.cyclocoop.org/%28%28?a=commitdiff_plain;h=6d82fa2f1577422c9d8b0659dbe97f9ff2d5fe4b;p=lhc%2Fweb%2Fwiklou.git Added local message cache feature ($wgLocalMessageCache), to reduce bandwidth requirements to the memcached server. --- diff --git a/RELEASE-NOTES b/RELEASE-NOTES index a5e1582cb5..8dc3a02f9e 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -212,7 +212,8 @@ fully support the editing toolbar, but was found to be too confusing. * Require POST for action=purge, to stop bots from purging the cache * (bug 3817) Use localized date formats in preferences; 'no preference' option localizable as 'datedefault' message. Tweaked lots of languages files... - +* Added local message cache feature ($wgLocalMessageCache), to reduce bandwidth + requirements to the memcached server. === Caveats === diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index a95925b7d0..a671dd2686 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -533,6 +533,10 @@ $wgMemCachedDebug = false; # Will be set to false in Setup.php, if the server $wgMemCachedServers = array( '127.0.0.1:11000' ); $wgMemCachedDebug = false; +/** + * Directory for local copy of message cache, for use in addition to memcached + */ +$wgLocalMessageCache = false; # Language settings diff --git a/includes/MessageCache.php b/includes/MessageCache.php index 1987fe93cc..a02bd6255e 100755 --- a/includes/MessageCache.php +++ b/includes/MessageCache.php @@ -30,6 +30,7 @@ class MessageCache var $mDeferred = true; function initialise( &$memCached, $useDB, $expiry, $memcPrefix) { + global $wgLocalMessageCache; $fname = 'MessageCache::initialise'; wfProfileIn( $fname ); @@ -58,13 +59,65 @@ class MessageCache wfProfileOut( $fname ); } + /** + * Try to load the cache from a local file + */ + function loadFromLocal( $hash ) { + global $wgLocalMessageCache, $wgDBname; + + $this->mCache = false; + if ( $wgLocalMessageCache === false ) { + return; + } + + $filename = "$wgLocalMessageCache/messages-$wgDBname"; + + $file = fopen( $filename, 'r' ); + if ( !$file ) { + return; + } + + // Check to see if the file has the hash specified + $localHash = fread( $file, 32 ); + if ( $hash == $localHash ) { + // All good, get the rest of it + $serialized = fread( $file, 1000000 ); + $this->mCache = unserialize( $serialized ); + } + fclose( $file ); + } + + /** + * Save the cache to a local file + */ + function saveToLocal( $serialized, $hash ) { + global $wgLocalMessageCache, $wgDBname; + + if ( $wgLocalMessageCache === false ) { + return; + } + + $filename = "$wgLocalMessageCache/messages-$wgDBname"; + wfMkdirParents( $wgLocalMessageCache, 0777 ); + + $file = fopen( $filename, 'w' ); + if ( !$file ) { + wfDebug( "Unable to open local cache file for writing\n" ); + return; + } + + fwrite( $file, $hash . $serialized ); + fclose( $file ); + } + + /** * 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() { - global $wgAllMessagesEn; + global $wgAllMessagesEn, $wgLocalMessageCache; if ( $this->mDisable ) { static $shownDisabled = false; @@ -79,9 +132,33 @@ class MessageCache $success = true; if ( $this->mUseCache ) { - wfProfileIn( $fname.'-fromcache' ); - $this->mCache = $this->mMemc->get( $this->mMemcKey ); - wfProfileOut( $fname.'-fromcache' ); + $this->mCache = false; + + # Try local cache + wfProfileIn( $fname.'-fromlocal' ); + $hash = $this->mMemc->get( "{$this->mMemcKey}-hash" ); + if ( $hash ) { + $this->loadFromLocal( $hash ); + } + wfProfileOut( $fname.'-fromlocal' ); + + # Try memcached + if ( !$this->mCache ) { + wfProfileIn( $fname.'-fromcache' ); + $this->mCache = $this->mMemc->get( $this->mMemcKey ); + + # 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 ); + } + $this->saveToLocal( $serialized, $hash ); + } + wfProfileOut( $fname.'-fromcache' ); + } + # If there's nothing in memcached, load all the messages from the database if ( !$this->mCache ) { @@ -93,6 +170,7 @@ class MessageCache wfProfileIn( $fname.'-load' ); $this->loadFromDB(); wfProfileOut( $fname.'-load' ); + # Save in memcached # Keep trying if it fails, this is kind of important wfProfileIn( $fname.'-save' ); @@ -101,6 +179,15 @@ class MessageCache $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 ); + $this->saveToLocal( $serialized, $hash ); + } + wfProfileOut( $fname.'-save' ); if ( $i == 20 ) { $this->mMemc->set( $this->mMemcKey.'-status', 'error', 60*5 ); @@ -199,11 +286,23 @@ class MessageCache } function replace( $title, $text ) { + global $wgLocalMessageCache; + $this->lock(); $this->load(); if ( is_array( $this->mCache ) ) { $this->mCache[$title] = $text; $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 ); + $this->saveToLocal( $serialized, $hash ); + } + + } $this->unlock(); }