r34218 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r34217‎ | r34218 | r34219 >
Date:18:12, 4 May 2008
Author:nikerabbit
Status:old
Tags:
Comment:
* New extension
Modified paths:
  • /trunk/extensions/APC (added) (history)
  • /trunk/extensions/APC/APCCacheMode.php (added) (history)
  • /trunk/extensions/APC/APCHostMode.php (added) (history)
  • /trunk/extensions/APC/APCImages.php (added) (history)
  • /trunk/extensions/APC/APCUtils.php (added) (history)
  • /trunk/extensions/APC/SpecialAPC.php (added) (history)
  • /trunk/extensions/APC/ViewAPC.i18n.php (added) (history)
  • /trunk/extensions/APC/ViewAPC.php (added) (history)
  • /trunk/extensions/APC/apc.css (added) (history)

Diff [purge]

Index: trunk/extensions/APC/APCImages.php
@@ -0,0 +1,225 @@
 2+<?php
 3+
 4+class APCImages {
 5+
 6+ const IMG_NONE = 0;
 7+ const IMG_MEM_USAGE = 1;
 8+ const IMG_HITS = 2;
 9+ const IMG_FRAGMENTATION = 3;
 10+
 11+ const GRAPH_SIZE = 200;
 12+
 13+ // create graphics
 14+ //
 15+ public static function graphics_avail() {
 16+ return extension_loaded('gd');
 17+ }
 18+
 19+ public static function fill_arc($im, $centerX, $centerY, $diameter, $start, $end, $color1,$color2,$text='',$placeindex=0) {
 20+ $r=$diameter/2;
 21+ $w=deg2rad((360+$start+($end-$start)/2)%360);
 22+
 23+
 24+ if (function_exists("imagefilledarc")) {
 25+ // exists only if GD 2.0.1 is avaliable
 26+ imagefilledarc($im, $centerX+1, $centerY+1, $diameter, $diameter, $start, $end, $color1, IMG_ARC_PIE);
 27+ imagefilledarc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color2, IMG_ARC_PIE);
 28+ imagefilledarc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color1, IMG_ARC_NOFILL|IMG_ARC_EDGED);
 29+ } else {
 30+ imagearc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color2);
 31+ imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start)) * $r, $centerY + sin(deg2rad($start)) * $r, $color2);
 32+ imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start+1)) * $r, $centerY + sin(deg2rad($start)) * $r, $color2);
 33+ imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end-1)) * $r, $centerY + sin(deg2rad($end)) * $r, $color2);
 34+ imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end)) * $r, $centerY + sin(deg2rad($end)) * $r, $color2);
 35+ imagefill($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2, $color2);
 36+ }
 37+ if ($text) {
 38+ if ($placeindex>0) {
 39+ imageline($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$diameter, $placeindex*12,$color1);
 40+ imagestring($im,4,$diameter, $placeindex*12,$text,$color1);
 41+
 42+ } else {
 43+ imagestring($im,4,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$text,$color1);
 44+ }
 45+ }
 46+ }
 47+
 48+ public static function text_arc($im, $centerX, $centerY, $diameter, $start, $end, $color1,$text,$placeindex=0) {
 49+ $r=$diameter/2;
 50+ $w=deg2rad((360+$start+($end-$start)/2)%360);
 51+
 52+ if ($placeindex>0) {
 53+ imageline($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$diameter, $placeindex*12,$color1);
 54+ imagestring($im,4,$diameter, $placeindex*12,$text,$color1);
 55+
 56+ } else {
 57+ imagestring($im,4,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$text,$color1);
 58+ }
 59+ }
 60+
 61+ public static function fill_box($im, $x, $y, $w, $h, $color1, $color2,$text='',$placeindex='') {
 62+ global $col_black;
 63+ $x1=$x+$w-1;
 64+ $y1=$y+$h-1;
 65+
 66+ imagerectangle($im, $x, $y1, $x1+1, $y+1, $col_black);
 67+ if($y1>$y) imagefilledrectangle($im, $x, $y, $x1, $y1, $color2);
 68+ else imagefilledrectangle($im, $x, $y1, $x1, $y, $color2);
 69+ imagerectangle($im, $x, $y1, $x1, $y, $color1);
 70+ if ($text) {
 71+ if ($placeindex>0) {
 72+
 73+ if ($placeindex<16)
 74+ {
 75+ $px=5;
 76+ $py=$placeindex*12+6;
 77+ imagefilledrectangle($im, $px+90, $py+3, $px+90-4, $py-3, $color2);
 78+ imageline($im,$x,$y+$h/2,$px+90,$py,$color2);
 79+ imagestring($im,2,$px,$py-6,$text,$color1);
 80+
 81+ } else {
 82+ if ($placeindex<31) {
 83+ $px=$x+40*2;
 84+ $py=($placeindex-15)*12+6;
 85+ } else {
 86+ $px=$x+40*2+100*intval(($placeindex-15)/15);
 87+ $py=($placeindex%15)*12+6;
 88+ }
 89+ imagefilledrectangle($im, $px, $py+3, $px-4, $py-3, $color2);
 90+ imageline($im,$x+$w,$y+$h/2,$px,$py,$color2);
 91+ imagestring($im,2,$px+2,$py-6,$text,$color1);
 92+ }
 93+ } else {
 94+ imagestring($im,4,$x+5,$y1-16,$text,$color1);
 95+ }
 96+ }
 97+ }
 98+
 99+ public static function generateImage( $type ) {
 100+ global $wgLang;
 101+
 102+ $mem = apc_sma_info();
 103+ $cache = apc_cache_info( 'opcode' );
 104+
 105+ $size = self::GRAPH_SIZE; // image size
 106+ if ($type==self::IMG_FRAGMENTATION)
 107+ $image = imagecreate(2*$size+150, $size+10);
 108+ else
 109+ $image = imagecreate($size+10, $size+10);
 110+
 111+ $col_white = imagecolorallocate($image, 0xFF, 0xFF, 0xFF);
 112+ $col_red = imagecolorallocate($image, 0xD0, 0x60, 0x30);
 113+ $col_green = imagecolorallocate($image, 0x60, 0xF0, 0x60);
 114+ $col_black = imagecolorallocate($image, 0, 0, 0);
 115+ imagecolortransparent($image,$col_white);
 116+
 117+ switch ($type) {
 118+
 119+ case 1:
 120+ $s=$mem['num_seg']*$mem['seg_size'];
 121+ $a=$mem['avail_mem'];
 122+ $x=$y=$size/2;
 123+ $fuzz = 0.000001;
 124+
 125+ // This block of code creates the pie chart. It is a lot more complex than you
 126+ // would expect because we try to visualize any memory fragmentation as well.
 127+ $angle_from = 0;
 128+ $string_placement=array();
 129+ for($i=0; $i<$mem['num_seg']; $i++) {
 130+ $ptr = 0;
 131+ $free = $mem['block_lists'][$i];
 132+ foreach($free as $block) {
 133+ if($block['offset']!=$ptr) { // Used block
 134+ $angle_to = $angle_from+($block['offset']-$ptr)/$s;
 135+ if(($angle_to+$fuzz)>1) $angle_to = 1;
 136+ self::fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_red);
 137+ if (($angle_to-$angle_from)>0.05) {
 138+ array_push($string_placement, array($angle_from,$angle_to));
 139+ }
 140+ $angle_from = $angle_to;
 141+ }
 142+ $angle_to = $angle_from+($block['size'])/$s;
 143+ if(($angle_to+$fuzz)>1) $angle_to = 1;
 144+ self::fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_green);
 145+ if (($angle_to-$angle_from)>0.05) {
 146+ array_push($string_placement, array($angle_from,$angle_to));
 147+ }
 148+ $angle_from = $angle_to;
 149+ $ptr = $block['offset']+$block['size'];
 150+ }
 151+ if ($ptr < $mem['seg_size']) { // memory at the end
 152+ $angle_to = $angle_from + ($mem['seg_size'] - $ptr)/$s;
 153+ if(($angle_to+$fuzz)>1) $angle_to = 1;
 154+ self::fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_red);
 155+ if (($angle_to-$angle_from)>0.05) {
 156+ array_push($string_placement, array($angle_from,$angle_to));
 157+ }
 158+ }
 159+ }
 160+ foreach ($string_placement as $angle) {
 161+ self::text_arc($image,$x,$y,$size,$angle[0]*360,$angle[1]*360,$col_black,$wgLang->formatSize($s*($angle[1]-$angle[0])));
 162+ }
 163+ break;
 164+
 165+ case 2:
 166+ $s=$cache['num_hits']+$cache['num_misses'];
 167+ $a=$cache['num_hits'];
 168+
 169+ self::fill_box($image, 30,$size,50,-$a*($size-21)/$s,$col_black,$col_green,sprintf("%.1f%%",$cache['num_hits']*100/$s));
 170+ self::fill_box($image,130,$size,50,-max(4,($s-$a)*($size-21)/$s),$col_black,$col_red,sprintf("%.1f%%",$cache['num_misses']*100/$s));
 171+ break;
 172+
 173+ case 3:
 174+ $s=$mem['num_seg']*$mem['seg_size'];
 175+ $a=$mem['avail_mem'];
 176+ $x=130;
 177+ $y=1;
 178+ $j=1;
 179+
 180+ // This block of code creates the bar chart. It is a lot more complex than you
 181+ // would expect because we try to visualize any memory fragmentation as well.
 182+ for($i=0; $i<$mem['num_seg']; $i++) {
 183+ $ptr = 0;
 184+ $free = $mem['block_lists'][$i];
 185+ foreach($free as $block) {
 186+ if($block['offset']!=$ptr) { // Used block
 187+ $h=(self::GRAPH_SIZE-5)*($block['offset']-$ptr)/$s;
 188+ if ($h>0) {
 189+ $j++;
 190+ if($j<75) self::fill_box($image,$x,$y,50,$h,$col_black,$col_red,$wgLang->formatSize($block['offset']-$ptr),$j);
 191+ else self::fill_box($image,$x,$y,50,$h,$col_black,$col_red);
 192+ }
 193+ $y+=$h;
 194+ }
 195+ $h=(self::GRAPH_SIZE-5)*($block['size'])/$s;
 196+ if ($h>0) {
 197+ $j++;
 198+ if($j<75) self::fill_box($image,$x,$y,50,$h,$col_black,$col_green,$wgLang->formatSize($block['size']),$j);
 199+ else self::fill_box($image,$x,$y,50,$h,$col_black,$col_green);
 200+ }
 201+ $y+=$h;
 202+ $ptr = $block['offset']+$block['size'];
 203+ }
 204+ if ($ptr < $mem['seg_size']) { // memory at the end
 205+ $h = (self::GRAPH_SIZE-5) * ($mem['seg_size'] - $ptr) / $s;
 206+ if ($h > 0) {
 207+ self::fill_box($image,$x,$y,50,$h,$col_black,$col_red,$wgLang->formatSize($mem['seg_size']-$ptr),$j++);
 208+ }
 209+ }
 210+ }
 211+ break;
 212+ case 4:
 213+ $s=$cache['num_hits']+$cache['num_misses'];
 214+ $a=$cache['num_hits'];
 215+
 216+ self::fill_box($image, 30,$size,50,-$a*($size-21)/$s,$col_black,$col_green,sprintf("%.1f%%",$cache['num_hits']*100/$s));
 217+ self::fill_box($image,130,$size,50,-max(4,($s-$a)*($size-21)/$s),$col_black,$col_red,sprintf("%.1f%%",$cache['num_misses']*100/$s));
 218+ break;
 219+
 220+ }
 221+
 222+ return imagepng( $image );
 223+
 224+ }
 225+
 226+}
