From be76d86932bea59ea18d729b28d05fbc4775cf25 Mon Sep 17 00:00:00 2001 From: Tim Starling Date: Thu, 3 Mar 2011 09:37:37 +0000 Subject: [PATCH] * Rewrote ObjectCache.php to conform to the modern coding style, and to be less convoluted about how CACHE_ANYTHING and CACHE_ACCEL are resolved. Moved most functionality to static members of a new ObjectCache class. * Moved the global functions to GlobalFunctions.php, where they are now just convenience wrappers. Made them return non-references. Updated callers (none found in extensions). * Added an advanced configuration method, $wgObjectCaches, which allows a lot more detail in the object cache configuration than $wgMainCacheType. * Made all object cache classes derive from BagOStuff. * Split the MWMemcached class into a generic client class and a MediaWiki-specific wrapper class. The wrapper class presents a simple BagOStuff interface to calling code, hiding memcached client internals, and will simplify the task of supporting the PECL extension. * Added some extra constructor parameters to MWMemcached, configurable via $wgObjectCaches. * Removed the *_multi() methods from BagOStuff, my grepping indicates that they are not used. * Rewrote FakeMemCachedClient as a BagOStuff subclass, called EmptyBagOStuff. * Added an optional "server" parameter to SQLBagOStuff. This allows the server holding the objectcache table to be different from the server holding the core DB. * Added MultiWriteBagOStuff: a cache class which writes to multiple locations, and reads from them in a defined fallback sequence. This can be used to extend the cache space by adding disk-backed storage to existing in-memory caches. * Made MWMemcached::get() return false on failure instead of null, to match the BagOStuff documentation and the other BagOStuff subclasses. Anything that was relying on it returning null would have already been broken with SqlBagOStuff. * Fixed a bug in the memcached client causing keys with spaces or line breaks in them to break the memcached protocol, injecting arbitrary commands or parameters. Since the PECL client apparently also has this flaw, I implemented the fix in the wrapper class. * Renamed BagOStuff::set_debug() to setDebug(), since we aren't emulating the memcached client anymore * Fixed spelling error in MWMemcached: persistant -> persistent --- includes/AutoLoader.php | 6 +- includes/DefaultSettings.php | 32 ++++ includes/GlobalFunctions.php | 30 ++++ includes/Setup.php | 7 +- includes/objectcache/BagOStuff.php | 30 +--- includes/objectcache/EmptyBagOStuff.php | 27 ++++ includes/objectcache/MemcachedClient.php | 21 +-- .../objectcache/MemcachedPhpBagOStuff.php | 116 ++++++++++++++ includes/objectcache/MultiWriteBagOStuff.php | 95 +++++++++++ includes/objectcache/ObjectCache.php | 148 +++++++++--------- includes/objectcache/SqlBagOStuff.php | 37 +++-- maintenance/mcc.php | 2 +- .../phpunit/includes/parser/NewParserTest.php | 6 +- .../phpunit/suites/UploadFromUrlTestSuite.php | 6 +- 14 files changed, 427 insertions(+), 136 deletions(-) create mode 100644 includes/objectcache/EmptyBagOStuff.php create mode 100644 includes/objectcache/MemcachedPhpBagOStuff.php create mode 100644 includes/objectcache/MultiWriteBagOStuff.php diff --git a/includes/AutoLoader.php b/includes/AutoLoader.php index 705d7e8fea..961f180afd 100644 --- a/includes/AutoLoader.php +++ b/includes/AutoLoader.php @@ -505,11 +505,15 @@ $wgAutoloadLocalClasses = array( 'BagOStuff' => 'includes/objectcache/BagOStuff.php', 'DBABagOStuff' => 'includes/objectcache/DBABagOStuff.php', 'eAccelBagOStuff' => 'includes/objectcache/eAccelBagOStuff.php', - 'FakeMemCachedClient' => 'includes/objectcache/ObjectCache.php', + 'EmptyBagOStuff' => 'includes/objectcache/EmptyBagOStuff.php', + 'FakeMemCachedClient' => 'includes/objectcache/EmptyBagOStuff.php', 'HashBagOStuff' => 'includes/objectcache/HashBagOStuff.php', 'MWMemcached' => 'includes/objectcache/MemcachedClient.php', 'MediaWikiBagOStuff' => 'includes/objectcache/SqlBagOStuff.php', 'MemCachedClientforWiki' => 'includes/objectcache/MemcachedClient.php', + 'MemcachedPhpBagOStuff' => 'includes/objectcache/MemcachedPhpBagOStuff.php', + 'MultiWriteBagOStuff' => 'includes/objectcache/MultiWriteBagOStuff.php', + 'ObjectCache' => 'includes/objectcache/ObjectCache.php', 'SqlBagOStuff' => 'includes/objectcache/SqlBagOStuff.php', 'WinCacheBagOStuff' => 'includes/objectcache/WinCacheBagOStuff.php', 'XCacheBagOStuff' => 'includes/objectcache/XCacheBagOStuff.php', diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index 3c73d5534f..37c64cfb17 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -1481,6 +1481,8 @@ $wgCacheDirectory = false; * - CACHE_DBA: Use PHP's DBA extension to store in a DBM-style * database. This is slow, and is not recommended for * anything other than debugging. + * - (other): A string may be used which identifies a cache + * configuration in $wgObjectCaches. * * @see $wgMessageCacheType, $wgParserCacheType */ @@ -1502,6 +1504,36 @@ $wgMessageCacheType = CACHE_ANYTHING; */ $wgParserCacheType = CACHE_ANYTHING; +/** + * Advanced object cache configuration. + * + * Use this to define the class names and constructor parameters which are used + * for the various cache types. Custom cache types may be defined here and + * referenced from $wgMainCacheType, $wgMessageCacheType or $wgParserCacheType. + * + * The format is an associative array where the key is a cache identifier, and + * the value is an associative array of parameters. The "class" parameter is the + * class name which will be used. Alternatively, a "factory" parameter may be + * given, giving a callable function which will generate a suitable cache object. + * + * The other parameters are dependent on the class used. + */ +$wgObjectCaches = array( + CACHE_NONE => array( 'class' => 'FakeMemCachedClient' ), + CACHE_DB => array( 'class' => 'SqlBagOStuff', 'table' => 'objectcache' ), + CACHE_DBA => array( 'class' => 'DBABagOStuff' ), + + CACHE_ANYTHING => array( 'factory' => 'ObjectCache::newAnything' ), + CACHE_ACCEL => array( 'factory' => 'ObjectCache::newAccelerator' ), + CACHE_MEMCACHED => array( 'factory' => 'ObjectCache::newMemcached' ), + + 'eaccelerator' => array( 'class' => 'eAccelBagOStuff' ), + 'apc' => array( 'class' => 'APCBagOStuff' ), + 'xcache' => array( 'class' => 'XCacheBagOStuff' ), + 'wincache' => array( 'class' => 'WinCacheBagOStuff' ), + 'memcached-php' => array( 'class' => 'MemcachedPhpBagOStuff' ), +); + /** * The expiry time for the parser cache, in seconds. The default is 86.4k * seconds, otherwise known as a day. diff --git a/includes/GlobalFunctions.php b/includes/GlobalFunctions.php index e925c4b52a..d906255d8f 100644 --- a/includes/GlobalFunctions.php +++ b/includes/GlobalFunctions.php @@ -3357,3 +3357,33 @@ function wfArrayMap( $function, $input ) { } return $ret; } + + +/** + * Get a cache object. + * @param $inputType Cache type, one the the CACHE_* constants. + * + * @return BagOStuff + */ +function wfGetCache( $inputType ) { + return ObjectCache::getInstance( $inputType ); +} + +/** Get the main cache object */ +function wfGetMainCache() { + global $wgMainCacheType; + return ObjectCache::getInstance( $wgMainCacheType ); +} + +/** Get the cache object used by the message cache */ +function wfGetMessageCacheStorage() { + global $wgMessageCacheType; + return ObjectCache::getInstance( $wgMessageCacheType ); +} + +/** Get the cache object used by the parser cache */ +function wfGetParserCacheStorage() { + global $wgParserCacheType; + return ObjectCache::getInstance( $wgParserCacheType ); +} + diff --git a/includes/Setup.php b/includes/Setup.php index f331dc4951..7dfe94be11 100644 --- a/includes/Setup.php +++ b/includes/Setup.php @@ -283,7 +283,6 @@ require_once( "$IP/includes/GlobalFunctions.php" ); require_once( "$IP/includes/Hooks.php" ); require_once( "$IP/includes/Namespace.php" ); require_once( "$IP/includes/ProxyTools.php" ); -require_once( "$IP/includes/objectcache/ObjectCache.php" ); require_once( "$IP/includes/ImageFunctions.php" ); wfProfileOut( $fname . '-includes' ); wfProfileIn( $fname . '-misc1' ); @@ -323,9 +322,9 @@ if ( $wgCommandLineMode ) { wfProfileOut( $fname . '-misc1' ); wfProfileIn( $fname . '-memcached' ); -$wgMemc =& wfGetMainCache(); -$messageMemc =& wfGetMessageCacheStorage(); -$parserMemc =& wfGetParserCacheStorage(); +$wgMemc = wfGetMainCache(); +$messageMemc = wfGetMessageCacheStorage(); +$parserMemc = wfGetParserCacheStorage(); wfDebug( 'CACHES: ' . get_class( $wgMemc ) . '[main] ' . get_class( $messageMemc ) . '[message] ' . diff --git a/includes/objectcache/BagOStuff.php b/includes/objectcache/BagOStuff.php index f85722ba69..adb6abcd7b 100644 --- a/includes/objectcache/BagOStuff.php +++ b/includes/objectcache/BagOStuff.php @@ -43,7 +43,7 @@ abstract class BagOStuff { var $debugMode = false; - public function set_debug( $bool ) { + public function setDebug( $bool ) { $this->debugMode = $bool; } @@ -87,22 +87,6 @@ abstract class BagOStuff { } /* *** Emulated functions *** */ - /* Better performance can likely be got with custom written versions */ - public function get_multi( $keys ) { - $out = array(); - - foreach ( $keys as $key ) { - $out[$key] = $this->get( $key ); - } - - return $out; - } - - public function set_multi( $hash, $exptime = 0 ) { - foreach ( $hash as $key => $value ) { - $this->set( $key, $value, $exptime ); - } - } public function add( $key, $value, $exptime = 0 ) { if ( !$this->get( $key ) ) { @@ -112,18 +96,6 @@ abstract class BagOStuff { } } - public function add_multi( $hash, $exptime = 0 ) { - foreach ( $hash as $key => $value ) { - $this->add( $key, $value, $exptime ); - } - } - - public function delete_multi( $keys, $time = 0 ) { - foreach ( $keys as $key ) { - $this->delete( $key, $time ); - } - } - public function replace( $key, $value, $exptime = 0 ) { if ( $this->get( $key ) !== false ) { $this->set( $key, $value, $exptime ); diff --git a/includes/objectcache/EmptyBagOStuff.php b/includes/objectcache/EmptyBagOStuff.php new file mode 100644 index 0000000000..f811352f1d --- /dev/null +++ b/includes/objectcache/EmptyBagOStuff.php @@ -0,0 +1,27 @@ + false, * 'compress_threshold' => 10240, - * 'persistant' => true)); + * 'persistent' => true)); * * $mc->add('key', array('some', 'array')); * $mc->replace('key', 'some random string'); @@ -158,12 +158,12 @@ class MWMemcached { var $_compress_threshold; /** - * Are we using persistant links? + * Are we using persistent links? * * @var boolean * @access private */ - var $_persistant; + var $_persistent; /** * If only using one server; contains ip:port to connect to @@ -245,12 +245,11 @@ class MWMemcached { * @return mixed */ public function __construct( $args ) { - global $wgMemCachedTimeout; $this->set_servers( isset( $args['servers'] ) ? $args['servers'] : array() ); $this->_debug = isset( $args['debug'] ) ? $args['debug'] : false; $this->stats = array(); $this->_compress_threshold = isset( $args['compress_threshold'] ) ? $args['compress_threshold'] : 0; - $this->_persistant = isset( $args['persistant'] ) ? $args['persistant'] : false; + $this->_persistent = isset( $args['persistent'] ) ? $args['persistent'] : false; $this->_compress_enable = true; $this->_have_zlib = function_exists( 'gzcompress' ); @@ -258,9 +257,9 @@ class MWMemcached { $this->_host_dead = array(); $this->_timeout_seconds = 0; - $this->_timeout_microseconds = $wgMemCachedTimeout; + $this->_timeout_microseconds = isset( $args['timeout'] ) ? $args['timeout'] : 100000; - $this->_connect_timeout = 0.01; + $this->_connect_timeout = isset( $args['connect_timeout'] ) ? $args['connect_timeout'] : 0.1; $this->_connect_attempts = 2; } @@ -433,7 +432,11 @@ class MWMemcached { } wfProfileOut( __METHOD__ ); - return @$val[$key]; + if ( isset( $val[$key] ) ) { + return $val[$key]; + } else { + return false; + } } // }}} @@ -695,7 +698,7 @@ class MWMemcached { $errno = $errstr = null; for( $i = 0; !$sock && $i < $this->_connect_attempts; $i++ ) { wfSuppressWarnings(); - if ( $this->_persistant == 1 ) { + if ( $this->_persistent == 1 ) { $sock = pfsockopen( $ip, $port, $errno, $errstr, $timeout ); } else { $sock = fsockopen( $ip, $port, $errno, $errstr, $timeout ); diff --git a/includes/objectcache/MemcachedPhpBagOStuff.php b/includes/objectcache/MemcachedPhpBagOStuff.php new file mode 100644 index 0000000000..4538bb0d51 --- /dev/null +++ b/includes/objectcache/MemcachedPhpBagOStuff.php @@ -0,0 +1,116 @@ +client = new MemCachedClientforWiki( $params ); + $this->client->set_servers( $params['servers'] ); + $this->client->set_debug( $params['debug'] ); + } + + public function setDebug( $debug ) { + $this->client->set_debug( $debug ); + } + + public function get( $key ) { + return $this->client->get( $this->encodeKey( $key ) ); + } + + public function set( $key, $value, $exptime = 0 ) { + return $this->client->set( $this->encodeKey( $key ), $value, $exptime ); + } + + public function delete( $key, $time = 0 ) { + return $this->client->delete( $this->encodeKey( $key ), $time ); + } + + public function lock( $key, $timeout = 0 ) { + return $this->client->lock( $this->encodeKey( $key ), $timeout ); + } + + public function unlock( $key ) { + return $this->client->unlock( $this->encodeKey( $key ) ); + } + + public function add( $key, $value, $exptime = 0 ) { + return $this->client->add( $this->encodeKey( $key ), $value, $exptime ); + } + + public function replace( $key, $value, $exptime = 0 ) { + return $this->client->replace( $this->encodeKey( $key ), $value, $exptime ); + } + + public function incr( $key, $value = 1 ) { + return $this->client->incr( $this->encodeKey( $key ), $value ); + } + + public function decr( $key, $value = 1 ) { + return $this->client->decr( $this->encodeKey( $key ), $value ); + } + + /** + * Get the underlying client object. This is provided for debugging + * purposes. + */ + public function getClient() { + return $this->client; + } + + /** + * Encode a key for use on the wire inside the memcached protocol. + * + * We encode spaces and line breaks to avoid protocol errors. We encode + * the other control characters for compatibility with libmemcached + * verify_key. We leave other punctuation alone, to maximise backwards + * compatibility. + */ + public function encodeKey( $key ) { + return preg_replace_callback( '/[\x00-\x20\x25\x7f]+/', + array( $this, 'encodeKeyCallback' ), $key ); + } + + protected function encodeKeyCallback( $m ) { + return urlencode( $m[0] ); + } + + /** + * Decode a key encoded with encodeKey(). This is provided as a convenience + * function for debugging. + */ + public function decodeKey( $key ) { + return urldecode( $key ); + } +} + diff --git a/includes/objectcache/MultiWriteBagOStuff.php b/includes/objectcache/MultiWriteBagOStuff.php new file mode 100644 index 0000000000..0cb47c9a62 --- /dev/null +++ b/includes/objectcache/MultiWriteBagOStuff.php @@ -0,0 +1,95 @@ +caches = array(); + foreach ( $params['caches'] as $cacheInfo ) { + $this->caches[] = ObjectCache::newFromParams( $cacheInfo ); + } + } + + public function setDebug( $debug ) { + $this->doWrite( 'setDebug', $debug ); + } + + public function get( $key ) { + foreach ( $this->caches as $cache ) { + $value = $cache->get( $key ); + if ( $value !== false ) { + return $value; + } + } + return false; + } + + public function set( $key, $value, $exptime = 0 ) { + return $this->doWrite( 'set', $key, $value, $exptime ); + } + + public function delete( $key, $time = 0 ) { + return $this->doWrite( 'delete', $key, $time ); + } + + public function add( $key, $value, $exptime = 0 ) { + return $this->doWrite( 'add', $key, $value, $exptime ); + } + + public function replace( $key, $value, $exptime = 0 ) { + return $this->doWrite( 'replace', $key, $value, $exptime ); + } + + public function incr( $key, $value = 1 ) { + return $this->doWrite( 'incr', $key, $value ); + } + + public function decr( $key, $value = 1 ) { + return $this->doWrite( 'decr', $key, $value ); + } + + public function lock( $key, $timeout = 0 ) { + // Lock only the first cache, to avoid deadlocks + if ( isset( $this->caches[0] ) ) { + return $this->caches[0]->lock( $key, $timeout ); + } else { + return true; + } + } + + public function unlock( $key ) { + if ( isset( $this->caches[0] ) ) { + return $this->caches[0]->unlock( $key ); + } else { + return true; + } + } + + protected function doWrite( $method /*, ... */ ) { + $ret = true; + $args = func_get_args(); + array_shift( $args ); + + foreach ( $this->caches as $cache ) { + $ret = $ret && call_user_func_array( array( $cache, $method ), $args ); + } + return $ret; + } + +} diff --git a/includes/objectcache/ObjectCache.php b/includes/objectcache/ObjectCache.php index 74b7dcd4ee..96dd4cf7b7 100644 --- a/includes/objectcache/ObjectCache.php +++ b/includes/objectcache/ObjectCache.php @@ -5,96 +5,90 @@ * @file * @ingroup Cache */ +class ObjectCache { + static $instances = array(); -global $wgCaches; -$wgCaches = array(); + /** + * Get a cached instance of the specified type of cache object. + */ + static function getInstance( $id ) { + if ( isset( self::$instances[$id] ) ) { + return self::$instances[$id]; + } -/** - * Get a cache object. - * @param $inputType Integer: cache type, one the the CACHE_* constants. - * - * @return BagOStuff - */ -function &wfGetCache( $inputType ) { - global $wgCaches, $wgMemCachedServers, $wgMemCachedDebug, $wgMemCachedPersistent; - $cache = false; + $object = self::newFromId( $id ); + self::$instances[$id] = $object; + return $object; + } - if ( $inputType == CACHE_ANYTHING ) { - reset( $wgCaches ); - $type = key( $wgCaches ); - if ( $type === false || $type === CACHE_NONE ) { - $type = CACHE_DB; + /** + * Create a new cache object of the specified type. + */ + static function newFromId( $id ) { + global $wgObjectCaches; + + if ( !isset( $wgObjectCaches[$id] ) ) { + throw new MWException( "Invalid object cache type \"$id\" requested. " . + "It is not present in \$wgObjectCaches." ); } - } else { - $type = $inputType; + + return self::newFromParams( $wgObjectCaches[$id] ); } - if ( $type == CACHE_MEMCACHED ) { - if ( !array_key_exists( CACHE_MEMCACHED, $wgCaches ) ) { - $wgCaches[CACHE_MEMCACHED] = new MemCachedClientforWiki( - array('persistant' => $wgMemCachedPersistent, 'compress_threshold' => 1500 ) ); - $wgCaches[CACHE_MEMCACHED]->set_servers( $wgMemCachedServers ); - $wgCaches[CACHE_MEMCACHED]->set_debug( $wgMemCachedDebug ); - } - $cache =& $wgCaches[CACHE_MEMCACHED]; - } elseif ( $type == CACHE_ACCEL ) { - if ( !array_key_exists( CACHE_ACCEL, $wgCaches ) ) { - if ( function_exists( 'eaccelerator_get' ) ) { - $wgCaches[CACHE_ACCEL] = new eAccelBagOStuff; - } elseif ( function_exists( 'apc_fetch') ) { - $wgCaches[CACHE_ACCEL] = new APCBagOStuff; - } elseif( function_exists( 'xcache_get' ) ) { - $wgCaches[CACHE_ACCEL] = new XCacheBagOStuff(); - } elseif( function_exists( 'wincache_ucache_get' ) ) { - $wgCaches[CACHE_ACCEL] = new WinCacheBagOStuff(); - } else { - $wgCaches[CACHE_ACCEL] = false; - } - } - if ( $wgCaches[CACHE_ACCEL] !== false ) { - $cache =& $wgCaches[CACHE_ACCEL]; + /** + * Create a new cache object from parameters + */ + static function newFromParams( $params ) { + if ( isset( $params['factory'] ) ) { + return call_user_func( $params['factory'], $params ); + } elseif ( isset( $params['class'] ) ) { + $class = $params['class']; + return new $class( $params ); + } else { + throw new MWException( "The definition of cache type \"$id\" lacks both " . + "factory and class parameters." ); } - } elseif ( $type == CACHE_DBA ) { - if ( !array_key_exists( CACHE_DBA, $wgCaches ) ) { - $wgCaches[CACHE_DBA] = new DBABagOStuff; - } - $cache =& $wgCaches[CACHE_DBA]; } - if ( $type == CACHE_DB || ( $inputType == CACHE_ANYTHING && $cache === false ) ) { - if ( !array_key_exists( CACHE_DB, $wgCaches ) ) { - $wgCaches[CACHE_DB] = new SqlBagOStuff('objectcache'); + /** + * Factory function referenced from DefaultSettings.php for CACHE_ANYTHING + */ + static function newAnything( $params ) { + global $wgMainCacheType, $wgMessageCacheType, $wgParserCacheType; + $candidates = array( $wgMainCacheType, $wgMessageCacheType, $wgParserCacheType ); + foreach ( $candidates as $candidate ) { + if ( $candidate !== CACHE_NONE && $candidate !== CACHE_ANYTHING ) { + return self::newFromId( $candidate ); + } } - $cache =& $wgCaches[CACHE_DB]; + return self::newFromId( CACHE_DB ); } - if ( $cache === false ) { - if ( !array_key_exists( CACHE_NONE, $wgCaches ) ) { - $wgCaches[CACHE_NONE] = new FakeMemCachedClient; + /** + * Factory function referenced from DefaultSettings.php for CACHE_ACCEL. + */ + static function newAccelerator( $params ) { + if ( function_exists( 'eaccelerator_get' ) ) { + $id = 'eaccelerator'; + } elseif ( function_exists( 'apc_fetch') ) { + $id = 'apc'; + } elseif( function_exists( 'xcache_get' ) ) { + $id = 'xcache'; + } elseif( function_exists( 'wincache_ucache_get' ) ) { + $id = 'wincache'; + } else { + throw new MWException( "CACHE_ACCEL requested but no suitable object " . + "cache is present. You may want to install APC." ); } - $cache =& $wgCaches[CACHE_NONE]; + return self::newFromId( $id ); } - return $cache; -} - -/** Get the main cache object */ -function &wfGetMainCache() { - global $wgMainCacheType; - $ret =& wfGetCache( $wgMainCacheType ); - return $ret; -} - -/** Get the cache object used by the message cache */ -function &wfGetMessageCacheStorage() { - global $wgMessageCacheType; - $ret =& wfGetCache( $wgMessageCacheType ); - return $ret; -} - -/** Get the cache object used by the parser cache */ -function &wfGetParserCacheStorage() { - global $wgParserCacheType; - $ret =& wfGetCache( $wgParserCacheType ); - return $ret; + /** + * Factory function that creates a memcached client object. + * The idea of this is that it might eventually detect and automatically + * support the PECL extension, assuming someone can get it to compile. + */ + static function newMemcached( $params ) { + return new MemcachedPhpBagOStuff( $params ); + } } diff --git a/includes/objectcache/SqlBagOStuff.php b/includes/objectcache/SqlBagOStuff.php index e58ab51c0a..bed2e1287b 100644 --- a/includes/objectcache/SqlBagOStuff.php +++ b/includes/objectcache/SqlBagOStuff.php @@ -6,21 +6,40 @@ * @ingroup Cache */ class SqlBagOStuff extends BagOStuff { - var $lb, $db; + var $lb, $db, $serverInfo; var $lastExpireAll = 0; + /** + * Constructor. Parameters are: + * - server: A server info structure in the format required by each + * element in $wgDBServers. + */ + public function __construct( $params ) { + if ( isset( $params['server'] ) ) { + $this->serverInfo = $params['server']; + $this->serverInfo['load'] = 1; + } + } + protected function getDB() { if ( !isset( $this->db ) ) { - /* We must keep a separate connection to MySQL in order to avoid deadlocks - * However, SQLite has an opposite behaviour. - * @todo Investigate behaviour for other databases - */ - if ( wfGetDB( DB_MASTER )->getType() == 'sqlite' ) { - $this->db = wfGetDB( DB_MASTER ); - } else { - $this->lb = wfGetLBFactory()->newMainLB(); + # If server connection info was given, use that + if ( $this->serverInfo ) { + $this->lb = new LoadBalancer( array( + 'servers' => array( $this->serverInfo ) ) ); $this->db = $this->lb->getConnection( DB_MASTER ); $this->db->clearFlag( DBO_TRX ); + } else { + # We must keep a separate connection to MySQL in order to avoid deadlocks + # However, SQLite has an opposite behaviour. + # @todo Investigate behaviour for other databases + if ( wfGetDB( DB_MASTER )->getType() == 'sqlite' ) { + $this->db = wfGetDB( DB_MASTER ); + } else { + $this->lb = wfGetLBFactory()->newMainLB(); + $this->db = $this->lb->getConnection( DB_MASTER ); + $this->db->clearFlag( DBO_TRX ); + } } } diff --git a/maintenance/mcc.php b/maintenance/mcc.php index 13d0d6b062..024452788f 100644 --- a/maintenance/mcc.php +++ b/maintenance/mcc.php @@ -25,7 +25,7 @@ /** */ require_once( dirname( __FILE__ ) . '/commandLine.inc' ); -$mcc = new MWMemcached( array( 'persistant' => true/*, 'debug' => true*/ ) ); +$mcc = new MWMemcached( array( 'persistent' => true/*, 'debug' => true*/ ) ); $mcc->set_servers( $wgMemCachedServers ); # $mcc->set_debug( true ); diff --git a/tests/phpunit/includes/parser/NewParserTest.php b/tests/phpunit/includes/parser/NewParserTest.php index 391e925176..35b7540ed2 100644 --- a/tests/phpunit/includes/parser/NewParserTest.php +++ b/tests/phpunit/includes/parser/NewParserTest.php @@ -70,9 +70,9 @@ class NewParserTest extends MediaWikiTestCase { $tmpGlobals['wgEnableParserCache'] = false; $tmpGlobals['wgHooks'] = $wgHooks; $tmpGlobals['wgDeferredUpdateList'] = array(); - $tmpGlobals['wgMemc'] = &wfGetMainCache(); - $tmpGlobals['messageMemc'] = &wfGetMessageCacheStorage(); - $tmpGlobals['parserMemc'] = &wfGetParserCacheStorage(); + $tmpGlobals['wgMemc'] = wfGetMainCache(); + $tmpGlobals['messageMemc'] = wfGetMessageCacheStorage(); + $tmpGlobals['parserMemc'] = wfGetParserCacheStorage(); // $tmpGlobals['wgContLang'] = new StubContLang; $tmpGlobals['wgUser'] = new User; diff --git a/tests/phpunit/suites/UploadFromUrlTestSuite.php b/tests/phpunit/suites/UploadFromUrlTestSuite.php index cfa7cf5620..db8efcef10 100644 --- a/tests/phpunit/suites/UploadFromUrlTestSuite.php +++ b/tests/phpunit/suites/UploadFromUrlTestSuite.php @@ -42,9 +42,9 @@ class UploadFromUrlTestSuite extends PHPUnit_Framework_TestSuite { $wgEnableParserCache = false; $wgDeferredUpdateList = array(); - $wgMemc = &wfGetMainCache(); - $messageMemc = &wfGetMessageCacheStorage(); - $parserMemc = &wfGetParserCacheStorage(); + $wgMemc = wfGetMainCache(); + $messageMemc = wfGetMessageCacheStorage(); + $parserMemc = wfGetParserCacheStorage(); // $wgContLang = new StubContLang; $wgUser = new User; -- 2.20.1