Main Page | Namespace List | Class Hierarchy | Class List | File List | Class Members | File Members | Related Pages

ObjectCache.php

Go to the documentation of this file.
00001 <?php 00002 # $Id: ObjectCache.php,v 1.4 2004/06/12 03:17:39 vibber Exp $ 00003 # 00004 # Copyright (C) 2003-2004 Brion Vibber <brion@pobox.com> 00005 # http://www.mediawiki.org/ 00006 # 00007 # This program is free software; you can redistribute it and/or modify 00008 # it under the terms of the GNU General Public License as published by 00009 # the Free Software Foundation; either version 2 of the License, or 00010 # (at your option) any later version. 00011 # 00012 # This program is distributed in the hope that it will be useful, 00013 # but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 # GNU General Public License for more details. 00016 # 00017 # You should have received a copy of the GNU General Public License along 00018 # with this program; if not, write to the Free Software Foundation, Inc., 00019 # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00020 # http://www.gnu.org/copyleft/gpl.html 00021 00022 # Simple generic object store 00023 # interface is intended to be more or less compatible with 00024 # the PHP memcached client. 00025 # 00026 # backends for local hash array and SQL table included: 00027 # $bag = new HashBagOStuff(); 00028 # $bag = new MysqlBagOStuff($tablename); # connect to db first 00029 00030 class /* abstract */ BagOStuff { 00031 var $debugmode; 00032 00033 function BagOStuff() { 00034 set_debug( false ); 00035 } 00036 00037 function set_debug($bool) { 00038 $this->debugmode = $bool; 00039 } 00040 00041 /* *** THE GUTS OF THE OPERATION *** */ 00042 /* Override these with functional things in subclasses */ 00043 00044 function get($key) { 00045 /* stub */ 00046 return false; 00047 } 00048 00049 function set($key, $value, $exptime=0) { 00050 /* stub */ 00051 return false; 00052 } 00053 00054 function delete($key, $time=0) { 00055 /* stub */ 00056 return false; 00057 } 00058 00059 /* *** Emulated functions *** */ 00060 /* Better performance can likely be got with custom written versions */ 00061 function get_multi($keys) { 00062 $out = array(); 00063 foreach($keys as $key) 00064 $out[$key] = $this->get($key); 00065 return $out; 00066 } 00067 00068 function set_multi($hash, $exptime=0) { 00069 foreach($hash as $key => $value) 00070 $this->set($key, $value, $exptime); 00071 } 00072 00073 function add($key, $value, $exptime=0) { 00074 if( $this->get($key) == false ) { 00075 $this->set($key, $value, $exptime); 00076 return true; 00077 } 00078 } 00079 00080 function add_multi($hash, $exptime=0) { 00081 foreach($hash as $key => $value) 00082 $this->add($key, $value, $exptime); 00083 } 00084 00085 function delete_multi($keys, $time=0) { 00086 foreach($keys as $key) 00087 $this->delete($key, $time); 00088 } 00089 00090 function replace($key, $value, $exptime=0) { 00091 if( $this->get($key) !== false ) 00092 $this->set($key, $value, $exptime); 00093 } 00094 00095 function incr($key, $value=1) { 00096 $value = intval($value); 00097 if($value < 0) $value = 0; 00098 if( ($n = $this->get($key)) !== false ) { 00099 $this->set($key, $n+$value); // exptime? 00100 return $n+$value; 00101 } else { 00102 return false; 00103 } 00104 } 00105 00106 function decr($key, $value=1) { 00107 $value = intval($value); 00108 if($value < 0) $value = 0; 00109 if( ($n = $this->get($key)) !== false ) { 00110 $m = $n - $value; 00111 if($m < 0) $m = 0; 00112 $this->set($key, $m); // exptime? 00113 return $m; 00114 } else { 00115 return false; 00116 } 00117 } 00118 00119 function _debug($text) { 00120 if($this->debugmode) 00121 wfDebug("BagOStuff debug: $text\n"); 00122 } 00123 } 00124 00125 00126 /* Functional versions! */ 00127 class HashBagOStuff extends BagOStuff { 00128 /* 00129 This is a test of the interface, mainly. It stores 00130 things in an associative array, which is not going to 00131 persist between program runs. 00132 */ 00133 var $bag; 00134 00135 function HashBagOStuff() { 00136 $this->bag = array(); 00137 } 00138 00139 function _expire($key) { 00140 $et = $this->bag[$key][1]; 00141 if(($et == 0) || ($et > time())) 00142 return false; 00143 $this->delete($key); 00144 return true; 00145 } 00146 00147 function get($key) { 00148 if(!$this->bag[$key]) 00149 return false; 00150 if($this->_expire($key)) 00151 return false; 00152 return $this->bag[$key][0]; 00153 } 00154 00155 function set($key,$value,$exptime=0) { 00156 if(($exptime != 0) && ($exptime < 3600*24*30)) 00157 $exptime = time() + $exptime; 00158 $this->bag[$key] = array( $value, $exptime ); 00159 } 00160 00161 function delete($key,$time=0) { 00162 if(!$this->bag[$key]) 00163 return false; 00164 unset($this->bag[$key]); 00165 return true; 00166 } 00167 } 00168 00169 /* 00170 CREATE TABLE objectcache ( 00171 keyname char(255) binary not null default '', 00172 value mediumblob, 00173 exptime datetime, 00174 unique key (keyname), 00175 key (exptime) 00176 ); 00177 */ 00178 class /* abstract */ SqlBagOStuff extends BagOStuff { 00179 var $table; 00180 function SqlBagOStuff($tablename = "objectcache") { 00181 $this->table = $tablename; 00182 } 00183 00184 function get($key) { 00185 /* expire old entries if any */ 00186 $this->expireall(); 00187 00188 $res = $this->_query( 00189 "SELECT value,exptime FROM $0 WHERE keyname='$1'", $key); 00190 if(!$res) { 00191 $this->_debug("get: ** error: " . $this->_dberror($res) . " **"); 00192 return false; 00193 } 00194 if($row=$this->_fetchobject($res)) { 00195 $this->_debug("get: retrieved data; exp time is " . $row->exptime); 00196 return unserialize($row->value); 00197 } else { 00198 $this->_debug("get: no matching rows"); 00199 } 00200 return false; 00201 } 00202 00203 function set($key,$value,$exptime=0) { 00204 $exptime = intval($exptime); 00205 if($exptime < 0) $exptime = 0; 00206 if($exptime == 0) { 00207 $exp = $this->_maxdatetime(); 00208 } else { 00209 if($exptime < 3600*24*30) 00210 $exptime += time(); 00211 $exp = $this->_fromunixtime($exptime); 00212 } 00213 $this->delete( $key ); 00214 $this->_query( 00215 "INSERT INTO $0 (keyname,value,exptime) VALUES('$1','$2','$exp')", 00216 $key, serialize($value)); 00217 return true; /* ? */ 00218 } 00219 00220 function delete($key,$time=0) { 00221 $this->_query( 00222 "DELETE FROM $0 WHERE keyname='$1'", $key ); 00223 return true; /* ? */ 00224 } 00225 00226 function _query($sql) { 00227 $reps = func_get_args(); 00228 $reps[0] = $this->table; 00229 // ewwww 00230 for($i=0;$i<count($reps);$i++) { 00231 $sql = str_replace( 00232 "$" . $i, 00233 $this->_strencode($reps[$i]), 00234 $sql); 00235 } 00236 $res = $this->_doquery($sql); 00237 if($res == false) { 00238 $this->_debug("query failed: " . $this->_dberror($res)); 00239 } 00240 return $res; 00241 } 00242 00243 function _strencode($str) { 00244 /* Protect strings in SQL */ 00245 return str_replace( "'", "''", $str ); 00246 } 00247 00248 function _doquery($sql) { 00249 die( "abstract function SqlBagOStuff::_doquery() must be defined" ); 00250 } 00251 00252 function _fetchrow($res) { 00253 die( "abstract function SqlBagOStuff::_fetchrow() must be defined" ); 00254 } 00255 00256 function _freeresult($result) { 00257 /* stub */ 00258 return false; 00259 } 00260 00261 function _dberror($result) { 00262 /* stub */ 00263 return "unknown error"; 00264 } 00265 00266 function _maxdatetime() { 00267 die( "abstract function SqlBagOStuff::_maxdatetime() must be defined" ); 00268 } 00269 00270 function _fromunixtime() { 00271 die( "abstract function SqlBagOStuff::_fromunixtime() must be defined" ); 00272 } 00273 00274 function expireall() { 00275 /* Remove any items that have expired */ 00276 $now=$this->_fromunixtime(time()); 00277 $this->_query( "DELETE FROM $0 WHERE exptime<'$now'" ); 00278 } 00279 00280 function deleteall() { 00281 /* Clear *all* items from cache table */ 00282 $this->_query( "DELETE FROM $0" ); 00283 } 00284 } 00285 00286 class MediaWikiBagOStuff extends SqlBagOStuff { 00287 function _doquery($sql) { 00288 return wfQuery($sql, DB_READ, "MediaWikiBagOStuff:_doquery"); 00289 } 00290 function _fetchobject($result) { 00291 return wfFetchObject($result); 00292 } 00293 function _freeresult($result) { 00294 return wfFreeResult($result); 00295 } 00296 function _dberror($result) { 00297 return wfLastError(); 00298 } 00299 function _maxdatetime() { 00300 return "9999-12-31 12:59:59"; 00301 } 00302 function _fromunixtime($ts) { 00303 return gmdate( "Y-m-d H:i:s", $ts ); 00304 } 00305 function _strencode($s) { 00306 return wfStrEncode($s); 00307 } 00308 } 00309 00310 ?>

Generated on Tue Jun 29 23:40:05 2004 for Mediawiki by doxygen 1.3.7