\ No newline at end of file
Property changes on: trunk/extensions/APC/APCImages.php
___________________________________________________________________
Added: svn:eol-style
1227 + native
Index: trunk/extensions/APC/APCCacheMode.php
@@ -0,0 +1,288 @@
 2+<?php
 3+
 4+class APCCacheMode {
 5+
 6+ protected $opts, $title;
 7+
 8+ protected $userMode = false;
 9+ protected $fieldKey;
 10+
 11+ public function __construct( FormOptions $opts, Title $title ) {
 12+ $this->opts = $opts;
 13+ $this->title = $title;
 14+ $this->userMode = $opts->getValue( 'mode' ) === SpecialAPC::MODE_USER_CACHE;
 15+ $this->fieldKey = $this->userMode ? 'info' : (ini_get('apc.stat') ? 'inode' : 'filename');
 16+ }
 17+
 18+ protected $scopes = array(
 19+ 'A' => 'cache_list',
 20+ 'D' => 'deleted_list'
 21+ );
 22+
 23+ protected function displayObject( $object ) {
 24+ global $wgLang;
 25+
 26+ $cache = apc_cache_info( $this->userMode ? 'user' : 'opcode' );
 27+
 28+ $s =
 29+ Xml::openElement( 'div', array( 'class' => 'mw-apc-listing' ) ) .
 30+ Xml::openElement( 'table' ) . Xml::openElement( 'tbody' ) .
 31+ Xml::openElement( 'tr' ).
 32+ Xml::element( 'th', null, wfMsg( 'viewapc-display-attribute' ) ) .
 33+ Xml::element( 'th', null, wfMsg( 'viewapc-display-value' ) ) .
 34+ Xml::closeElement( 'tr' );
 35+
 36+ $r = 1;
 37+ foreach( $this->scopes as $list ) {
 38+ foreach( $cache[$list] as $entry ) {
 39+ if (md5($entry[$this->fieldKey]) !== $object) continue;
 40+
 41+ foreach($entry as $key => $value) {
 42+ $value = $this->formatValue( $key, $value );
 43+ switch ($key) {
 44+ case 'num_hits':
 45+ $value = $wgLang->formatNum( $value ) .
 46+ $wgLang->formatNum( sprintf(" (%.2f%%)", $value*100/$cache['num_hits'] ) );
 47+ break;
 48+ case 'deletion_time':
 49+ if ( !$value ) {
 50+ $value = wfMsg( 'viewapc-display-no-delete' );
 51+ break;
 52+ }
 53+ }
 54+
 55+ $s .= APCUtils::tableRow( $r=1-$r,
 56+ wfMsgHtml( 'viewapc-display-' . $key ),
 57+ htmlspecialchars( $value ) );
 58+
 59+ }
 60+
 61+ if ( $this->userMode ) {
 62+ $value = var_export(apc_fetch($entry[$this->fieldKey]),true);
 63+ $s .= APCUtils::tableRow( $r=1-$r,
 64+ wfMsgHtml( 'viewapc-display-stored-value' ),
 65+ Xml::element( 'pre', null, $value ) );
 66+ }
 67+ }
 68+ }
 69+
 70+ $s .= '</tbody></table></div>';
 71+ return $s;
 72+ }
 73+
 74+ // sortable table header in "scripts for this host" view
 75+ protected function sortHeader( $title, $overrides ) {
 76+ $changed = $this->opts->getUnconsumedValues();
 77+ $target = $this->title->getLocalURL( wfArrayToCGI( $overrides, $changed ) );
 78+ return Xml::tags( 'a', array( 'href' => $target ), $title );
 79+ }
 80+
 81+ protected function formatValue( $type, $value ) {
 82+ global $wgLang;
 83+ switch ( $type ) {
 84+ case 'deletion_time':
 85+ if ( !$value ) {
 86+ $value = false; break;
 87+ }
 88+ case 'mtime':
 89+ case 'creation_time':
 90+ case 'access_time':
 91+ $value = $wgLang->timeanddate( $value );
 92+ break;
 93+ case 'ref_count':
 94+ case 'num_hits':
 95+ $value = $wgLang->formatNum( $value );
 96+ break;
 97+ case 'mem_size':
 98+ $value = $wgLang->formatSize( $value );
 99+ break;
 100+ case 'ttl':
 101+ $value = $wgLang->formatTimePeriod( $value );
 102+ break;
 103+ case 'type':
 104+ $value = wfMsg( 'viewapc-display-type-' . $value );
 105+ break;
 106+ }
 107+ return $value;
 108+}
 109+
 110+ public function cacheView() {
 111+ global $wgOut, $wgLang;
 112+
 113+ $object = $this->opts->getValue( 'display' );
 114+ if ( $object ) {
 115+ $wgOut->addHTML( $this->displayObject( $object ) );
 116+ return;
 117+ }
 118+
 119+ $wgOut->addHTML( $this->options() );
 120+ $wgOut->addHTML( '<div><table><tbody><tr>' );
 121+
 122+ $fields = array( 'name', 'hits', 'size', 'accessed', 'modified', 'created' );
 123+ if ( $this->userMode ) $fields[] = 'timeout';
 124+ $fields[] = 'deleted';
 125+
 126+ $fieldKeys = array(
 127+ 'name' => $this->userMode ? 'info' : 'filename',
 128+ 'hits' => 'num_hits',
 129+ 'size' => 'mem_size',
 130+ 'accessed' => 'access_time',
 131+ 'modified' => 'mtime',
 132+ 'created' => 'creation_time',
 133+ 'timeout' => 'ttl',
 134+ 'deleted' => 'deletion_time',
 135+ );
 136+
 137+ $scope = $this->opts->getValue( 'scope' );
 138+ $sort = $this->opts->getValue( 'sort' );
 139+ $sortdir = $this->opts->getValue( 'sortdir' );
 140+ $limit = $this->opts->getValue( 'limit' );
 141+ $offset = $this->opts->getValue( 'offset' );
 142+ $search = $this->opts->getValue( 'searchi' );
 143+
 144+ foreach ( $fields as $field ) {
 145+ $extra = array();
 146+ if ( $sort === $field ) {
 147+ $extra = array( 'sortdir' => 1-$sortdir );
 148+ }
 149+
 150+ $wgOut->addHTML(
 151+ Xml::tags( 'th', null, $this->sortHeader(
 152+ wfMsgHtml( 'viewapc-ls-header-' . $field ),
 153+ array( 'sort' => $field ) + $extra ) )
 154+ );
 155+ }
 156+
 157+ $wgOut->addHTML( '</tr>' );
 158+
 159+ $cache = apc_cache_info( $this->userMode ? 'user' : 'opcode' );
 160+ $list = array();
 161+ if ( $scope === 'active' || $scope === 'both' ) {
 162+ foreach ( $cache['cache_list'] as $entry ) {
 163+ if ( $search && stripos( $entry[$fieldKeys['name']], $search ) === false ) continue;
 164+ $sortValue = sprintf('%015d-', $entry[$fieldKeys[$sort]]);
 165+ $list[$sortValue . $entry[$fieldKeys['name']]] = $entry;
 166+ }
 167+ }
 168+
 169+ if ( $scope === 'deleted' || $scope === 'both' ) {
 170+ foreach ( $cache['deleted_list'] as $entry ) {
 171+ if ( $search && stripos( $entry[$fieldKeys['name']], $search ) === false ) continue;
 172+ $sortValue = sprintf('%015d-', $entry[$fieldKeys[$sort]]);
 173+ $list[$sortValue . $entry[$fieldKeys['name']]] = $entry;
 174+ }
 175+ }
 176+
 177+ $sortdir ? krsort( $list ) : ksort( $list );
 178+
 179+ $i = 0;
 180+ if ( count($list) ) {
 181+ $r = 1;
 182+
 183+ foreach ( $list as $name => $entry ) {
 184+ if ( $limit === $i++ ) break;
 185+ $wgOut->addHTML(
 186+ Xml::openElement( 'tr', array( 'class' => 'mw-apc-tr-' . ($r=1-$r) ) )
 187+ );
 188+
 189+ foreach ( $fields as $field ) {
 190+ $index = $fieldKeys[$field];
 191+ if ( $field === 'name' ) {
 192+ if ( !$this->userMode ) {
 193+ $pos = strrpos( $entry[$index], '/' );
 194+ if ( $pos !== false ) $value = substr( $entry[$index], $pos+1 );
 195+ } else {
 196+ $value = $entry[$index];
 197+ }
 198+ $value = $this->sortHeader( htmlspecialchars($value), array( 'display' => md5($entry[$this->fieldKey]) ) );
 199+ } elseif( $field === 'deleted' && $this->userMode && !$entry[$index] ) {
 200+ $value = $this->sortHeader(
 201+ wfMsgHtml( 'viewapc-ls-delete' ),
 202+ array( 'delete' => $entry[$this->fieldKey] )
 203+ );
 204+ } else {
 205+ $value = $this->formatValue( $index, $entry[$index] );
 206+ }
 207+
 208+ $wgOut->addHTML( Xml::tags( 'td', null, $value ) );
 209+ }
 210+
 211+ $wgOut->addHTML( '</tr>' );
 212+ }
 213+ }
 214+
 215+ if ( $i < count($list) ) {
 216+ $left = $wgLang->formatNum( count($list) - ($i+$offset) );
 217+ $wgOut->addHTML(
 218+ Xml::tags( 'tr', array( 'colspan' => count( $fields ) ),
 219+ Xml::tags( 'td', null, $this->sortHeader(
 220+ wfMsgExt( 'viewapc-ls-more', 'parseinline', $left ),
 221+ array( 'offset' => $offset+$limit ) ) ) )
 222+ );
 223+ } elseif ( !count($list) ) {
 224+ $wgOut->addHTML(
 225+ Xml::tags( 'tr', array( 'colspan' => count( $fields ) ),
 226+ Xml::tags( 'td', null, wfMsgExt( 'viewapc-ls-nodata', 'parseinline' ) ) )
 227+ );
 228+ }
 229+
 230+ $wgOut->addHTML( '</tbody></table></div>' );
 231+ }
 232+
 233+ protected function options() {
 234+ global $wgLang;
 235+
 236+ $s =
 237+ Xml::openElement( 'fieldset' ) .
 238+ Xml::element( 'legend', null, wfMsg( 'viewapc-ls-options-legend' ) ) .
 239+ Xml::openElement( 'form', array( 'action' => $this->title->getLocalURl() ) );
 240+
 241+ foreach ( $this->opts->getUnconsumedValues() as $key => $value ) {
 242+ $s .= Xml::hidden( $key, $value );
 243+ }
 244+
 245+ $options = array();
 246+ $scope = $this->opts->consumeValue( 'scope' );
 247+ $scopeOptions = array( 'active', 'deleted', 'both' );
 248+ foreach ( $scopeOptions as $name ) {
 249+ $options[] = Xml::option( wfMsg( 'viewapc-ls-scope-' . $name ), $name, $scope === $name );
 250+ }
 251+ $scopeSelector = Xml::tags( 'select', array( 'name' => 'scope' ), implode( "\n", $options ) );
 252+
 253+ $options = array();
 254+ $sort = $this->opts->consumeValue( 'sort' );
 255+ $sortOptions = array( 'hits', 'size', 'name', 'accessed', 'modified', 'created', 'deleted' );
 256+ if ( $this->userMode ) $sortOptions[] = 'timeout';
 257+ foreach ( $sortOptions as $name ) {
 258+ $options[] = Xml::option( wfMsg( 'viewapc-ls-sort-' . $name ), $name, $sort === $name );
 259+ }
 260+ $sortSelector = Xml::tags( 'select', array( 'name' => 'sort' ), implode( "\n", $options ) );
 261+
 262+ $options = array();
 263+ $sortdir = $this->opts->consumeValue( 'sortdir' );
 264+ $options[] = Xml::option( wfMsg( 'ascending_abbrev' ), 0, !$sortdir );
 265+ $options[] = Xml::option( wfMsg( 'descending_abbrev' ), 1, $sortdir );
 266+ $sortdirSelector = Xml::tags( 'select', array( 'name' => 'sortdir' ), implode( "\n", $options ) );
 267+
 268+
 269+ $options = array();
 270+ $limit = $this->opts->consumeValue( 'limit' );
 271+ $limitOptions = array( 10, 20, 50, 150, 200, 500, $limit );
 272+ sort( $limitOptions );
 273+ foreach ( $limitOptions as $name ) {
 274+ $options[] = Xml::option( $wgLang->formatNum( $name ), $name, $limit === $name );
 275+ }
 276+ $options[] = Xml::option( wfMsg( 'viewapc-ls-limit-none' ), 0, $limit === $name );
 277+ $limitSelector = Xml::tags( 'select', array( 'name' => 'limit' ), implode( "\n", $options ) );
 278+
 279+
 280+ $searchBox = Xml::input( 'searchi', 25, $this->opts->getValue( 'searchi' ) );
 281+ $submit = Xml::submitButton( wfMsg( 'viewapc-ls-submit' ) );
 282+
 283+ $s .= wfMsgHtml( 'viewapc-ls-options', $scopeSelector, $sortSelector,
 284+ $sortdirSelector, $limitSelector, $searchBox, $submit );
 285+ $s .= '</form></fieldset><br />';
 286+
 287+ return $s;
 288+ }
 289+}
