Spaces to tabs
[lhc/web/wiklou.git] / includes / ObjectCache.php
index 30c5e0b..db22c07 100644 (file)
 <?php
-# $Id$
-#
-# Copyright (C) 2003-2004 Brion Vibber <brion@pobox.com>
-# 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
+/**
+ * Functions to get cache objects
+ *
+ * @file
+ * @ingroup 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
+/**
+ * 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.
+ * @ingroup Cache
+ */
+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) { }
+}
 
-class /* abstract */ BagOStuff {
-       var $debugmode;
-       
-       function BagOStuff() {
-               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;
-       }
+global $wgCaches;
+$wgCaches = array();
 
-       function set($key, $value, $exptime=0) {
-               /* stub */
-               return false;
-       }
-       
-       function delete($key, $time=0) {
-               /* stub */
-               return false;
-       }
-       
-       /* *** 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);
-       }
-       
-       function add_multi($hash, $exptime=0) {
-               foreach($hash as $key => $value)
-                       $this->add($key, $value, $exptime);
-       }
+/**
+ * Get a cache object.
+ * @param $inputType Integer: cache type, one the the CACHE_* constants. 
+ */
+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) {
-               $value = intval($value);
-               if($value < 0) $value = 0;
-               if( ($n = $this->get($key)) !== false ) {
-                       $this->set($key, $n+$value); // exptime?
-                       return $n+$value;
-               } else {
-                       return false;
-               }
-       }
-       
-       function decr($key, $value=1) {
-               $value = intval($value);
-               if($value < 0) $value = 0;
-               if( ($n = $this->get($key)) !== false ) {
-                       $m = $n - $value;
-                       if($m < 0) $m = 0;
-                       $this->set($key, $m); // exptime?
-                       return $m;
-               } else {
-                       return false;
+       if ( $inputType == CACHE_ANYTHING ) {
+               reset( $wgCaches );
+               $type = key( $wgCaches );
+               if ( $type === false || $type === CACHE_NONE ) {
+                       $type = CACHE_DB;
                }
+       } else {
+               $type = $inputType;
        }
-       
-       function _debug($text) {
-               if($this->debugmode)
-                       wfDebug("BagOStuff debug: $text\n");
-       }
-}
-
 
-/* Functional versions! */
-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 );
-       }
-       
-       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)
-);
-*/
-class /* abstract */ SqlBagOStuff extends BagOStuff {
-       var $table;
-       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;
+       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 );
                }
-               if($arr = $this->_fetchrow($res)) {
-                       $this->_debug("get: retrieved data; exp time is " . $arr['exptime']);
-                       return unserialize($arr['value']);
-               } else {
-                       $this->_debug("get: no matching rows");
+               $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;
+                       }
                }
-               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, serialize(&$value));
-               return true; /* ? */
-       }
-       
-       function delete($key,$time=0) {
-               $this->_query(
-                       "DELETE FROM $0 WHERE keyname='$1'", $key );
-               return true; /* ? */
-       }
-       
-       function _query($sql) {
-               $reps = func_get_args();
-               $reps[0] = $this->table;
-               // ewwww
-               for($i=0;$i<count($reps);$i++) {
-                       $sql = str_replace(
-                               "$" . $i,
-                               $this->_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;
+               $cache =& $wgCaches[CACHE_DBA];
        }
-       
-       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 */
-               $this->_query( "DELETE FROM $0 WHERE exptime<=NOW()" );
+
+       if ( $type == CACHE_DB || ( $inputType == CACHE_ANYTHING && $cache === false ) ) {
+               if ( !array_key_exists( CACHE_DB, $wgCaches ) ) {
+                       $wgCaches[CACHE_DB] = new SqlBagOStuff('objectcache');
+               }
+               $cache =& $wgCaches[CACHE_DB];
        }
-       
-       function deleteall() {
-               /* Clear *all* items from cache table */
-               $this->_query( "DELETE FROM $0" );
+
+       if ( $cache === false ) {
+               if ( !array_key_exists( CACHE_NONE, $wgCaches ) ) {
+                       $wgCaches[CACHE_NONE] = new FakeMemCachedClient;
+               }
+               $cache =& $wgCaches[CACHE_NONE];
        }
+
+       return $cache;
 }
 
-class MediaWikiBagOStuff extends SqlBagOStuff {
-       function _doquery($sql) {
-               return wfQuery($sql, DB_READ, "MediaWikiBagOStuff:_doquery");
-       }
-       function _fetchrow($result) {
-               return wfFetchRow($result);
-       }
-       function _freeresult($result) {
-               return wfFreeResult($result);
-       }
-       function _dberror($result) {
-               return wfLastError();
-       }
-       function _maxdatetime() {
-               return "9999-12-31 12:59:59";
-       }
-       function _fromunixtime($ts) {
-               return gmdate( "Y-m-d H:i:s", $ts );
-       }
-       function _strencode($s) {
-               return wfStrEncode($s);
-       }
+/** 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;
+}