bagostuff.php

来自「php 开发的内容管理系统」· PHP 代码 · 共 539 行

PHP
539
字号
<?php## 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.,# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.# http://www.gnu.org/copyleft/gpl.html/** * * @package MediaWiki *//** * 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 * * @package MediaWiki */class BagOStuff {	var $debugmode;	function BagOStuff() {		$this->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;	}	function set($key, $value, $exptime=0) {		/* stub */		return false;	}	function delete($key, $time=0) {		/* stub */		return false;	}	function lock($key, $timeout = 0) {		/* stub */		return true;	}	function unlock($key) {		/* stub */		return true;	}	/* *** 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);			return true;		}	}	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);	}	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) ) {			return false;		}		$value = intval($value);		if($value < 0) $value = 0;		$n = false;		if( ($n = $this->get($key)) !== false ) {			$n += $value;			$this->set($key, $n); // exptime?		}		$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;	}	function _debug($text) {		if($this->debugmode)			wfDebug("BagOStuff debug: $text\n");	}}/** * Functional versions! * @todo document * @package MediaWiki */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));*//** * @todo document * @abstract * @package MediaWiki */abstract class SqlBagOStuff extends BagOStuff {	var $table;	var $lastexpireall = 0;	function SqlBagOStuff($tablename = 'objectcache') {		$this->table = $tablename;	}	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) . " **");			return false;		}		if($row=$this->_fetchobject($res)) {			$this->_debug("get: retrieved data; exp time is " . $row->exptime);			return $this->_unserialize($this->_blobdecode($row->value));		} else {			$this->_debug('get: no matching rows');		}		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);		}		$this->delete( $key );		$this->_doinsert($this->getTableName(), array(					'keyname' => $key,					'value' => $this->_blobencode($this->_serialize($value)),					'exptime' => $exp				));		return true; /* ? */	}	function delete($key,$time=0) {		$this->_query(			"DELETE FROM $0 WHERE keyname='$1'", $key );		return true; /* ? */	}	function getTableName() {		return $this->table;	}	function _query($sql) {		$reps = func_get_args();		$reps[0] = $this->getTableName();		// ewwww		for($i=0;$i<count($reps);$i++) {			$sql = str_replace(				'$' . $i,				$i > 0 ? $this->_strencode($reps[$i]) : $reps[$i],				$sql);		}		$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 _blobencode($str) {		return $str;	}	function _blobdecode($str) {		return $str;	}	abstract function _doinsert($table, $vals);	abstract function _doquery($sql);	function _freeresult($result) {		/* stub */		return false;	}	function _dberror($result) {		/* stub */		return 'unknown error';	}	abstract function _maxdatetime();	abstract function _fromunixtime($ts);	function garbageCollect() {		/* Ignore 99% of requests */		if ( !mt_rand( 0, 100 ) ) {			$nowtime = time();			/* Avoid repeating the delete within a few seconds */			if ( $nowtime > ($this->lastexpireall + 1) ) {				$this->lastexpireall = $nowtime;				$this->expireall();			}		}	}	function expireall() {		/* Remove any items that have expired */		$now = $this->_fromunixtime( time() );		$this->_query( "DELETE FROM $0 WHERE exptime < '$now'" );	}	function deleteall() {		/* Clear *all* items from cache table */		$this->_query( "DELETE FROM $0" );	}	/**	 * Serialize an object and, if possible, compress the representation.	 * On typical message and page data, this can provide a 3X decrease	 * in storage requirements.	 *	 * @param mixed $data	 * @return string	 */	function _serialize( &$data ) {		$serial = serialize( $data );		if( function_exists( 'gzdeflate' ) ) {			return gzdeflate( $serial );		} else {			return $serial;		}	}	/**	 * Unserialize and, if necessary, decompress an object.	 * @param string $serial	 * @return mixed	 */	function _unserialize( $serial ) {		if( function_exists( 'gzinflate' ) ) {			$decomp = @gzinflate( $serial );			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');	}	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() {		$dbw =& wfGetDB(DB_MASTER);		return $dbw->timestamp('9999-12-31 12:59:59');	}	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;		}		return $this->table;	}}/** * This is a wrapper for Turck MMCache's shared memory functions. * * You can store objects with mmcache_put() and mmcache_get(), but Turck seems * to use a weird custom serializer that randomly segfaults. So we wrap calls * with serialize()/unserialize(). * * The thing I noticed about the Turck serialized data was that unlike ordinary * serialize(), it contained the names of methods, and judging by the amount of * binary data, perhaps even the bytecode of the methods themselves. It may be * that Turck's serializer is faster, so a possible future extension would be * to use it for arrays but not for objects. * * @package MediaWiki */class TurckBagOStuff extends BagOStuff {	function get($key) {		$val = mmcache_get( $key );		if ( is_string( $val ) ) {			$val = unserialize( $val );		}		return $val;	}	function set($key, $value, $exptime=0) {		mmcache_put( $key, serialize( $value ), $exptime );		return true;	}	function delete($key, $time=0) {		mmcache_rm( $key );		return true;	}	function lock($key, $waitTimeout = 0 ) {		mmcache_lock( $key );		return true;	}	function unlock($key) {		mmcache_unlock( $key );		return true;	}}/** * This is a wrapper for APC's shared memory functions * * @package MediaWiki */class APCBagOStuff extends BagOStuff {	function get($key) {		$val = apc_fetch($key);		return $val;	}		function set($key, $value, $exptime=0) {		apc_store($key, $value, $exptime);		return true;	}		function delete($key) {		apc_delete($key);		return true;	}}/** * This is a wrapper for eAccelerator's shared memory functions. * * This is basically identical to the Turck MMCache version, * mostly because eAccelerator is based on Turck MMCache. * * @package MediaWiki */class eAccelBagOStuff extends BagOStuff {	function get($key) {		$val = eaccelerator_get( $key );		if ( is_string( $val ) ) {			$val = unserialize( $val );		}		return $val;	}	function set($key, $value, $exptime=0) {		eaccelerator_put( $key, serialize( $value ), $exptime );		return true;	}	function delete($key, $time=0) {		eaccelerator_rm( $key );		return true;	}	function lock($key, $waitTimeout = 0 ) {		eaccelerator_lock( $key );		return true;	}	function unlock($key) {		eaccelerator_unlock( $key );		return true;	}}?>

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?