\ No newline at end of file
Property changes on: trunk/extensions/APC/APCCacheMode.php
___________________________________________________________________
Added: svn:eol-style
1290 + native
Index: trunk/extensions/APC/ViewAPC.i18n.php
@@ -0,0 +1,128 @@
 2+<?php
 3+
 4+$messages = array();
 5+
 6+$messages['en'] = array(
 7+'viewapc' => 'APC information',
 8+'viewapc-desc' => 'View and manage APC cache with MediaWiki',
 9+'right-apc' => 'Use all features in Special:APC',
 10+
 11+'viewapc-apc-not-available' => 'No cache info available. APC does not appear to be running.',
 12+'viewapc-clear-confirm' => 'Do you want to clear the cache?',
 13+'viewapc-clear-user-cache' => 'Clear user cache',
 14+'viewapc-clear-code-cache' => 'Clear opcode cache',
 15+
 16+'viewapc-mode-stats' => 'View host stats',
 17+'viewapc-mode-system-cache' => 'System cache entries',
 18+'viewapc-mode-system-cache-dir' => 'Per-directory entries',
 19+'viewapc-mode-user-cache' => 'User cache entries',
 20+'viewapc-mode-version-check' => 'Check version',
 21+
 22+'viewapc-info-general' => 'General information',
 23+'viewapc-apc-version' => 'APC version',
 24+'viewapc-php-version' => 'PHP version',
 25+'viewapc-shared-memory' => 'Shared memory',
 26+'viewapc-shared-memory-details' => '{{PLURAL:$1|1 segment of $2|$1 segments $2 each}}.<br />
 27+($3 memory, $4 locking)',
 28+'viewapc-start-time' => 'Start time',
 29+'viewapc-uptime' => 'Uptime',
 30+'viewapc-upload-support' => 'File upload support',
 31+
 32+'viewapc-filecache-info' => 'File cache information',
 33+'viewapc-usercache-info' => 'User cache information',
 34+'viewapc-cached-files' => 'Cached files',
 35+'viewapc-cached-files-d' => '$1 {{PLURAL:$1|file|files}} ($2)',
 36+'viewapc-hits' => 'Hits',
 37+'viewapc-misses' => 'Misses',
 38+'viewapc-requests' => 'Request rate',
 39+'viewapc-hitrate' => 'Hit rate',
 40+'viewapc-missrate' => 'Miss rate',
 41+'viewapc-insertrate' => 'Insertion rate',
 42+'viewapc-cachefull' => 'Cache full count',
 43+'viewapc-rps' => '$1 requests per second',
 44+
 45+'viewapc-info-runtime' => 'Runtime information',
 46+
 47+'viewapc-info-memory' => 'Host status diagrams',
 48+'viewapc-memory-usage-detailed' => 'Memory Usage<br />
 49+(multiple slices indicate fragments)',
 50+'viewapc-memory-usage' => 'Memory Usage',
 51+'viewapc-cache-efficiency' => 'Hits and misses',
 52+
 53+'viewapc-memory-free' => 'Free: $1 ($2)',
 54+'viewapc-memory-used' => 'Used: $1 ($2)',
 55+'viewapc-memory-hits' => 'Hits: $1 ($2)',
 56+'viewapc-memory-miss' => 'Misses: $1 ($2)',
 57+
 58+'viewapc-memoryfragmentation' => 'Detailed memory usage and fragmentation',
 59+'viewapc-fragmentation-info' => 'Fragmentation: $1 ($2 out of $3 in $4 {{PLURAL:$4|fragment|fragments}})',
 60+'viewapc-fragmentation-none' => 'Fragmentation: no fragmentation',
 61+
 62+'viewapc-display-attribute' => 'Attribute',
 63+'viewapc-display-value' => 'Value',
 64+
 65+'viewapc-display-filename' => 'Filename',
 66+'viewapc-display-device' => 'Device',
 67+'viewapc-display-info' => 'Name',
 68+'viewapc-display-ttl' => 'Expiry time',
 69+'viewapc-display-inode' => 'Inode',
 70+'viewapc-display-type' => 'Type',
 71+'viewapc-display-type-file' => 'Cached file',
 72+'viewapc-display-type-user' => 'Cached application data',
 73+'viewapc-display-num_hits' => 'Hits',
 74+'viewapc-display-mtime' => 'Modified',
 75+'viewapc-display-creation_time' => 'Created',
 76+'viewapc-display-deletion_time' => 'Deleted',
 77+'viewapc-display-no-delete' => 'Not deleted',
 78+'viewapc-display-access_time' => 'Accessed',
 79+'viewapc-display-ref_count' => 'Reference count',
 80+'viewapc-display-mem_size' => 'Size',
 81+'viewapc-display-stored-value' => 'Stored value',
 82+
 83+'viewapc-ls-options-legend' => 'Options',
 84+'viewapc-ls-options' => 'Scope: $1 Sorting: $2$3$4 Search: $5 $6',
 85+'viewapc-ls-submit' => 'Go!',
 86+
 87+'viewapc-ls-header-name' => 'Name',
 88+'viewapc-ls-header-hits' => 'Hits',
 89+'viewapc-ls-header-size' => 'Size',
 90+'viewapc-ls-header-accessed' => 'Last accessed',
 91+'viewapc-ls-header-modified' => 'Last modified',
 92+'viewapc-ls-header-created' => 'Created',
 93+'viewapc-ls-header-deleted' => 'Deleted',
 94+'viewapc-ls-header-timeout' => 'Timeout',
 95+
 96+'viewapc-ls-delete' => '[Delete now]',
 97+
 98+'viewapc-ls-scope-active' => 'Active',
 99+'viewapc-ls-scope-deleted' => 'Deleted',
 100+'viewapc-ls-scope-both' => 'Both',
 101+
 102+
 103+'viewapc-ls-sort-hits' => 'Hits',
 104+'viewapc-ls-sort-size' => 'Size',
 105+'viewapc-ls-sort-name' => 'Name',
 106+'viewapc-ls-sort-accessed' => 'Last accessed',
 107+'viewapc-ls-sort-modified' => 'Last modified',
 108+'viewapc-ls-sort-created' => 'Created',
 109+'viewapc-ls-sort-deleted' => 'Deleted',
 110+'viewapc-ls-sort-timeout' => 'Timeout',
 111+
 112+'viewapc-ls-limit-none' => 'All',
 113+'viewapc-ls-more' => "''There is $1 more {{PLURAL:$1|entry|entries}}''",
 114+'viewapc-ls-nodata' => "''No matching data''",
 115+
 116+'viewapc-delete-ok' => 'Cache entry <nowiki>$1</nowiki> is deleted.',
 117+'viewapc-delete-failed' => 'Failed to delete cache entry <nowiki>$1</nowiki>.',
 118+
 119+'viewapc-version-info' => 'Version information',
 120+'viewapc-version-changelog' => 'Changelog',
 121+'viewapc-version-failed' => 'Unable to fetch version information.',
 122+'viewapc-version-ok' => 'You are running the latest version of APC ($1)',
 123+'viewapc-version-old' => 'You are running an older version of APC ($1).
 124+Newer version $2 is available at http://pecl.php.net/package/APC/$2',
 125+
 126+'viewapc-filecache-cleared' => "'''''File cache cleared.'''''",
 127+'viewapc-usercache-cleared' => "'''''Application cache cleared.'''''",
 128+
 129+);
