X-Git-Url: http://git.cyclocoop.org/?a=blobdiff_plain;f=includes%2FBagOStuff.php;h=2ec615369aedaf5b0f21eed264d1d77c5d3dcebf;hb=adbb5e80d64de08f0be300f4484a81e5fb72b29a;hp=4154990da54f56fea8c68d1d7226c7146a5727fd;hpb=b144fcb85da4316289421284d156e3eecf94e3da;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/BagOStuff.php b/includes/BagOStuff.php index 4154990da5..2ec615369a 100644 --- a/includes/BagOStuff.php +++ b/includes/BagOStuff.php @@ -17,141 +17,142 @@ # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # http://www.gnu.org/copyleft/gpl.html + /** + * @defgroup Cache Cache * - * @package MediaWiki + * @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 + * + * $bag = new HashBagOStuff(); + * $bag = new MediaWikiBagOStuff($tablename); # connect to db first + * * - * @package MediaWiki + * @ingroup Cache */ -class BagOStuff { - var $debugmode; - - function __construct() { - $this->set_debug( false ); - } +abstract class BagOStuff { + var $debugMode = false; - function set_debug($bool) { - $this->debugmode = $bool; + public 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; - } + /** + * Get an item with the given key. Returns false if it does not exist. + * @param $key string + */ + abstract public function get( $key ); - function set($key, $value, $exptime=0) { - /* stub */ - return false; - } + /** + * Set an item. + * @param $key string + * @param $value mixed + * @param $exptime int Either an interval in seconds or a unix timestamp for expiry + */ + abstract public function set( $key, $value, $exptime = 0 ); - function delete($key, $time=0) { + /* + * Delete an item. + * @param $key string + * @param $time int Amount of time to delay the operation (mostly memcached-specific) + */ + abstract public function delete( $key, $time = 0 ); + + public function lock( $key, $timeout = 0 ) { /* stub */ - return false; + return true; } - function lock($key, $timeout = 0) { + public function unlock( $key ) { /* stub */ return true; } - function unlock($key) { + public function keys() { /* stub */ - return true; + return array(); } /* *** Emulated functions *** */ /* Better performance can likely be got with custom written versions */ - function get_multi($keys) { + public function get_multi( $keys ) { $out = array(); - foreach($keys as $key) - $out[$key] = $this->get($key); + 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); + public 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); + public 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); + public function add_multi( $hash, $exptime = 0 ) { + foreach ( $hash as $key => $value ) { + $this->add( $key, $value, $exptime ); + } } - function delete_multi($keys, $time=0) { - foreach($keys as $key) - $this->delete($key, $time); + public 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); + public 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) ) { + public function incr( $key, $value = 1 ) { + if ( !$this->lock( $key ) ) { return false; } - $value = intval($value); - if($value < 0) $value = 0; + $value = intval( $value ); $n = false; - if( ($n = $this->get($key)) !== false ) { + if ( ( $n = $this->get( $key ) ) !== false ) { $n += $value; - $this->set($key, $n); // exptime? + $this->set( $key, $n ); // exptime? } - $this->unlock($key); + $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; + public function decr( $key, $value = 1 ) { + return $this->incr( $key, -$value ); } - function _debug($text) { - if($this->debugmode) - wfDebug("BagOStuff debug: $text\n"); + public function debug( $text ) { + if ( $this->debugMode ) + wfDebug( "BagOStuff debug: $text\n" ); } /** * Convert an optionally relative time to an absolute time */ - static function convertExpiry( $exptime ) { - if(($exptime != 0) && ($exptime < 3600*24*30)) { + protected function convertExpiry( $exptime ) { + if ( ( $exptime != 0 ) && ( $exptime < 3600 * 24 * 30 ) ) { return time() + $exptime; } else { return $exptime; @@ -162,192 +163,236 @@ class BagOStuff { /** * Functional versions! - * @todo document - * @package MediaWiki + * This is a test of the interface, mainly. It stores things in an associative + * array, which is not going to persist between program runs. + * + * @ingroup Cache */ 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() { + function __construct() { $this->bag = array(); } - function _expire($key) { + protected function expire( $key ) { $et = $this->bag[$key][1]; - if(($et == 0) || ($et > time())) + if ( ( $et == 0 ) || ( $et > time() ) ) { return false; - $this->delete($key); + } + $this->delete( $key ); return true; } - function get($key) { - if(!$this->bag[$key]) + function get( $key ) { + if ( !isset( $this->bag[$key] ) ) { return false; - if($this->_expire($key)) + } + if ( $this->expire( $key ) ) { return false; + } return $this->bag[$key][0]; } - function set($key,$value,$exptime=0) { - $this->bag[$key] = array( $value, BagOStuff::convertExpiry( $exptime ) ); + function set( $key, $value, $exptime = 0 ) { + $this->bag[$key] = array( $value, $this->convertExpiry( $exptime ) ); } - function delete($key,$time=0) { - if(!$this->bag[$key]) + function delete( $key, $time = 0 ) { + if ( !isset( $this->bag[$key] ) ) { return false; - unset($this->bag[$key]); + } + 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) -); -*/ + function keys() { + return array_keys( $this->bag ); + } +} /** - * @todo document - * @abstract - * @package MediaWiki + * Class to store objects in the database + * + * @ingroup Cache */ -abstract class SqlBagOStuff extends BagOStuff { - var $table; - var $lastexpireall = 0; - - function SqlBagOStuff($tablename = 'objectcache') { - $this->table = $tablename; +class SqlBagOStuff extends BagOStuff { + var $lb, $db; + var $lastExpireAll = 0; + + protected function getDB() { + if ( !isset( $this->lb ) ) { + $this->lb = wfGetLBFactory()->newMainLB(); + $this->db = $this->lb->getConnection( DB_MASTER ); + $this->db->clearFlag( DBO_TRX ); + } + return $this->db; } - function get($key) { - /* expire old entries if any */ + public function get( $key ) { + # expire old entries if any $this->garbageCollect(); - - $res = $this->_query( - "SELECT value,exptime FROM $0 WHERE keyname='$1'", $key); - if(!$res) { - $this->_debug("get: ** error: " . $this->_dberror($res) . " **"); + $db = $this->getDB(); + $row = $db->selectRow( 'objectcache', array( 'value', 'exptime' ), + array( 'keyname' => $key ), __METHOD__ ); + if ( !$row ) { + $this->debug( 'get: no matching rows' ); return false; } - if($row=$this->_fetchobject($res)) { - $this->_debug("get: retrieved data; exp time is " . $row->exptime); - if ( $row->exptime != $this->_maxdatetime() && - wfTimestamp( TS_UNIX, $row->exptime ) < time() ) - { - $this->_debug("get: key has expired, deleting"); - $this->delete($key); - return false; + + $this->debug( "get: retrieved data; expiry time is " . $row->exptime ); + if ( $this->isExpired( $row->exptime ) ) { + $this->debug( "get: key has expired, deleting" ); + try { + $db->begin(); + # Put the expiry time in the WHERE condition to avoid deleting a + # newly-inserted value + $db->delete( 'objectcache', + array( + 'keyname' => $key, + 'exptime' => $row->exptime + ), __METHOD__ ); + $db->commit(); + } catch ( DBQueryError $e ) { + $this->handleWriteError( $e ); } - return $this->_unserialize($this->_blobdecode($row->value)); - } else { - $this->_debug('get: no matching rows'); + return false; } - return false; + return $this->unserialize( $db->decodeBlob( $row->value ) ); } - function set($key,$value,$exptime=0) { - $exptime = intval($exptime); - if($exptime < 0) $exptime = 0; - if($exptime == 0) { - $exp = $this->_maxdatetime(); + public function set( $key, $value, $exptime = 0 ) { + $db = $this->getDB(); + $exptime = intval( $exptime ); + if ( $exptime < 0 ) $exptime = 0; + if ( $exptime == 0 ) { + $encExpiry = $this->getMaxDateTime(); } else { - if($exptime < 3.16e8) # ~10 years + if ( $exptime < 3.16e8 ) # ~10 years $exptime += time(); - $exp = $this->_fromunixtime($exptime); + $encExpiry = $db->timestamp( $exptime ); } - $this->delete( $key ); - $this->_doinsert($this->getTableName(), array( + try { + $db->begin(); + $db->delete( 'objectcache', array( 'keyname' => $key ), __METHOD__ ); + $db->insert( 'objectcache', + array( 'keyname' => $key, - 'value' => $this->_blobencode($this->_serialize($value)), - 'exptime' => $exp - )); - return true; /* ? */ + 'value' => $db->encodeBlob( $this->serialize( $value ) ), + 'exptime' => $encExpiry + ), __METHOD__ ); + $db->commit(); + } catch ( DBQueryError $e ) { + $this->handleWriteError( $e ); + return false; + } + return true; } - function delete($key,$time=0) { - $this->_query( - "DELETE FROM $0 WHERE keyname='$1'", $key ); - return true; /* ? */ + public function delete( $key, $time = 0 ) { + $db = $this->getDB(); + try { + $db->begin(); + $db->delete( 'objectcache', array( 'keyname' => $key ), __METHOD__ ); + $db->commit(); + } catch ( DBQueryError $e ) { + $this->handleWriteError( $e ); + return false; + } + return true; } - function getTableName() { - return $this->table; - } + public function incr( $key, $step = 1 ) { + $db = $this->getDB(); + $step = intval( $step ); - function _query($sql) { - $reps = func_get_args(); - $reps[0] = $this->getTableName(); - // ewwww - for($i=0;$i 0 ? $this->_strencode($reps[$i]) : $reps[$i], - $sql); - } - $res = $this->_doquery($sql); - if($res == false) { - $this->_debug('query failed: ' . $this->_dberror($res)); + try { + $db->begin(); + $row = $db->selectRow( 'objectcache', array( 'value', 'exptime' ), + array( 'keyname' => $key ), __METHOD__, array( 'FOR UPDATE' ) ); + if ( $row === false ) { + // Missing + $db->commit(); + return false; + } + $db->delete( 'objectcache', array( 'keyname' => $key ), __METHOD__ ); + if ( $this->isExpired( $row->exptime ) ) { + // Expired, do not reinsert + $db->commit(); + return false; + } + + $oldValue = intval( $this->unserialize( $db->decodeBlob( $row->value ) ) ); + $newValue = $oldValue + $step; + $db->insert( 'objectcache', + array( + 'keyname' => $key, + 'value' => $db->encodeBlob( $this->serialize( $newValue ) ), + 'exptime' => $row->exptime + ), __METHOD__ ); + $db->commit(); + } catch ( DBQueryError $e ) { + $this->handleWriteError( $e ); + return false; } - return $res; + return $newValue; } - function _strencode($str) { - /* Protect strings in SQL */ - return str_replace( "'", "''", $str ); - } - function _blobencode($str) { - return $str; - } - function _blobdecode($str) { - return $str; + public function keys() { + $db = $this->getDB(); + $res = $db->select( 'objectcache', array( 'keyname' ), false, __METHOD__ ); + $result = array(); + foreach ( $res as $row ) { + $result[] = $row->keyname; + } + return $result; } - abstract function _doinsert($table, $vals); - abstract function _doquery($sql); - - function _freeresult($result) { - /* stub */ - return false; + protected function isExpired( $exptime ) { + return $exptime != $this->getMaxDateTime() && wfTimestamp( TS_UNIX, $exptime ) < time(); } - function _dberror($result) { - /* stub */ - return 'unknown error'; + protected function getMaxDateTime() { + if ( time() > 0x7fffffff ) { + return $this->getDB()->timestamp( 1 << 62 ); + } else { + return $this->getDB()->timestamp( 0x7fffffff ); + } } - abstract function _maxdatetime(); - abstract function _fromunixtime($ts); - - function garbageCollect() { + protected function garbageCollect() { /* Ignore 99% of requests */ if ( !mt_rand( 0, 100 ) ) { - $nowtime = time(); + $now = time(); /* Avoid repeating the delete within a few seconds */ - if ( $nowtime > ($this->lastexpireall + 1) ) { - $this->lastexpireall = $nowtime; - $this->expireall(); + if ( $now > ( $this->lastExpireAll + 1 ) ) { + $this->lastExpireAll = $now; + $this->expireAll(); } } } - function expireall() { - /* Remove any items that have expired */ - $now = $this->_fromunixtime( time() ); - $this->_query( "DELETE FROM $0 WHERE exptime < '$now'" ); + public function expireAll() { + $db = $this->getDB(); + $now = $db->timestamp(); + try { + $db->begin(); + $db->delete( 'objectcache', array( 'exptime < ' . $db->addQuotes( $now ) ), __METHOD__ ); + $db->commit(); + } catch ( DBQueryError $e ) { + $this->handleWriteError( $e ); + } } - function deleteall() { - /* Clear *all* items from cache table */ - $this->_query( "DELETE FROM $0" ); + public function deleteAll() { + $db = $this->getDB(); + try { + $db->begin(); + $db->delete( 'objectcache', '*', __METHOD__ ); + $db->commit(); + } catch ( DBQueryError $e ) { + $this->handleWriteError( $e ); + } } /** @@ -355,12 +400,12 @@ abstract class SqlBagOStuff extends BagOStuff { * On typical message and page data, this can provide a 3X decrease * in storage requirements. * - * @param mixed $data + * @param $data mixed * @return string */ - function _serialize( &$data ) { + protected function serialize( &$data ) { $serial = serialize( $data ); - if( function_exists( 'gzdeflate' ) ) { + if ( function_exists( 'gzdeflate' ) ) { return gzdeflate( $serial ); } else { return $serial; @@ -369,86 +414,43 @@ abstract class SqlBagOStuff extends BagOStuff { /** * Unserialize and, if necessary, decompress an object. - * @param string $serial + * @param $serial string * @return mixed */ - function _unserialize( $serial ) { - if( function_exists( 'gzinflate' ) ) { + protected function unserialize( $serial ) { + if ( function_exists( 'gzinflate' ) ) { $decomp = @gzinflate( $serial ); - if( false !== $decomp ) { + if ( false !== $decomp ) { $serial = $decomp; } } $ret = unserialize( $serial ); return $ret; } -} - -/** - * @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 _doinsert($t, $v) { - $dbw =& wfGetDB( DB_MASTER ); - return $dbw->insert($t, $v, 'MediaWikiBagOStuff::_doinsert', - array( 'IGNORE' ) ); - } - 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() { - if ( time() > 0x7fffffff ) { - return $this->_fromunixtime( 1<<62 ); - } else { - return $this->_fromunixtime( 0x7fffffff ); + /** + * Handle a DBQueryError which occurred during a write operation. + * Ignore errors which are due to a read-only database, rethrow others. + */ + protected function handleWriteError( $exception ) { + $db = $this->getDB(); + if ( !$db->wasReadOnlyError() ) { + throw $exception; } - } - function _fromunixtime($ts) { - $dbw =& wfGetDB(DB_MASTER); - return $dbw->timestamp($ts); - } - function _strencode($s) { - $dbw =& wfGetDB( DB_MASTER ); - return $dbw->strencode($s); - } - function _blobencode($s) { - $dbw =& wfGetDB( DB_MASTER ); - return $dbw->encodeBlob($s); - } - function _blobdecode($s) { - $dbw =& wfGetDB( DB_MASTER ); - return $dbw->decodeBlob($s); - } - function getTableName() { - if ( !$this->tableInitialised ) { - $dbw =& wfGetDB( DB_MASTER ); - /* This is actually a hack, we should be able - to use Language classes here... or not */ - if (!$dbw) - throw new MWException("Could not connect to database"); - $this->table = $dbw->tableName( $this->table ); - $this->tableInitialised = true; + try { + $db->rollback(); + } catch ( DBQueryError $e ) { } - return $this->table; + wfDebug( __METHOD__ . ": ignoring query error\n" ); + $db->ignoreErrors( false ); } } +/** + * Backwards compatibility alias + */ +class MediaWikiBagOStuff extends SqlBagOStuff {} + /** * This is a wrapper for Turck MMCache's shared memory functions. * @@ -462,10 +464,10 @@ class MediaWikiBagOStuff extends SqlBagOStuff { * that Turck's serializer is faster, so a possible future extension would be * to use it for arrays but not for objects. * - * @package MediaWiki + * @ingroup Cache */ class TurckBagOStuff extends BagOStuff { - function get($key) { + public function get( $key ) { $val = mmcache_get( $key ); if ( is_string( $val ) ) { $val = unserialize( $val ); @@ -473,22 +475,22 @@ class TurckBagOStuff extends BagOStuff { return $val; } - function set($key, $value, $exptime=0) { + public function set( $key, $value, $exptime = 0 ) { mmcache_put( $key, serialize( $value ), $exptime ); return true; } - function delete($key, $time=0) { + public function delete( $key, $time = 0 ) { mmcache_rm( $key ); return true; } - function lock($key, $waitTimeout = 0 ) { + public function lock( $key, $waitTimeout = 0 ) { mmcache_lock( $key ); return true; } - function unlock($key) { + public function unlock( $key ) { mmcache_unlock( $key ); return true; } @@ -497,25 +499,24 @@ class TurckBagOStuff extends BagOStuff { /** * This is a wrapper for APC's shared memory functions * - * @package MediaWiki + * @ingroup Cache */ - class APCBagOStuff extends BagOStuff { - function get($key) { - $val = apc_fetch($key); + public function get( $key ) { + $val = apc_fetch( $key ); if ( is_string( $val ) ) { $val = unserialize( $val ); } return $val; } - - function set($key, $value, $exptime=0) { - apc_store($key, serialize($value), $exptime); + + public function set( $key, $value, $exptime = 0 ) { + apc_store( $key, serialize( $value ), $exptime ); return true; } - - function delete($key, $time=0) { - apc_delete($key); + + public function delete( $key, $time = 0 ) { + apc_delete( $key ); return true; } } @@ -527,10 +528,10 @@ class APCBagOStuff extends BagOStuff { * This is basically identical to the Turck MMCache version, * mostly because eAccelerator is based on Turck MMCache. * - * @package MediaWiki + * @ingroup Cache */ class eAccelBagOStuff extends BagOStuff { - function get($key) { + public function get( $key ) { $val = eaccelerator_get( $key ); if ( is_string( $val ) ) { $val = unserialize( $val ); @@ -538,37 +539,94 @@ class eAccelBagOStuff extends BagOStuff { return $val; } - function set($key, $value, $exptime=0) { + public function set( $key, $value, $exptime = 0 ) { eaccelerator_put( $key, serialize( $value ), $exptime ); return true; } - function delete($key, $time=0) { + public function delete( $key, $time = 0 ) { eaccelerator_rm( $key ); return true; } - function lock($key, $waitTimeout = 0 ) { + public function lock( $key, $waitTimeout = 0 ) { eaccelerator_lock( $key ); return true; } - function unlock($key) { + public function unlock( $key ) { eaccelerator_unlock( $key ); return true; } } +/** + * Wrapper for XCache object caching functions; identical interface + * to the APC wrapper + * + * @ingroup Cache + */ +class XCacheBagOStuff extends BagOStuff { + + /** + * Get a value from the XCache object cache + * + * @param $key String: cache key + * @return mixed + */ + public function get( $key ) { + $val = xcache_get( $key ); + if ( is_string( $val ) ) + $val = unserialize( $val ); + return $val; + } + + /** + * Store a value in the XCache object cache + * + * @param $key String: cache key + * @param $value Mixed: object to store + * @param $expire Int: expiration time + * @return bool + */ + public function set( $key, $value, $expire = 0 ) { + xcache_set( $key, serialize( $value ), $expire ); + return true; + } + + /** + * Remove a value from the XCache object cache + * + * @param $key String: cache key + * @param $time Int: not used in this implementation + * @return bool + */ + public function delete( $key, $time = 0 ) { + xcache_unset( $key ); + return true; + } + +} + +/** + * Cache that uses DBA as a backend. + * Slow due to the need to constantly open and close the file to avoid holding + * writer locks. Intended for development use only, as a memcached workalike + * for systems that don't have it. + * + * @ingroup Cache + */ class DBABagOStuff extends BagOStuff { var $mHandler, $mFile, $mReader, $mWriter, $mDisabled; - - function __construct( $handler = 'db3', $dir = false ) { + + public function __construct( $handler = 'db3', $dir = false ) { if ( $dir === false ) { global $wgTmpDirectory; $dir = $wgTmpDirectory; } $this->mFile = "$dir/mw-cache-" . wfWikiID(); $this->mFile .= '.db'; + wfDebug( __CLASS__ . ": using cache file {$this->mFile}\n" ); $this->mHandler = $handler; } @@ -577,7 +635,7 @@ class DBABagOStuff extends BagOStuff { */ function encode( $value, $expiry ) { # Convert to absolute time - $expiry = BagOStuff::convertExpiry( $expiry ); + $expiry = $this->convertExpiry( $expiry ); return sprintf( '%010u', intval( $expiry ) ) . ' ' . serialize( $value ); } @@ -588,7 +646,7 @@ class DBABagOStuff extends BagOStuff { if ( !is_string( $blob ) ) { return array( null, 0 ); } else { - return array( + return array( unserialize( substr( $blob, 11 ) ), intval( substr( $blob, 0, 10 ) ) ); @@ -617,7 +675,7 @@ class DBABagOStuff extends BagOStuff { function get( $key ) { wfProfileIn( __METHOD__ ); - wfDebug( __METHOD__."($key)\n" ); + wfDebug( __METHOD__ . "($key)\n" ); $handle = $this->getReader(); if ( !$handle ) { return null; @@ -632,16 +690,16 @@ class DBABagOStuff extends BagOStuff { $handle = $this->getWriter(); dba_delete( $key, $handle ); dba_close( $handle ); - wfDebug( __METHOD__.": $key expired\n" ); + wfDebug( __METHOD__ . ": $key expired\n" ); $val = null; } wfProfileOut( __METHOD__ ); return $val; } - function set( $key, $value, $exptime=0 ) { + function set( $key, $value, $exptime = 0 ) { wfProfileIn( __METHOD__ ); - wfDebug( __METHOD__."($key)\n" ); + wfDebug( __METHOD__ . "($key)\n" ); $blob = $this->encode( $value, $exptime ); $handle = $this->getWriter(); if ( !$handle ) { @@ -655,6 +713,7 @@ class DBABagOStuff extends BagOStuff { function delete( $key, $time = 0 ) { wfProfileIn( __METHOD__ ); + wfDebug( __METHOD__ . "($key)\n" ); $handle = $this->getWriter(); if ( !$handle ) { return false; @@ -688,6 +747,17 @@ class DBABagOStuff extends BagOStuff { wfProfileOut( __METHOD__ ); return $ret; } + + function keys() { + $reader = $this->getReader(); + $k1 = dba_firstkey( $reader ); + if ( !$k1 ) { + return array(); + } + $result[] = $k1; + while ( $key = dba_nextkey( $reader ) ) { + $result[] = $key; + } + return $result; + } } - -?>