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 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
00042
00043
00044 function
get($key) {
00045
00046
return false;
00047 }
00048
00049 function
set($key, $value, $exptime=0) {
00050
00051
return false;
00052 }
00053
00054 function
delete($key, $time=0) {
00055
00056
return false;
00057 }
00058
00059
00060
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);
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);
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
00127 class HashBagOStuff extends BagOStuff {
00128
00129
00130
00131
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
00171
00172
00173
00174
00175
00176
00177
00178 class SqlBagOStuff extends BagOStuff {
00179 var
$table;
00180 function
SqlBagOStuff($tablename =
"objectcache") {
00181 $this->table = $tablename;
00182 }
00183
00184 function
get($key) {
00185
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
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
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
00258
return false;
00259 }
00260
00261 function
_dberror($result) {
00262
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
00276 $now=$this->
_fromunixtime(time());
00277 $this->_query(
"DELETE FROM $0 WHERE exptime<'$now'" );
00278 }
00279
00280 function
deleteall() {
00281
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 ?>