Property changes on: trunk/extensions/APC/ViewAPC.i18n.php
___________________________________________________________________
Added: svn:eol-style
1130 + native
Index: trunk/extensions/APC/ViewAPC.php
@@ -0,0 +1,32 @@
 2+<?php
 3+if (!defined('MEDIAWIKI')) die();
 4+/**
 5+ * An extension to allow access to APC status with MediaWiki rights
 6+ *
 7+ * @addtogroup Extensions
 8+ *
 9+ * @author Niklas Laxström
 10+ * @copyright Copyright © 2008, Niklas Laxström
 11+ */
 12+
 13+
 14+$wgExtensionCredits['specialpage'][] = array(
 15+ 'name' => 'Apc',
 16+ 'version' => '2008-05-04',
 17+ 'author' => 'Niklas Laxström',
 18+ 'description' => '[[Special:ViewAPC|Special page]] for viewing memory cache',
 19+ 'descriptionmsg' => 'viewapc-desc',
 20+);
 21+
 22+$dir = dirname(__FILE__) . '/';
 23+$wgAutoloadClasses['SpecialAPC'] = $dir . 'SpecialAPC.php';
 24+$wgAutoloadClasses['APCImages'] = $dir . 'APCImages.php';
 25+$wgAutoloadClasses['APCUtils'] = $dir . 'APCUtils.php';
 26+
 27+$wgAutoloadClasses['APCHostMode'] = $dir . 'APCHostMode.php';
 28+$wgAutoloadClasses['APCCacheMode'] = $dir . 'APCCacheMode.php';
 29+
 30+$wgExtensionMessagesFiles['ViewAPC'] = $dir . 'ViewAPC.i18n.php';
 31+$wgSpecialPages['ViewAPC'] = 'SpecialAPC';
 32+
 33+$wgAvailableRights[] = 'apc';
