/**
*
*/
-define( 'MSG_LOAD_TIMEOUT', 60);
-define( 'MSG_LOCK_TIMEOUT', 10);
-define( 'MSG_WAIT_TIMEOUT', 10);
+define( 'MSG_LOAD_TIMEOUT', 60 );
+define( 'MSG_LOCK_TIMEOUT', 10 );
+define( 'MSG_WAIT_TIMEOUT', 10 );
define( 'MSG_CACHE_VERSION', 1 );
/**
* better sample, but also takes longer to adapt changes. The counts
* are aggregrated per day, regardless of the value of this variable.
*/
- protected static $mAdaptiveDataAge = 7*24*3600;
+ protected static $mAdaptiveDataAge = 604800; // Is 7*24*3600
/**
* Filter the tail of less used messages that are requested more seldom
*/
protected static $mAdaptiveInclusionThreshold = 0.05;
+ /**
+ * Singleton instance
+ */
+ private static $instance;
+
+ /**
+ * Get the signleton instance of this class
+ *
+ * @since 1.18
+ * @return MessageCache object
+ */
+ public static function singleton() {
+ if ( is_null( self::$instance ) ) {
+ global $wgUseDatabaseMessages, $wgMsgCacheExpiry;
+ self::$instance = new self( wfGetMessageCacheStorage(), $wgUseDatabaseMessages, $wgMsgCacheExpiry );
+ }
+ return self::$instance;
+ }
+
+ /**
+ * Destroy the singleton instance
+ *
+ * @since 1.18
+ */
+ public static function destroyInstance() {
+ self::$instance = null;
+ }
+
function __construct( $memCached, $useDB, $expiry ) {
if ( !$memCached ) {
$memCached = wfGetCache( CACHE_NONE );
$this->mExpiry = $expiry;
}
-
/**
* ParserOptions is lazy initialised.
*/
return false; // Wrong hash
}
} else {
- $localHash=substr(fread($file,40),8);
- fclose($file);
- if ($hash!=$localHash) {
+ $localHash = substr( fread( $file, 40 ), 8 );
+ fclose( $file );
+ if ( $hash != $localHash ) {
return false; // Wrong hash
}
wfMkdirParents( $wgCacheDirectory ); // might fail
wfSuppressWarnings();
- $file = fopen( $tempFilename, 'w');
+ $file = fopen( $tempFilename, 'w' );
wfRestoreWarnings();
if ( !$file ) {
return;
}
- fwrite($file,"<?php\n//$hash\n\n \$this->mCache = array(");
+ fwrite( $file, "<?php\n//$hash\n\n \$this->mCache = array(" );
- foreach ($array as $key => $message) {
- $key = $this->escapeForScript($key);
- $messages = $this->escapeForScript($message);
- fwrite($file, "'$key' => '$message',\n");
+ foreach ( $array as $key => $message ) {
+ $key = $this->escapeForScript( $key );
+ $message = $this->escapeForScript( $message );
+ fwrite( $file, "'$key' => '$message',\n" );
}
- fwrite($file,");\n?>");
- fclose($file);
- rename($tempFilename, $filename);
+ fwrite( $file, ");\n?>" );
+ fclose( $file);
+ rename( $tempFilename, $filename );
}
- function escapeForScript($string) {
+ function escapeForScript( $string ) {
$string = str_replace( '\\', '\\\\', $string );
$string = str_replace( '\'', '\\\'', $string );
return $string;
}
# Don't do double loading...
- if ( isset($this->mLoadedLanguages[$code]) ) return true;
+ if ( isset( $this->mLoadedLanguages[$code] ) ) {
+ return true;
+ }
# 8 lines of code just to say (once) that message cache is disabled
if ( $this->mDisable ) {
$where = array(); # Debug info, delayed to avoid spamming debug log too much
$cacheKey = wfMemcKey( 'messages', $code ); # Key in memc for messages
-
# (1) local cache
# Hash of the contents is stored in memcache, to detect if local cache goes
# out of date (due to update in other thread?)
wfProfileOut( __METHOD__ . '-fromcache' );
}
-
# (3)
# Nothing in caches... so we need create one and store it in caches
if ( !$success ) {
$where[] = 'cache is empty';
$where[] = 'loading from database';
- $this->lock($cacheKey);
+ $this->lock( $cacheKey );
# Limit the concurrency of loadFromDB to a single process
# This prevents the site from going down when the cache expires
if ( $success ) {
$this->mMemc->delete( $statusKey );
} else {
- $this->mMemc->set( $statusKey, 'error', 60*5 );
+ $this->mMemc->set( $statusKey, 'error', 60 * 5 );
wfDebug( "MemCached set error in MessageCache: restart memcached server!\n" );
}
}
* $wgMaxMsgCacheEntrySize are assigned a special value, and are loaded
* on-demand from the database later.
*
- * @param $code \string Language code.
- * @return \array Loaded messages for storing in caches.
+ * @param $code String: language code.
+ * @return Array: loaded messages for storing in caches.
*/
function loadFromDB( $code ) {
wfProfileIn( __METHOD__ );
if ( $wgAdaptiveMessageCache ) {
$mostused = $this->getMostUsedMessages();
if ( $code !== $wgLanguageCode ) {
- foreach ( $mostused as $key => $value ) $mostused[$key] = "$value/$code";
+ foreach ( $mostused as $key => $value ) {
+ $mostused[$key] = "$value/$code";
+ }
}
}
$smallConds[] = 'rev_text_id=old_id';
$smallConds[] = 'page_len <= ' . intval( $wgMaxMsgCacheEntrySize );
- $res = $dbr->select( array( 'page', 'revision', 'text' ),
+ $res = $dbr->select(
+ array( 'page', 'revision', 'text' ),
array( 'page_title', 'old_text', 'old_flags' ),
- $smallConds, __METHOD__ . "($code)-small" );
+ $smallConds,
+ __METHOD__ . "($code)-small"
+ );
foreach ( $res as $row ) {
$cache[$row->page_title] = ' ' . Revision::getRevisionText( $row );
wfProfileIn( __METHOD__ );
if ( $this->mDisable ) {
+ wfProfileOut( __METHOD__ );
return;
}
# 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 );
$sidebarKey = wfMemcKey( 'sidebar', $code );
$parserMemc->delete( $sidebarKey );
}
-
+
// Update the message in the message blob store
global $wgContLang;
MessageBlobStore::updateMessage( $wgContLang->lcfirst( $msg ) );
- wfRunHooks( "MessageCacheReplace", array( $title, $text ) );
+ wfRunHooks( 'MessageCacheReplace', array( $title, $text ) );
wfProfileOut( __METHOD__ );
}
*
* @return Boolean: success
*/
- function lock($key) {
+ function lock( $key ) {
$lockKey = $key . ':lock';
- for ($i=0; $i < MSG_WAIT_TIMEOUT && !$this->mMemc->add( $lockKey, 1, MSG_LOCK_TIMEOUT ); $i++ ) {
- sleep(1);
+ for ( $i = 0; $i < MSG_WAIT_TIMEOUT && !$this->mMemc->add( $lockKey, 1, MSG_LOCK_TIMEOUT ); $i++ ) {
+ sleep( 1 );
}
return $i >= MSG_WAIT_TIMEOUT;
}
- function unlock($key) {
+ function unlock( $key ) {
$lockKey = $key . ':lock';
$this->mMemc->delete( $lockKey );
}
global $wgLanguageCode, $wgContLang;
if ( !is_string( $key ) ) {
- throw new MWException( "Non-string key given" );
+ throw new MWException( 'Non-string key given' );
}
if ( strval( $key ) === '' ) {
$uckey = $wgContLang->ucfirst( $lckey );
}
- /* Record each message request, but only once per request.
+ /**
+ * Record each message request, but only once per request.
* This information is not used unless $wgAdaptiveMessageCache
- * is enabled. */
+ * is enabled.
+ */
$this->mRequestedMessages[$uckey] = true;
# Try the MediaWiki namespace
if( !$this->mDisable && $useDB ) {
$title = $uckey;
- if(!$isFullKey && ( $langcode != $wgLanguageCode ) ) {
+ if( !$isFullKey && ( $langcode != $wgLanguageCode ) ) {
$title .= '/' . $langcode;
}
$message = $this->getMsgFromNamespace( $title, $langcode );
}
# Is this a custom message? Try the default language in the db...
- if( ($message === false || $message === '-' ) &&
+ if( ( $message === false || $message === '-' ) &&
!$this->mDisable && $useDB &&
- !$isFullKey && ($langcode != $wgLanguageCode) ) {
+ !$isFullKey && ( $langcode != $wgLanguageCode ) ) {
$message = $this->getMsgFromNamespace( $uckey, $wgLanguageCode );
}
*/
function getMsgFromNamespace( $title, $code ) {
global $wgAdaptiveMessageCache;
- $big = false;
$this->load( $code );
if ( isset( $this->mCache[$code][$title] ) ) {
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;
+ wfRunHooks( 'MessagesPreLoad', array( $title, &$message ) );
+ if ( $message !== false ) {
+ return $message;
+ }
- } else {
- // XXX: This is not cached in process cache, should it?
- $message = false;
- wfRunHooks('MessagesPreLoad', array( $title, &$message ) );
- if ( $message !== false ) {
- return $message;
- }
-
- /* If message cache is in normal mode, it is guaranteed
- * (except bugs) that there is always entry (or placeholder)
- * in the cache if message exists. Thus we can do minor
- * performance improvement and return false early.
- */
- if ( !$wgAdaptiveMessageCache ) {
- return false;
- }
+ /**
+ * If message cache is in normal mode, it is guaranteed
+ * (except bugs) that there is always entry (or placeholder)
+ * in the cache if message exists. Thus we can do minor
+ * performance improvement and return false early.
+ */
+ if ( !$wgAdaptiveMessageCache ) {
+ return false;
}
}
return $message;
}
- function transform( $message, $interface = false, $language = null ) {
+ function transform( $message, $interface = false, $language = null, $title = null ) {
// Avoid creating parser if nothing to transform
if( strpos( $message, '{{' ) === false ) {
return $message;
$popts->setInterfaceMessage( $interface );
$popts->setTargetLanguage( $language );
$popts->setUserLang( $language );
- $message = $this->mParser->transformMsg( $message, $popts );
+ $message = $this->mParser->transformMsg( $message, $popts, $title );
}
return $message;
}
- function disable() { $this->mDisable = true; }
- function enable() { $this->mDisable = false; }
-
- /** @deprecated */
- function disableTransform(){
- wfDeprecated( __METHOD__ );
+ function disable() {
+ $this->mDisable = true;
}
- function enableTransform() {
- wfDeprecated( __METHOD__ );
- }
- function setTransform( $x ) {
- wfDeprecated( __METHOD__ );
- }
- function getTransform() {
- wfDeprecated( __METHOD__ );
- return false;
+
+ function enable() {
+ $this->mDisable = false;
}
/**
$this->mLoadedLanguages = array();
}
- /**
- * Add a message to the cache
- * @deprecated Use $wgExtensionMessagesFiles
- *
- * @param $key Mixed
- * @param $value Mixed
- * @param $lang String: the messages language, English by default
- */
- function addMessage( $key, $value, $lang = 'en' ) {
- wfDeprecated( __METHOD__ );
- $lc = Language::getLocalisationCache();
- $lc->addLegacyMessages( array( $lang => array( $key => $value ) ) );
- }
-
- /**
- * Add an associative array of message to the cache
- * @deprecated Use $wgExtensionMessagesFiles
- *
- * @param $messages Array: an associative array of key => values to be added
- * @param $lang String: the messages language, English by default
- */
- function addMessages( $messages, $lang = 'en' ) {
- wfDeprecated( __METHOD__ );
- $lc = Language::getLocalisationCache();
- $lc->addLegacyMessages( array( $lang => $messages ) );
- }
-
- /**
- * Add a 2-D array of messages by lang. Useful for extensions.
- * @deprecated Use $wgExtensionMessagesFiles
- *
- * @param $messages Array: the array to be added
- */
- function addMessagesByLang( $messages ) {
- wfDeprecated( __METHOD__ );
- $lc = Language::getLocalisationCache();
- $lc->addLegacyMessages( $messages );
- }
-
- /**
- * Set a hook for addMessagesByLang()
- */
- function setExtensionMessagesHook( $callback ) {
- $this->mAddMessagesHook = $callback;
- }
-
- /**
- * @deprecated
- */
- function loadAllMessages( $lang = false ) {
- }
-
- /**
- * @deprecated
- */
- function loadMessagesFile( $filename, $langcode = false ) {
- }
-
public function figureMessage( $key ) {
global $wgLanguageCode;
$pieces = explode( '/', $key );
- if( count( $pieces ) < 2 )
+ if( count( $pieces ) < 2 ) {
return array( $key, $wgLanguageCode );
+ }
$lang = array_pop( $pieces );
$validCodes = Language::getLanguageNames();
- if( !array_key_exists( $lang, $validCodes ) )
+ if( !array_key_exists( $lang, $validCodes ) ) {
return array( $key, $wgLanguageCode );
+ }
$message = implode( '/', $pieces );
return array( $message, $lang );
}
public static function logMessages() {
- global $wgMessageCache, $wgAdaptiveMessageCache;
- if ( !$wgAdaptiveMessageCache || !$wgMessageCache instanceof MessageCache ) {
+ wfProfileIn( __METHOD__ );
+ global $wgAdaptiveMessageCache;
+ if ( !$wgAdaptiveMessageCache || !self::$instance instanceof MessageCache ) {
+ wfProfileOut( __METHOD__ );
return;
}
$cache = wfGetCache( CACHE_DB );
$data = $cache->get( $cachekey );
- if ( !$data ) $data = array();
+ if ( !$data ) {
+ $data = array();
+ }
$age = self::$mAdaptiveDataAge;
- $filterDate = substr( wfTimestamp( TS_MW, time()-$age ), 0, 8 );
+ $filterDate = substr( wfTimestamp( TS_MW, time() - $age ), 0, 8 );
foreach ( array_keys( $data ) as $key ) {
- if ( $key < $filterDate ) unset( $data[$key] );
+ if ( $key < $filterDate ) {
+ unset( $data[$key] );
+ }
}
$index = substr( wfTimestampNow(), 0, 8 );
- if ( !isset( $data[$index] ) ) $data[$index] = array();
+ if ( !isset( $data[$index] ) ) {
+ $data[$index] = array();
+ }
- foreach ( $wgMessageCache->mRequestedMessages as $message => $_ ) {
- if ( !isset( $data[$index][$message] ) ) $data[$index][$message] = 0;
+ foreach ( self::$instance->mRequestedMessages as $message => $_ ) {
+ if ( !isset( $data[$index][$message] ) ) {
+ $data[$index][$message] = 0;
+ }
$data[$index][$message]++;
}
$cache->set( $cachekey, $data );
+ wfProfileOut( __METHOD__ );
}
public function getMostUsedMessages() {
- $cachekey = wfMemckey( 'message-profiling' );
+ wfProfileIn( __METHOD__ );
+ $cachekey = wfMemcKey( 'message-profiling' );
$cache = wfGetCache( CACHE_DB );
$data = $cache->get( $cachekey );
- if ( !$data ) return array();
+ if ( !$data ) {
+ wfProfileOut( __METHOD__ );
+ return array();
+ }
$list = array();
- foreach( $data as $date => $messages ) {
+ foreach( $data as $messages ) {
foreach( $messages as $message => $count ) {
$key = $message;
- if ( !isset( $list[$key] ) ) $list[$key] = 0;
+ if ( !isset( $list[$key] ) ) {
+ $list[$key] = 0;
+ }
$list[$key] += $count;
}
}
}
}
+ wfProfileOut( __METHOD__ );
return array_keys( $list );
}