全部博文(42)
分类:
2010-04-18 17:01:55
<?php
class CacheException extends Exception {}
/**
* 缓存抽象类
*/
abstract class Cache_Abstract {
/**
* 读缓存变量
*
* @param string $key 缓存下标
*/
abstract public function fetch($key);
/**
* 缓存变量
*
* @param string $key 缓存变量下标
* @param string $value 缓存变量的值
*/
abstract public function store($key, $value);
/**
* 删除缓存变量
*
* @param string $key 缓存下标
*/
abstract public function delete($key);
/**
* 清(删)除所有缓存
*
*/
abstract public function clean();
/**
* 锁定缓存变量
*
* @param string $key 缓存下标
*/
abstract public function lock($key);
/**
* 缓存变量解锁
*
* @param string $key 缓存下标
*/
abstract public function unlock($key);
/**
* 取得缓存变量是否被锁定
*
* @param string $key 缓存下标
*/
abstract public function isLocked($key);
/**
* 确保不是锁定状态
* 最多做$tries次睡眠等待解锁,超时则跳过并解锁
*
* @param string $key 缓存下标
*/
public function checkLock($key) {
if (!$this->isLocked($key)) {
return $this;
}
$tries =
10;
$count =
0;
do {
usleep(100);
$count ++;
} while ($count <= $tries && $this->isLocked($key)); //
最多做十次睡眠等待解锁,超时则跳过并解锁
if ($this->isLocked($key)) {
$this->unlock($key);
}
return $this;
}
}
<?php
/**
* 文件缓存
*
*
* @category Mjie
* @package Cache
* @author 流水孟春
* @copyright Copyright (c) 2008-
* @license New BSD License
* @version $Id: Cache/File.php 版本号 2010-04-18 16:46 cmpan $
*/
class Cache_File extends Cache_Abstract {
protected $_cachesDir = 'cache';
public function __construct() {
if (defined('DATA_DIR')) {
$this->_setCacheDir(DATA_DIR . '/cache');
}
}
protected function _getCacheFile($key) {
return $this->_cachesDir . '/'
. substr($key, 0, 2) . '/' . $key . '.php';
}
/**
* 读取缓存变量
* 为防止信息泄露,缓存文件格式为php文件,并以"<?php exit;?>"开头
*
* @param string $key 缓存下标
*/
public function fetch($key) {
$cacheFile = self::_getCacheFile($key);
if (file_exists($cacheFile) && is_readable($cacheFile)) {
return @file_get_contents($cacheFile, false, NULL, 13);
}
return false;
}
/**
* 缓存变量
* 为防止信息泄露,缓存文件格式为php文件,并以"<?php exit;?>"开头
*
* @param string $key 缓存变量下标
* @param string $value 缓存变量的值
*/
public function store($key, $value) {
$cacheFile = self::_getCacheFile($key);
$cacheDir =
dirname($cacheFile);
if(!is_dir($cacheDir)) {
if(!@mkdir($cacheDir, 0755,
true)) {
throw new CacheException("Could not make cache directory");
}
}
return @file_put_contents($cacheFile, '<?php exit;?>' . $value);
}
/**
* 删除缓存变量
*
* @param string $key 缓存下标
* @return Cache_Abstract
*/
public function delete($key) {
if(empty($key)) {
throw new CacheException("Missing argument 1 for Cache_File::delete()");
}
$cacheFile = self::_getCacheFile($key);
if(!@unlink($cacheFile)) {
throw new CacheException("Cache file could not be deleted");
}
return $this;
}
public function isLocked($key) {
$cacheFile = self::_getCacheFile($key);
clearstatcache();
return file_exists($cacheFile . '.lock');
}
/**
* 锁定
*
* @param string $key
* @return Cache_Abstract
*/
public function lock($key) {
$cacheFile = self::_getCacheFile($key);
$cacheDir =
dirname($cacheFile);
if(!is_dir($cacheDir)) {
if(!@mkdir($cacheDir, 0755,
true)) {
if(!is_dir($cacheDir)) {
throw new CacheException("Could not make cache directory");
}
}
}
// 设定缓存锁文件的访问和修改时间
@touch($cacheFile . '.lock');
return $this;
}
/**
* 解锁
*
* @param string $key
* @return Cache_Abstract
*/
public function unlock($key) {
$cacheFile = self::_getCacheFile($key);
@unlink($cacheFile . '.lock');
return $this;
}
/**
* 设置文件缓存目录
* @param string $dir
* @return Cache_Abstract
*/
protected function _setCacheDir($dir) {
$this->_cachesDir = rtrim(str_replace('\\', '/', trim($dir)), '/');
clearstatcache();
if(!is_dir($this->_cachesDir)) {
mkdir($this->_cachesDir,
0755, true);
}
//
return $this;
}
public function getCacheDir() {
return $this->_cachesDir;
}
/**
* 清空所有缓存
*
* @return Cache_Abstract
*/
public function clean() {
// 遍历目录清除缓存
$cacheDir =
$this->_cachesDir;
$d =
dir($cacheDir);
while(false !== ($entry = $d->read())) {
if('.' == $entry[0]) {
continue;
}
$cacheEntry = $cacheDir . '/'
. $entry;
if(is_file($cacheEntry)) {
@unlink($cacheEntry);
} elseif(is_dir($cacheEntry)) {
// 缓存文件夹有两级
$d2 = dir($cacheEntry);
while(false !== ($entry = $d2->read())) {
if('.' == $entry[0]) {
continue;
}
$cacheEntry .= '/' . $entry;
if(is_file($cacheEntry)) {
@unlink($cacheEntry);
}
}
$d2->close();
}
}
$d->close();
return $this;
}
}
<?php
/**
* 缓存单元的数据结构
* array(
* 'time' => time(), // 缓存写入时的时间戳
* 'expire' => $expire, // 缓存过期时间
* 'valid' => true, // 缓存是否有效
* 'data' => $value // 缓存的值
* );
*/
final class Cache {
/**
* 缓存过期时间长度(s)
*
* @var int
*/
private $_expire = 3600;
/**
* 请求时间
*
* @var int
*/
private $_time = 0;
/**
* 缓存处理类
*
* @var Cache_Abstract
*/
private $_storage = null;
/**
* @return Cache
*/
static public function createCache($cacheClass, $time = 0) {
return new self($cacheClass, $time);
}
private function __construct($cacheClass, $time = 0) {
$this->_storage = new
$cacheClass();
if (!$time) {
$this->_time = time();
} else {
$this->_time = $time;
}
}
/**
* 读取缓存
*
* @param string $key
* @return mixed
*/
public function get($key) {
$data =
$this->fetch($key);
if ($data && $data['valid'] && !$data['isExpired']) {
return $data['data'];
}
return false;
}
/**
* 读缓存,包括过期的和无效的,取得完整的存贮结构
*
* @param string $key
*/
public function fetch($key) {
$this->_storage->checkLock($key);
$data =
$this->_storage->fetch($key);
if ($data) {
$data = unserialize($data);
$data['isExpired'] = (time() - $data['time']) > $data['expire'] ? true : false;
return $data;
}
return false;
}
/**
* 设置缓存
*
* @param string $key
* @param mixed $value
* @param int $expire
*/
public function set($key, $value, $expire = false) {
if (!$expire) {
$expire = $this->_expire;
}
$this->_storage->checkLock($key);
$data =
serialize(array('time' =>
time(), 'expire' => $expire, 'valid' => true, 'data' =>
$value));
$this->_storage->lock($key);
try {
$this->_storage->store($key, $data);
$this->_storage->unlock($key);
} catch (CacheException $e) {
$this->_storage->unlock($key);
throw $e;
}
}
/**
* 删除缓存
*
* @param string $key
*/
public function delete($key) {
$this->_storage->checkLock($key)
->lock($key)
->delete($key)
->unlock($key);
}
/**
* 把缓存设为无效
*
* @param string $key
*/
public function setInvalidate($key) {
$this->_storage->checkLock($key)
->lock($key);
try {
$data = $this->_storage->fetch($key);
if ($data) {
$data = unserialize($data);
$data['valid'] = false;
$this->_storage->store($key, serialize($data));
}
$this->_storage->unlock($key);
} catch (CacheException $e) {
$this->_storage->unlock($key);
throw $e;
}
}
/**
* 设置缓存过期时间(s)
*
* @param int $expire
*/
public function setExpire($expire) {
$this->_expire = (int) $expire;
return $this;
}
}
注: 所有的"
<
"
换成"<","
>
"换成">"