Browse Source

merged r514-r539 from trunk

git-svn-id: svn://svn.lighttpd.net/xcache/branches/1.3@623 c26eb9a1-5813-0410-bd6c-c2e55f420ca7
1.3
Xuefer 12 years ago
parent
commit
ad5e1b4a4c
  1. 18
      Decompiler.class.php
  2. 20
      admin/common-zh-simplified-utf-8.lang.php
  3. 20
      admin/common-zh-traditional-utf-8.lang.php
  4. 4
      admin/common.php
  5. 7
      admin/config.php.example
  6. 2
      admin/header.tpl.php
  7. 5
      admin/help-en.lang.php
  8. 5
      admin/help-zh-simplified-utf-8.lang.php
  9. 2
      admin/help-zh-traditional-utf-8.lang.php
  10. 32
      admin/xcache.css
  11. 148
      admin/xcache.php
  12. 118
      admin/xcache.tpl.php
  13. 3
      coverager.c
  14. 2
      coverager/config.php.example
  15. 8
      coverager/coverager.css
  16. 6
      coverager/coverager.php
  17. 31
      coverager/coverager.tpl.php
  18. 6
      mkopcode_spec.awk
  19. 2
      phpdc.phpr
  20. 2
      processor/hashtable.m4
  21. 5
      processor/processor.m4
  22. 6
      processor/struct.m4
  23. 2
      run-xcachetest
  24. 9
      utils.c
  25. 5
      utils.h
  26. 1
      xcache-test.ini
  27. 191
      xcache.c
  28. 7
      xcache.h
  29. 4
      xcache.ini

18
Decompiler.class.php

