Index: trunk/phase3/maintenance/mcc.php |
— | — | @@ -25,7 +25,7 @@ |
26 | 26 | /** */ |
27 | 27 | require_once( dirname( __FILE__ ) . '/commandLine.inc' ); |
28 | 28 | |
29 | | -$mcc = new MWMemcached( array( 'persistant' => true/*, 'debug' => true*/ ) ); |
| 29 | +$mcc = new MWMemcached( array( 'persistent' => true/*, 'debug' => true*/ ) ); |
30 | 30 | $mcc->set_servers( $wgMemCachedServers ); |
31 | 31 | # $mcc->set_debug( true ); |
32 | 32 | |
Index: trunk/phase3/tests/phpunit/includes/parser/NewParserTest.php |
— | — | @@ -70,9 +70,9 @@ |
71 | 71 | $tmpGlobals['wgEnableParserCache'] = false; |
72 | 72 | $tmpGlobals['wgHooks'] = $wgHooks; |
73 | 73 | $tmpGlobals['wgDeferredUpdateList'] = array(); |
74 | | - $tmpGlobals['wgMemc'] = &wfGetMainCache(); |
75 | | - $tmpGlobals['messageMemc'] = &wfGetMessageCacheStorage(); |
76 | | - $tmpGlobals['parserMemc'] = &wfGetParserCacheStorage(); |
| 74 | + $tmpGlobals['wgMemc'] = wfGetMainCache(); |
| 75 | + $tmpGlobals['messageMemc'] = wfGetMessageCacheStorage(); |
| 76 | + $tmpGlobals['parserMemc'] = wfGetParserCacheStorage(); |
77 | 77 | |
78 | 78 | // $tmpGlobals['wgContLang'] = new StubContLang; |
79 | 79 | $tmpGlobals['wgUser'] = new User; |
Index: trunk/phase3/tests/phpunit/suites/UploadFromUrlTestSuite.php |
— | — | @@ -42,9 +42,9 @@ |
43 | 43 | |
44 | 44 | $wgEnableParserCache = false; |
45 | 45 | $wgDeferredUpdateList = array(); |
46 | | - $wgMemc = &wfGetMainCache(); |
47 | | - $messageMemc = &wfGetMessageCacheStorage(); |
48 | | - $parserMemc = &wfGetParserCacheStorage(); |
| 46 | + $wgMemc = wfGetMainCache(); |
| 47 | + $messageMemc = wfGetMessageCacheStorage(); |
| 48 | + $parserMemc = wfGetParserCacheStorage(); |
49 | 49 | |
50 | 50 | // $wgContLang = new StubContLang; |
51 | 51 | $wgUser = new User; |
Index: trunk/phase3/includes/GlobalFunctions.php |
— | — | @@ -3357,3 +3357,33 @@ |
3358 | 3358 | } |
3359 | 3359 | return $ret; |
3360 | 3360 | } |
| 3361 | + |
| 3362 | + |
| 3363 | +/** |
| 3364 | + * Get a cache object. |
| 3365 | + * @param $inputType Cache type, one the the CACHE_* constants. |
| 3366 | + * |
| 3367 | + * @return BagOStuff |
| 3368 | + */ |
| 3369 | +function wfGetCache( $inputType ) { |
| 3370 | + return ObjectCache::getInstance( $inputType ); |
| 3371 | +} |
| 3372 | + |
| 3373 | +/** Get the main cache object */ |
| 3374 | +function wfGetMainCache() { |
| 3375 | + global $wgMainCacheType; |
| 3376 | + return ObjectCache::getInstance( $wgMainCacheType ); |
| 3377 | +} |
| 3378 | + |
| 3379 | +/** Get the cache object used by the message cache */ |
| 3380 | +function wfGetMessageCacheStorage() { |
| 3381 | + global $wgMessageCacheType; |
| 3382 | + return ObjectCache::getInstance( $wgMessageCacheType ); |
| 3383 | +} |
| 3384 | + |
| 3385 | +/** Get the cache object used by the parser cache */ |
| 3386 | +function wfGetParserCacheStorage() { |
| 3387 | + global $wgParserCacheType; |
| 3388 | + return ObjectCache::getInstance( $wgParserCacheType ); |
| 3389 | +} |
| 3390 | + |
Index: trunk/phase3/includes/objectcache/ObjectCache.php |
— | — | @@ -5,96 +5,90 @@ |
6 | 6 | * @file |
7 | 7 | * @ingroup Cache |
8 | 8 | */ |
| 9 | +class ObjectCache { |
| 10 | + static $instances = array(); |
9 | 11 | |
10 | | -global $wgCaches; |
11 | | -$wgCaches = array(); |
| 12 | + /** |
| 13 | + * Get a cached instance of the specified type of cache object. |
| 14 | + */ |
| 15 | + static function getInstance( $id ) { |
| 16 | + if ( isset( self::$instances[$id] ) ) { |
| 17 | + return self::$instances[$id]; |
| 18 | + } |
12 | 19 | |
13 | | -/** |
14 | | - * Get a cache object. |
15 | | - * @param $inputType Integer: cache type, one the the CACHE_* constants. |
16 | | - * |
17 | | - * @return BagOStuff |
18 | | - */ |
19 | | -function &wfGetCache( $inputType ) { |
20 | | - global $wgCaches, $wgMemCachedServers, $wgMemCachedDebug, $wgMemCachedPersistent; |
21 | | - $cache = false; |
| 20 | + $object = self::newFromId( $id ); |
| 21 | + self::$instances[$id] = $object; |
| 22 | + return $object; |
| 23 | + } |
22 | 24 | |
23 | | - if ( $inputType == CACHE_ANYTHING ) { |
24 | | - reset( $wgCaches ); |
25 | | - $type = key( $wgCaches ); |
26 | | - if ( $type === false || $type === CACHE_NONE ) { |
27 | | - $type = CACHE_DB; |
| 25 | + /** |
| 26 | + * Create a new cache object of the specified type. |
| 27 | + */ |
| 28 | + static function newFromId( $id ) { |
| 29 | + global $wgObjectCaches; |
| 30 | + |
| 31 | + if ( !isset( $wgObjectCaches[$id] ) ) { |
| 32 | + throw new MWException( "Invalid object cache type \"$id\" requested. " . |
| 33 | + "It is not present in \$wgObjectCaches." ); |
28 | 34 | } |
29 | | - } else { |
30 | | - $type = $inputType; |
| 35 | + |
| 36 | + return self::newFromParams( $wgObjectCaches[$id] ); |
31 | 37 | } |
32 | 38 | |
33 | | - if ( $type == CACHE_MEMCACHED ) { |
34 | | - if ( !array_key_exists( CACHE_MEMCACHED, $wgCaches ) ) { |
35 | | - $wgCaches[CACHE_MEMCACHED] = new MemCachedClientforWiki( |
36 | | - array('persistant' => $wgMemCachedPersistent, 'compress_threshold' => 1500 ) ); |
37 | | - $wgCaches[CACHE_MEMCACHED]->set_servers( $wgMemCachedServers ); |
38 | | - $wgCaches[CACHE_MEMCACHED]->set_debug( $wgMemCachedDebug ); |
| 39 | + /** |
| 40 | + * Create a new cache object from parameters |
| 41 | + */ |
| 42 | + static function newFromParams( $params ) { |
| 43 | + if ( isset( $params['factory'] ) ) { |
| 44 | + return call_user_func( $params['factory'], $params ); |
| 45 | + } elseif ( isset( $params['class'] ) ) { |
| 46 | + $class = $params['class']; |
| 47 | + return new $class( $params ); |
| 48 | + } else { |
| 49 | + throw new MWException( "The definition of cache type \"$id\" lacks both " . |
| 50 | + "factory and class parameters." ); |
39 | 51 | } |
40 | | - $cache =& $wgCaches[CACHE_MEMCACHED]; |
41 | | - } elseif ( $type == CACHE_ACCEL ) { |
42 | | - if ( !array_key_exists( CACHE_ACCEL, $wgCaches ) ) { |
43 | | - if ( function_exists( 'eaccelerator_get' ) ) { |
44 | | - $wgCaches[CACHE_ACCEL] = new eAccelBagOStuff; |
45 | | - } elseif ( function_exists( 'apc_fetch') ) { |
46 | | - $wgCaches[CACHE_ACCEL] = new APCBagOStuff; |
47 | | - } elseif( function_exists( 'xcache_get' ) ) { |
48 | | - $wgCaches[CACHE_ACCEL] = new XCacheBagOStuff(); |
49 | | - } elseif( function_exists( 'wincache_ucache_get' ) ) { |
50 | | - $wgCaches[CACHE_ACCEL] = new WinCacheBagOStuff(); |
51 | | - } else { |
52 | | - $wgCaches[CACHE_ACCEL] = false; |
53 | | - } |
54 | | - } |
55 | | - if ( $wgCaches[CACHE_ACCEL] !== false ) { |
56 | | - $cache =& $wgCaches[CACHE_ACCEL]; |
57 | | - } |
58 | | - } elseif ( $type == CACHE_DBA ) { |
59 | | - if ( !array_key_exists( CACHE_DBA, $wgCaches ) ) { |
60 | | - $wgCaches[CACHE_DBA] = new DBABagOStuff; |
61 | | - } |
62 | | - $cache =& $wgCaches[CACHE_DBA]; |
63 | 52 | } |
64 | 53 | |
65 | | - if ( $type == CACHE_DB || ( $inputType == CACHE_ANYTHING && $cache === false ) ) { |
66 | | - if ( !array_key_exists( CACHE_DB, $wgCaches ) ) { |
67 | | - $wgCaches[CACHE_DB] = new SqlBagOStuff('objectcache'); |
| 54 | + /** |
| 55 | + * Factory function referenced from DefaultSettings.php for CACHE_ANYTHING |
| 56 | + */ |
| 57 | + static function newAnything( $params ) { |
| 58 | + global $wgMainCacheType, $wgMessageCacheType, $wgParserCacheType; |
| 59 | + $candidates = array( $wgMainCacheType, $wgMessageCacheType, $wgParserCacheType ); |
| 60 | + foreach ( $candidates as $candidate ) { |
| 61 | + if ( $candidate !== CACHE_NONE && $candidate !== CACHE_ANYTHING ) { |
| 62 | + return self::newFromId( $candidate ); |
| 63 | + } |
68 | 64 | } |
69 | | - $cache =& $wgCaches[CACHE_DB]; |
| 65 | + return self::newFromId( CACHE_DB ); |
70 | 66 | } |
71 | 67 | |
72 | | - if ( $cache === false ) { |
73 | | - if ( !array_key_exists( CACHE_NONE, $wgCaches ) ) { |
74 | | - $wgCaches[CACHE_NONE] = new FakeMemCachedClient; |
| 68 | + /** |
| 69 | + * Factory function referenced from DefaultSettings.php for CACHE_ACCEL. |
| 70 | + */ |
| 71 | + static function newAccelerator( $params ) { |
| 72 | + if ( function_exists( 'eaccelerator_get' ) ) { |
| 73 | + $id = 'eaccelerator'; |
| 74 | + } elseif ( function_exists( 'apc_fetch') ) { |
| 75 | + $id = 'apc'; |
| 76 | + } elseif( function_exists( 'xcache_get' ) ) { |
| 77 | + $id = 'xcache'; |
| 78 | + } elseif( function_exists( 'wincache_ucache_get' ) ) { |
| 79 | + $id = 'wincache'; |
| 80 | + } else { |
| 81 | + throw new MWException( "CACHE_ACCEL requested but no suitable object " . |
| 82 | + "cache is present. You may want to install APC." ); |
75 | 83 | } |
76 | | - $cache =& $wgCaches[CACHE_NONE]; |
| 84 | + return self::newFromId( $id ); |
77 | 85 | } |
78 | 86 | |
79 | | - return $cache; |
| 87 | + /** |
| 88 | + * Factory function that creates a memcached client object. |
| 89 | + * The idea of this is that it might eventually detect and automatically |
| 90 | + * support the PECL extension, assuming someone can get it to compile. |
| 91 | + */ |
| 92 | + static function newMemcached( $params ) { |
| 93 | + return new MemcachedPhpBagOStuff( $params ); |
| 94 | + } |
80 | 95 | } |
81 | | - |
82 | | -/** Get the main cache object */ |
83 | | -function &wfGetMainCache() { |
84 | | - global $wgMainCacheType; |
85 | | - $ret =& wfGetCache( $wgMainCacheType ); |
86 | | - return $ret; |
87 | | -} |
88 | | - |
89 | | -/** Get the cache object used by the message cache */ |
90 | | -function &wfGetMessageCacheStorage() { |
91 | | - global $wgMessageCacheType; |
92 | | - $ret =& wfGetCache( $wgMessageCacheType ); |
93 | | - return $ret; |
94 | | -} |
95 | | - |
96 | | -/** Get the cache object used by the parser cache */ |
97 | | -function &wfGetParserCacheStorage() { |
98 | | - global $wgParserCacheType; |
99 | | - $ret =& wfGetCache( $wgParserCacheType ); |
100 | | - return $ret; |
101 | | -} |
Index: trunk/phase3/includes/objectcache/EmptyBagOStuff.php |
— | — | @@ -0,0 +1,27 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + * A BagOStuff object with no objects in it. Used to provide a no-op object to calling code. |
| 6 | + * |
| 7 | + * @ingroup Cache |
| 8 | + */ |
| 9 | +class EmptyBagOStuff extends BagOStuff { |
| 10 | + function get( $key ) { |
| 11 | + return false; |
| 12 | + } |
| 13 | + |
| 14 | + function set( $key, $value, $exp = 0 ) { |
| 15 | + return true; |
| 16 | + } |
| 17 | + |
| 18 | + function delete( $key, $time = 0 ) { |
| 19 | + return true; |
| 20 | + } |
| 21 | +} |
| 22 | + |
| 23 | +/** |
| 24 | + * Backwards compatibility alias for EmptyBagOStuff |
| 25 | + * @deprecated |
| 26 | + */ |
| 27 | +class FakeMemCachedClient extends EmptyBagOStuff { |
| 28 | +} |
Property changes on: trunk/phase3/includes/objectcache/EmptyBagOStuff.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 29 | + native |
Index: trunk/phase3/includes/objectcache/MemcachedPhpBagOStuff.php |
— | — | @@ -0,0 +1,116 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + * A wrapper class for the pure-PHP memcached client, exposing a BagOStuff interface. |
| 6 | + */ |
| 7 | +class MemcachedPhpBagOStuff extends BagOStuff { |
| 8 | + /** |
| 9 | + * Constructor. |
| 10 | + * |
| 11 | + * Available parameters are: |
| 12 | + * - servers: The list of IP:port combinations holding the memcached servers. |
| 13 | + * - debug: Whether to set the debug flag in the underlying client. |
| 14 | + * - persistent: Whether to use a persistent connection |
| 15 | + * - compress_threshold: The minimum size an object must be before it is compressed |
| 16 | + * - timeout: The read timeout in microseconds |
| 17 | + * - connect_timeout: The connect timeout in seconds |
| 18 | + */ |
| 19 | + function __construct( $params ) { |
| 20 | + if ( !isset( $params['servers'] ) ) { |
| 21 | + $params['servers'] = $GLOBALS['wgMemCachedServers']; |
| 22 | + } |
| 23 | + if ( !isset( $params['debug'] ) ) { |
| 24 | + $params['debug'] = $GLOBALS['wgMemCachedDebug']; |
| 25 | + } |
| 26 | + if ( !isset( $params['persistent'] ) ) { |
| 27 | + $params['persistent'] = $GLOBALS['wgMemCachedPersistent']; |
| 28 | + } |
| 29 | + if ( !isset( $params['compress_threshold'] ) ) { |
| 30 | + $params['compress_threshold'] = 1500; |
| 31 | + } |
| 32 | + if ( !isset( $params['timeout'] ) ) { |
| 33 | + $params['timeout'] = $GLOBALS['wgMemCachedTimeout']; |
| 34 | + } |
| 35 | + if ( !isset( $params['connect_timeout'] ) ) { |
| 36 | + $params['connect_timeout'] = 0.1; |
| 37 | + } |
| 38 | + |
| 39 | + $this->client = new MemCachedClientforWiki( $params ); |
| 40 | + $this->client->set_servers( $params['servers'] ); |
| 41 | + $this->client->set_debug( $params['debug'] ); |
| 42 | + } |
| 43 | + |
| 44 | + public function setDebug( $debug ) { |
| 45 | + $this->client->set_debug( $debug ); |
| 46 | + } |
| 47 | + |
| 48 | + public function get( $key ) { |
| 49 | + return $this->client->get( $this->encodeKey( $key ) ); |
| 50 | + } |
| 51 | + |
| 52 | + public function set( $key, $value, $exptime = 0 ) { |
| 53 | + return $this->client->set( $this->encodeKey( $key ), $value, $exptime ); |
| 54 | + } |
| 55 | + |
| 56 | + public function delete( $key, $time = 0 ) { |
| 57 | + return $this->client->delete( $this->encodeKey( $key ), $time ); |
| 58 | + } |
| 59 | + |
| 60 | + public function lock( $key, $timeout = 0 ) { |
| 61 | + return $this->client->lock( $this->encodeKey( $key ), $timeout ); |
| 62 | + } |
| 63 | + |
| 64 | + public function unlock( $key ) { |
| 65 | + return $this->client->unlock( $this->encodeKey( $key ) ); |
| 66 | + } |
| 67 | + |
| 68 | + public function add( $key, $value, $exptime = 0 ) { |
| 69 | + return $this->client->add( $this->encodeKey( $key ), $value, $exptime ); |
| 70 | + } |
| 71 | + |
| 72 | + public function replace( $key, $value, $exptime = 0 ) { |
| 73 | + return $this->client->replace( $this->encodeKey( $key ), $value, $exptime ); |
| 74 | + } |
| 75 | + |
| 76 | + public function incr( $key, $value = 1 ) { |
| 77 | + return $this->client->incr( $this->encodeKey( $key ), $value ); |
| 78 | + } |
| 79 | + |
| 80 | + public function decr( $key, $value = 1 ) { |
| 81 | + return $this->client->decr( $this->encodeKey( $key ), $value ); |
| 82 | + } |
| 83 | + |
| 84 | + /** |
| 85 | + * Get the underlying client object. This is provided for debugging |
| 86 | + * purposes. |
| 87 | + */ |
| 88 | + public function getClient() { |
| 89 | + return $this->client; |
| 90 | + } |
| 91 | + |
| 92 | + /** |
| 93 | + * Encode a key for use on the wire inside the memcached protocol. |
| 94 | + * |
| 95 | + * We encode spaces and line breaks to avoid protocol errors. We encode |
| 96 | + * the other control characters for compatibility with libmemcached |
| 97 | + * verify_key. We leave other punctuation alone, to maximise backwards |
| 98 | + * compatibility. |
| 99 | + */ |
| 100 | + public function encodeKey( $key ) { |
| 101 | + return preg_replace_callback( '/[\x00-\x20\x25\x7f]+/', |
| 102 | + array( $this, 'encodeKeyCallback' ), $key ); |
| 103 | + } |
| 104 | + |
| 105 | + protected function encodeKeyCallback( $m ) { |
| 106 | + return urlencode( $m[0] ); |
| 107 | + } |
| 108 | + |
| 109 | + /** |
| 110 | + * Decode a key encoded with encodeKey(). This is provided as a convenience |
| 111 | + * function for debugging. |
| 112 | + */ |
| 113 | + public function decodeKey( $key ) { |
| 114 | + return urldecode( $key ); |
| 115 | + } |
| 116 | +} |
| 117 | + |
Property changes on: trunk/phase3/includes/objectcache/MemcachedPhpBagOStuff.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 118 | + native |
Index: trunk/phase3/includes/objectcache/BagOStuff.php |
— | — | @@ -43,7 +43,7 @@ |
44 | 44 | abstract class BagOStuff { |
45 | 45 | var $debugMode = false; |
46 | 46 | |
47 | | - public function set_debug( $bool ) { |
| 47 | + public function setDebug( $bool ) { |
48 | 48 | $this->debugMode = $bool; |
49 | 49 | } |
50 | 50 | |
— | — | @@ -87,23 +87,7 @@ |
88 | 88 | } |
89 | 89 | |
90 | 90 | /* *** Emulated functions *** */ |
91 | | - /* Better performance can likely be got with custom written versions */ |
92 | | - public function get_multi( $keys ) { |
93 | | - $out = array(); |
94 | 91 | |
95 | | - foreach ( $keys as $key ) { |
96 | | - $out[$key] = $this->get( $key ); |
97 | | - } |
98 | | - |
99 | | - return $out; |
100 | | - } |
101 | | - |
102 | | - public function set_multi( $hash, $exptime = 0 ) { |
103 | | - foreach ( $hash as $key => $value ) { |
104 | | - $this->set( $key, $value, $exptime ); |
105 | | - } |
106 | | - } |
107 | | - |
108 | 92 | public function add( $key, $value, $exptime = 0 ) { |
109 | 93 | if ( !$this->get( $key ) ) { |
110 | 94 | $this->set( $key, $value, $exptime ); |
— | — | @@ -112,18 +96,6 @@ |
113 | 97 | } |
114 | 98 | } |
115 | 99 | |
116 | | - public function add_multi( $hash, $exptime = 0 ) { |
117 | | - foreach ( $hash as $key => $value ) { |
118 | | - $this->add( $key, $value, $exptime ); |
119 | | - } |
120 | | - } |
121 | | - |
122 | | - public function delete_multi( $keys, $time = 0 ) { |
123 | | - foreach ( $keys as $key ) { |
124 | | - $this->delete( $key, $time ); |
125 | | - } |
126 | | - } |
127 | | - |
128 | 100 | public function replace( $key, $value, $exptime = 0 ) { |
129 | 101 | if ( $this->get( $key ) !== false ) { |
130 | 102 | $this->set( $key, $value, $exptime ); |
Index: trunk/phase3/includes/objectcache/SqlBagOStuff.php |
— | — | @@ -6,21 +6,40 @@ |
7 | 7 | * @ingroup Cache |
8 | 8 | */ |
9 | 9 | class SqlBagOStuff extends BagOStuff { |
10 | | - var $lb, $db; |
| 10 | + var $lb, $db, $serverInfo; |
11 | 11 | var $lastExpireAll = 0; |
12 | 12 | |
| 13 | + /** |
| 14 | + * Constructor. Parameters are: |
| 15 | + * - server: A server info structure in the format required by each |
| 16 | + * element in $wgDBServers. |
| 17 | + */ |
| 18 | + public function __construct( $params ) { |
| 19 | + if ( isset( $params['server'] ) ) { |
| 20 | + $this->serverInfo = $params['server']; |
| 21 | + $this->serverInfo['load'] = 1; |
| 22 | + } |
| 23 | + } |
| 24 | + |
13 | 25 | protected function getDB() { |
14 | 26 | if ( !isset( $this->db ) ) { |
15 | | - /* We must keep a separate connection to MySQL in order to avoid deadlocks |
16 | | - * However, SQLite has an opposite behaviour. |
17 | | - * @todo Investigate behaviour for other databases |
18 | | - */ |
19 | | - if ( wfGetDB( DB_MASTER )->getType() == 'sqlite' ) { |
20 | | - $this->db = wfGetDB( DB_MASTER ); |
21 | | - } else { |
22 | | - $this->lb = wfGetLBFactory()->newMainLB(); |
| 27 | + # If server connection info was given, use that |
| 28 | + if ( $this->serverInfo ) { |
| 29 | + $this->lb = new LoadBalancer( array( |
| 30 | + 'servers' => array( $this->serverInfo ) ) ); |
23 | 31 | $this->db = $this->lb->getConnection( DB_MASTER ); |
24 | 32 | $this->db->clearFlag( DBO_TRX ); |
| 33 | + } else { |
| 34 | + # We must keep a separate connection to MySQL in order to avoid deadlocks |
| 35 | + # However, SQLite has an opposite behaviour. |
| 36 | + # @todo Investigate behaviour for other databases |
| 37 | + if ( wfGetDB( DB_MASTER )->getType() == 'sqlite' ) { |
| 38 | + $this->db = wfGetDB( DB_MASTER ); |
| 39 | + } else { |
| 40 | + $this->lb = wfGetLBFactory()->newMainLB(); |
| 41 | + $this->db = $this->lb->getConnection( DB_MASTER ); |
| 42 | + $this->db->clearFlag( DBO_TRX ); |
| 43 | + } |
25 | 44 | } |
26 | 45 | } |
27 | 46 | |
Index: trunk/phase3/includes/objectcache/MemcachedClient.php |
— | — | @@ -51,7 +51,7 @@ |
52 | 52 | * '127.0.0.1:10020'), |
53 | 53 | * 'debug' => false, |
54 | 54 | * 'compress_threshold' => 10240, |
55 | | - * 'persistant' => true)); |
| 55 | + * 'persistent' => true)); |
56 | 56 | * |
57 | 57 | * $mc->add('key', array('some', 'array')); |
58 | 58 | * $mc->replace('key', 'some random string'); |
— | — | @@ -158,12 +158,12 @@ |
159 | 159 | var $_compress_threshold; |
160 | 160 | |
161 | 161 | /** |
162 | | - * Are we using persistant links? |
| 162 | + * Are we using persistent links? |
163 | 163 | * |
164 | 164 | * @var boolean |
165 | 165 | * @access private |
166 | 166 | */ |
167 | | - var $_persistant; |
| 167 | + var $_persistent; |
168 | 168 | |
169 | 169 | /** |
170 | 170 | * If only using one server; contains ip:port to connect to |
— | — | @@ -245,12 +245,11 @@ |
246 | 246 | * @return mixed |
247 | 247 | */ |
248 | 248 | public function __construct( $args ) { |
249 | | - global $wgMemCachedTimeout; |
250 | 249 | $this->set_servers( isset( $args['servers'] ) ? $args['servers'] : array() ); |
251 | 250 | $this->_debug = isset( $args['debug'] ) ? $args['debug'] : false; |
252 | 251 | $this->stats = array(); |
253 | 252 | $this->_compress_threshold = isset( $args['compress_threshold'] ) ? $args['compress_threshold'] : 0; |
254 | | - $this->_persistant = isset( $args['persistant'] ) ? $args['persistant'] : false; |
| 253 | + $this->_persistent = isset( $args['persistent'] ) ? $args['persistent'] : false; |
255 | 254 | $this->_compress_enable = true; |
256 | 255 | $this->_have_zlib = function_exists( 'gzcompress' ); |
257 | 256 | |
— | — | @@ -258,9 +257,9 @@ |
259 | 258 | $this->_host_dead = array(); |
260 | 259 | |
261 | 260 | $this->_timeout_seconds = 0; |
262 | | - $this->_timeout_microseconds = $wgMemCachedTimeout; |
| 261 | + $this->_timeout_microseconds = isset( $args['timeout'] ) ? $args['timeout'] : 100000; |
263 | 262 | |
264 | | - $this->_connect_timeout = 0.01; |
| 263 | + $this->_connect_timeout = isset( $args['connect_timeout'] ) ? $args['connect_timeout'] : 0.1; |
265 | 264 | $this->_connect_attempts = 2; |
266 | 265 | } |
267 | 266 | |
— | — | @@ -433,7 +432,11 @@ |
434 | 433 | } |
435 | 434 | |
436 | 435 | wfProfileOut( __METHOD__ ); |
437 | | - return @$val[$key]; |
| 436 | + if ( isset( $val[$key] ) ) { |
| 437 | + return $val[$key]; |
| 438 | + } else { |
| 439 | + return false; |
| 440 | + } |
438 | 441 | } |
439 | 442 | |
440 | 443 | // }}} |
— | — | @@ -695,7 +698,7 @@ |
696 | 699 | $errno = $errstr = null; |
697 | 700 | for( $i = 0; !$sock && $i < $this->_connect_attempts; $i++ ) { |
698 | 701 | wfSuppressWarnings(); |
699 | | - if ( $this->_persistant == 1 ) { |
| 702 | + if ( $this->_persistent == 1 ) { |
700 | 703 | $sock = pfsockopen( $ip, $port, $errno, $errstr, $timeout ); |
701 | 704 | } else { |
702 | 705 | $sock = fsockopen( $ip, $port, $errno, $errstr, $timeout ); |
Index: trunk/phase3/includes/objectcache/MultiWriteBagOStuff.php |
— | — | @@ -0,0 +1,95 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + * A cache class that replicates all writes to multiple child caches. Reads |
| 6 | + * are implemented by reading from the caches in the order they are given in |
| 7 | + * the configuration until a cache gives a positive result. |
| 8 | + */ |
| 9 | +class MultiWriteBagOStuff extends BagOStuff { |
| 10 | + var $caches; |
| 11 | + |
| 12 | + /** |
| 13 | + * Constructor. Parameters are: |
| 14 | + * |
| 15 | + * - caches: This should have a numbered array of cache parameter |
| 16 | + * structures, in the style required by $wgObjectCaches. See |
| 17 | + * the documentation of $wgObjectCaches for more detail. |
| 18 | + */ |
| 19 | + public function __construct( $params ) { |
| 20 | + if ( !isset( $params['caches'] ) ) { |
| 21 | + throw new MWException( __METHOD__.': the caches parameter is required' ); |
| 22 | + } |
| 23 | + |
| 24 | + $this->caches = array(); |
| 25 | + foreach ( $params['caches'] as $cacheInfo ) { |
| 26 | + $this->caches[] = ObjectCache::newFromParams( $cacheInfo ); |
| 27 | + } |
| 28 | + } |
| 29 | + |
| 30 | + public function setDebug( $debug ) { |
| 31 | + $this->doWrite( 'setDebug', $debug ); |
| 32 | + } |
| 33 | + |
| 34 | + public function get( $key ) { |
| 35 | + foreach ( $this->caches as $cache ) { |
| 36 | + $value = $cache->get( $key ); |
| 37 | + if ( $value !== false ) { |
| 38 | + return $value; |
| 39 | + } |
| 40 | + } |
| 41 | + return false; |
| 42 | + } |
| 43 | + |
| 44 | + public function set( $key, $value, $exptime = 0 ) { |
| 45 | + return $this->doWrite( 'set', $key, $value, $exptime ); |
| 46 | + } |
| 47 | + |
| 48 | + public function delete( $key, $time = 0 ) { |
| 49 | + return $this->doWrite( 'delete', $key, $time ); |
| 50 | + } |
| 51 | + |
| 52 | + public function add( $key, $value, $exptime = 0 ) { |
| 53 | + return $this->doWrite( 'add', $key, $value, $exptime ); |
| 54 | + } |
| 55 | + |
| 56 | + public function replace( $key, $value, $exptime = 0 ) { |
| 57 | + return $this->doWrite( 'replace', $key, $value, $exptime ); |
| 58 | + } |
| 59 | + |
| 60 | + public function incr( $key, $value = 1 ) { |
| 61 | + return $this->doWrite( 'incr', $key, $value ); |
| 62 | + } |
| 63 | + |
| 64 | + public function decr( $key, $value = 1 ) { |
| 65 | + return $this->doWrite( 'decr', $key, $value ); |
| 66 | + } |
| 67 | + |
| 68 | + public function lock( $key, $timeout = 0 ) { |
| 69 | + // Lock only the first cache, to avoid deadlocks |
| 70 | + if ( isset( $this->caches[0] ) ) { |
| 71 | + return $this->caches[0]->lock( $key, $timeout ); |
| 72 | + } else { |
| 73 | + return true; |
| 74 | + } |
| 75 | + } |
| 76 | + |
| 77 | + public function unlock( $key ) { |
| 78 | + if ( isset( $this->caches[0] ) ) { |
| 79 | + return $this->caches[0]->unlock( $key ); |
| 80 | + } else { |
| 81 | + return true; |
| 82 | + } |
| 83 | + } |
| 84 | + |
| 85 | + protected function doWrite( $method /*, ... */ ) { |
| 86 | + $ret = true; |
| 87 | + $args = func_get_args(); |
| 88 | + array_shift( $args ); |
| 89 | + |
| 90 | + foreach ( $this->caches as $cache ) { |
| 91 | + $ret = $ret && call_user_func_array( array( $cache, $method ), $args ); |
| 92 | + } |
| 93 | + return $ret; |
| 94 | + } |
| 95 | + |
| 96 | +} |
Property changes on: trunk/phase3/includes/objectcache/MultiWriteBagOStuff.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 97 | + native |
Index: trunk/phase3/includes/Setup.php |
— | — | @@ -283,7 +283,6 @@ |
284 | 284 | require_once( "$IP/includes/Hooks.php" ); |
285 | 285 | require_once( "$IP/includes/Namespace.php" ); |
286 | 286 | require_once( "$IP/includes/ProxyTools.php" ); |
287 | | -require_once( "$IP/includes/objectcache/ObjectCache.php" ); |
288 | 287 | require_once( "$IP/includes/ImageFunctions.php" ); |
289 | 288 | wfProfileOut( $fname . '-includes' ); |
290 | 289 | wfProfileIn( $fname . '-misc1' ); |
— | — | @@ -323,9 +322,9 @@ |
324 | 323 | wfProfileOut( $fname . '-misc1' ); |
325 | 324 | wfProfileIn( $fname . '-memcached' ); |
326 | 325 | |
327 | | -$wgMemc =& wfGetMainCache(); |
328 | | -$messageMemc =& wfGetMessageCacheStorage(); |
329 | | -$parserMemc =& wfGetParserCacheStorage(); |
| 326 | +$wgMemc = wfGetMainCache(); |
| 327 | +$messageMemc = wfGetMessageCacheStorage(); |
| 328 | +$parserMemc = wfGetParserCacheStorage(); |
330 | 329 | |
331 | 330 | wfDebug( 'CACHES: ' . get_class( $wgMemc ) . '[main] ' . |
332 | 331 | get_class( $messageMemc ) . '[message] ' . |
Index: trunk/phase3/includes/AutoLoader.php |
— | — | @@ -505,11 +505,15 @@ |
506 | 506 | 'BagOStuff' => 'includes/objectcache/BagOStuff.php', |
507 | 507 | 'DBABagOStuff' => 'includes/objectcache/DBABagOStuff.php', |
508 | 508 | 'eAccelBagOStuff' => 'includes/objectcache/eAccelBagOStuff.php', |
509 | | - 'FakeMemCachedClient' => 'includes/objectcache/ObjectCache.php', |
| 509 | + 'EmptyBagOStuff' => 'includes/objectcache/EmptyBagOStuff.php', |
| 510 | + 'FakeMemCachedClient' => 'includes/objectcache/EmptyBagOStuff.php', |
510 | 511 | 'HashBagOStuff' => 'includes/objectcache/HashBagOStuff.php', |
511 | 512 | 'MWMemcached' => 'includes/objectcache/MemcachedClient.php', |
512 | 513 | 'MediaWikiBagOStuff' => 'includes/objectcache/SqlBagOStuff.php', |
513 | 514 | 'MemCachedClientforWiki' => 'includes/objectcache/MemcachedClient.php', |
| 515 | + 'MemcachedPhpBagOStuff' => 'includes/objectcache/MemcachedPhpBagOStuff.php', |
| 516 | + 'MultiWriteBagOStuff' => 'includes/objectcache/MultiWriteBagOStuff.php', |
| 517 | + 'ObjectCache' => 'includes/objectcache/ObjectCache.php', |
514 | 518 | 'SqlBagOStuff' => 'includes/objectcache/SqlBagOStuff.php', |
515 | 519 | 'WinCacheBagOStuff' => 'includes/objectcache/WinCacheBagOStuff.php', |
516 | 520 | 'XCacheBagOStuff' => 'includes/objectcache/XCacheBagOStuff.php', |
Index: trunk/phase3/includes/DefaultSettings.php |
— | — | @@ -1481,6 +1481,8 @@ |
1482 | 1482 | * - CACHE_DBA: Use PHP's DBA extension to store in a DBM-style |
1483 | 1483 | * database. This is slow, and is not recommended for |
1484 | 1484 | * anything other than debugging. |
| 1485 | + * - (other): A string may be used which identifies a cache |
| 1486 | + * configuration in $wgObjectCaches. |
1485 | 1487 | * |
1486 | 1488 | * @see $wgMessageCacheType, $wgParserCacheType |
1487 | 1489 | */ |
— | — | @@ -1503,6 +1505,36 @@ |
1504 | 1506 | $wgParserCacheType = CACHE_ANYTHING; |
1505 | 1507 | |
1506 | 1508 | /** |
| 1509 | + * Advanced object cache configuration. |
| 1510 | + * |
| 1511 | + * Use this to define the class names and constructor parameters which are used |
| 1512 | + * for the various cache types. Custom cache types may be defined here and |
| 1513 | + * referenced from $wgMainCacheType, $wgMessageCacheType or $wgParserCacheType. |
| 1514 | + * |
| 1515 | + * The format is an associative array where the key is a cache identifier, and |
| 1516 | + * the value is an associative array of parameters. The "class" parameter is the |
| 1517 | + * class name which will be used. Alternatively, a "factory" parameter may be |
| 1518 | + * given, giving a callable function which will generate a suitable cache object. |
| 1519 | + * |
| 1520 | + * The other parameters are dependent on the class used. |
| 1521 | + */ |
| 1522 | +$wgObjectCaches = array( |
| 1523 | + CACHE_NONE => array( 'class' => 'FakeMemCachedClient' ), |
| 1524 | + CACHE_DB => array( 'class' => 'SqlBagOStuff', 'table' => 'objectcache' ), |
| 1525 | + CACHE_DBA => array( 'class' => 'DBABagOStuff' ), |
| 1526 | + |
| 1527 | + CACHE_ANYTHING => array( 'factory' => 'ObjectCache::newAnything' ), |
| 1528 | + CACHE_ACCEL => array( 'factory' => 'ObjectCache::newAccelerator' ), |
| 1529 | + CACHE_MEMCACHED => array( 'factory' => 'ObjectCache::newMemcached' ), |
| 1530 | + |
| 1531 | + 'eaccelerator' => array( 'class' => 'eAccelBagOStuff' ), |
| 1532 | + 'apc' => array( 'class' => 'APCBagOStuff' ), |
| 1533 | + 'xcache' => array( 'class' => 'XCacheBagOStuff' ), |
| 1534 | + 'wincache' => array( 'class' => 'WinCacheBagOStuff' ), |
| 1535 | + 'memcached-php' => array( 'class' => 'MemcachedPhpBagOStuff' ), |
| 1536 | +); |
| 1537 | + |
| 1538 | +/** |
1507 | 1539 | * The expiry time for the parser cache, in seconds. The default is 86.4k |
1508 | 1540 | * seconds, otherwise known as a day. |
1509 | 1541 | */ |