Permalink
Fetching contributors…
Cannot retrieve contributors at this time
207 lines (177 sloc) 6.94 KB
<?php
require 'Reader.php';
require 'Preprocessor.php';
/**
* Class handling access to data-files(original and preprocessed) for webgrind.
* @author Jacob Oettinger
* @author Joakim Nygård
*/
class Webgrind_FileHandler
{
private static $singleton = null;
/**
* @return Singleton instance of the filehandler
*/
public static function getInstance() {
if (self::$singleton==null)
self::$singleton = new self();
return self::$singleton;
}
private function __construct() {
// Get list of files matching the defined format
$files = $this->getFiles(Webgrind_Config::xdebugOutputFormat(), Webgrind_Config::xdebugOutputDir());
// Get list of preprocessed files
$prepFiles = $this->getPrepFiles('/\\'.Webgrind_Config::$preprocessedSuffix.'$/', Webgrind_Config::storageDir());
// Loop over the preprocessed files.
foreach ($prepFiles as $fileName=>$prepFile) {
$fileName = str_replace(Webgrind_Config::$preprocessedSuffix,'',$fileName);
// If it is older than its corrosponding original: delete it.
// If it's original does not exist: delete it
if (!isset($files[$fileName]) || $files[$fileName]['mtime']>$prepFile['mtime'])
unlink($prepFile['absoluteFilename']);
else
$files[$fileName]['preprocessed'] = true;
}
// Sort by mtime
uasort($files,array($this,'mtimeCmp'));
$this->files = $files;
}
/**
* Get the value of the cmd header in $file
*
* @return void string
*/
private function getInvokeUrl($file) {
if (preg_match('/\.webgrind$/', $file))
return 'Webgrind internal';
// Grab name of invoked file.
$fp = fopen($file, 'r');
$invokeUrl = '';
while ((($line = fgets($fp)) !== FALSE) && !strlen($invokeUrl)) {
if (preg_match('/^cmd: (.*)$/', $line, $parts)) {
$invokeUrl = isset($parts[1]) ? $parts[1] : '';
}
}
fclose($fp);
if (!strlen($invokeUrl))
$invokeUrl = 'Unknown!';
return $invokeUrl;
}
/**
* List of files in $dir whose filename has the format $format
*
* @return array Files
*/
private function getFiles($format, $dir) {
$list = preg_grep($format,scandir($dir));
$files = array();
$scriptFilename = $_SERVER['SCRIPT_FILENAME'];
# Moved this out of loop to run faster
if (function_exists('xdebug_get_profiler_filename'))
$selfFile = realpath(xdebug_get_profiler_filename());
else
$selfFile = '';
foreach ($list as $file) {
$absoluteFilename = $dir.$file;
// Exclude webgrind preprocessed files
if (false !== strstr($absoluteFilename, Webgrind_Config::$preprocessedSuffix))
continue;
// Make sure that script never parses the profile currently being generated. (infinite loop)
if ($selfFile == realpath($absoluteFilename))
continue;
$invokeUrl = rtrim($this->getInvokeUrl($absoluteFilename));
if (Webgrind_Config::$hideWebgrindProfiles && $invokeUrl == dirname(dirname(__FILE__)).DIRECTORY_SEPARATOR.'index.php')
continue;
$files[$file] = array('absoluteFilename' => $absoluteFilename,
'mtime' => filemtime($absoluteFilename),
'preprocessed' => false,
'invokeUrl' => $invokeUrl,
'filesize' => $this->bytestostring(filesize($absoluteFilename))
);
}
return $files;
}
/**
* List of files in $dir whose filename has the format $format
*
* @return array Files
*/
private function getPrepFiles($format, $dir) {
$list = preg_grep($format,scandir($dir));
$files = array();
$scriptFilename = $_SERVER['SCRIPT_FILENAME'];
foreach ($list as $file) {
$absoluteFilename = $dir.$file;
// Make sure that script does not include the profile currently being generated. (infinite loop)
if (function_exists('xdebug_get_profiler_filename') && realpath(xdebug_get_profiler_filename())==realpath($absoluteFilename))
continue;
$files[$file] = array('absoluteFilename' => $absoluteFilename,
'mtime' => filemtime($absoluteFilename),
'preprocessed' => true,
'filesize' => $this->bytestostring(filesize($absoluteFilename))
);
}
return $files;
}
/**
* Get list of available trace files. Optionally including traces of the webgrind script it self
*
* @return array Files
*/
public function getTraceList() {
$result = array();
foreach ($this->files as $fileName=>$file) {
$result[] = array('filename' => $fileName,
'invokeUrl' => str_replace($_SERVER['DOCUMENT_ROOT'].'/', '', $file['invokeUrl']),
'filesize' => $file['filesize'],
'mtime' => date(Webgrind_Config::$dateFormat, $file['mtime'])
);
}
return $result;
}
/**
* Get a trace reader for the specific file.
*
* If the file has not been preprocessed yet this will be done first.
*
* @param string File to read
* @param Cost format for the reader
* @return Webgrind_Reader Reader for $file
*/
public function getTraceReader($file, $costFormat) {
$prepFile = Webgrind_Config::storageDir().$file.Webgrind_Config::$preprocessedSuffix;
try {
$r = new Webgrind_Reader($prepFile, $costFormat);
} catch (Exception $e) {
// Preprocessed file does not exist or other error
Webgrind_Preprocessor::parse(Webgrind_Config::xdebugOutputDir().$file, $prepFile);
$r = new Webgrind_Reader($prepFile, $costFormat);
}
return $r;
}
/**
* Comparison function for sorting
*
* @return boolean
*/
private function mtimeCmp($a, $b) {
if ($a['mtime'] == $b['mtime'])
return 0;
return ($a['mtime'] > $b['mtime']) ? -1 : 1;
}
/**
* Present a size (in bytes) as a human-readable value
*
* @param int $size size (in bytes)
* @param int $precision number of digits after the decimal point
* @return string
*/
private function bytestostring($size, $precision = 0) {
$sizes = array('YB', 'ZB', 'EB', 'PB', 'TB', 'GB', 'MB', 'KB', 'B');
$total = count($sizes);
while ($total-- && $size > 1024) {
$size /= 1024;
}
return round($size, $precision).$sizes[$total];
}
}