X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2FObjectCache.php;h=a493a75c26c13a705747a5aa73caa4c5b4990a78;hb=e115a47d4c46a8214db907480dab8d0aee72a9ef;hp=7689b9442b1f7cec4790ba542dd59efa25232e7b;hpb=b3ca6226ca1ab65ba8faa7a848bc8eae9c24c9df;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/ObjectCache.php b/includes/ObjectCache.php index 7689b9442b..a493a75c26 100644 --- a/includes/ObjectCache.php +++ b/includes/ObjectCache.php @@ -1,448 +1,124 @@ -# http://www.mediawiki.org/ -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# http://www.gnu.org/copyleft/gpl.html /** - * - * @package MediaWiki + * @addtogroup Cache */ - + /** - * Simple generic object store - * - * interface is intended to be more or less compatible with - * the PHP memcached client. - * - * backends for local hash array and SQL table included: - * $bag = new HashBagOStuff(); - * $bag = new MysqlBagOStuff($tablename); # connect to db first - * - * @package MediaWiki - * @abstract + * FakeMemCachedClient imitates the API of memcached-client v. 0.1.2. + * It acts as a memcached server with no RAM, that is, all objects are + * cleared the moment they are set. All set operations succeed and all + * get operations return null. + * @addtogroup Cache */ -class BagOStuff { - var $debugmode; - - function BagOStuff() { - $this->set_debug( false ); - } - - function set_debug($bool) { - $this->debugmode = $bool; - } - - /* *** THE GUTS OF THE OPERATION *** */ - /* Override these with functional things in subclasses */ - - function get($key) { - /* stub */ - return false; - } +class FakeMemCachedClient { + function add ($key, $val, $exp = 0) { return true; } + function decr ($key, $amt=1) { return null; } + function delete ($key, $time = 0) { return false; } + function disconnect_all () { } + function enable_compress ($enable) { } + function forget_dead_hosts () { } + function get ($key) { return null; } + function get_multi ($keys) { return array_pad(array(), count($keys), null); } + function incr ($key, $amt=1) { return null; } + function replace ($key, $value, $exp=0) { return false; } + function run_command ($sock, $cmd) { return null; } + function set ($key, $value, $exp=0){ return true; } + function set_compress_threshold ($thresh){ } + function set_debug ($dbg) { } + function set_servers ($list) { } +} - function set($key, $value, $exptime=0) { - /* stub */ - return false; - } - - function delete($key, $time=0) { - /* stub */ - return false; - } - - function lock($key, $timeout = 0) { - /* stub */ - return true; - } +global $wgCaches; +$wgCaches = array(); - function unlock($key) { - /* stub */ - return true; - } - - /* *** Emulated functions *** */ - /* Better performance can likely be got with custom written versions */ - function get_multi($keys) { - $out = array(); - foreach($keys as $key) - $out[$key] = $this->get($key); - return $out; - } - - function set_multi($hash, $exptime=0) { - foreach($hash as $key => $value) - $this->set($key, $value, $exptime); - } - - function add($key, $value, $exptime=0) { - if( $this->get($key) == false ) { - $this->set($key, $value, $exptime); - return true; - } - } - - function add_multi($hash, $exptime=0) { - foreach($hash as $key => $value) - $this->add($key, $value, $exptime); - } +/** @todo document */ +function &wfGetCache( $inputType ) { + global $wgCaches, $wgMemCachedServers, $wgMemCachedDebug, $wgMemCachedPersistent; + $cache = false; - function delete_multi($keys, $time=0) { - foreach($keys as $key) - $this->delete($key, $time); - } - - function replace($key, $value, $exptime=0) { - if( $this->get($key) !== false ) - $this->set($key, $value, $exptime); - } - - function incr($key, $value=1) { - if ( !$this->lock($key) ) { - return false; + if ( $inputType == CACHE_ANYTHING ) { + reset( $wgCaches ); + $type = key( $wgCaches ); + if ( $type === false || $type === CACHE_NONE ) { + $type = CACHE_DB; } - $value = intval($value); - if($value < 0) $value = 0; - - $n = false; - if( ($n = $this->get($key)) !== false ) { - $n += $value; - $this->set($key, $n); // exptime? - } - $this->unlock($key); - return $n; - } - - function decr($key, $value=1) { - if ( !$this->lock($key) ) { - return false; - } - $value = intval($value); - if($value < 0) $value = 0; - - $m = false; - if( ($n = $this->get($key)) !== false ) { - $m = $n - $value; - if($m < 0) $m = 0; - $this->set($key, $m); // exptime? - } - $this->unlock($key); - return $m; - } - - function _debug($text) { - if($this->debugmode) - wfDebug("BagOStuff debug: $text\n"); - } -} - - -/** - * Functional versions! - * @todo document - * @package MediaWiki - */ -class HashBagOStuff extends BagOStuff { - /* - This is a test of the interface, mainly. It stores - things in an associative array, which is not going to - persist between program runs. - */ - var $bag; - - function HashBagOStuff() { - $this->bag = array(); - } - - function _expire($key) { - $et = $this->bag[$key][1]; - if(($et == 0) || ($et > time())) - return false; - $this->delete($key); - return true; - } - - function get($key) { - if(!$this->bag[$key]) - return false; - if($this->_expire($key)) - return false; - return $this->bag[$key][0]; - } - - function set($key,$value,$exptime=0) { - if(($exptime != 0) && ($exptime < 3600*24*30)) - $exptime = time() + $exptime; - $this->bag[$key] = array( $value, $exptime ); + } else { + $type = $inputType; } - - function delete($key,$time=0) { - if(!$this->bag[$key]) - return false; - unset($this->bag[$key]); - return true; - } -} -/* -CREATE TABLE objectcache ( - keyname char(255) binary not null default '', - value mediumblob, - exptime datetime, - unique key (keyname), - key (exptime) -); -*/ + if ( $type == CACHE_MEMCACHED ) { + if ( !array_key_exists( CACHE_MEMCACHED, $wgCaches ) ){ + require_once( 'memcached-client.php' ); -/** - * @todo document - * @abstract - * @package MediaWiki - */ -class SqlBagOStuff extends BagOStuff { - var $table; + if (!class_exists("MemcachedClientforWiki")) { + class MemCachedClientforWiki extends memcached { + function _debugprint( $text ) { + wfDebug( "memcached: $text\n" ); + } + } + } - function SqlBagOStuff($tablename = 'objectcache') { - $this->table = $tablename; - } - - function get($key) { - /* expire old entries if any */ - $this->expireall(); - - $res = $this->_query( - "SELECT value,exptime FROM $0 WHERE keyname='$1'", $key); - if(!$res) { - $this->_debug("get: ** error: " . $this->_dberror($res) . " **"); - return false; + $wgCaches[CACHE_DB] = new MemCachedClientforWiki( + array('persistant' => $wgMemCachedPersistent, 'compress_threshold' => 1500 ) ); + $cache =& $wgCaches[CACHE_DB]; + $cache->set_servers( $wgMemCachedServers ); + $cache->set_debug( $wgMemCachedDebug ); } - if($row=$this->_fetchobject($res)) { - $this->_debug("get: retrieved data; exp time is " . $row->exptime); - return $this->_unserialize($row->value); - } else { - $this->_debug('get: no matching rows'); + } 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( 'mmcache_get' ) ) { + $wgCaches[CACHE_ACCEL] = new TurckBagOStuff; + } else { + $wgCaches[CACHE_ACCEL] = false; + } } - return false; - } - - function set($key,$value,$exptime=0) { - $exptime = intval($exptime); - if($exptime < 0) $exptime = 0; - if($exptime == 0) { - $exp = $this->_maxdatetime(); - } else { - if($exptime < 3600*24*30) - $exptime += time(); - $exp = $this->_fromunixtime($exptime); + if ( $wgCaches[CACHE_ACCEL] !== false ) { + $cache =& $wgCaches[CACHE_ACCEL]; } - $this->delete( $key ); - $this->_query( - "INSERT INTO $0 (keyname,value,exptime) VALUES('$1','$2','$exp')", - $key, $this->_serialize($value)); - return true; /* ? */ - } - - function delete($key,$time=0) { - $this->_query( - "DELETE FROM $0 WHERE keyname='$1'", $key ); - return true; /* ? */ - } - - function getTableName() { - return $this->table; - } - - function _query($sql) { - $reps = func_get_args(); - $reps[0] = $this->getTableName(); - // ewwww - for($i=0;$i_strencode($reps[$i]), - $sql); + } elseif ( $type == CACHE_DBA ) { + if ( !array_key_exists( CACHE_DBA, $wgCaches ) ) { + $wgCaches[CACHE_DBA] = new DBABagOStuff; } - $res = $this->_doquery($sql); - if($res == false) { - $this->_debug('query failed: ' . $this->_dberror($res)); - } - return $res; - } - - function _strencode($str) { - /* Protect strings in SQL */ - return str_replace( "'", "''", $str ); - } - - function _doquery($sql) { - die( 'abstract function SqlBagOStuff::_doquery() must be defined' ); - } - - function _fetchrow($res) { - die( 'abstract function SqlBagOStuff::_fetchrow() must be defined' ); - } - - function _freeresult($result) { - /* stub */ - return false; - } - - function _dberror($result) { - /* stub */ - return 'unknown error'; - } - - function _maxdatetime() { - die( 'abstract function SqlBagOStuff::_maxdatetime() must be defined' ); - } - - function _fromunixtime() { - die( 'abstract function SqlBagOStuff::_fromunixtime() must be defined' ); - } - - function expireall() { - /* Remove any items that have expired */ - $now=$this->_fromunixtime(time()); - $this->_query( "DELETE FROM $0 WHERE exptime<'$now'" ); - } - - function deleteall() { - /* Clear *all* items from cache table */ - $this->_query( "DELETE FROM $0" ); + $cache =& $wgCaches[CACHE_DBA]; } - /** - * Serialize an object and, if possible, compress the representation. - * On typical message and page data, this can provide a 3X decrease - * in storage requirements. - * - * @param mixed $data - * @return string - */ - function _serialize( &$data ) { - $serial = serialize( $data ); - if( function_exists( 'gzdeflate' ) ) { - return gzdeflate( $serial ); - } else { - return $serial; + if ( $type == CACHE_DB || ( $inputType == CACHE_ANYTHING && $cache === false ) ) { + if ( !array_key_exists( CACHE_DB, $wgCaches ) ) { + $wgCaches[CACHE_DB] = new MediaWikiBagOStuff('objectcache'); } + $cache =& $wgCaches[CACHE_DB]; } - - /** - * Unserialize and, if necessary, decompress an object. - * @param string $serial - * @return mixed - */ - function &_unserialize( $serial ) { - if( function_exists( 'gzinflate' ) ) { - $decomp = @gzinflate( $serial ); - if( false !== $decomp ) { - $serial = $decomp; - } - } - return unserialize( $serial ); - } -} - -/** - * @todo document - * @package MediaWiki - */ -class MediaWikiBagOStuff extends SqlBagOStuff { - var $tableInitialised = false; - function _doquery($sql) { - $dbw =& wfGetDB( DB_MASTER ); - return $dbw->query($sql, 'MediaWikiBagOStuff:_doquery'); - } - function _fetchobject($result) { - $dbw =& wfGetDB( DB_MASTER ); - return $dbw->fetchObject($result); - } - function _freeresult($result) { - $dbw =& wfGetDB( DB_MASTER ); - return $dbw->freeResult($result); - } - function _dberror($result) { - $dbw =& wfGetDB( DB_MASTER ); - return $dbw->lastError(); - } - function _maxdatetime() { - return '9999-12-31 12:59:59'; - } - function _fromunixtime($ts) { - return gmdate( 'Y-m-d H:i:s', $ts ); - } - function _strencode($s) { - $dbw =& wfGetDB( DB_MASTER ); - return $dbw->strencode($s); - } - function getTableName() { - if ( !$this->tableInitialised ) { - $dbw =& wfGetDB( DB_MASTER ); - $this->table = $dbw->tableName( $this->table ); - $this->tableInitialised = true; + if ( $cache === false ) { + if ( !array_key_exists( CACHE_NONE, $wgCaches ) ) { + $wgCaches[CACHE_NONE] = new FakeMemCachedClient; } - return $this->table; + $cache =& $wgCaches[CACHE_NONE]; } + + return $cache; } -/** - * This is a wrapper for Turck MMCache's shared memory functions. - * - * You can store objects with mmcache_put() and mmcache_get(), but Turck seems - * to use a weird custom serializer that randomly segfaults. So we wrap calls - * with serialize()/unserialize(). - * - * The thing I noticed about the Turck serialized data was that unlike ordinary - * serialize(), it contained the names of methods, and judging by the amount of - * binary data, perhaps even the bytecode of the methods themselves. It may be - * that Turck's serializer is faster, so a possible future extension would be - * to use it for arrays but not for objects. - * - * @package MediaWiki - */ -class TurckBagOStuff extends BagOStuff { - function get($key) { - $val = mmcache_get( $key ); - if ( is_string( $val ) ) { - $val = unserialize( $val ); - } - return $val; - } +function &wfGetMainCache() { + global $wgMainCacheType; + $ret =& wfGetCache( $wgMainCacheType ); + return $ret; +} - function set($key, $value, $exptime=0) { - mmcache_put( $key, serialize( $value ), $exptime ); - return true; - } - - function delete($key, $time=0) { - mmcache_rm( $key ); - return true; - } +function &wfGetMessageCacheStorage() { + global $wgMessageCacheType; + $ret =& wfGetCache( $wgMessageCacheType ); + return $ret; +} - function lock($key, $waitTimeout = 0 ) { - mmcache_lock( $key ); - return true; - } +function &wfGetParserCacheStorage() { + global $wgParserCacheType; + $ret =& wfGetCache( $wgParserCacheType ); + return $ret; +} - function unlock($key) { - mmcache_unlock( $key ); - return true; - } -} ?>