@ -28,8 +28,8 @@ function str($src, $indent = '') // {{{
if (is_array($src)) {
die_error('array str');
$src = new Decompiler_Array($src);
return $src->__toString($indent);
$src = new Decompiler_Array($src, false, $indent);
return $src->__toString();
}
if (is_object($src)) {
@ -164,9 +164,9 @@ class Decompiler_Box // {{{
$this->obj = &$obj;
}
function __toString($indent)
function __toString()
{
return $this->obj->__toString($indent);
return $this->obj->__toString();
}
}
// }}}
@ -257,17 +257,19 @@ class Decompiler_ListBox extends Decompiler_Box // {{{
class Decompiler_Array extends Decompiler_Value // {{{
{
var $needExport = false;
var $indent = '';
function Decompiler_Array($value = array(), $needexport = false)
function Decompiler_Array($value = array(), $needexport = false, $indent = '')
{
$this->value = $value;
$this->needExport = $needexport;
$this->indent = $indent;
}
function __toString($indent)
function __toString()
{
$exp = "array(";
$indent .= INDENT;
$indent = $this->indent . INDENT;
$assoclen = 0;
$multiline = 0;
$i = 0;
@ -334,7 +336,7 @@ class Decompiler_ForeachBox extends Decompiler_Box // {{{
{
var $iskey;
function __toString($indent)
function __toString()
{
return 'foreach (' . '';
}

20
admin/common-zh-simplified-utf-8.lang.php

@ -23,10 +23,18 @@ $strings = array(
=> '确认要清除吗?',
'Compiling'
=> '编译中',
'%'
=> '%',
'% Free'
=> '% 剩余',
'% Used'
=> '% 已用',
'Hits'
=> '命中',
'Hits 24H'
=> '24H 分布',
'Hits/H'
=> '命中/H',
'Hits/S'
=> '命中/S',
'Misses'
=> '错过',
'Clogs'
@ -68,6 +76,14 @@ $strings = array(
=> '建议参考',
'GC'
=> 'GC',
'Legends:'
=> '图例:',
'Used Blocks'
=> '已用块',
'Free Blocks'
=> '未用块',
'Total'
=> '总共',
'Cache'
=> '缓冲区',
'Caches'

20
admin/common-zh-traditional-utf-8.lang.php

@ -23,10 +23,18 @@ $strings = array(
=> '確認要清除嗎?',
'Compiling'
=> '編譯中',
'%'
=> '%',
'% Free'
=> '% 剩余',
'% Used'
=> '% 已用',
'Hits'
=> '命中',
'Hits 24H'
=> '24H 分布',
'Hits/H'
=> '命中/H',
'Hits/S'
=> '命中/S',
'Misses'
=> '錯過',
'Clogs'
@ -68,6 +76,14 @@ $strings = array(
=> '建議參考',
'GC'
=> 'GC',
'Legends:'
=> '图例:',
'Used Blocks'
=> '已用块',
'Free Blocks'
=> '未用块',
'Total'
=> '总共',
'Cache'
=> '快取',
'Caches'

4
admin/common.php

@ -108,5 +108,9 @@ include(get_language_file("common"));
if (!isset($lang)) {
$lang = 'en-us';
}
if (!isset($usage_graph_width) && !isset($free_graph_width)) {
$usage_graph_width = 120;
}
$graph_width = isset($free_graph_width) ? $free_graph_width : $usage_graph_width;
?>

7
admin/config.php.example

@ -11,12 +11,17 @@ $charset = "UTF-8";
// developers only
$show_todo_strings = false;
// width of graph for free or usage blocks
$usage_graph_width = 120;
// do not define both with
// $free_graph_width = 120;
// this function is detected by xcache.tpl.php, and enabled if function_exists
// this ob filter is applied for the cache list, not the whole page
function ob_filter_path_nicer($o)
{
$sep = DIRECTORY_SEPARATOR;
$o = str_replace($_SERVER['DOCUMENT_ROOT'], "{DOCROOT}$sep", $o);
$o = str_replace($_SERVER['DOCUMENT_ROOT'], "{DOCROOT}" . (substr($d, -1) == $sep ? $sep : ""), $o);
$xcachedir = realpath(dirname(__FILE__) . "$sep..$sep");
$o = str_replace($xcachedir . $sep, "{XCache}$sep", $o);
if ($sep == '/') {

2
admin/header.tpl.php

@ -1,4 +1,4 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<?php

5
admin/help-en.lang.php

@ -3,10 +3,13 @@
<dt><?php echo _T('Slots'); ?>: </dt><dd>Number of hash slots. the setting from your php.ini</dd>
<dt><?php echo _T('Size'); ?>: </dt><dd>Cache Size, Size of the cache (or cache chunk), in bytes</dd>
<dt><?php echo _T('Avail'); ?>: </dt><dd>Available Memory, free memory in bytes of this cache</dd>
<dt><?php echo _T('%'); ?>: </dt><dd>Percent, A bar shows how much memory available in percent</dd>
<dt><?php echo _T('% Used'); ?>: </dt><dd>Percent, A bar shows how much memory available in percent, and memory blocks status</dd>
<dt><?php echo _T('Clear'); ?>: </dt><dd>Clear Button, Press the button to clean this cache</dd>
<dt><?php echo _T('Compiling'); ?>: </dt><dd>Compiling flag, "yes" if the cache is busy compiling php script</dd>
<dt><?php echo _T('Hits'); ?>: </dt><dd>Cache Hits, hit=a var/php is loaded from this cache</dd>
<dt><?php echo _T('Hits/H'); ?>: </dt><dd>Average Hits per Hour. Only last 24 hours is logged</dd>
<dt><?php echo _T('Hits 24H'); ?>: </dt><dd>Hits 24 Hours. Hits graph of last 24 hours</dd>
<dt><?php echo _T('Hits/S'); ?>: </dt><dd>Average Hits per Second. Only last 5 seconds is logged</dd>
<dt><?php echo _T('Misses'); ?>: </dt><dd>Cache Misses, miss=a var/php is requested but not in the cache</dd>
<dt><?php echo _T('Clogs'); ?>: </dt><dd>Compiling Clogs, clog=compiling is needed but avoided to wait(be blocked) when the cache is busy compiling already</dd>
<dt><?php echo _T('OOMs'); ?>: </dt><dd>Out Of Memory, how many times a new item should be stored but there isn't enough memory in the cache, think of increasing the xcache.size or xcache.var_size</dd>

5
admin/help-zh-simplified-utf-8.lang.php

@ -3,10 +3,13 @@
<dt><?php echo _T('Slots'); ?>: </dt><dd>Hash 槽个数, 对应 php.ini 里的设置</dd>
<dt><?php echo _T('Size'); ?>: </dt><dd>共享内存区大小, 单位: 字节</dd>
<dt><?php echo _T('Avail'); ?>: </dt><dd>可用内存, 对应共享内存区的剩余内存字节数</dd>
<dt><?php echo _T('%'); ?>: </dt><dd>百分比, 条状显示可用内存的比例</dd>
<dt><?php echo _T('% Used'); ?>: </dt><dd>百分比, 条状显示可用内存的比例, 以及显示分配块状态</dd>
<dt><?php echo _T('Clear'); ?>: </dt><dd>清除按钮, 点击按钮清除对应共享内存区的数据</dd>
<dt><?php echo _T('Compiling'); ?>: </dt><dd>编译标记, 当共享内存区正在编译 php 脚本时标记为 "yes"</dd>
<dt><?php echo _T('Hits'); ?>: </dt><dd>共享内存命中次数, 命中=从该共享内存载入php或者变量</dd>
<dt><?php echo _T('Hits/H'); ?>: </dt><dd>每小时命中次数. 只统计最后 24 小时</dd>
<dt><?php echo _T('Hits 24H'); ?>: </dt><dd>24 小时命中分布图. 图表现是最后 24 小时的命中次数</dd>
<dt><?php echo _T('Hits/S'); ?>: </dt><dd>每秒命中次数. 只统计最后 5 秒</dd>
<dt><?php echo _T('Misses'); ?>: </dt><dd>共享内存错过次数, 错过=请求的php或者变量并不在该共享内存内</dd>
<dt><?php echo _T('Clogs'); ?>: </dt><dd>编译阻塞跳过, 阻塞=当需该共享内存区负责编译时, 其他进程/现成无法访问此共享内存. 跳过=XCache 自动判断阻塞的共享内存区自动跳过阻塞等待, 直接使用非共享内存方式继续处理请求</dd>
<dt><?php echo _T('OOMs'); ?>: </dt><dd>内存不足次数, 显示需要存储新数据但是共享内存区内存不足的次数. 如果出现太频繁请考虑加大配置中的 xcache.size 或者 xcache.var_size</dd>

2
admin/help-zh-traditional-utf-8.lang.php

@ -3,7 +3,7 @@
<dt><?php echo _T('Slots'); ?>: </dt><dd>Hash 槽個數,對應 php.ini 裡的設置</dd>
<dt><?php echo _T('Size'); ?>: </dt><dd>共享記憶體區大小,單位:位元</dd>
<dt><?php echo _T('Avail'); ?>: </dt><dd>可用記憶體,對應共享記憶體區的剩餘記憶體位元數</dd>
<dt><?php echo _T('%'); ?>: </dt><dd>百分比,條狀顯示可用記憶體的比例</dd>
<dt><?php echo _T('% Used'); ?>: </dt><dd>百分比,條狀顯示可用記憶體的比例</dd>
<dt><?php echo _T('Clear'); ?>: </dt><dd>清除按鈕,點擊按鈕清除對應共享記憶體區的資料</dd>
<dt><?php echo _T('Compiling'); ?>: </dt><dd>編譯標記,當共享記憶體區正在編譯 php 指令時標記為 "yes"</dd>
<dt><?php echo _T('Hits'); ?>: </dt><dd>共享記憶體命中次數,命中=從該共享記憶體載入php或者變數</dd>

32
admin/xcache.css

@ -1,6 +1,8 @@
input, table { font-family: sans-serif; }
input { font-size: 12px; }
table { border-collapse: collapse; font-size: 11px; }
table { border-collapse: collapse; font-size: 11px; margin: 0; margin-bottom: 10px; }
table caption, h2 { font-size: 16px; font-weight: bold; text-align: left; padding-top: 20px; margin-bottom: 2px; }
table { white-space: pre; }
table.cycles { border: 1px solid black; margin-top: 5px; margin-bottom: 5px; }
table.cycles .col1 { background-color: #f5f5f5; }
table.cycles .col2 { background-color: #e0e0e0; }
@ -16,13 +18,26 @@ th { font-size: 12px; }
.moduleinfo .v {background-color: #cccccc; color: #000000;}
.button { }
span.sortarrow { color: white; text-decoration: none; }
.freeblocks { float: left; margin-right: 4px;}
.freeblocks td { text-align: right; }
form {margin: 0; padding: 0}
.percent { border: 1px solid black; width: 80%; height: 20px; }
.percent div { font-size: 1px; line-height: 1px; width: 100%;}
.percent .pavail { background: blue; }
.switcher, h1, h2 { text-align: center; display: block; }
.percent { height: 3px; margin-bottom: 1px; border: 1px solid gray; }
.percent div { float: left; height: 100%; }
.pvalue { background: limegreen; }
.blocksgraph { height: 16px; }
.blocksgraph div { float: left; height: 3px; width: 4px; border: solid gray; border-width: 0 0px 1px 0; }
.blocksgraph { border: 1px solid gray; border-bottom: 0px; }
.hitsgraph { height: 20px; margin: auto; }
.hitsgraph div { float: left; width: 2px; height: 100%; }
.hitsgraph div:hover { background: gray; }
.hitsgraph div div { float: none; width: 100%; }
.hitsgraph div div.barf { border: 0px solid gray; border-width: 1px 0 0 0; }
.hitsgraph div div.barv { border: 0px solid gray; border-width: 0 0 1px 0; }
.hitsgraph div div.barf.active { border-color: yellow; }
.hitsgraph div div.barv.active { border-color: yellow; }
.switcher, h1 { text-align: center; display: block; }
.switcher * { color: blue; }
.switcher a.active { font-weight: bold; font-size: 130%; color: black; }
#help { display: block; float: right; }
@ -30,3 +45,6 @@ form {margin: 0; padding: 0}
dl { overflow: hidden; }
dt { font-weight: bold; clear: both; float: left; width: 100px; text-align: right; margin: 0; }
dd { margin: 0; }
.blockarea { overflow: hidden; _width: 1px; }
div.legend { float: left; border: 1px solid gray; font: 12px/12px monospace; }
div.legendtitle { float: left; padding: 2px; padding-right: 10px; font: 12px/12px monospace; }

148
admin/xcache.php

@ -74,6 +74,114 @@ function age($time)
return '0 s';
}
function freeblock_to_graph($freeblocks, $size)
{
global $graph_width, $usage_graph_width, $free_graph_width;
// cached in static variable
static $graph_initial;
if (!isset($graph_initial)) {
$graph_initial = array_fill(0, $graph_width, 0);
}
$graph = $graph_initial;
foreach ($freeblocks as $b) {
$begin = $b['offset'] / $size * $graph_width;
$end = ($b['offset'] + $b['size']) / $size * $graph_width;
if ((int) $begin == (int) $end) {
$v = $end - $begin;
$graph[(int) $v] += $v - (int) $v;
}
else {
$graph[(int) $begin] += 1 - ($begin - (int) $begin);
$graph[(int) $end] += $end - (int) $end;
for ($i = (int) $begin + 1, $e = (int) $end; $i < $e; $i ++) {
$graph[$i] += 1;
}
}
}
$html = array();
$c = 255;
foreach ($graph as $k => $v) {
if (!isset($free_graph_width)) {
$v = 1 - $v;
}
$v = (int) ($v * $c);
$r = $g = $c - $v;
$b = $c;
$html[] = '<div style="background: rgb(' . "$r,$g,$b" . ')"></div>';
}
return implode('', $html);
}
function calc_total(&$total, $data)
{
foreach ($data as $k => $v) {
switch ($k) {
case 'type':
case 'cache_name':
case 'cacheid':
case 'free_blocks':
continue 2;
}
if (!isset($total[$k])) {
$total[$k] = $v;
}
else {
switch ($k) {
case 'his_by_hour':
case 'his_by_second':
foreach ($data[$k] as $kk => $vv) {
$total[$k][$kk] += $vv;
}
break;
default:
$total[$k] += $v;
}
}
}
}
function array_avg($a)
{
if (count($a) == 0) {
return '';
}
return array_sum($a) / count($a);
}
function bar_hits_percent($v, $percent, $active)
{
$r = 220 + (int) ($percent * 25);
$g = $b = 220 - (int) ($percent * 220);
$percent = (int) ($percent * 100);
$a = $active ? ' active' : '';
return '<div title="' . $v . '">'
. '<div class="barf' . $a . '" style="height: ' . (100 - $percent) . '%"></div>'
. '<div class="barv' . $a . '" style="background: rgb(' . "$r,$g,$b" . '); height: ' . $percent . '%"></div>'
. '</div>';
}
function hits_to_graph($hits)
{
$max = 0;
foreach ($hits as $v) {
if ($max < $v) {
$max = $v;
}
}
if (!$max) {
return '';
}
$t = (time() / (60 * 60)) % 24;
$html = array();
foreach ($hits as $i => $v) {
$html[] = bar_hits_percent($v, $v / $max, $i == $t);
}
return implode('', $html);
}
function switcher($name, $options)
{
$n = isset($_GET[$name]) ? $_GET[$name] : null;
@ -129,7 +237,15 @@ function processClear()
if (isset($type)) {
$cacheid = (int) (isset($_POST['cacheid']) ? $_POST['cacheid'] : 0);
if (isset($_POST['clearcache'])) {
xcache_clear_cache($type, $cacheid);
$count = xcache_count($type);
if ($cacheid == $count) {
for ($cacheid = 0; $cacheid < $count; $cacheid ++) {
xcache_clear_cache($type, $cacheid);
}
}
else {
xcache_clear_cache($type, $cacheid);
}
}
}
}
@ -137,6 +253,7 @@ processClear();
// }}}
// {{{ load info/list
$cacheinfos = array();
$total = array();
for ($i = 0; $i < $pcnt; $i ++) {
$data = xcache_info(XC_TYPE_PHP, $i);
if ($type === XC_TYPE_PHP) {
@ -146,7 +263,21 @@ for ($i = 0; $i < $pcnt; $i ++) {
$data['cache_name'] = "php#$i";
$data['cacheid'] = $i;
$cacheinfos[] = $data;
if ($pcnt >= 2) {
calc_total($total, $data);
}
}
if ($pcnt >= 2) {
$total['type'] = XC_TYPE_PHP;
$total['cache_name'] = _T('Total');
$total['cacheid'] = $pcnt;
$total['gc'] = null;
$total['istotal'] = true;
$cacheinfos[] = $total;
}
$total = array();
for ($i = 0; $i < $vcnt; $i ++) {
$data = xcache_info(XC_TYPE_VAR, $i);
if ($type === XC_TYPE_VAR) {
@ -156,6 +287,18 @@ for ($i = 0; $i < $vcnt; $i ++) {
$data['cache_name'] = "var#$i";
$data['cacheid'] = $i;
$cacheinfos[] = $data;
if ($pcnt >= 2) {
calc_total($total, $data);
}
}
if ($vcnt >= 2) {
$total['type'] = XC_TYPE_VAR;
$total['cache_name'] = _T('Total');
$total['cacheid'] = $vcnt;
$total['gc'] = null;
$total['istotal'] = true;
$cacheinfos[] = $total;
}
// }}}
// {{{ merge the list
@ -170,6 +313,9 @@ case XC_TYPE_VAR:
$cachelist['type_name'] = 'php';
}
foreach ($cacheinfos as $i => $c) {
if (!empty($c['istotal'])) {
continue;
}
if ($c['type'] == $type && isset($c['cache_list'])) {
foreach ($c['cache_list'] as $e) {
$e['cache_name'] = $c['cache_name'];

118
admin/xcache.tpl.php

@ -1,12 +1,14 @@
<?php include("header.tpl.php"); ?>
<a href="help.php" target="_blank" id="help"><?php echo _T("Help") ?> &raquo;</a>
<span class="switcher"><?php echo switcher("type", $types); ?></span>
<div id="help">
<a href="help.php"><?php echo _T("Help") ?> &raquo;</a>
</div>
<div class="switcher"><?php echo switcher("type", $types); ?></div>
<?php
$a = new Cycle('class="col1"', 'class="col2"');
$b = new Cycle('class="col1"', 'class="col2"');
?>
<?php echo _T('Caches'); ?>:
<table cellspacing="0" cellpadding="4" class="cycles">
<caption><?php echo _T('Caches'); ?></caption>
<col />
<col align="right" />
<col align="right" />
@ -16,6 +18,9 @@ $b = new Cycle('class="col1"', 'class="col2"');
<col align="right" />
<col align="right" />
<col align="right" />
<col />
<col align="right" />
<col align="right" />
<col align="right" />
<col align="right" />
<col align="right" />
@ -27,10 +32,13 @@ $b = new Cycle('class="col1"', 'class="col2"');
<th><?php echo _T('Slots'); ?></th>
<th><?php echo _T('Size'); ?></th>
<th><?php echo _T('Avail'); ?></th>
<th><?php echo _T('%'); ?></th>
<th><?php echo _T(isset($free_graph_width) ? '% Free' : '% Used'); ?></th>
<th><?php echo _T('Clear'); ?></th>
<th><?php echo _T('Compiling'); ?></th>
<th><?php echo _T('Hits'); ?></th>
<th><?php echo _T('Hits/H'); ?></th>
<th><?php echo _T('Hits 24H'); ?></th>
<th><?php echo _T('Hits/S'); ?></th>
<th><?php echo _T('Misses'); ?></th>
<th><?php echo _T('Clogs'); ?></th>
<th><?php echo _T('OOMs'); ?></th>
@ -47,32 +55,67 @@ $b = new Cycle('class="col1"', 'class="col2"');
foreach ($cacheinfos as $i => $ci) {
echo "
<tr ", $a->next(), ">";
$pavail = (int) ($ci['avail'] / $ci['size'] * 100);
$pused = 100 - $pavail;
$pvalue = (int) ($ci['avail'] / $ci['size'] * 100);
$pempty = 100 - $pvalue;
if (!isset($free_graph_width)) {
// swap
$tmp = $pvalue;
$pvalue = $pempty;
$pempty = $tmp;
}
$w = $graph_width;
if (empty($ci['istotal'])) {
$graph = freeblock_to_graph($ci['free_blocks'], $ci['size']);
$blocksgraph = "<div class=\"blocksgraph\" style=\"width: {$w}px\">{$graph}</div>";
}
else {
$blocksgraph = '';
}
$ci_slots = size($ci['slots']);
$ci_size = size($ci['size']);
$ci_avail = size($ci['avail']);
$ci = number_formats($ci, $numkeys);
$ci['compiling'] = $ci['type'] == $type_php ? ($ci['compiling'] ? 'yes' : 'no') : '-';
$ci['can_readonly'] = $ci['can_readonly'] ? 'yes' : 'no';
$hits_avg_h = number_format(array_avg($ci['hits_by_hour']), 2);
$hits_avg_s = number_format(array_avg($ci['hits_by_second']), 2);
$hits_graph_h = hits_to_graph($ci['hits_by_hour']);
$hits_graph_h_w = count($ci['hits_by_hour']) * 2;
if (!empty($ci['istotal'])) {
$ci['compiling'] = '-';
$ci['can_readonly'] = '-';
}
else {
$ci['compiling'] = $ci['type'] == $type_php ? ($ci['compiling'] ? 'yes' : 'no') : '-';
$ci['can_readonly'] = $ci['can_readonly'] ? 'yes' : 'no';
}
echo <<<EOS
<th>{$ci['cache_name']}</th>
<td title="{$ci['slots']}">{$ci_slots}</td>
<td title="{$ci['size']}">{$ci_size}</td>
<td title="{$ci['avail']}">{$ci_avail}</td>
<td title="{$pavail} %"><div class="percent"><div style="height: {$pused}%" class="pused">&nbsp;</div><div style="height: {$pavail}%" class="pavail">&nbsp;</div></div></td>
<td>
<form method="post">
<div>
<input type="hidden" name="type" value="{$ci['type']}">
<input type="hidden" name="cacheid" value="{$ci['cacheid']}">
<input type="submit" name="clearcache" value="{$l_clear}" class="submit" onclick="return confirm('{$l_clear_confirm}');" />
</div>
</form>
</td>
<td title="{$pvalue} %"
><div class="percent" style="width: {$w}px"
><div style="width: {$pvalue}%" class="pvalue"></div
><div style="width: {$pempty}%" class="pempty"></div
></div
>{$blocksgraph}</td>
<td
><form method="post" action=""
><div
><input type="hidden" name="type" value="{$ci['type']}"
/><input type="hidden" name="cacheid" value="{$ci['cacheid']}"
/><input type="submit" name="clearcache" value="{$l_clear}" class="submit" onclick="return confirm('{$l_clear_confirm}');"
/></div
></form
></td>
<td>{$ci['compiling']}</td>
<td>{$ci['hits']}</td>
<td>{$hits_avg_h}</td>
<td><div class="hitsgraph" style="width: {$hits_graph_h_w}px">{$hits_graph_h}</div></td>
<td>{$hits_avg_s}</td>
<td>{$ci['misses']}</td>
<td>{$ci['clogs']}</td>
<td>{$ci['ooms']}</td>
@ -88,34 +131,16 @@ EOS;
</tr>
<?php } ?>
</table>
<div>
<?php echo _T('Free Blocks'); ?>:
<div class="blockarea legends">
<div class="legendtitle"><?php echo _T('Legends:'); ?></div>
<div class="legend pvalue">&nbsp;&nbsp;</div>
<div class="legendtitle"><?php echo _T(isset($free_graph_width) ? '% Free' : '% Used'); ?></div>
<div class="legend" style="background: rgb(0,0,255)">&nbsp;&nbsp;</div>
<div class="legendtitle"><?php echo _T(isset($free_graph_width) ? 'Free Blocks' : 'Used Blocks'); ?></div>
<div class="legend" style="background: rgb(255,0,0)">&nbsp;&nbsp;</div>
<div class="legendtitle"><?php echo _T('Hits'); ?></div>
</div>
<?php
foreach ($cacheinfos as $i => $ci) {
$b->reset();
?>
<table cellspacing="0" cellpadding="4" class="cycles freeblocks">
<tr>
<th><?php echo $ci['cache_name']; ?> <?php echo _T("size"); ?><br><?php echo _T("offset"); ?></th>
<?php
foreach ($ci['free_blocks'] as $block) {
$size = size($block['size']);
$offset = size($block['offset']);
$c = $b->next();
echo "
<td $c><nobr>$size<br>$offset</nobr></td>";
}
?>
</tr>
</table>
<?php
}
?>
<div style="clear: both">&nbsp;</div>
<?php
if ($cachelist) {
$isphp = $cachelist['type'] == $type_php;
@ -124,12 +149,11 @@ if ($cachelist) {
}
foreach (array('Cached' => $cachelist['cache_list'], 'Deleted' => $cachelist['deleted_list']) as $listname => $entries) {
$a->reset();
echo "
<caption>", _T("{$cachelist['type_name']} $listname"), "</caption>";
?>
<form action="" method="post">
<table cellspacing="0" cellpadding="4" class="cycles entrys" width="100%">
<table cellspacing="0" cellpadding="4" class="cycles entries" width="100%">
<caption><?php echo _T("{$cachelist['type_name']} $listname"); ?></caption>
<col />
<col />
<col />

3
coverager.c

@ -469,6 +469,7 @@ int xc_coverager_init(int module_number TSRMLS_DC) /* {{{ */
zend_compile_file = xc_compile_file_for_coverage;
if (cfg_get_string("xcache.coveragedump_directory", &xc_coveragedump_dir) == SUCCESS && xc_coveragedump_dir) {
xc_coveragedump_dir = pestrdup(xc_coveragedump_dir, 1);
int len = strlen(xc_coveragedump_dir);
if (len) {
if (xc_coveragedump_dir[len - 1] == '/') {
@ -476,6 +477,7 @@ int xc_coverager_init(int module_number TSRMLS_DC) /* {{{ */
}
}
if (!strlen(xc_coveragedump_dir)) {
pefree(xc_coveragedump_dir, 1);
xc_coveragedump_dir = NULL;
}
}
@ -489,6 +491,7 @@ void xc_coverager_destroy() /* {{{ */
zend_compile_file = old_compile_file;
}
if (xc_coveragedump_dir) {
pefree(xc_coveragedump_dir, 1);
xc_coveragedump_dir = NULL;
}
}

2
coverager/config.php.example

@ -21,7 +21,7 @@ $usecache = false;
function ob_filter_path_nicer($o)
{
$sep = DIRECTORY_SEPARATOR;
$o = str_replace($_SERVER['DOCUMENT_ROOT'], "{DOCROOT}$sep", $o);
$o = str_replace($_SERVER['DOCUMENT_ROOT'], "{DOCROOT}" . (substr($d, -1) == $sep ? $sep : ""), $o);
$xcachedir = realpath(dirname(__FILE__) . "$sep..$sep");
$o = str_replace($xcachedir . $sep, "{XCache}$sep", $o);
if ($sep == '/') {

8
coverager/coverager.css

@ -2,6 +2,8 @@ h1 { text-align: center; display: block; }
input, table { font-family: sans-serif; font-size: 11px; }
th { font-size: 12px; }
table { border-collapse: collapse; }
table.center { margin-left: auto; margin-right: auto; }
table\-center { text-align: center; }
table.cycles { border: 1px solid black; margin-top: 5px; margin-bottom: 5px; }
table.cycles .col1 { background-color: #f5f5f5; }
table.cycles .col2 { background-color: #e0e0e0; }
@ -54,11 +56,15 @@ th a { color: black; font-weight: bold; display: block; width: 100%; height: 100
.lineCov { background-color: #F0F0F0; }
.lineNoCov { background-color: #ffe0e0; }
div.code {
border: 1px solid gray;
font-size: 12px;
}
pre.code {
font-family: monospace;
font-size: 12px;
white-space: pre;
border: 1px solid gray;
padding: 0; margin: 0;
}
.footnote { text-align: right; font-size: 12px; }

6
coverager/coverager.php

@ -113,8 +113,8 @@ class XcacheCoverageViewer
$lines = preg_replace('(^<span[^>]*>|</span>$)', '', $lines);
$lines = explode('<br />', $lines);
$last = array_pop($lines);
$lines[count($lines) - 1] .= $last;
$filecov = sprint_cov($fileinfo['cov'], $lines, false);
$filecov .= $last;
unset($source);
}
else {
@ -324,13 +324,13 @@ function sprint_cov($cov, $lines, $encode = true)
}
}
if (isset($cov[$offs])) {
$lines[$l] = sprintf("<li class=\"line%sCov\"> %s\t%s\n</li>"
$lines[$l] = sprintf("<li class=\"line%sCov\"><pre class=\"code\"> %s\t%s\n</pre></li>"
, $cov[$offs] ? '' : 'No'
, $cov[$offs]
, $line);
}
else {
$lines[$l] = "<li>\t$line\n</li>";
$lines[$l] = "<li><pre class=\"code\">\t$line\n</pre></li>";
}
}
return implode('', $lines);

31
coverager/coverager.tpl.php

@ -1,4 +1,4 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<?php
@ -55,7 +55,8 @@ function dir_head()
$l_lns = _T("Lines");
$l_tds = _T("TODO");
return <<<EOS
<table align="center" cellpadding="2" cellspacing="0" border="0" class="cycles">
<div class="table-center">
<table cellpadding="2" cellspacing="0" border="0" class="cycles center">
<tr>
<th>{$l_dir}</th><th>{$l_per}</th><th>{$l_hit}</th><th>{$l_lns}</th><th>{$l_tds}</th>
</tr>
@ -104,6 +105,7 @@ function dir_foot()
{
return <<<EOS
</table>
</div>
EOS;
}
@ -116,8 +118,8 @@ function file_head()
$l_hit = _T("Hits");
$l_lns = _T("Lines");
return <<<EOS
<br>
<table align="center" cellpadding="2" cellspacing="0" border="0" class="cycles">
<div class="center-table">
<table cellpadding="2" cellspacing="0" border="0" class="cycles center">
<tr>
<th>{$l_fil}</th><th>{$l_per}</th><th>{$l_hit}</th><th>{$l_lns}</th>
</tr>
@ -161,6 +163,7 @@ function file_foot()
{
return <<<EOS
</table>
</div>
EOS;
}
@ -171,7 +174,9 @@ if ($action == 'dir') {
}
$path_html = htmlspecialchars($path);
echo <<<EOS
<a href="?">$l_root</a> $path<br />
<div>
<a href="?">$l_root</a> $path<br />
</div>
EOS;
echo dir_head($dirinfo);
echo dir_row($dirinfo, $path);
@ -198,7 +203,9 @@ else if ($action == 'file') {
$dir_url = urlencode($dir);
$dir_html = htmlspecialchars($dir);
echo <<<EOS
<a href="?">$l_root</a> <a href="?path={$dir_url}">{$dir_html}</a>/<strong>{$filename}</strong><br />
<div>
<a href="?">$l_root</a> <a href="?path={$dir_url}">{$dir_html}</a>/<strong>{$filename}</strong><br />
</div>
EOS;
echo file_head();
@ -208,19 +215,25 @@ EOS;
if ($tplfile) {
$tplfile_html = htmlspecialchars($tplfile);
echo <<<EOS
<a href="#tpl">{$tplfile_html}</a><br />
<div>
<a href="#tpl">{$tplfile_html}</a><br />
</div>
EOS;
}
if (function_exists('ob_filter_path_nicer')) {
ob_end_flush();
}
echo <<<EOS
<pre class="code"><ol>{$filecov}</ol></pre>
<div class="code">
<ol>{$filecov}</ol>
</div>
EOS;
if ($tplfile) {
echo <<<EOS
<a name="tpl">{$tplfile}</a>
<pre class="code"><ol>{$tplcov}</ol></pre>
<div class="code">
<ol>{$tplcov}</ol>
</div>
EOS;
}
}

6
mkopcode_spec.awk

@ -14,7 +14,11 @@ BEGIN {
print "error" $0
exit
}
printf "\tOPSPEC(%10s, %10s, %10s, %10s)\n", array[1], array[2], array[3], array[4]
comment = "";
if (match($0, /\/\* (\d+) \*\//, comments)) {
comment = comments[1];
}
printf "\tOPSPEC(%10s, %10s, %10s, %10s)%s\n", array[1], array[2], array[3], array[4], comment;
next
}
}

2
phpdc.phpr

@ -12,7 +12,7 @@ if (!isset($argv)) {
$argc = $_SERVER['argc'];
}
$dc = &new Decompiler();
$dc = new Decompiler();
if (isset($argv[1])) {
$dc->decompileFile($argv[1]);
}

2
processor/hashtable.m4

@ -122,7 +122,7 @@ define(`DEF_HASH_TABLE_FUNC', `
INDENT()
fprintf(stderr, "$2:\"");
xc_dprint_str_len(BUCKET_KEY_S(b), BUCKET_KEY_SIZE(b));
fprintf(stderr, "\" %d:h=%lu", BUCKET_KEY_SIZE(b), b->h);
fprintf(stderr, "\" %d:h=%lu ", BUCKET_KEY_SIZE(b), b->h);
')
if (sizeof(void *) == sizeof($2)) {
IFCOPY(`pnew->pData = &pnew->pDataPtr;')

5
processor/processor.m4

@ -210,7 +210,7 @@ DEF_STRUCT_P_FUNC(`zval_ptr', , `dnl {{{
IFCOPY(`
dnl fprintf(stderr, "copy from %p to %p\n", src[0], dst[0]);
')
IFDPRINT(`INDENT()`'fprintf(stderr, "[%p]", src[0]);')
IFDPRINT(`INDENT()`'fprintf(stderr, "[%p] ", src[0]);')
STRUCT_P_EX(zval, dst[0], src[0], `[0]', `', ` ')
FIXPOINTER_EX(zval, dst[0])
} while (0);
@ -474,6 +474,9 @@ DEF_STRUCT_P_FUNC(`zend_op', , `dnl {{{
#ifdef ZEND_ENGINE_2_1
IFCOPY(`
switch (src->opcode) {
#ifdef ZEND_GOTO
case ZEND_GOTO:
#endif
case ZEND_JMP:
dst->op1.u.jmp_addr = processor->active_opcodes_dst + (src->op1.u.jmp_addr - processor->active_opcodes_src);
break;

6
processor/struct.m4

@ -59,7 +59,7 @@ DECL_STRUCT_P_FUNC(`$1', `$2', 1)
')')
IFDPRINT(`
fprintf(stderr, "%s", " {\n");
fprintf(stderr, "%s", "{\n");
indent ++;
')
$3`'
@ -145,7 +145,7 @@ dnl {{{ STRUCT_P(1:type, 2:elm, 3:name=type)
define(`STRUCT_P', `
DBG(`$0($*)')
if (src->$2) {
IFDPRINT(`INDENT()`'fprintf(stderr, "$1:$2");')
IFDPRINT(`INDENT()`'fprintf(stderr, "$1:$2 ");')
STRUCT_P_EX(`$1', `dst->$2', `src->$2', `$2', `$3')
}
else {
@ -159,7 +159,7 @@ dnl {{{ STRUCT(1:type, 2:elm, 3:name=type)
define(`STRUCT', `
DBG(`$0($*)')
assert(sizeof($1) == sizeof(src->$2));
IFDPRINT(`INDENT()`'fprintf(stderr, "$1:$2");')
IFDPRINT(`INDENT()`'fprintf(stderr, "$1:$2 ");')
STRUCT_P_EX(`$1', `dst->$2', `src->$2', `$2', `$3', `&')
DONE(`$2')
')

2
run-xcachetest

@ -18,7 +18,7 @@ fi
test -z "$PHP_SRC" && PHP_SRC=./php-src
if test -z "$TEST_PHP_USER" ; then
TEST_PHP_USER="$PHP_SRC/tests"
for i in Zend ZendEngine2 ext/standard/tests ext/reflection/tests ; do
for i in Zend ZendEngine2 ext/standard/tests ext/reflection/tests ext/spl/tests; do
if test -d "$PHP_SRC/$i" ; then
TEST_PHP_USER="$TEST_PHP_USER,$PHP_SRC/$i"
fi

9
utils.c

@ -143,6 +143,9 @@ int xc_undo_pass_two(zend_op_array *op_array TSRMLS_DC) /* {{{ */
while (opline < end) {
#ifdef ZEND_ENGINE_2_1
switch (opline->opcode) {
#ifdef ZEND_GOTO
case ZEND_GOTO:
#endif
case ZEND_JMP:
opline->op1.u.opline_num = opline->op1.u.jmp_addr - op_array->opcodes;
assert(opline->op1.u.opline_num < op_array->last);
@ -193,6 +196,9 @@ int xc_redo_pass_two(zend_op_array *op_array TSRMLS_DC) /* {{{ */
}
#ifdef ZEND_ENGINE_2_1
switch (opline->opcode) {
#ifdef ZEND_GOTO
case ZEND_GOTO:
#endif
case ZEND_JMP:
assert(opline->op1.u.opline_num < op_array->last);
opline->op1.u.jmp_addr = op_array->opcodes + opline->op1.u.opline_num;
@ -293,6 +299,9 @@ int xc_foreach_early_binding_class(zend_op_array *op_array, void (*callback)(zen
end = opline + op_array->last;
while (opline < end) {
switch (opline->opcode) {
#ifdef ZEND_GOTO
case ZEND_GOTO:
#endif
case ZEND_JMP:
next = begin + opline->op1.u.opline_num;
break;

5
utils.h

@ -79,7 +79,6 @@ ZESW(xc_cest_t *, void) xc_install_class(char *filename, xc_cest_t *cest, int op
/* sandbox */
typedef struct {
int alloc;
int orig_user_error_handler_error_reporting;
char *filename;
HashTable orig_included_files;
@ -97,6 +96,10 @@ typedef struct {
HashTable tmp_auto_globals;
Bucket *tmp_internal_function_tail;
Bucket *tmp_internal_class_tail;
#ifdef E_STRICT
int orig_user_error_handler_error_reporting;
#endif
} xc_sandbox_t;
typedef enum _xc_install_action_t {

1
xcache-test.ini

@ -1,4 +1,3 @@
auto_globals_jit = Off
memory_limit = 256M
[xcache]

191
xcache.c

@ -86,6 +86,11 @@ static xc_cache_t **xc_php_caches = NULL;
static xc_cache_t **xc_var_caches = NULL;
static zend_bool xc_initized = 0;
static time_t xc_init_time = 0;
static long unsigned xc_init_instance_id = 0;
#ifdef ZTS
static long unsigned xc_init_instance_subid = 0;
#endif
static zend_compile_file_t *origin_compile_file = NULL;
static zend_compile_file_t *old_compile_file = NULL;
static zend_llist_element *xc_llist_zend_extension = NULL;
@ -246,6 +251,55 @@ static void xc_entry_hold_var_dmz(xc_entry_t *xce TSRMLS_DC) /* {{{ */
}
/* }}} */
#endif
static inline zend_uint advance_wrapped(zend_uint val, zend_uint count) /* {{{ */
{
if (val + 1 >= count) {
return 0;
}
return val + 1;
}
/* }}} */
static void xc_counters_inc(time_t *curtime, zend_uint *curslot, time_t period, zend_ulong *counters, zend_uint count TSRMLS_DC) /* {{{ */
{
time_t n = XG(request_time) / period;
if (*curtime != n) {
zend_uint target_slot = n % count;
if (n - *curtime > period) {
memset(counters, 0, sizeof(counters[0]) * count);
}
else {
zend_uint slot;
for (slot = advance_wrapped(*curslot, count);
slot != target_slot;
slot = advance_wrapped(slot, count)) {
counters[slot] = 0;
}
counters[target_slot] = 0;
}
*curtime = n;
*curslot = target_slot;
}
counters[*curslot] ++;
}
/* }}} */
static void xc_cache_hit_dmz(xc_cache_t *cache TSRMLS_DC) /* {{{ */
{
cache->hits ++;
xc_counters_inc(&cache->hits_by_hour_cur_time
, &cache->hits_by_hour_cur_slot, 60 * 60
, cache->hits_by_hour
, sizeof(cache->hits_by_hour) / sizeof(cache->hits_by_hour[0])
TSRMLS_CC);
xc_counters_inc(&cache->hits_by_second_cur_time
, &cache->hits_by_second_cur_slot
, 1
, cache->hits_by_second
, sizeof(cache->hits_by_second) / sizeof(cache->hits_by_second[0])
TSRMLS_CC);
}
/* }}} */
/* helper function that loop through each entry */
#define XC_ENTRY_APPLY_FUNC(name) int name(xc_entry_t *entry TSRMLS_DC)
@ -310,7 +364,7 @@ static void xc_gc_expires_php(TSRMLS_D) /* {{{ */
{
int i, c;
if (!xc_php_ttl || !xc_php_gc_interval) {
if (!xc_php_ttl || !xc_php_gc_interval || !xc_php_caches) {
return;
}
@ -323,7 +377,7 @@ static void xc_gc_expires_var(TSRMLS_D) /* {{{ */
{
int i, c;
if (!xc_var_gc_interval) {
if (!xc_var_gc_interval || !xc_var_caches) {
return;
}
@ -371,12 +425,16 @@ static void xc_gc_deletes(TSRMLS_D) /* {{{ */
{
int i, c;
for (i = 0, c = xc_php_hcache.size; i < c; i ++) {
xc_gc_deletes_one(xc_php_caches[i] TSRMLS_CC);
if (xc_php_caches) {
for (i = 0, c = xc_php_hcache.size; i < c; i ++) {
xc_gc_deletes_one(xc_php_caches[i] TSRMLS_CC);
}
}
for (i = 0, c = xc_var_hcache.size; i < c; i ++) {
xc_gc_deletes_one(xc_var_caches[i] TSRMLS_CC);
if (xc_var_caches) {
for (i = 0, c = xc_var_hcache.size; i < c; i ++) {
xc_gc_deletes_one(xc_var_caches[i] TSRMLS_CC);
}
}
}
/* }}} */
@ -384,7 +442,8 @@ static void xc_gc_deletes(TSRMLS_D) /* {{{ */
/* helper functions for user functions */
static void xc_fillinfo_dmz(int cachetype, xc_cache_t *cache, zval *return_value TSRMLS_DC) /* {{{ */
{
zval *blocks;
zval *blocks, *hits;
int i;
const xc_block_t *b;
#ifndef NDEBUG
xc_memsize_t avail = 0;
@ -416,6 +475,19 @@ static void xc_fillinfo_dmz(int cachetype, xc_cache_t *cache, zval *return_value
else {
add_assoc_null_ex(return_value, ZEND_STRS("gc"));
}
MAKE_STD_ZVAL(hits);
array_init(hits);
for (i = 0; i < sizeof(cache->hits_by_hour) / sizeof(cache->hits_by_hour[0]); i ++) {
add_next_index_long(hits, (long) cache->hits_by_hour[i]);
}
add_assoc_zval_ex(return_value, ZEND_STRS("hits_by_hour"), hits);
MAKE_STD_ZVAL(hits);
array_init(hits);
for (i = 0; i < sizeof(cache->hits_by_second) / sizeof(cache->hits_by_second[0]); i ++) {
add_next_index_long(hits, (long) cache->hits_by_second[i]);
}
add_assoc_zval_ex(return_value, ZEND_STRS("hits_by_second"), hits);
MAKE_STD_ZVAL(blocks);
array_init(blocks);
@ -639,8 +711,13 @@ static inline void xc_entry_unholds_real(xc_stack_t *holds, xc_cache_t **caches,
/* }}} */
static void xc_entry_unholds(TSRMLS_D) /* {{{ */
{
xc_entry_unholds_real(XG(php_holds), xc_php_caches, xc_php_hcache.size TSRMLS_CC);
xc_entry_unholds_real(XG(var_holds), xc_var_caches, xc_var_hcache.size TSRMLS_CC);
if (xc_php_caches) {
xc_entry_unholds_real(XG(php_holds), xc_php_caches, xc_php_hcache.size TSRMLS_CC);
}
if (xc_var_caches) {
xc_entry_unholds_real(XG(var_holds), xc_var_caches, xc_var_hcache.size TSRMLS_CC);
}
}
/* }}} */
static int xc_stat(const char *filename, const char *include_path, struct stat *pbuf TSRMLS_DC) /* {{{ */
@ -913,7 +990,7 @@ static zend_op_array *xc_compile_file(zend_file_handle *h, int type TSRMLS_DC) /
if (stored_xce) {
TRACE("found %s, catch it", stored_xce->name.str.val);
xc_entry_hold_php_dmz(stored_xce TSRMLS_CC);
cache->hits ++;
xc_cache_hit_dmz(cache);
break;
}
@ -1221,19 +1298,22 @@ int xc_is_rw(const void *p) /* {{{ */
{
xc_shm_t *shm;
int i;
if (!xc_initized) {
return 0;
}
for (i = 0; i < xc_php_hcache.size; i ++) {
shm = xc_php_caches[i]->shm;
if (shm->handlers->is_readwrite(shm, p)) {
return 1;
if (xc_php_caches) {
for (i = 0; i < xc_php_hcache.size; i ++) {
shm = xc_php_caches[i]->shm;
if (shm->handlers->is_readwrite(shm, p)) {
return 1;
}
}
}
for (i = 0; i < xc_var_hcache.size; i ++) {
shm = xc_var_caches[i]->shm;
if (shm->handlers->is_readwrite(shm, p)) {
return 1;
if (xc_var_caches) {
for (i = 0; i < xc_var_hcache.size; i ++) {
shm = xc_var_caches[i]->shm;
if (shm->handlers->is_readwrite(shm, p)) {
return 1;
}
}
}
return 0;
@ -1243,19 +1323,22 @@ int xc_is_ro(const void *p) /* {{{ */
{
xc_shm_t *shm;
int i;
if (!xc_initized) {
return 0;
}
for (i = 0; i < xc_php_hcache.size; i ++) {
shm = xc_php_caches[i]->shm;
if (shm->handlers->is_readonly(shm, p)) {
return 1;
if (xc_php_caches) {
for (i = 0; i < xc_php_hcache.size; i ++) {
shm = xc_php_caches[i]->shm;
if (shm->handlers->is_readonly(shm, p)) {
return 1;
}
}
}
for (i = 0; i < xc_var_hcache.size; i ++) {
shm = xc_var_caches[i]->shm;
if (shm->handlers->is_readonly(shm, p)) {
return 1;
if (xc_var_caches) {
for (i = 0; i < xc_var_hcache.size; i ++) {
shm = xc_var_caches[i]->shm;
if (shm->handlers->is_readonly(shm, p)) {
return 1;
}
}
}
return 0;
@ -1514,14 +1597,14 @@ static void xc_request_init(TSRMLS_D) /* {{{ */
XG(internal_table_copied) = 1;
}
if (xc_php_hcache.size && !XG(php_holds)) {
if (xc_php_caches && !XG(php_holds)) {
XG(php_holds) = calloc(xc_php_hcache.size, sizeof(xc_stack_t));
for (i = 0; i < xc_php_hcache.size; i ++) {
xc_stack_init(&XG(php_holds[i]));
}
}
if (xc_initized && xc_var_hcache.size && !XG(var_holds)) {
if (xc_var_caches && !XG(var_holds)) {
XG(var_holds) = calloc(xc_var_hcache.size, sizeof(xc_stack_t));
for (i = 0; i < xc_var_hcache.size; i ++) {
xc_stack_init(&XG(var_holds[i]));
@ -1674,10 +1757,10 @@ static int xcache_admin_auth_check(TSRMLS_D) /* {{{ */
}
}
#define STR "WWW-authenticate: Basic Realm=\"XCache Administration\""
#define STR "HTTP/1.0 401 Unauthorized"
sapi_add_header_ex(STR, sizeof(STR) - 1, 1, 1 TSRMLS_CC);
#undef STR
#define STR "HTTP/1.0 401 Unauthorized"
#define STR "WWW-authenticate: Basic Realm=\"XCache Administration\""
sapi_add_header_ex(STR, sizeof(STR) - 1, 1, 1 TSRMLS_CC);
#undef STR
ZEND_PUTS("XCache Auth Failed. User and Password is case sense\n");
@ -1883,7 +1966,7 @@ PHP_FUNCTION(xcache_get)
RETVAL_NULL();
} LEAVE_LOCK(xce.cache);
if (found) {
xce.cache->hits ++;
xc_cache_hit_dmz(xce.cache TSRMLS_CC);
}
else {
xce.cache->misses ++;
@ -1964,7 +2047,7 @@ PHP_FUNCTION(xcache_isset)
RETVAL_FALSE;
} LEAVE_LOCK(xce.cache);
if (found) {
xce.cache->hits ++;
xc_cache_hit_dmz(xce.cache TSRMLS_CC);
}
else {
xce.cache->misses ++;
@ -2097,6 +2180,20 @@ PHP_FUNCTION(xcache_dec)
xc_var_inc_dec(-1, INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
/* }}} */
#ifdef HAVE_XCACHE_DPRINT
/* {{{ proto bool xcache_dprint(mixed value)
Prints variable (or value) internal struct (debug only) */
PHP_FUNCTION(xcache_dprint)
{
zval *value;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == FAILURE) {
return;
}
xc_dprint_zval(value, 0 TSRMLS_CC);
}
/* }}} */
#endif
/* {{{ proto string xcache_asm(string filename)
*/
#ifdef HAVE_XCACHE_ASSEMBLER
@ -2322,6 +2419,9 @@ static function_entry xcache_functions[] = /* {{{ */
PHP_FE(xcache_set, NULL)
PHP_FE(xcache_isset, NULL)
PHP_FE(xcache_unset, NULL)
#ifdef HAVE_XCACHE_DPRINT
PHP_FE(xcache_dprint, NULL)
#endif
{NULL, NULL, NULL}
};
/* }}} */
@ -2459,6 +2559,16 @@ static PHP_MINFO_FUNCTION(xcache)
php_info_print_table_row(2, "Version", XCACHE_VERSION);
php_info_print_table_row(2, "Modules Built", XCACHE_MODULES);
php_info_print_table_row(2, "Readonly Protection", xc_readonly_protection ? "enabled" : "N/A");
ptr = php_format_date("Y-m-d H:i:s", sizeof("Y-m-d H:i:s") - 1, xc_init_time, 1 TSRMLS_CC);
php_info_print_table_row(2, "Cache Init Time", ptr);
efree(ptr);
#ifdef ZTS
snprintf(buf, sizeof(buf), "%lu.%lu", xc_init_instance_id, xc_init_instance_subid);
#else
snprintf(buf, sizeof(buf), "%lu", xc_init_instance_id);
#endif
php_info_print_table_row(2, "Cache Instance Id", buf);
if (xc_php_size) {
ptr = _php_math_number_format(xc_php_size, 0, '.', ',');
@ -2693,6 +2803,11 @@ static PHP_MINIT_FUNCTION(xcache)
goto err_init;
}
xc_initized = 1;
xc_init_time = time(NULL);
xc_init_instance_id = getpid();
#ifdef ZTS
xc_init_instance_subid = tsrm_thread_id();
#endif
}
#ifdef HAVE_XCACHE_COVERAGER

7
xcache.h

@ -219,6 +219,13 @@ typedef struct {
time_t last_gc_deletes;
time_t last_gc_expires;
time_t hits_by_hour_cur_time;
zend_uint hits_by_hour_cur_slot;
zend_ulong hits_by_hour[24];
time_t hits_by_second_cur_time;
zend_uint hits_by_second_cur_slot;
zend_ulong hits_by_second[5];
} xc_cache_t;
/* }}} */
/* {{{ xc_classinfo_t */

4
xcache.ini

@ -22,7 +22,7 @@ xcache.admin.pass = ""
xcache.shm_scheme = "mmap"
; to disable: xcache.size=0
; to enable : xcache.size=64M etc (any size > 0) and your system mmap allows
xcache.size = 0M
xcache.size = 60M
; set to cpu count (cat /proc/cpuinfo |grep -c processor)
xcache.count = 1
; just a hash hints, you can always store count(items) > slots
@ -33,7 +33,7 @@ xcache.ttl = 0
xcache.gc_interval = 0
; same as aboves but for variable cache
xcache.var_size = 0M
xcache.var_size = 4M
xcache.var_count = 1
xcache.var_slots = 8K
; default ttl