From 4f4530b98dcb8b60abd7c4ffd91c0d9de9380c4b Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Fri, 8 Jul 2016 12:09:37 +0200 Subject: [PATCH] * Admin: add used caching provider and APCu stats to "PHP Information" --- admin/apcu.php | 1166 +++++++++++++++++++++++++++++++++++++++++++++ admin/phpinfo.php | 20 + api/src/Cache.php | 13 + 3 files changed, 1199 insertions(+) create mode 100644 admin/apcu.php diff --git a/admin/apcu.php b/admin/apcu.php new file mode 100644 index 0000000000..9a342819ec --- /dev/null +++ b/admin/apcu.php @@ -0,0 +1,1166 @@ + True, + 'nonavbar' => True, + 'currentapp' => 'admin' +); +include('../header.inc.php'); + +if ($GLOBALS['egw']->acl->check('info_access',1,'admin')) +{ + $GLOBALS['egw']->redirect_link('/index.php'); +} + +/* + +----------------------------------------------------------------------+ + | APC | + +----------------------------------------------------------------------+ + | Copyright (c) 2006-2011 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Ralf Becker | + | Rasmus Lerdorf | + | Ilia Alshanetsky | + +----------------------------------------------------------------------+ + + All other licensing and usage conditions are those of the PHP Group. + + */ + +$VERSION='$Id$'; + +////////// READ OPTIONAL CONFIGURATION FILE //////////// +if (file_exists("apc.conf.php")) include("apc.conf.php"); +//////////////////////////////////////////////////////// + +////////// BEGIN OF DEFAULT CONFIG AREA /////////////////////////////////////////////////////////// + +defaults('USE_AUTHENTICATION',1); // Use (internal) authentication - best choice if + // no other authentication is available + // If set to 0: + // There will be no further authentication. You + // will have to handle this by yourself! + // If set to 1: + // You need to change ADMIN_PASSWORD to make + // this work! +defaults('ADMIN_USERNAME','apc'); // Admin Username +defaults('ADMIN_PASSWORD','password'); // Admin Password - CHANGE THIS TO ENABLE!!! + +// (beckerr) I'm using a clear text password here, because I've no good idea how to let +// users generate a md5 or crypt password in a easy way to fill it in above + +//defaults('DATE_FORMAT', "d.m.Y H:i:s"); // German +defaults('DATE_FORMAT', 'Y/m/d H:i:s'); // US + +defaults('GRAPH_SIZE',200); // Image size + +//defaults('PROXY', 'tcp://127.0.0.1:8080'); + +////////// END OF DEFAULT CONFIG AREA ///////////////////////////////////////////////////////////// + + +// "define if not defined" +function defaults($d,$v) { + if (!defined($d)) define($d,$v); // or just @define(...) +} + +// rewrite $PHP_SELF to block XSS attacks +// +$PHP_SELF= isset($_SERVER['PHP_SELF']) ? htmlentities(strip_tags($_SERVER['PHP_SELF'],''), ENT_QUOTES, 'UTF-8') : ''; +$time = time(); +$host = php_uname('n'); +if($host) { $host = '('.$host.')'; } +if (isset($_SERVER['SERVER_ADDR'])) { + $host .= ' ('.$_SERVER['SERVER_ADDR'].')'; +} + +// operation constants +define('OB_HOST_STATS',1); +define('OB_USER_CACHE',2); +define('OB_VERSION_CHECK',3); + +// check validity of input variables +$vardom=array( + 'OB' => '/^\d+$/', // operational mode switch + 'CC' => '/^[01]$/', // clear cache requested + 'DU' => '/^.*$/', // Delete User Key + 'SH' => '/^[a-z0-9]+$/', // shared object description + + 'IMG' => '/^[123]$/', // image to generate + 'LO' => '/^1$/', // login requested + + 'COUNT' => '/^\d+$/', // number of line displayed in list + 'SCOPE' => '/^[AD]$/', // list view scope + 'SORT1' => '/^[AHSMCDTZ]$/', // first sort key + 'SORT2' => '/^[DA]$/', // second sort key + 'AGGR' => '/^\d+$/', // aggregation by dir level + 'SEARCH' => '~^[a-zA-Z0-9/_.-]*$~' // aggregation by dir level +); + +// cache scope +$scope_list=array( + 'A' => 'cache_list', + 'D' => 'deleted_list' +); + +// handle POST and GET requests +if (empty($_REQUEST)) { + if (!empty($_GET) && !empty($_POST)) { + $_REQUEST = array_merge($_GET, $_POST); + } else if (!empty($_GET)) { + $_REQUEST = $_GET; + } else if (!empty($_POST)) { + $_REQUEST = $_POST; + } else { + $_REQUEST = array(); + } +} + +// check parameter syntax +foreach($vardom as $var => $dom) { + if (!isset($_REQUEST[$var])) { + $MYREQUEST[$var]=NULL; + } else if (!is_array($_REQUEST[$var]) && preg_match($dom.'D',$_REQUEST[$var])) { + $MYREQUEST[$var]=$_REQUEST[$var]; + } else { + $MYREQUEST[$var]=$_REQUEST[$var]=NULL; + } +} + +// check parameter sematics +if (empty($MYREQUEST['SCOPE'])) $MYREQUEST['SCOPE']="A"; +if (empty($MYREQUEST['SORT1'])) $MYREQUEST['SORT1']="H"; +if (empty($MYREQUEST['SORT2'])) $MYREQUEST['SORT2']="D"; +if (empty($MYREQUEST['OB'])) $MYREQUEST['OB']=OB_HOST_STATS; +if (!isset($MYREQUEST['COUNT'])) $MYREQUEST['COUNT']=20; +if (!isset($scope_list[$MYREQUEST['SCOPE']])) $MYREQUEST['SCOPE']='A'; + +$MY_SELF= + "$PHP_SELF". + "?SCOPE=".$MYREQUEST['SCOPE']. + "&SORT1=".$MYREQUEST['SORT1']. + "&SORT2=".$MYREQUEST['SORT2']. + "&COUNT=".$MYREQUEST['COUNT']; +$MY_SELF_WO_SORT= + "$PHP_SELF". + "?SCOPE=".$MYREQUEST['SCOPE']. + "&COUNT=".$MYREQUEST['COUNT']; + +// authentication needed? +// +if (!USE_AUTHENTICATION) { + $AUTHENTICATED=1; +} else { + $AUTHENTICATED=0; + if (ADMIN_PASSWORD!='password' && ($MYREQUEST['LO'] == 1 || isset($_SERVER['PHP_AUTH_USER']))) { + + if (!isset($_SERVER['PHP_AUTH_USER']) || + !isset($_SERVER['PHP_AUTH_PW']) || + $_SERVER['PHP_AUTH_USER'] != ADMIN_USERNAME || + $_SERVER['PHP_AUTH_PW'] != ADMIN_PASSWORD) { + Header("WWW-Authenticate: Basic realm=\"APC Login\""); + Header("HTTP/1.0 401 Unauthorized"); + + echo << +