Property changes on: trunk/extensions/APC/ViewAPC.php
___________________________________________________________________
Added: svn:eol-style
134 + native
Index: trunk/extensions/APC/APCUtils.php
@@ -0,0 +1,31 @@
 2+<?php
 3+
 4+class APCUtils {
 5+
 6+ public static function tableRow( $class, $first, $second = null ) {
 7+ $class = $class !== null ? array( 'class' => 'mw-apc-tr-' . $class ) : null;
 8+
 9+ return Xml::tags( 'tr', $class,
 10+ Xml::tags( 'td', array( 'class' => 'mw-apc-td-0' ), $first ) .
 11+ Xml::tags( 'td', null, $second ) );
 12+ }
 13+
 14+ public static function tableHeader( $header, $class = '' ) {
 15+ return
 16+ Xml::openElement( 'div', array( 'class' => "mw-apc-stats $class" ) ) .
 17+ Xml::element( 'h2', null, $header ) .
 18+ Xml::openElement( 'table' ) .
 19+ Xml::openElement( 'tbody' );
 20+ }
 21+
 22+ public static function tableFooter() {
 23+ return "</tbody></table></div>";
 24+ }
 25+
 26+ public static function formatReqPerS( $number ) {
 27+ global $wgLang;
 28+ return wfMsgExt( 'viewapc-rps', 'parsemag',
 29+ $wgLang->formatNum( sprintf("%.2f", $number ), true ) );
 30+ }
 31+
 32+}
