更新内核,删除部分不常用驱动
This commit is contained in:
94
core/library/think/cache/driver/Apc.php
vendored
94
core/library/think/cache/driver/Apc.php
vendored
@@ -1,94 +0,0 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: liu21st <liu21st@gmail.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace think\cache\driver;
|
||||
|
||||
use think\Cache;
|
||||
use think\Exception;
|
||||
|
||||
/**
|
||||
* Apc缓存驱动
|
||||
* @author liu21st <liu21st@gmail.com>
|
||||
*/
|
||||
class Apc
|
||||
{
|
||||
protected $options = [
|
||||
'expire' => 0,
|
||||
'prefix' => '',
|
||||
];
|
||||
/*****************************
|
||||
需要支持apc_cli模式
|
||||
******************************/
|
||||
/**
|
||||
* 架构函数
|
||||
* @param array $options 缓存参数
|
||||
* @throws Exception
|
||||
* @access public
|
||||
*/
|
||||
public function __construct($options = [])
|
||||
{
|
||||
if (!function_exists('apc_cache_info')) {
|
||||
throw new \BadFunctionCallException('not support: Apc');
|
||||
}
|
||||
if (!empty($options)) {
|
||||
$this->options = array_merge($this->options, $options);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取缓存
|
||||
* @access public
|
||||
* @param string $name 缓存变量名
|
||||
* @return mixed
|
||||
*/
|
||||
public function get($name)
|
||||
{
|
||||
return apc_fetch($this->options['prefix'] . $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* 写入缓存
|
||||
* @access public
|
||||
* @param string $name 缓存变量名
|
||||
* @param mixed $value 存储数据
|
||||
* @param integer $expire 有效时间(秒)
|
||||
* @return bool
|
||||
*/
|
||||
public function set($name, $value, $expire = null)
|
||||
{
|
||||
if (is_null($expire)) {
|
||||
$expire = $this->options['expire'];
|
||||
}
|
||||
$name = $this->options['prefix'] . $name;
|
||||
return apc_store($name, $value, $expire);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除缓存
|
||||
* @access public
|
||||
* @param string $name 缓存变量名
|
||||
* @return bool|\string[]
|
||||
*/
|
||||
public function rm($name)
|
||||
{
|
||||
return apc_delete($this->options['prefix'] . $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除缓存
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
return apc_clear_cache('user');
|
||||
}
|
||||
}
|
||||
763
core/library/think/cache/driver/Secache.php
vendored
763
core/library/think/cache/driver/Secache.php
vendored
@@ -1,763 +0,0 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: liu21st <liu21st@gmail.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace think\cache\driver;
|
||||
|
||||
use think\Cache;
|
||||
|
||||
/**
|
||||
* Secache缓存驱动
|
||||
* @author liu21st <liu21st@gmail.com>
|
||||
*/
|
||||
class Secache
|
||||
{
|
||||
protected $handler = null;
|
||||
protected $options = [
|
||||
'project' => '',
|
||||
'path' => '',
|
||||
'expire' => 0,
|
||||
'prefix' => '',
|
||||
];
|
||||
|
||||
/**
|
||||
* 架构函数
|
||||
* @param array $options 缓存参数
|
||||
* @access public
|
||||
*/
|
||||
public function __construct($options = [])
|
||||
{
|
||||
if (!empty($options)) {
|
||||
$this->options = array_merge($this->options, $options);
|
||||
}
|
||||
if (substr($this->options['path'], -1) != '/') {
|
||||
$this->options['path'] .= '/';
|
||||
}
|
||||
|
||||
$this->handler = new SecacheClient;
|
||||
$this->handler->workat($this->options['path'] . $this->options['project']);
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取缓存
|
||||
* @access public
|
||||
* @param string $name 缓存变量名
|
||||
* @return mixed
|
||||
*/
|
||||
public function get($name)
|
||||
{
|
||||
$name = $this->options['prefix'] . $name;
|
||||
$key = md5($name);
|
||||
$this->handler->fetch($key, $return);
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* 写入缓存
|
||||
* @access public
|
||||
* @param string $name 缓存变量名
|
||||
* @param mixed $value 存储数据
|
||||
* @param integer $expire 有效时间(秒)
|
||||
* @return boolean
|
||||
*/
|
||||
public function set($name, $value)
|
||||
{
|
||||
$name = $this->options['prefix'] . $name;
|
||||
$key = md5($name);
|
||||
return $this->handler->store($key, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除缓存
|
||||
* @access public
|
||||
* @param string $name 缓存变量名
|
||||
* @return boolen
|
||||
*/
|
||||
public function rm($name)
|
||||
{
|
||||
$name = $this->options['prefix'] . $name;
|
||||
$key = md5($name);
|
||||
return $this->handler->delete($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除缓存
|
||||
* @access public
|
||||
* @return boolen
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
return $this->handler->_format(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!defined('SECACHE_SIZE')) {
|
||||
define('SECACHE_SIZE', '15M');
|
||||
}
|
||||
class SecacheClient
|
||||
{
|
||||
|
||||
public $idx_node_size = 40;
|
||||
public $data_base_pos = 262588; //40+20+24*16+16*16*16*16*4;
|
||||
public $schema_item_size = 24;
|
||||
public $header_padding = 20; //保留空间 放置php标记防止下载
|
||||
public $info_size = 20; //保留空间 4+16 maxsize|ver
|
||||
|
||||
//40起 添加20字节保留区域
|
||||
public $idx_seq_pos = 40; //id 计数器节点地址
|
||||
public $dfile_cur_pos = 44; //id 计数器节点地址
|
||||
public $idx_free_pos = 48; //id 空闲链表入口地址
|
||||
|
||||
public $idx_base_pos = 444; //40+20+24*16
|
||||
public $min_size = 10240; //10M最小值
|
||||
public $schema_struct = array('size', 'free', 'lru_head', 'lru_tail', 'hits', 'miss');
|
||||
public $ver = '$Rev: 3 $';
|
||||
public $name = '系统默认缓存(文件型)';
|
||||
|
||||
public function workat($file)
|
||||
{
|
||||
|
||||
$this->_file = $file . '.php';
|
||||
$this->_bsize_list = array(
|
||||
512 => 10,
|
||||
3 << 10 => 10,
|
||||
8 << 10 => 10,
|
||||
20 << 10 => 4,
|
||||
30 << 10 => 2,
|
||||
50 << 10 => 2,
|
||||
80 << 10 => 2,
|
||||
96 << 10 => 2,
|
||||
128 << 10 => 2,
|
||||
224 << 10 => 2,
|
||||
256 << 10 => 2,
|
||||
512 << 10 => 1,
|
||||
1024 << 10 => 1,
|
||||
);
|
||||
|
||||
$this->_node_struct = array(
|
||||
'next' => array(0, 'V'),
|
||||
'prev' => array(4, 'V'),
|
||||
'data' => array(8, 'V'),
|
||||
'size' => array(12, 'V'),
|
||||
'lru_right' => array(16, 'V'),
|
||||
'lru_left' => array(20, 'V'),
|
||||
'key' => array(24, 'H*'),
|
||||
);
|
||||
|
||||
if (!file_exists($this->_file)) {
|
||||
$this->create();
|
||||
} else {
|
||||
$this->_rs = fopen($this->_file, 'rb+') || $this->triggerError('Can\'t open the cachefile: ' . realpath($this->_file), E_USER_ERROR);
|
||||
$this->_seek($this->header_padding);
|
||||
$info = unpack('V1max_size/a*ver', fread($this->_rs, $this->info_size));
|
||||
if ($info['ver'] != $this->ver) {
|
||||
$this->_format(true);
|
||||
} else {
|
||||
$this->max_size = $info['max_size'];
|
||||
}
|
||||
}
|
||||
|
||||
$this->idx_node_base = $this->data_base_pos + $this->max_size;
|
||||
$this->_block_size_list = array_keys($this->_bsize_list);
|
||||
sort($this->_block_size_list);
|
||||
return true;
|
||||
}
|
||||
|
||||
public function create()
|
||||
{
|
||||
$this->_rs = fopen($this->_file, 'wb+') || $this->triggerError('Can\'t open the cachefile: ' . realpath($this->_file), E_USER_ERROR);
|
||||
fseek($this->_rs, 0);
|
||||
fputs($this->_rs, '<' . '?php exit()?' . '>');
|
||||
return $this->_format();
|
||||
}
|
||||
|
||||
public function _puts($offset, $data)
|
||||
{
|
||||
if ($offset < $this->max_size * 1.5) {
|
||||
$this->_seek($offset);
|
||||
return fputs($this->_rs, $data);
|
||||
} else {
|
||||
$this->triggerError('Offset over quota:' . $offset, E_USER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
public function _seek($offset)
|
||||
{
|
||||
return fseek($this->_rs, $offset);
|
||||
}
|
||||
|
||||
public function clear()
|
||||
{
|
||||
return $this->_format(true);
|
||||
}
|
||||
|
||||
public function fetch($key, &$return)
|
||||
{
|
||||
$locked = false;
|
||||
if ($this->lock(false)) {
|
||||
$locked = true;
|
||||
}
|
||||
|
||||
if ($this->search($key, $offset)) {
|
||||
$info = $this->_get_node($offset);
|
||||
$schema_id = $this->_get_size_schema_id($info['size']);
|
||||
if (false === $schema_id) {
|
||||
if ($locked) {
|
||||
$this->unlock();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->_seek($info['data']);
|
||||
$data = fread($this->_rs, $info['size']);
|
||||
$return = unserialize($data);
|
||||
|
||||
if (false === $return) {
|
||||
if ($locked) {
|
||||
$this->unlock();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($locked) {
|
||||
$this->_lru_push($schema_id, $info['offset']);
|
||||
$this->_set_schema($schema_id, 'hits', $this->_get_schema($schema_id, 'hits') + 1);
|
||||
return $this->unlock();
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if ($locked) {
|
||||
$this->unlock();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* lock
|
||||
* 如果flock不管用,请继承本类,并重载此方法
|
||||
*
|
||||
* @param mixed $is_block 是否阻塞
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function lock($is_block, $whatever = false)
|
||||
{
|
||||
return flock($this->_rs, $is_block ? LOCK_EX : LOCK_EX + LOCK_NB);
|
||||
}
|
||||
|
||||
/**
|
||||
* unlock
|
||||
* 如果flock不管用,请继承本类,并重载此方法
|
||||
*
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function unlock()
|
||||
{
|
||||
return flock($this->_rs, LOCK_UN);
|
||||
}
|
||||
|
||||
public function delete($key, $pos = false)
|
||||
{
|
||||
if ($pos || $this->search($key, $pos)) {
|
||||
if ($info = $this->_get_node($pos)) {
|
||||
//删除data区域
|
||||
if ($info['prev']) {
|
||||
$this->_set_node($info['prev'], 'next', $info['next']);
|
||||
$this->_set_node($info['next'], 'prev', $info['prev']);
|
||||
} else {
|
||||
//改入口位置
|
||||
$this->_set_node($info['next'], 'prev', 0);
|
||||
$this->_set_node_root($key, $info['next']);
|
||||
}
|
||||
$this->_free_dspace($info['size'], $info['data']);
|
||||
$this->_lru_delete($info);
|
||||
$this->_free_node($pos);
|
||||
return $info['prev'];
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function store($key, $value)
|
||||
{
|
||||
|
||||
if ($this->lock(true)) {
|
||||
//save data
|
||||
$data = serialize($value);
|
||||
$size = strlen($data);
|
||||
|
||||
//get list_idx
|
||||
$has_key = $this->search($key, $list_idx_offset);
|
||||
$schema_id = $this->_get_size_schema_id($size);
|
||||
if (false === $schema_id) {
|
||||
$this->unlock();
|
||||
return false;
|
||||
}
|
||||
if ($has_key) {
|
||||
$hdseq = $list_idx_offset;
|
||||
|
||||
$info = $this->_get_node($hdseq);
|
||||
if ($this->_get_size_schema_id($info['size']) == $schema_id) {
|
||||
$dataoffset = $info['data'];
|
||||
} else {
|
||||
//破掉原有lru
|
||||
$this->_lru_delete($info);
|
||||
if (!($dataoffset = $this->_dalloc($schema_id))) {
|
||||
$this->unlock();
|
||||
return false;
|
||||
}
|
||||
$this->_free_dspace($info['size'], $info['data']);
|
||||
$this->_set_node($hdseq, 'lru_left', 0);
|
||||
$this->_set_node($hdseq, 'lru_right', 0);
|
||||
}
|
||||
|
||||
$this->_set_node($hdseq, 'size', $size);
|
||||
$this->_set_node($hdseq, 'data', $dataoffset);
|
||||
} else {
|
||||
|
||||
if (!($dataoffset = $this->_dalloc($schema_id))) {
|
||||
$this->unlock();
|
||||
return false;
|
||||
}
|
||||
$hdseq = $this->_alloc_idx(array(
|
||||
'next' => 0,
|
||||
'prev' => $list_idx_offset,
|
||||
'data' => $dataoffset,
|
||||
'size' => $size,
|
||||
'lru_right' => 0,
|
||||
'lru_left' => 0,
|
||||
'key' => $key,
|
||||
));
|
||||
|
||||
if ($list_idx_offset > 0) {
|
||||
$this->_set_node($list_idx_offset, 'next', $hdseq);
|
||||
} else {
|
||||
$this->_set_node_root($key, $hdseq);
|
||||
}
|
||||
}
|
||||
|
||||
if ($dataoffset > $this->max_size) {
|
||||
$this->triggerError('alloc datasize:' . $dataoffset, E_USER_WARNING);
|
||||
return false;
|
||||
}
|
||||
$this->_puts($dataoffset, $data);
|
||||
|
||||
$this->_set_schema($schema_id, 'miss', $this->_get_schema($schema_id, 'miss') + 1);
|
||||
|
||||
$this->_lru_push($schema_id, $hdseq);
|
||||
$this->unlock();
|
||||
return true;
|
||||
} else {
|
||||
$this->triggerError("Couldn't lock the file !", E_USER_WARNING);
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* search
|
||||
* 查找指定的key
|
||||
* 如果找到节点则$pos=节点本身 返回true
|
||||
* 否则 $pos=树的末端 返回false
|
||||
*
|
||||
* @param mixed $key
|
||||
* @access public
|
||||
* @return mixed
|
||||
*/
|
||||
public function search($key, &$pos)
|
||||
{
|
||||
return $this->_get_pos_by_key($this->_get_node_root($key), $key, $pos);
|
||||
}
|
||||
|
||||
public function _get_size_schema_id($size)
|
||||
{
|
||||
foreach ($this->_block_size_list as $k => $block_size) {
|
||||
if ($size <= $block_size) {
|
||||
return $k;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function _parse_str_size($str_size, $default)
|
||||
{
|
||||
if (preg_match('/^([0-9]+)\s*([gmk]|)$/i', $str_size, $match)) {
|
||||
switch (strtolower($match[2])) {
|
||||
case 'g':
|
||||
if ($match[1] > 1) {
|
||||
$this->triggerError('Max cache size 1G', E_USER_ERROR);
|
||||
}
|
||||
$size = $match[1] << 30;
|
||||
break;
|
||||
case 'm':
|
||||
$size = $match[1] << 20;
|
||||
break;
|
||||
case 'k':
|
||||
$size = $match[1] << 10;
|
||||
break;
|
||||
default:
|
||||
$size = $match[1];
|
||||
}
|
||||
if ($size <= 0) {
|
||||
$this->triggerError('Error cache size ' . $this->max_size, E_USER_ERROR);
|
||||
return false;
|
||||
} elseif ($size < 10485760) {
|
||||
return 10485760;
|
||||
} else {
|
||||
return $size;
|
||||
}
|
||||
} else {
|
||||
return $default;
|
||||
}
|
||||
}
|
||||
|
||||
public function _format($truncate = false)
|
||||
{
|
||||
if ($this->lock(true, true)) {
|
||||
|
||||
if ($truncate) {
|
||||
$this->_seek(0);
|
||||
ftruncate($this->_rs, $this->idx_node_base);
|
||||
}
|
||||
|
||||
$this->max_size = $this->_parse_str_size(SECACHE_SIZE, 15728640); //default:15m
|
||||
$this->_puts($this->header_padding, pack('V1a*', $this->max_size, $this->ver));
|
||||
|
||||
ksort($this->_bsize_list);
|
||||
$ds_offset = $this->data_base_pos;
|
||||
$i = 0;
|
||||
foreach ($this->_bsize_list as $size => $count) {
|
||||
|
||||
//将预分配的空间注册到free链表里
|
||||
$count *= min(3, floor($this->max_size / 10485760));
|
||||
$next_free_node = 0;
|
||||
for ($j = 0; $j < $count; $j++) {
|
||||
$this->_puts($ds_offset, pack('V', $next_free_node));
|
||||
$next_free_node = $ds_offset;
|
||||
$ds_offset += intval($size);
|
||||
}
|
||||
|
||||
$code = pack(str_repeat('V1', count($this->schema_struct)), $size, $next_free_node, 0, 0, 0, 0);
|
||||
|
||||
$this->_puts(60 + $i * $this->schema_item_size, $code);
|
||||
$i++;
|
||||
}
|
||||
$this->_set_dcur_pos($ds_offset);
|
||||
|
||||
$this->_puts($this->idx_base_pos, str_repeat("\0", 262144));
|
||||
$this->_puts($this->idx_seq_pos, pack('V', 1));
|
||||
$this->unlock();
|
||||
return true;
|
||||
} else {
|
||||
$this->triggerError("Couldn't lock the file !", E_USER_ERROR);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function _get_node_root($key)
|
||||
{
|
||||
$this->_seek(hexdec(substr($key, 0, 4)) * 4 + $this->idx_base_pos);
|
||||
$a = fread($this->_rs, 4);
|
||||
list(, $offset) = unpack('V', $a);
|
||||
return $offset;
|
||||
}
|
||||
|
||||
public function _set_node_root($key, $value)
|
||||
{
|
||||
return $this->_puts(hexdec(substr($key, 0, 4)) * 4 + $this->idx_base_pos, pack('V', $value));
|
||||
}
|
||||
|
||||
public function _set_node($pos, $key, $value)
|
||||
{
|
||||
|
||||
if (!$pos) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isset($this->_node_struct[$key])) {
|
||||
return $this->_puts($pos * $this->idx_node_size + $this->idx_node_base + $this->_node_struct[$key][0], pack($this->_node_struct[$key][1], $value));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function _get_pos_by_key($offset, $key, &$pos)
|
||||
{
|
||||
if (!$offset) {
|
||||
$pos = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
$info = $this->_get_node($offset);
|
||||
|
||||
if ($info['key'] == $key) {
|
||||
$pos = $info['offset'];
|
||||
return true;
|
||||
} elseif ($info['next'] && $info['next'] != $offset) {
|
||||
return $this->_get_pos_by_key($info['next'], $key, $pos);
|
||||
} else {
|
||||
$pos = $offset;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function _lru_delete($info)
|
||||
{
|
||||
|
||||
if ($info['lru_right']) {
|
||||
$this->_set_node($info['lru_right'], 'lru_left', $info['lru_left']);
|
||||
} else {
|
||||
$this->_set_schema($this->_get_size_schema_id($info['size']), 'lru_tail', $info['lru_left']);
|
||||
}
|
||||
|
||||
if ($info['lru_left']) {
|
||||
$this->_set_node($info['lru_left'], 'lru_right', $info['lru_right']);
|
||||
} else {
|
||||
$this->_set_schema($this->_get_size_schema_id($info['size']), 'lru_head', $info['lru_right']);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function _lru_push($schema_id, $offset)
|
||||
{
|
||||
$lru_head = $this->_get_schema($schema_id, 'lru_head');
|
||||
$lru_tail = $this->_get_schema($schema_id, 'lru_tail');
|
||||
|
||||
if ((!$offset) || ($lru_head == $offset)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$info = $this->_get_node($offset);
|
||||
|
||||
$this->_set_node($info['lru_right'], 'lru_left', $info['lru_left']);
|
||||
$this->_set_node($info['lru_left'], 'lru_right', $info['lru_right']);
|
||||
|
||||
$this->_set_node($offset, 'lru_right', $lru_head);
|
||||
$this->_set_node($offset, 'lru_left', 0);
|
||||
|
||||
$this->_set_node($lru_head, 'lru_left', $offset);
|
||||
$this->_set_schema($schema_id, 'lru_head', $offset);
|
||||
|
||||
if (0 == $lru_tail) {
|
||||
$this->_set_schema($schema_id, 'lru_tail', $offset);
|
||||
} elseif ($lru_tail == $offset && $info['lru_left']) {
|
||||
$this->_set_schema($schema_id, 'lru_tail', $info['lru_left']);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function _get_node($offset)
|
||||
{
|
||||
$this->_seek($offset * $this->idx_node_size + $this->idx_node_base);
|
||||
$info = unpack('V1next/V1prev/V1data/V1size/V1lru_right/V1lru_left/H*key', fread($this->_rs, $this->idx_node_size));
|
||||
$info['offset'] = $offset;
|
||||
return $info;
|
||||
}
|
||||
|
||||
public function _lru_pop($schema_id)
|
||||
{
|
||||
if ($node = $this->_get_schema($schema_id, 'lru_tail')) {
|
||||
$info = $this->_get_node($node);
|
||||
if (!$info['data']) {
|
||||
return false;
|
||||
}
|
||||
$this->delete($info['key'], $info['offset']);
|
||||
if (!$this->_get_schema($schema_id, 'free')) {
|
||||
$this->triggerError('pop lru,But nothing free...', E_USER_ERROR);
|
||||
}
|
||||
return $info;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function _dalloc($schema_id, $lru_freed = false)
|
||||
{
|
||||
|
||||
if ($free = $this->_get_schema($schema_id, 'free')) {
|
||||
//如果lru里有链表
|
||||
$this->_seek($free);
|
||||
list(, $next) = unpack('V', fread($this->_rs, 4));
|
||||
$this->_set_schema($schema_id, 'free', $next);
|
||||
return $free;
|
||||
} elseif ($lru_freed) {
|
||||
$this->triggerError('Bat lru poped freesize', E_USER_ERROR);
|
||||
return false;
|
||||
} else {
|
||||
$ds_offset = $this->_get_dcur_pos();
|
||||
$size = $this->_get_schema($schema_id, 'size');
|
||||
|
||||
if ($size + $ds_offset > $this->max_size) {
|
||||
if ($info = $this->_lru_pop($schema_id)) {
|
||||
return $this->_dalloc($schema_id, $info);
|
||||
} else {
|
||||
$this->triggerError('Can\'t alloc dataspace', E_USER_ERROR);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
$this->_set_dcur_pos($ds_offset + $size);
|
||||
return $ds_offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function _get_dcur_pos()
|
||||
{
|
||||
$this->_seek($this->dfile_cur_pos);
|
||||
list(, $ds_offset) = unpack('V', fread($this->_rs, 4));
|
||||
return $ds_offset;
|
||||
}
|
||||
public function _set_dcur_pos($pos)
|
||||
{
|
||||
return $this->_puts($this->dfile_cur_pos, pack('V', $pos));
|
||||
}
|
||||
|
||||
public function _free_dspace($size, $pos)
|
||||
{
|
||||
|
||||
if ($pos > $this->max_size) {
|
||||
$this->triggerError('free dspace over quota:' . $pos, E_USER_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
$schema_id = $this->_get_size_schema_id($size);
|
||||
if ($free = $this->_get_schema($schema_id, 'free')) {
|
||||
$this->_puts($free, pack('V1', $pos));
|
||||
} else {
|
||||
$this->_set_schema($schema_id, 'free', $pos);
|
||||
}
|
||||
$this->_puts($pos, pack('V1', 0));
|
||||
}
|
||||
|
||||
public function _dfollow($pos, &$c)
|
||||
{
|
||||
$c++;
|
||||
$this->_seek($pos);
|
||||
list(, $next) = unpack('V1', fread($this->_rs, 4));
|
||||
if ($next) {
|
||||
return $this->_dfollow($next, $c);
|
||||
} else {
|
||||
return $pos;
|
||||
}
|
||||
}
|
||||
|
||||
public function _free_node($pos)
|
||||
{
|
||||
$this->_seek($this->idx_free_pos);
|
||||
list(, $prev_free_node) = unpack('V', fread($this->_rs, 4));
|
||||
$this->_puts($pos * $this->idx_node_size + $this->idx_node_base, pack('V', $prev_free_node) . str_repeat("\0", $this->idx_node_size - 4));
|
||||
return $this->_puts($this->idx_free_pos, pack('V', $pos));
|
||||
}
|
||||
|
||||
public function _alloc_idx($data)
|
||||
{
|
||||
$this->_seek($this->idx_free_pos);
|
||||
list(, $list_pos) = unpack('V', fread($this->_rs, 4));
|
||||
if ($list_pos) {
|
||||
|
||||
$this->_seek($list_pos * $this->idx_node_size + $this->idx_node_base);
|
||||
list(, $prev_free_node) = unpack('V', fread($this->_rs, 4));
|
||||
$this->_puts($this->idx_free_pos, pack('V', $prev_free_node));
|
||||
|
||||
} else {
|
||||
$this->_seek($this->idx_seq_pos);
|
||||
list(, $list_pos) = unpack('V', fread($this->_rs, 4));
|
||||
$this->_puts($this->idx_seq_pos, pack('V', $list_pos + 1));
|
||||
}
|
||||
return $this->_create_node($list_pos, $data);
|
||||
}
|
||||
|
||||
public function _create_node($pos, $data)
|
||||
{
|
||||
$this->_puts($pos * $this->idx_node_size + $this->idx_node_base
|
||||
, pack('V1V1V1V1V1V1H*', $data['next'], $data['prev'], $data['data'], $data['size'], $data['lru_right'], $data['lru_left'], $data['key']));
|
||||
return $pos;
|
||||
}
|
||||
|
||||
public function _set_schema($schema_id, $key, $value)
|
||||
{
|
||||
$info = array_flip($this->schema_struct);
|
||||
return $this->_puts(60 + $schema_id * $this->schema_item_size + $info[$key] * 4, pack('V', $value));
|
||||
}
|
||||
|
||||
public function _get_schema($id, $key)
|
||||
{
|
||||
$info = array_flip($this->schema_struct);
|
||||
|
||||
$this->_seek(60 + $id * $this->schema_item_size);
|
||||
unpack('V1' . implode('/V1', $this->schema_struct), fread($this->_rs, $this->schema_item_size));
|
||||
|
||||
$this->_seek(60 + $id * $this->schema_item_size + $info[$key] * 4);
|
||||
list(, $value) = unpack('V', fread($this->_rs, 4));
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function _all_schemas()
|
||||
{
|
||||
$schema = [];
|
||||
for ($i = 0; $i < 16; $i++) {
|
||||
$this->_seek(60 + $i * $this->schema_item_size);
|
||||
$info = unpack('V1' . implode('/V1', $this->schema_struct), fread($this->_rs, $this->schema_item_size));
|
||||
if ($info['size']) {
|
||||
$info['id'] = $i;
|
||||
$schema[$i] = $info;
|
||||
} else {
|
||||
return $schema;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function schemaStatus()
|
||||
{
|
||||
$return = [];
|
||||
foreach ($this->_all_schemas() as $k => $schemaItem) {
|
||||
if ($schemaItem['free']) {
|
||||
$this->_dfollow($schemaItem['free'], $schemaItem['freecount']);
|
||||
}
|
||||
$return[] = $schemaItem;
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
public function status(&$curBytes, &$totalBytes)
|
||||
{
|
||||
$totalBytes = $curBytes = 0;
|
||||
$hits = $miss = 0;
|
||||
|
||||
$schemaStatus = $this->schemaStatus();
|
||||
$totalBytes = $this->max_size;
|
||||
$freeBytes = $this->max_size - $this->_get_dcur_pos();
|
||||
|
||||
foreach ($schemaStatus as $schema) {
|
||||
$freeBytes += $schema['freecount'] * $schema['size'];
|
||||
$miss += $schema['miss'];
|
||||
$hits += $schema['hits'];
|
||||
}
|
||||
$curBytes = $totalBytes - $freeBytes;
|
||||
|
||||
$return[] = array('name' => '缓存命中', 'value' => $hits);
|
||||
$return[] = array('name' => '缓存未命中', 'value' => $miss);
|
||||
return $return;
|
||||
}
|
||||
|
||||
public function triggerError($errstr, $errno)
|
||||
{
|
||||
triggerError($errstr, $errno);
|
||||
}
|
||||
|
||||
}
|
||||
67
core/library/think/cache/driver/Test.php
vendored
67
core/library/think/cache/driver/Test.php
vendored
@@ -1,67 +0,0 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: liu21st <liu21st@gmail.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace think\cache\driver;
|
||||
|
||||
use think\Cache;
|
||||
|
||||
/**
|
||||
* 测试缓存类
|
||||
* @author liu21st <liu21st@gmail.com>
|
||||
*/
|
||||
class Test
|
||||
{
|
||||
|
||||
/**
|
||||
* 读取缓存
|
||||
* @access public
|
||||
* @param string $name 缓存变量名
|
||||
* @return mixed
|
||||
*/
|
||||
public function get($name)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 写入缓存
|
||||
* @access public
|
||||
* @param string $name 缓存变量名
|
||||
* @param mixed $value 存储数据
|
||||
* @param int $expire 有效时间 0为永久
|
||||
* @return boolean
|
||||
*/
|
||||
public function set($name, $value, $expire = null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除缓存
|
||||
* @access public
|
||||
* @param string $name 缓存变量名
|
||||
* @return boolean
|
||||
*/
|
||||
public function rm($name)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除缓存
|
||||
* @access public
|
||||
* @return boolean
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user