* 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
95 lines
2.4 KiB
PHP
95 lines
2.4 KiB
PHP
<?php
|
|
|
|
/**
|
|
* A cache class that replicates all writes to multiple child caches. Reads
|
|
* are implemented by reading from the caches in the order they are given in
|
|
* the configuration until a cache gives a positive result.
|
|
*/
|
|
class MultiWriteBagOStuff extends BagOStuff {
|
|
var $caches;
|
|
|
|
/**
|
|
* Constructor. Parameters are:
|
|
*
|
|
* - caches: This should have a numbered array of cache parameter
|
|
* structures, in the style required by $wgObjectCaches. See
|
|
* the documentation of $wgObjectCaches for more detail.
|
|
*/
|
|
public function __construct( $params ) {
|
|
if ( !isset( $params['caches'] ) ) {
|
|
throw new MWException( __METHOD__.': the caches parameter is required' );
|
|
}
|
|
|
|
$this->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;
|
|
}
|
|
|
|
}
|