\ No newline at end of file
Property changes on: trunk/extensions/APC/APCUtils.php
___________________________________________________________________
Added: svn:eol-style
133 + native
Index: trunk/extensions/APC/SpecialAPC.php
@@ -0,0 +1,269 @@
 2+<?php
 3+
 4+class SpecialAPC extends SpecialPage {
 5+
 6+ const GRAPH_SIZE = 200;
 7+
 8+ // Stored objects
 9+
 10+ protected $opts, $title;
 11+ function __construct() {
 12+ SpecialPage::SpecialPage( 'ViewAPC' );
 13+ $this->title = $this->getTitle();
 14+ }
 15+
 16+ const MODE_STATS = 0;
 17+ const MODE_SYSTEM_CACHE = 1;
 18+ const MODE_USER_CACHE = 2;
 19+ const MODE_SYSTEM_CACHE_DIR = 3;
 20+ const MODE_VERSION_CHECK = 4;
 21+
 22+ public function setup() {
 23+ global $wgRequest;
 24+
 25+ $opts = new FormOptions();
 26+ // Bind to the member variable
 27+ $this->opts = $opts;
 28+
 29+
 30+ $opts->add( 'mode', self::MODE_STATS );
 31+ $opts->add( 'image', APCImages::IMG_NONE );
 32+ $opts->add( 'clearcache', false );
 33+ $opts->add( 'limit', 20 );
 34+ $opts->add( 'offset', 0 );
 35+ $opts->add( 'display', '' );
 36+ $opts->add( 'delete', '' );
 37+ $opts->add( 'sort', 'hits' );
 38+ $opts->add( 'sortdir', 0 );
 39+ $opts->add( 'scope', 'active' );
 40+ $opts->add( 'searchi', ''); // MediaWiki captures search, ARGH!
 41+
 42+ $opts->fetchValuesFromRequest( $wgRequest );
 43+ $opts->validateIntBounds( 'limit', 0, 5000 );
 44+ $opts->validateIntBounds( 'sortdir', 0, 1 );
 45+ $this->opts->consumeValues( array( 'display', 'clearcache', 'image' ) );
 46+
 47+ }
 48+
 49+ public function execute( $parameters ) {
 50+ global $wgOut, $wgScriptPath, $wgStyleVersion, $wgUser;
 51+ wfLoadExtensionMessages( 'ViewAPC' );
 52+ $this->setHeaders();
 53+ $this->setup();
 54+
 55+
 56+ if( !function_exists('apc_cache_info')) {
 57+ $wgOut->addWikiMsg( 'viewapc-apc-not-available' );
 58+ return;
 59+ }
 60+
 61+ if ( $this->opts->getValue('image') ) {
 62+ $wgOut->disable();
 63+ header('Content-type: image/png');
 64+ echo APCImages::generateImage( $this->opts->getValue('image') );
 65+ return;
 66+ }
 67+
 68+ if ( $this->opts->getValue('mode') !== self::MODE_STATS ) {
 69+ if ( !$wgUser->isAllowed( 'apc' ) ) {
 70+ $wgOut->permissionRequired( 'apc' );
 71+ return;
 72+ }
 73+ }
 74+
 75+
 76+
 77+ // clear cache
 78+ if ( $this->opts->consumeValue( 'clearcache' ) ) {
 79+ $usermode = $this->opts->getValue( 'mode' ) === self::MODE_USER_CACHE;
 80+ $mode = $usermode ? 'user' : 'opcode';
 81+ apc_clear_cache( $mode );
 82+ if ( $usermode ) {
 83+ $wgOut->addWikiMsg( 'viewapc-filecache-cleared' );
 84+ } else {
 85+ $wgOut->addWikiMsg( 'viewapc-usercache-cleared' );
 86+ }
 87+ }
 88+
 89+ $delete = $this->opts->consumeValue( 'delete' );
 90+ if ( $delete ) {
 91+ $result = apc_delete( $delete );
 92+ if ( $result ) {
 93+ $wgOut->addWikiMsg( 'viewapc-delete-ok', $delete );
 94+ } else {
 95+ $wgOut->addWikiMsg( 'viewapc-delete-failed', $delete );
 96+ }
 97+ }
 98+
 99+
 100+ $dir = dirname( __FILE__ );
 101+ $wgOut->addLink( array( 'rel' => 'stylesheet', 'type' => 'text/css',
 102+ 'href' => "$wgScriptPath/extensions/APC/apc.css?$wgStyleVersion", )
 103+ );
 104+
 105+ $this->getLogo();
 106+ $this->mainMenu();
 107+ $this->doPage();
 108+ }
 109+
 110+ protected function selfLink( $parms, $name, $attribs = array() ) {
 111+ $title = $this->getTitle();
 112+ $target = $title->getLocalURL( $parms );
 113+ return Xml::element( 'a', array( 'href' => $target ) + $attribs, $name );
 114+ }
 115+
 116+ protected function getSelfURL( $overrides ) {
 117+ $changed = $this->opts->getUnconsumedValues();
 118+ $target = $this->title->getLocalURL( wfArrayToCGI( $overrides, $changed ) );
 119+ return $target;
 120+ }
 121+
 122+ protected function selfLink2( $title, $overrides ) {
 123+ $changed = $this->opts->getUnconsumedValues();
 124+ $target = $this->title->getLocalURL( wfArrayToCGI( $overrides, $changed ) );
 125+ return Xml::tags( 'a', array( 'href' => $target ), $title );
 126+ }
 127+
 128+ protected function menuItem( $mode, $text ) {
 129+ $params = array( 'mode' => $mode );
 130+ return Xml::tags( 'li', null, $this->selfLink2( $text, $params ) );
 131+ }
 132+
 133+ const APCURL = 'http://pecl.php.net/package/APC';
 134+ protected function getLogo() {
 135+ global $wgOut;
 136+
 137+ $logo =
 138+ Xml::wrapClass( Xml::element( 'a', array( 'href' => self::APCURL) , 'APC' ), 'mw-apc-logo' ) .
 139+ Xml::wrapClass( 'Opcode Cache', 'mw-apc-nameinfo' );
 140+
 141+ $wgOut->addHTML(
 142+ Xml::openElement( 'div', array( 'class' => 'head' ) ) .
 143+ Xml::tags( 'h1', array( 'class' => 'apc-header-1' ),
 144+ Xml::wrapClass( $logo, 'mw-apc-logo-outer', 'span' )
 145+ ) .
 146+
 147+ Xml::wrapClass( '', 'mw-apc-separator', 'hr' ) .
 148+ Xml::closeElement( 'div' )
 149+ );
 150+
 151+ }
 152+
 153+ protected function mainMenu() {
 154+
 155+
 156+ $clearParams = array(
 157+ 'clearcache' => 1,
 158+ );
 159+ $clearText = $this->opts->getValue( 'mode' ) === self::MODE_USER_CACHE ?
 160+ wfMsgExt( 'viewapc-clear-user-cache', 'escape' ) :
 161+ wfMsgExt( 'viewapc-clear-code-cache', 'escape' );
 162+
 163+ global $wgOut;
 164+ $wgOut->addHTML(
 165+ Xml::openElement( 'ol', array( 'class' => 'mw-apc-menu' ) ) .
 166+ $this->menuItem( self::MODE_STATS, wfMsgExt( 'viewapc-mode-stats', 'escape' ) ) .
 167+ $this->menuItem( self::MODE_SYSTEM_CACHE, wfMsgExt( 'viewapc-mode-system-cache', 'escape' ) ) .
 168+ //$this->menuItem( self::MODE_SYSTEM_CACHE_DIR, wfMsgExt( 'viewapc-mode-system-cache-dir', 'escape' )) .
 169+ $this->menuItem( self::MODE_USER_CACHE, wfMsgExt( 'viewapc-mode-user-cache', 'escape' )).
 170+ $this->menuItem( self::MODE_VERSION_CHECK, wfMsgExt( 'viewapc-mode-version-check', 'escape' )) .
 171+ Xml::tags( 'li', null,
 172+ $this->selfLink2( $clearText, $clearParams ) ) .
 173+ Xml::closeElement( 'ol' )
 174+ );
 175+ }
 176+
 177+
 178+
 179+ protected function doObHostStats() {
 180+ global $wgOut, $wgLang;
 181+
 182+ $mem = apc_sma_info();
 183+
 184+ $clear = Xml::element( 'br', array( 'style' => 'clear: both;' ) );
 185+
 186+ $usermode = $this->opts->getValue( 'mode' ) === self::MODE_USER_CACHE;
 187+ $cache = apc_cache_info( $usermode ? 'user' : 'opcode' );
 188+
 189+
 190+ $wgOut->addHTML(
 191+ APCHostMode::doGeneralInfoTable( $cache, $mem ) .
 192+ APCHostMode::doMemoryInfoTable( $cache, $mem, $this->title ) . $clear .
 193+ APCHostMode::doCacheTable( $cache ) .
 194+ APCHostMode::doCacheTable( apc_cache_info('user', 1), true ) . $clear .
 195+ APCHostMode::doRuntimeInfoTable( $mem ) .
 196+ APCHostMode::doFragmentationTable( $mem, $this->title ) . $clear
 197+ );
 198+
 199+ }
 200+
 201+
 202+ protected function doPage() {
 203+ global $wgOut;
 204+ $wgOut->addHTML(
 205+ Xml::openElement( 'div', array( 'class' => 'mw-apc-content' ) )
 206+ );
 207+
 208+ switch ( $this->opts->getValue('mode') ) {
 209+ case self::MODE_STATS:
 210+ $this->doObHostStats();
 211+ break;
 212+ case self::MODE_SYSTEM_CACHE:
 213+ case self::MODE_USER_CACHE:
 214+ $mode = new APCCacheMode( $this->opts, $this->title );
 215+ $mode->cacheView();
 216+ break;
 217+ case self::MODE_VERSION_CHECK:
 218+ $this->versionCheck();
 219+ break;
 220+ }
 221+
 222+ $wgOut->addHTML(
 223+ Xml::closeElement( 'div' )
 224+ );
 225+ }
 226+
 227+ protected function versionCheck() {
 228+ global $wgOut;
 229+ $wgOut->addHTML(
 230+ Xml::element( 'h2', null, wfMsg( 'viewapc-version-info' ) )
 231+ );
 232+
 233+ $rss = @file_get_contents('http://pecl.php.net/feeds/pkg_apc.rss');
 234+ if (!$rss) {
 235+ $wgOut->addWikiMsg( 'viewapc-version-failed' );
 236+ } else {
 237+ $apcversion = phpversion('apc');
 238+
 239+ preg_match('!<title>APC ([0-9.]+)</title>!', $rss, $match);
 240+ if (version_compare($apcversion, $match[1], '>=')) {
 241+ $wgOut->addWikiMsg( 'viewapc-version-ok', $apcversion );
 242+ $i = 3;
 243+ } else {
 244+ $wgOut->addWikiMsg( 'viewapc-version-old', $apcversion, $match[1] );
 245+ $i = -1;
 246+ }
 247+
 248+ $wgOut->addHTML(
 249+ Xml::element( 'h3', null, wfMsg( 'viewapc-version-changelog' ) )
 250+ );
 251+
 252+
 253+ preg_match_all('!<(title|description)>([^<]+)</\\1>!', $rss, $match);
 254+ next($match[2]); next($match[2]);
 255+
 256+ while (list(,$v) = each($match[2])) {
 257+ list(,$ver) = explode(' ', $v, 2);
 258+ if ($i < 0 && version_compare($apcversion, $ver, '>=')) {
 259+ break;
 260+ } else if (!$i--) {
 261+ break;
 262+ }
 263+ $data = current($match[2]);
 264+ $wgOut->addWikiText( "''[http://pecl.php.net/package/APC/$ver $v]''<br /><pre>$data</pre>" );
 265+ next($match[2]);
 266+ }
 267+ }
 268+ }
 269+
 270+}