Rejected!

+ Wrong Username or Password!
 
  + Continue... + +EOB; + exit; + + } else { + $AUTHENTICATED=1; + } + } +} + +// clear cache +if ($AUTHENTICATED && isset($MYREQUEST['CC']) && $MYREQUEST['CC']) { + apcu_clear_cache(); +} + +if ($AUTHENTICATED && !empty($MYREQUEST['DU'])) { + apcu_delete($MYREQUEST['DU']); +} + +if(!function_exists('apcu_cache_info')) { + echo "No cache info available. APC does not appear to be running."; + exit; +} + +$cache = apcu_cache_info(); + +$mem=apcu_sma_info(); + +// don't cache this page +// +header("Cache-Control: no-store, no-cache, must-revalidate"); // HTTP/1.1 +header("Cache-Control: post-check=0, pre-check=0", false); +header("Pragma: no-cache"); // HTTP/1.0 + +function duration($ts) { + global $time; + $years = (int)((($time - $ts)/(7*86400))/52.177457); + $rem = (int)(($time-$ts)-($years * 52.177457 * 7 * 86400)); + $weeks = (int)(($rem)/(7*86400)); + $days = (int)(($rem)/86400) - $weeks*7; + $hours = (int)(($rem)/3600) - $days*24 - $weeks*7*24; + $mins = (int)(($rem)/60) - $hours*60 - $days*24*60 - $weeks*7*24*60; + $str = ''; + if($years==1) $str .= "$years year, "; + if($years>1) $str .= "$years years, "; + if($weeks==1) $str .= "$weeks week, "; + if($weeks>1) $str .= "$weeks weeks, "; + if($days==1) $str .= "$days day,"; + if($days>1) $str .= "$days days,"; + if($hours == 1) $str .= " $hours hour and"; + if($hours>1) $str .= " $hours hours and"; + if($mins == 1) $str .= " 1 minute"; + else $str .= " $mins minutes"; + return $str; +} + +// create graphics +// +function graphics_avail() { + return extension_loaded('gd'); +} +if (isset($MYREQUEST['IMG'])) +{ + if (!graphics_avail()) { + exit(0); + } + + function fill_arc($im, $centerX, $centerY, $diameter, $start, $end, $color1,$color2,$text='',$placeindex=0) { + $r=$diameter/2; + $w=deg2rad((360+$start+($end-$start)/2)%360); + + + if (function_exists("imagefilledarc")) { + // exists only if GD 2.0.1 is avaliable + imagefilledarc($im, $centerX+1, $centerY+1, $diameter, $diameter, $start, $end, $color1, IMG_ARC_PIE); + imagefilledarc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color2, IMG_ARC_PIE); + imagefilledarc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color1, IMG_ARC_NOFILL|IMG_ARC_EDGED); + } else { + imagearc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color2); + imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start)) * $r, $centerY + sin(deg2rad($start)) * $r, $color2); + imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start+1)) * $r, $centerY + sin(deg2rad($start)) * $r, $color2); + imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end-1)) * $r, $centerY + sin(deg2rad($end)) * $r, $color2); + imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end)) * $r, $centerY + sin(deg2rad($end)) * $r, $color2); + imagefill($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2, $color2); + } + if ($text) { + if ($placeindex>0) { + imageline($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$diameter, $placeindex*12,$color1); + imagestring($im,4,$diameter, $placeindex*12,$text,$color1); + + } else { + imagestring($im,4,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$text,$color1); + } + } + } + + function text_arc($im, $centerX, $centerY, $diameter, $start, $end, $color1,$text,$placeindex=0) { + $r=$diameter/2; + $w=deg2rad((360+$start+($end-$start)/2)%360); + + if ($placeindex>0) { + imageline($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$diameter, $placeindex*12,$color1); + imagestring($im,4,$diameter, $placeindex*12,$text,$color1); + + } else { + imagestring($im,4,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$text,$color1); + } + } + + function fill_box($im, $x, $y, $w, $h, $color1, $color2,$text='',$placeindex='') { + global $col_black; + $x1=$x+$w-1; + $y1=$y+$h-1; + + imagerectangle($im, $x, $y1, $x1+1, $y+1, $col_black); + if($y1>$y) imagefilledrectangle($im, $x, $y, $x1, $y1, $color2); + else imagefilledrectangle($im, $x, $y1, $x1, $y, $color2); + imagerectangle($im, $x, $y1, $x1, $y, $color1); + if ($text) { + if ($placeindex>0) { + + if ($placeindex<16) + { + $px=5; + $py=$placeindex*12+6; + imagefilledrectangle($im, $px+90, $py+3, $px+90-4, $py-3, $color2); + imageline($im,$x,$y+$h/2,$px+90,$py,$color2); + imagestring($im,2,$px,$py-6,$text,$color1); + + } else { + if ($placeindex<31) { + $px=$x+40*2; + $py=($placeindex-15)*12+6; + } else { + $px=$x+40*2+100*intval(($placeindex-15)/15); + $py=($placeindex%15)*12+6; + } + imagefilledrectangle($im, $px, $py+3, $px-4, $py-3, $color2); + imageline($im,$x+$w,$y+$h/2,$px,$py,$color2); + imagestring($im,2,$px+2,$py-6,$text,$color1); + } + } else { + imagestring($im,4,$x+5,$y1-16,$text,$color1); + } + } + } + + + $size = GRAPH_SIZE; // image size + if ($MYREQUEST['IMG']==3) + $image = imagecreate(2*$size+150, $size+10); + else + $image = imagecreate($size+50, $size+10); + + $col_white = imagecolorallocate($image, 0xFF, 0xFF, 0xFF); + $col_red = imagecolorallocate($image, 0xD0, 0x60, 0x30); + $col_green = imagecolorallocate($image, 0x60, 0xF0, 0x60); + $col_black = imagecolorallocate($image, 0, 0, 0); + imagecolortransparent($image,$col_white); + + switch ($MYREQUEST['IMG']) { + + case 1: + $s=$mem['num_seg']*$mem['seg_size']; + $a=$mem['avail_mem']; + $x=$y=$size/2; + $fuzz = 0.000001; + + // This block of code creates the pie chart. It is a lot more complex than you + // would expect because we try to visualize any memory fragmentation as well. + $angle_from = 0; + $string_placement=array(); + for($i=0; $i<$mem['num_seg']; $i++) { + $ptr = 0; + $free = $mem['block_lists'][$i]; + uasort($free, 'block_sort'); + foreach($free as $block) { + if($block['offset']!=$ptr) { // Used block + $angle_to = $angle_from+($block['offset']-$ptr)/$s; + if(($angle_to+$fuzz)>1) $angle_to = 1; + if( ($angle_to*360) - ($angle_from*360) >= 1) { + fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_red); + if (($angle_to-$angle_from)>0.05) { + array_push($string_placement, array($angle_from,$angle_to)); + } + } + $angle_from = $angle_to; + } + $angle_to = $angle_from+($block['size'])/$s; + if(($angle_to+$fuzz)>1) $angle_to = 1; + if( ($angle_to*360) - ($angle_from*360) >= 1) { + fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_green); + if (($angle_to-$angle_from)>0.05) { + array_push($string_placement, array($angle_from,$angle_to)); + } + } + $angle_from = $angle_to; + $ptr = $block['offset']+$block['size']; + } + if ($ptr < $mem['seg_size']) { // memory at the end + $angle_to = $angle_from + ($mem['seg_size'] - $ptr)/$s; + if(($angle_to+$fuzz)>1) $angle_to = 1; + fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_red); + if (($angle_to-$angle_from)>0.05) { + array_push($string_placement, array($angle_from,$angle_to)); + } + } + } + foreach ($string_placement as $angle) { + text_arc($image,$x,$y,$size,$angle[0]*360,$angle[1]*360,$col_black,bsize($s*($angle[1]-$angle[0]))); + } + break; + + case 2: + $s=$cache['num_hits']+$cache['num_misses']; + $a=$cache['num_hits']; + + fill_box($image, 30,$size,50,$s ? (-$a*($size-21)/$s) : 0,$col_black,$col_green,sprintf("%.1f%%",$s ? $cache['num_hits']*100/$s : 0)); + fill_box($image,130,$size,50,$s ? -max(4,($s-$a)*($size-21)/$s) : 0,$col_black,$col_red,sprintf("%.1f%%",$s ? $cache['num_misses']*100/$s : 0)); + break; + + case 3: + $s=$mem['num_seg']*$mem['seg_size']; + $a=$mem['avail_mem']; + $x=130; + $y=1; + $j=1; + + // This block of code creates the bar chart. It is a lot more complex than you + // would expect because we try to visualize any memory fragmentation as well. + for($i=0; $i<$mem['num_seg']; $i++) { + $ptr = 0; + $free = $mem['block_lists'][$i]; + uasort($free, 'block_sort'); + foreach($free as $block) { + if($block['offset']!=$ptr) { // Used block + $h=(GRAPH_SIZE-5)*($block['offset']-$ptr)/$s; + if ($h>0) { + $j++; + if($j<75) fill_box($image,$x,$y,50,$h,$col_black,$col_red,bsize($block['offset']-$ptr),$j); + else fill_box($image,$x,$y,50,$h,$col_black,$col_red); + } + $y+=$h; + } + $h=(GRAPH_SIZE-5)*($block['size'])/$s; + if ($h>0) { + $j++; + if($j<75) fill_box($image,$x,$y,50,$h,$col_black,$col_green,bsize($block['size']),$j); + else fill_box($image,$x,$y,50,$h,$col_black,$col_green); + } + $y+=$h; + $ptr = $block['offset']+$block['size']; + } + if ($ptr < $mem['seg_size']) { // memory at the end + $h = (GRAPH_SIZE-5) * ($mem['seg_size'] - $ptr) / $s; + if ($h > 0) { + fill_box($image,$x,$y,50,$h,$col_black,$col_red,bsize($mem['seg_size']-$ptr),$j++); + } + } + } + break; + + case 4: + $s=$cache['num_hits']+$cache['num_misses']; + $a=$cache['num_hits']; + + fill_box($image, 30,$size,50,$s ? -$a*($size-21)/$s : 0,$col_black,$col_green,sprintf("%.1f%%", $s ? $cache['num_hits']*100/$s : 0)); + fill_box($image,130,$size,50,$s ? -max(4,($s-$a)*($size-21)/$s) : 0,$col_black,$col_red,sprintf("%.1f%%", $s ? $cache['num_misses']*100/$s : 0)); + break; + } + + header("Content-type: image/png"); + imagepng($image); + exit; +} + +// pretty printer for byte values +// +function bsize($s) { + foreach (array('','K','M','G') as $i => $k) { + if ($s < 1024) break; + $s/=1024; + } + return sprintf("%5.1f %sBytes",$s,$k); +} + +// sortable table header in "scripts for this host" view +function sortheader($key,$name,$extra='') { + global $MYREQUEST, $MY_SELF_WO_SORT; + + if ($MYREQUEST['SORT1']==$key) { + $MYREQUEST['SORT2'] = $MYREQUEST['SORT2']=='A' ? 'D' : 'A'; + } + return "$name"; + +} + +// create menu entry +function menu_entry($ob,$title) { + global $MYREQUEST,$MY_SELF; + if ($MYREQUEST['OB']!=$ob) { + return "
  • $title
  • "; + } else if (empty($MYREQUEST['SH'])) { + return "
  • $title
  • "; + } else { + return "
  • $title
  • "; + } +} + +function put_login_link($s="Login") +{ + global $MY_SELF,$MYREQUEST,$AUTHENTICATED; + // needs ADMIN_PASSWORD to be changed! + // + if (!USE_AUTHENTICATION) { + return; + } else if (ADMIN_PASSWORD=='password') + { + print <<$s +EOB; + } else if ($AUTHENTICATED) { + print <<$s +EOB; + } +} + +function block_sort($array1, $array2) +{ + if ($array1['offset'] > $array2['offset']) { + return 1; + } else { + return -1; + } +} + + +?> + + +APCu INFO <?php echo $host ?> + + + +
    +

    + +
    User Cache
    +

    + +
    +
    + + +
  • Refresh Data
  • +EOB; +echo + menu_entry(OB_HOST_STATS,'View Host Stats'), + menu_entry(OB_USER_CACHE,'User Cache Entries'), + menu_entry(OB_VERSION_CHECK,'Version Check'); + +if ($AUTHENTICATED) { + echo <<Clear Cache +EOB; +} +echo << +EOB; + + +// CONTENT +echo << +EOB; + +// MAIN SWITCH STATEMENT + +switch ($MYREQUEST['OB']) { +// ----------------------------------------------- +// Host Stats +// ----------------------------------------------- +case OB_HOST_STATS: + $mem_size = $mem['num_seg']*$mem['seg_size']; + $mem_avail= $mem['avail_mem']; + $mem_used = $mem_size-$mem_avail; + $seg_size = bsize($mem['seg_size']); + $req_rate_user = sprintf("%.2f", $cache['num_hits'] ? (($cache['num_hits']+$cache['num_misses'])/($time-$cache['start_time'])) : 0); + $hit_rate_user = sprintf("%.2f", $cache['num_hits'] ? (($cache['num_hits'])/($time-$cache['start_time'])) : 0); + $miss_rate_user = sprintf("%.2f", $cache['num_misses'] ? (($cache['num_misses'])/($time-$cache['start_time'])) : 0); + $insert_rate_user = sprintf("%.2f", $cache['num_inserts'] ? (($cache['num_inserts'])/($time-$cache['start_time'])) : 0); + $apcversion = phpversion('apcu'); + $phpversion = phpversion(); + $number_vars = $cache['num_entries']; + $size_vars = bsize($cache['mem_size']); + $i=0; + echo <<< EOB +

    General Cache Information

    + + + +EOB; + + if(!empty($_SERVER['SERVER_NAME'])) + echo "\n"; + if(!empty($_SERVER['SERVER_SOFTWARE'])) + echo "\n"; + + echo << +EOB; + echo ''; + echo ''; + echo <<
    APCu Version$apcversion
    PHP Version$phpversion
    APCu Host{$_SERVER['SERVER_NAME']} $host
    Server Software{$_SERVER['SERVER_SOFTWARE']}
    Shared Memory{$mem['num_seg']} Segment(s) with $seg_size +
    ({$cache['memory_type']} memory) +
    Start Time',date(DATE_FORMAT,$cache['start_time']),'
    Uptime',duration($cache['start_time']),'
    +
    + +

    Cache Information

    + + + + + + + + + + + +
    Cached Variables$number_vars ($size_vars)
    Hits{$cache['num_hits']}
    Misses{$cache['num_misses']}
    Request Rate (hits, misses)$req_rate_user cache requests/second
    Hit Rate$hit_rate_user cache requests/second
    Miss Rate$miss_rate_user cache requests/second
    Insert Rate$insert_rate_user cache requests/second
    Cache full count{$cache['expunges']}
    +
    + +

    Runtime Settings

    +EOB; + + $j = 0; + foreach (ini_get_all('apcu') as $k => $v) { + echo "\n"; + $j = 1 - $j; + } + + if($mem['num_seg']>1 || $mem['num_seg']==1 && count($mem['block_lists'][0])>1) + $mem_note = "Memory Usage
    (multiple slices indicate fragments)"; + else + $mem_note = "Memory Usage"; + + echo <<< EOB +
    ",$k,"",str_replace(',',',
    ',$v['local_value']),"
    +
    + +

    Host Status Diagrams

    + +EOB; + $size='width='.(GRAPH_SIZE+50).' height='.(GRAPH_SIZE+10); +echo << + + + +EOB; + + echo + graphics_avail() ? + ''. + "". + "\n" + : "", + '', + '\n", + '\n", + '', + '', + '\n", + '\n"; + echo <<< EOB + +
    $mem_noteHits & Misses
    \"\"\"\"
     Free: ',bsize($mem_avail).sprintf(" (%.1f%%)",$mem_avail*100/$mem_size)," Hits: ',$cache['num_hits'].@sprintf(" (%.1f%%)",$cache['num_hits']*100/($cache['num_hits']+$cache['num_misses'])),"
     Used: ',bsize($mem_used).sprintf(" (%.1f%%)",$mem_used *100/$mem_size)," Misses: ',$cache['num_misses'].@sprintf(" (%.1f%%)",$cache['num_misses']*100/($cache['num_hits']+$cache['num_misses'])),"
    + +
    +

    Detailed Memory Usage and Fragmentation

    + + + + +EOB; + if(isset($mem['adist'])) { + foreach($mem['adist'] as $i=>$v) { + $cur = pow(2,$i); $nxt = pow(2,$i+1)-1; + if($i==0) $range = "1"; + else $range = "$cur - $nxt"; + echo "\n"; + } + } + echo <<

    +EOB; + + // Fragementation: (freeseg - 1) / total_seg + $nseg = $freeseg = $fragsize = $freetotal = 0; + for($i=0; $i<$mem['num_seg']; $i++) { + $ptr = 0; + foreach($mem['block_lists'][$i] as $block) { + if ($block['offset'] != $ptr) { + ++$nseg; + } + $ptr = $block['offset'] + $block['size']; + /* Only consider blocks <5M for the fragmentation % */ + if($block['size']<(5*1024*1024)) $fragsize+=$block['size']; + $freetotal+=$block['size']; + } + $freeseg += count($mem['block_lists'][$i]); + } + + if ($freeseg > 1) { + $frag = sprintf("%.2f%% (%s out of %s in %d fragments)", ($fragsize/$freetotal)*100,bsize($fragsize),bsize($freetotal),$freeseg); + } else { + $frag = "0%"; + } + + if (graphics_avail()) { + $size='width='.(2*GRAPH_SIZE+150).' height='.(GRAPH_SIZE+10); + echo << +EOB; + } + echo <<Fragmentation: $frag +
    $range$v
    +
    +EOB; + + break; + + +// ----------------------------------------------- +// User Cache Entries +// ----------------------------------------------- +case OB_USER_CACHE: + if (!$AUTHENTICATED) { + echo '
    You need to login to see the user values here!
     
    '; + put_login_link("Login now!"); + echo '
    '; + break; + } + $fieldname='info'; + $fieldheading='User Entry Label'; + $fieldkey='info'; + + $cols=6; + echo <<
    Scope: + + ", + ", Sorting:', + '', + '', + '  Search: ', + ' ', + '
    '; + + if (isset($MYREQUEST['SEARCH'])) { + // Don't use preg_quote because we want the user to be able to specify a + // regular expression subpattern. + $MYREQUEST['SEARCH'] = '/'.str_replace('/', '\\/', $MYREQUEST['SEARCH']).'/i'; + if (preg_match($MYREQUEST['SEARCH'], 'test') === false) { + echo '
    Error: enter a valid regular expression as a search query.
    '; + break; + } + } + + echo + '
    ', + '', + '', + '', + '', + '', + '', + ''; + + if($fieldname=='info') { + $cols+=2; + echo ''; + } + echo ''; + + // builds list with alpha numeric sortable keys + // + $list = array(); + + foreach($cache[$scope_list[$MYREQUEST['SCOPE']]] as $i => $entry) { + switch($MYREQUEST['SORT1']) { + case 'A': $k=sprintf('%015d-',$entry['access_time']); break; + case 'H': $k=sprintf('%015d-',$entry['num_hits']); break; + case 'Z': $k=sprintf('%015d-',$entry['mem_size']); break; + case 'M': $k=sprintf('%015d-',$entry['mtime']); break; + case 'C': $k=sprintf('%015d-',$entry['creation_time']); break; + case 'T': $k=sprintf('%015d-',$entry['ttl']); break; + case 'D': $k=sprintf('%015d-',$entry['deletion_time']); break; + case 'S': $k=$entry["info"]; break; + } + if (!$AUTHENTICATED) { + // hide all path entries if not logged in + $list[$k.$entry[$fieldname]]=preg_replace('/^.*(\\/|\\\\)/','*hidden*/',$entry); + } else { + $list[$k.$entry[$fieldname]]=$entry; + } + } + + if ($list) { + // sort list + // + switch ($MYREQUEST['SORT2']) { + case "A": krsort($list); break; + case "D": ksort($list); break; + } + + // output list + $i=0; + foreach($list as $k => $entry) { + if(!$MYREQUEST['SEARCH'] || preg_match($MYREQUEST['SEARCH'], $entry[$fieldname]) != 0) { + $sh=md5($entry["info"]); + $field_value = htmlentities(strip_tags($entry[$fieldname],''), ENT_QUOTES, 'UTF-8'); + echo + '', + "', + '', + '', + '', + '', + ''; + + if($fieldname=='info') { + if($entry['ttl']) + echo ''; + else + echo ''; + } + if ($entry['deletion_time']) { + + echo ''; + } else if ($MYREQUEST['OB'] == OB_USER_CACHE) { + + echo ''; + } else { + echo ''; + } + echo ''; + if ($sh == $MYREQUEST["SH"]) { + echo ''; + echo ''; + echo ''; + } + $i++; + if ($i == $MYREQUEST['COUNT']) + break; + } + } + + } else { + echo ''; + } + echo <<< EOB +
    ',sortheader('S',$fieldheading, "&OB=".$MYREQUEST['OB']),'',sortheader('H','Hits', "&OB=".$MYREQUEST['OB']),'',sortheader('Z','Size', "&OB=".$MYREQUEST['OB']),'',sortheader('A','Last accessed',"&OB=".$MYREQUEST['OB']),'',sortheader('M','Last modified',"&OB=".$MYREQUEST['OB']),'',sortheader('C','Created at', "&OB=".$MYREQUEST['OB']),'',sortheader('T','Timeout',"&OB=".$MYREQUEST['OB']),'',sortheader('D','Deleted at',"&OB=".$MYREQUEST['OB']),'
    ",$field_value,'',$entry['num_hits'],'',$entry['mem_size'],'',date(DATE_FORMAT,$entry['access_time']),'',date(DATE_FORMAT,$entry['mtime']),'',date(DATE_FORMAT,$entry['creation_time']),''.$entry['ttl'].' secondsNone', date(DATE_FORMAT,$entry['deletion_time']), ''; + echo '[Delete Now]'; + echo '  
    '.htmlentities(print_r(apcu_fetch($entry['info']), 1)).'
    No data
    +EOB; + + if ($list && $i < count($list)) { + echo "",count($list)-$i,' more available...'; + } + + echo <<< EOB +
    +EOB; + break; + +// ----------------------------------------------- +// Version check +// ----------------------------------------------- +case OB_VERSION_CHECK: + echo <<

    APCu Version Information

    + + + + +EOB; + if (defined('PROXY')) { + $ctxt = stream_context_create( array( 'http' => array( 'proxy' => PROXY, 'request_fulluri' => True ) ) ); + $rss = @file_get_contents("http://pecl.php.net/feeds/pkg_apcu.rss", False, $ctxt); + } else { + $rss = @file_get_contents("http://pecl.php.net/feeds/pkg_apcu.rss"); + } + if (!$rss) { + echo ''; + } else { + $apcversion = phpversion('apcu'); + + preg_match('!APCu ([0-9.]+)!', $rss, $match); + echo ''; + echo ''; + } + echo <<< EOB +
    Unable to fetch version information.
    '; + if (version_compare($apcversion, $match[1], '>=')) { + echo '
    You are running the latest version of APCu ('.$apcversion.')
    '; + $i = 3; + } else { + echo '
    You are running an older version of APCu ('.$apcversion.'), + newer version '.$match[1].' is available at + http://pecl.php.net/package/APCu/'.$match[1].' +
    '; + $i = -1; + } + echo '

    Change Log:


    '; + + preg_match_all('!<(title|description)>([^<]+)!', $rss, $match); + next($match[2]); next($match[2]); + + while (list(,$v) = each($match[2])) { + list(,$ver) = explode(' ', $v, 2); + if ($i < 0 && version_compare($apcversion, $ver, '>=')) { + break; + } else if (!$i--) { + break; + } + echo "".htmlspecialchars($v, ENT_QUOTES, 'UTF-8')."
    "; + echo nl2br(htmlspecialchars(current($match[2]), ENT_QUOTES, 'UTF-8'))."
    "; + next($match[2]); + } + echo '
    + +EOB; + break; + +} + +echo <<< EOB + +EOB; + +?> + + + + diff --git a/admin/phpinfo.php b/admin/phpinfo.php index a624591492..0a5d5c13a1 100755 --- a/admin/phpinfo.php +++ b/admin/phpinfo.php @@ -8,6 +8,8 @@ * @version $Id$ */ +use EGroupware\Api; + $GLOBALS['egw_info']['flags'] = array( 'noheader' => True, 'nonavbar' => True, @@ -20,4 +22,22 @@ if ($GLOBALS['egw']->acl->check('info_access',1,'admin')) $GLOBALS['egw']->redirect_link('/index.php'); } +$cache_provider = Api\Cache::getProvider(); +$cache_info = ''; +$cache_info .= '
    EGroupware caching provider'.Api\Cache::getProvider(); +if ($cache_provider == 'EGroupware\\Api\\Cache\\Apcu') +{ + $cache_info .= ' View APCu stats'; +} +$cache_info .= '
    '."\n"; + +ob_start(); phpinfo(); +$phpinfo = ob_get_clean(); + +$info = str_ireplace('
    ', '
    '."\n".$cache_info, $phpinfo); +if ($info == $phpinfo) +{ + echo $cache_info; +} +echo $info; diff --git a/api/src/Cache.php b/api/src/Cache.php index 7ac39eafa3..6b856ffefa 100644 --- a/api/src/Cache.php +++ b/api/src/Cache.php @@ -559,6 +559,19 @@ class Cache return $providers[$level]; } + /** + * Get class-name of caching provider + * + * @param string $level + * @return string class-name of provider + */ + public static function getProvider($level=self::INSTANCE) + { + $provider = self::get_provider($level); + + return get_class($provider); + } + /** * Get a system configuration, even if in setup and it's not read *