2 # Copyright (C) 2003-2004 Brion Vibber <brion@pobox.com>
3 # http://www.mediawiki.org/
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License along
16 # with this program; if not, write to the Free Software Foundation, Inc.,
17 # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 # http://www.gnu.org/copyleft/gpl.html
20 # Simple generic object store
21 # interface is intended to be more or less compatible with
22 # the PHP memcached client.
24 # backends for local hash array and SQL table included:
25 # $bag = new HashBagOStuff();
26 # $bag = new MysqlBagOStuff($tablename); # connect to db first
28 class /* abstract */ BagOStuff
{
31 function BagOStuff() {
35 function set_debug($bool) {
36 $this->debugmode
= $bool;
39 /* *** THE GUTS OF THE OPERATION *** */
40 /* Override these with functional things in subclasses */
47 function set($key, $value, $exptime=0) {
52 function delete($key, $time=0) {
57 /* *** Emulated functions *** */
58 /* Better performance can likely be got with custom written versions */
59 function get_multi($keys) {
61 foreach($keys as $key)
62 $out[$key] = $this->get($key);
66 function set_multi($hash, $exptime=0) {
67 foreach($hash as $key => $value)
68 $this->set($key, $value, $exptime);
71 function add($key, $value, $exptime=0) {
72 if( $this->get($key) === false )
73 $this->set($key, $value, $exptime);
76 function add_multi($hash, $exptime=0) {
77 foreach($hash as $key => $value)
78 $this->add($key, $value, $exptime);
81 function delete_multi($keys, $time=0) {
82 foreach($keys as $key)
83 $this->delete($key, $time);
86 function replace($key, $value, $exptime=0) {
87 if( $this->get($key) !== false )
88 $this->set($key, $value, $exptime);
91 function incr($key, $value=1) {
92 $value = intval($value);
93 if($value < 0) $value = 0;
94 if( ($n = $this->get($key)) !== false ) {
95 $this->set($key, $n+
$value); // exptime?
102 function decr($key, $value=1) {
103 $value = intval($value);
104 if($value < 0) $value = 0;
105 if( ($n = $this->get($key)) !== false ) {
108 $this->set($key, $m); // exptime?
115 function _debug($text) {
117 echo "\ndebug: $text\n";
122 /* Functional versions! */
123 class HashBagOStuff
extends BagOStuff
{
125 This is a test of the interface, mainly. It stores
126 things in an associative array, which is not going to
127 persist between program runs.
131 function HashBagOStuff() {
132 $this->bag
= array();
135 function _expire($key) {
136 $et = $this->bag
[$key][1];
137 if(($et == 0) ||
($et > time()))
144 if(!$this->bag
[$key])
146 if($this->_expire($key))
148 return $this->bag
[$key][0];
151 function set($key,$value,$exptime=0) {
152 if(($exptime != 0) && ($exptime < 3600*24*30))
153 $exptime = time() +
$exptime;
154 $this->bag
[$key] = array( $value, $exptime );
157 function delete($key,$time=0) {
158 if(!$this->bag
[$key])
160 unset($this->bag
[$key]);
166 CREATE TABLE objectcache (
167 keyname char(255) binary not null default '',
170 unique key (keyname),
174 class /* abstract */ SqlBagOStuff
extends BagOStuff
{
176 function SqlBagOStuff($tablename = "objectcache") {
177 $this->table
= $tablename;
181 /* expire old entries if any */
184 $res = $this->_query(
185 "SELECT value,exptime FROM $0 WHERE keyname='$1'", $key);
187 $this->_debug("get: ** error: " . $this->_dberror($res) . " **");
190 if($arr = $this->_fetchrow($res)) {
191 $this->_debug("get: retrieved data; exp time is " . $arr['exptime']);
192 return unserialize($arr['value']);
194 $this->_debug("get: no matching rows");
199 function set($key,$value,$exptime=0) {
200 $exptime = intval($exptime);
201 if($exptime < 0) $exptime = 0;
203 $exp = $this->_maxdatetime();
205 if($exptime < 3600*24*30)
207 $exp = $this->_fromunixtime($exptime);
209 $this->delete( $key );
211 "INSERT INTO $0 (keyname,value,exptime) VALUES('$1','$2',$exp)",
212 $key, serialize(&$value));
216 function delete($key,$time=0) {
218 "DELETE FROM $0 WHERE keyname='$1'", $key );
222 function _query($sql) {
223 $reps = func_get_args();
224 $reps[0] = $this->table
;
226 for($i=0;$i<count($reps);$i++
) {
229 $this->_strencode($reps[$i]),
232 $res = $this->_doquery($sql);
234 $this->_debug("query failed: " . $this->_dberror($res));
239 function _strencode($str) {
240 /* Protect strings in SQL */
241 return str_replace( "'", "''", $str );
244 function _doquery($sql) {
245 die( "abstract function SqlBagOStuff::_doquery() must be defined" );
248 function _fetchrow($res) {
249 die( "abstract function SqlBagOStuff::_fetchrow() must be defined" );
252 function _freeresult($result) {
257 function _dberror($result) {
259 return "unknown error";
262 function _maxdatetime() {
263 die( "abstract function SqlBagOStuff::_maxdatetime() must be defined" );
266 function _fromunixtime() {
267 die( "abstract function SqlBagOStuff::_fromunixtime() must be defined" );
270 function expireall() {
271 /* Remove any items that have expired */
272 $this->_query( "DELETE FROM $0 WHERE exptime<=NOW()" );
275 function deleteall() {
276 /* Clear *all* items from cache table */
277 $this->_query( "DELETE FROM $0" );
281 class MysqlBagOStuff
extends SqlBagOStuff
{
282 function _doquery($sql) {
283 return mysql_query($sql);
285 function _fetchrow($result) {
286 return mysql_fetch_array($result);
288 function _freeresult($result) {
289 return mysql_free_result($result);
291 function _dberror($result) {
293 return mysql_error($result);
295 return mysql_error();
298 function _maxdatetime() {
299 return "'9999-12-31 12:59:59'";
302 function _fromunixtime($ts) {
303 return "FROM_UNIXTIME($ts)";
306 function _strencode($s) {
307 return mysql_escape_string($s);
311 class MediaWikiBagOStuff
extends MysqlBagOStuff
{
312 function _doquery($sql) {
313 return wfQuery($sql, DB_READ
, "MediaWikiBagOStuff:_doquery");
315 function _freeresult($result) {
316 return wfFreeResult($result);