\ No newline at end of file
Property changes on: trunk/extensions/APC/SpecialAPC.php
___________________________________________________________________
Added: svn:eol-style
1271 + native
Index: trunk/extensions/APC/apc.css
@@ -0,0 +1,90 @@
 2+.mw-apc-content {
 3+ clear: both;
 4+ font-size: x-small;
 5+}
 6+
 7+.apc-header-1 { background:rgb(153,153,204); margin:0; padding:0.5em 1em 0.5em 1em; }
 8+.apc-header-1 a:hover { text-decoration:none; color:rgb(90,90,90); }
 9+
 10+.mw-apc-logo {
 11+ background:rgb(119,123,180);
 12+ border-right: solid black 1px;
 13+ border-bottom: solid black 1px;
 14+ font-style:italic;
 15+ padding-left:1.2em;
 16+ padding-right:1.2em;
 17+ text-align:right;
 18+}
 19+
 20+.mw-apc-logo a {
 21+ color:black;
 22+}
 23+
 24+.mw-apc-nameinfo {
 25+ color:white;
 26+ display:inline;
 27+ font-size:0.4em;
 28+ margin-left: 3em;
 29+}
 30+
 31+.mw-apc-separator {
 32+ background:white;
 33+ border-bottom:solid rgb(102,102,153) 1px;
 34+ border-style:none;
 35+ border-top:solid rgb(102,102,153) 10px;
 36+ height:12px;
 37+ margin:0;
 38+ margin-top:1px;
 39+ padding:0;
 40+}
 41+
 42+.mw-apc-stats {
 43+ background:rgb(238,238,238);
 44+ border:solid rgb(238,238,238) 1px;
 45+ margin-bottom:1em;
 46+ }
 47+.mw-apc-content h2 {
 48+ background:rgb(204,204,204);
 49+ color:black;
 50+ font-size:1em;
 51+ margin:0;
 52+ padding:0.1em 1em 0.1em 1em;
 53+ }
 54+.mw-apc-content table {
 55+ border:solid rgb(204,204,204) 1px;
 56+ border-spacing:0;
 57+ width:100%;
 58+ border:solid rgb(204,204,204) 1px;
 59+ color:black;
 60+ }
 61+.mw-apc-content table th {
 62+ background:rgb(204,204,204);
 63+ color:white;
 64+ margin:0;
 65+ padding:0.1em 1em 0.1em 1em;
 66+ }
 67+.mw-apc-content th a.sortable { color:black; }
 68+.mw-apc-content td { padding:0.3em 1em 0.3em 1em; }
 69+.mw-apc-tr-0 { background:rgb(238,238,238); }
 70+.mw-apc-tr-1 { background:rgb(221,221,221); }
 71+.mw-apc-td-0 { border-right:solid rgb(102,102,153) 1px; white-space:nowrap; }
 72+.mw-apc-td-n { border-right:solid rgb(102,102,153) 1px; }
 73+
 74+.mw-apc-content td { padding:0.3em 1em 0.3em 1em; } td h3 {
 75+ color:black;
 76+ font-size:1.1em;
 77+ margin-left:-0.3em;
 78+ }
 79+
 80+
 81+.mw-apc-stats { margin:1em; width:45%; float: left; display: table;}
 82+
 83+span.box {
 84+ border: black solid 1px;
 85+ border-right:solid black 2px;
 86+ border-bottom:solid black 2px;
 87+ padding:0 0.5em 0 0.5em;
 88+ margin-right:1em;
 89+}
 90+span.green { background:#60F060; padding:0 0.5em 0 0.5em}
 91+span.red { background:#D06030; padding:0 0.5em 0 0.5em }
\ No newline at end of file
Property changes on: trunk/extensions/APC/apc.css
___________________________________________________________________
Added: svn:eol-style
192 + native
Index: trunk/extensions/APC/APCHostMode.php
@@ -0,0 +1,202 @@
 2+<?php
 3+
 4+class APCHostMode {
 5+
 6+ public static function doGeneralInfoTable( $c, $mem ) {
 7+ global $wgLang;
 8+ $r = 1;
 9+ return
 10+ APCUtils::tableHeader( wfMsg( 'viewapc-info-general' ) ) .
 11+ APCUtils::tableRow( $r=1-$r, wfMsgHtml( 'viewapc-apc-version' ), phpversion('apc') ) .
 12+ APCUtils::tableRow( $r=1-$r, wfMsgHtml( 'viewapc-php-version' ), phpversion() ) .
 13+
 14+ APCUtils::tableRow( $r=1-$r, wfMsgHtml( 'viewapc-shared-memory' ),
 15+ wfMsgExt( 'viewapc-shared-memory-details', 'parsemag',
 16+ $wgLang->formatNum( $mem['num_seg'] ),
 17+ $wgLang->formatSize( $mem['seg_size'] ),
 18+ $c['memory_type'], $c['locking_type'] ) ) .
 19+
 20+ APCUtils::tableRow( $r=1-$r, wfMsgHtml( 'viewapc-start-time' ),
 21+ $wgLang->timeanddate( $c['start_time'] ) ) .
 22+
 23+ APCUtils::tableRow( $r=1-$r, wfMsgHtml( 'viewapc-uptime' ),
 24+ $wgLang->formatTimePeriod( time() - $c['start_time'] ) ) .
 25+
 26+ APCUtils::tableRow( $r=1-$r, wfMsgHtml( 'viewapc-upload-support' ), $c['file_upload_progress'] ) .
 27+ APCUtils::tableFooter();
 28+ }
 29+
 30+ public static function doCacheTable( $c, $user = false ) {
 31+ global $wgLang;
 32+
 33+ // Calculate rates
 34+ $numHits = $wgLang->formatNum( $c['num_hits'] );
 35+ $numMiss = $wgLang->formatNum( $c['num_misses'] );
 36+ $numReqs = $c['num_hits']+$c['num_misses'];
 37+ $cPeriod = time()-$c['start_time'];
 38+ $rateReqs = APCUtils::formatReqPerS( $numReqs / $cPeriod );
 39+ $rateHits = APCUtils::formatReqPerS( $c['num_hits'] / $cPeriod );
 40+ $rateMiss = APCUtils::formatReqPerS( $c['num_misses'] / $cPeriod );
 41+ $rateInsert= APCUtils::formatReqPerS( $c['num_inserts'] / $cPeriod );
 42+
 43+ $cachedFiles = wfMsgExt( 'viewapc-cached-files-d', 'parsemag',
 44+ $wgLang->formatNum( $c['num_entries'] ),
 45+ $wgLang->formatSize( $c['mem_size'] ) );
 46+ $cacheFullCount = $wgLang->formatNum( $c['expunges'] );
 47+
 48+ $contentType = !$user ? wfMsg( 'viewapc-filecache-info' ) : wfMsg( 'viewapc-usercache-info' );
 49+
 50+ return
 51+ APCUtils::tableHeader( $contentType ) .
 52+ APCUtils::tableRow( $r=0, wfMsgHtml( 'viewapc-cached-files' ), $cachedFiles ) .
 53+ APCUtils::tableRow( $r=1-$r, wfMsgHtml( 'viewapc-hits' ), $numHits ) .
 54+ APCUtils::tableRow( $r=1-$r, wfMsgHtml( 'viewapc-misses' ), $numMiss ) .
 55+ APCUtils::tableRow( $r=1-$r, wfMsgHtml( 'viewapc-requests' ), $rateReqs ) .
 56+ APCUtils::tableRow( $r=1-$r, wfMsgHtml( 'viewapc-hitrate' ), $rateHits ) .
 57+ APCUtils::tableRow( $r=1-$r, wfMsgHtml( 'viewapc-missrate' ), $rateMiss ) .
 58+ APCUtils::tableRow( $r=1-$r, wfMsgHtml( 'viewapc-insertrate' ), $rateInsert ) .
 59+ APCUtils::tableRow( $r=1-$r, wfMsgHtml( 'viewapc-cachefull' ), $cacheFullCount ) .
 60+ APCUtils::tableFooter();
 61+ }
 62+
 63+ public static function doRuntimeInfoTable( $mem ) {
 64+ $s = APCUtils::tableHeader( wfMsg( 'viewapc-info-runtime' ) );
 65+
 66+ $r = 1;
 67+ foreach (ini_get_all('apc') as $k => $v) {
 68+ $s .= APCUtils::tableRow( $r=1-$r,
 69+ htmlspecialchars( $k ),
 70+ str_replace(',',',<br />', htmlspecialchars($v['local_value']) ) );
 71+ }
 72+
 73+ $s .= APCUtils::tableFooter();
 74+ return $s;
 75+ }
 76+
 77+ public static function doMemoryInfoTable( $c, $mem, $title ) {
 78+ global $wgLang;
 79+
 80+ $s = APCUtils::tableHeader( wfMsg( 'viewapc-info-memory' ), 'mw-apc-img-table' );
 81+
 82+ if ( $mem['num_seg'] > 1 || $mem['num_seg'] == 1 && count($mem['block_lists'][0]) > 1 ) {
 83+ $memHeader = wfMsgExt( 'viewapc-memory-usage-detailed', 'parseinline' );
 84+ } else {
 85+ $memHeader = wfMsgExt( 'viewapc-memory-usage', 'parseinline' );
 86+ }
 87+ $hitHeader = wfMsgExt( 'viewapc-cache-efficiency', 'parseinline' );
 88+
 89+ $s .= APCUtils::tableRow( null, $memHeader, $hitHeader );
 90+
 91+
 92+ if ( APCImages::graphics_avail() ) {
 93+ $attribs = array(
 94+ 'alt' => '',
 95+ 'width' => APCImages::GRAPH_SIZE+10,
 96+ 'height' => APCImages::GRAPH_SIZE+10,
 97+ );
 98+
 99+ $param1 = wfArrayToCGI( array( 'image' => APCImages::IMG_MEM_USAGE ) );
 100+ $param2 = wfArrayToCGI( array( 'image' => APCImages::IMG_HITS ) );
 101+
 102+ $attribs1 = array( 'src' => $title->getLocalURL( $param1 ) ) + $attribs;
 103+ $attribs2 = array( 'src' => $title->getLocalURL( $param2 ) ) + $attribs;
 104+
 105+ $s .= APCUtils::tableRow( null, Xml::element( 'img', $attribs1 ), Xml::element( 'img', $attribs2 ) );
 106+ }
 107+
 108+ $size = $mem['num_seg'] * $mem['seg_size'];
 109+ $free = $mem['avail_mem'];
 110+ $used = $size - $free;
 111+
 112+ $freeMem = wfMsgExt( 'viewapc-memory-free', 'parseinline',
 113+ $wgLang->formatSize( $free ),
 114+ $wgLang->formatNum( sprintf('%.1f%%', $free*100/$size) ) );
 115+
 116+ $usedMem = wfMsgExt( 'viewapc-memory-used', 'parseinline',
 117+ $wgLang->formatSize( $used ),
 118+ $wgLang->formatNum( sprintf('%.1f%%', $used*100/$size) ) );
 119+
 120+ $hits = $c['num_hits'];
 121+ $miss = $c['num_misses'];
 122+ $reqs = $hits + $miss;
 123+
 124+ $greenbox = Xml::element( 'span', array( 'class' => 'green box' ), ' ' );
 125+ $redbox = Xml::element( 'span', array( 'class' => 'red box' ), ' ' );
 126+
 127+ $memHits = wfMsgExt( 'viewapc-memory-hits', 'parseinline',
 128+ $wgLang->formatNum( $hits ),
 129+ $wgLang->formatNum( @sprintf('%.1f%%', $hits*100/$reqs) ) );
 130+
 131+ $memMiss = wfMsgExt( 'viewapc-memory-miss', 'parseinline',
 132+ $wgLang->formatNum( $miss ),
 133+ $wgLang->formatNum( @sprintf('%.1f%%', $miss*100/$reqs) ) );
 134+
 135+ $s .= APCUtils::tableRow( null, $greenbox . $freeMem, $greenbox . $memHits );
 136+ $s .= APCUtils::tableRow( null, $redbox . $usedMem, $redbox . $memMiss );
 137+ $s .= APCUtils::tableFooter();
 138+
 139+ return $s;
 140+ }
 141+
 142+ public static function doFragmentationTable( $mem, $title ) {
 143+ global $wgLang;
 144+ $s = APCUtils::tableHeader( wfMsg( 'viewapc-memoryfragmentation' ), 'mw-apc-img-table' );
 145+ $s .= Xml::openElement( 'tr' ) . Xml::openElement( 'td' );
 146+
 147+ // Fragementation: (freeseg - 1) / total_seg
 148+ $nseg = $freeseg = $fragsize = $freetotal = 0;
 149+ for( $i = 0; $i < $mem['num_seg']; $i++ ) {
 150+ $ptr = 0;
 151+ foreach( $mem['block_lists'][$i] as $block ) {
 152+ if ( $block['offset'] != $ptr ) {
 153+ ++$nseg;
 154+ }
 155+ $ptr = $block['offset'] + $block['size'];
 156+ /* Only consider blocks <5M for the fragmentation % */
 157+ if( $block['size'] < (5*1024*1024) ) $fragsize += $block['size'];
 158+ $freetotal += $block['size'];
 159+ }
 160+ $freeseg += count($mem['block_lists'][$i]);
 161+ }
 162+
 163+
 164+ if (APCImages::graphics_avail()) {
 165+ $attribs = array(
 166+ 'alt' => '',
 167+ 'width' => 2*APCImages::GRAPH_SIZE+150,
 168+ 'height' => APCImages::GRAPH_SIZE+10,
 169+ 'src' => $title->getLocalURL( 'image=' . APCImages::IMG_FRAGMENTATION)
 170+ );
 171+ $s .= Xml::element( 'img', $attribs );
 172+ }
 173+
 174+ if ($freeseg > 1) {
 175+ $fragPercent = sprintf( '%.2f%%', ($fragsize/$freetotal)*100 );
 176+ $s .= wfMsgExt( 'viewapc-fragmentation-info', 'parse',
 177+ $wgLang->formatNum( $fragPercent, true),
 178+ $wgLang->formatSize( $fragsize ),
 179+ $wgLang->formatSize( $freetotal ),
 180+ $wgLang->formatNum( $freeseg )
 181+ );
 182+ } else {
 183+ $s .= wfMsgExt( 'viewapc-fragmentation-none', 'parse' );
 184+ }
 185+
 186+ $s .= Xml::closeElement( 'td' ) . Xml::closeElement( 'tr' );
 187+
 188+ if(isset($mem['adist'])) {
 189+ foreach($mem['adist'] as $i=>$v) {
 190+ $cur = pow(2,$i); $nxt = pow(2,$i+1)-1;
 191+ if($i==0) $range = "1";
 192+ else $range = "$cur - $nxt";
 193+ $s .= Xml::tags( 'tr', null,
 194+ Xml::tags( 'th', array( 'align' => 'right' ), $range ) .
 195+ Xml::tags( 'td', array( 'align' => 'right' ), $v )
 196+ );
 197+ }
 198+ }
 199+
 200+ $s .= APCUtils::tableFooter();
 201+ return $s;
 202+ }
 203+}
\ No newline at end of file
Property changes on: trunk/extensions/APC/APCHostMode.php
___________________________________________________________________
Added: svn:eol-style
1204 + native

Status & tagging log