Location: PHPKode > projects > Weathermap5rrd > weathermap5rrd-1.3.11/lib/rrd.php
<?php
/*
 * weathermap5rrd - configfile.php
 * Copyright (C) 2008 Zdenek Styblik
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 * Authors:
 * Zdenek Styblik ~ 2007-2008
 * Alexandre Fontelle ~ 2005-2006
 *
 * This script is a modified version of rrd.php 
 * of Cacti project (http://www.cacti.net)
 *
 */
class rrdtools
{
	function __construct()
	{
		if (!defined('RRD_NL'))
			define('RRD_NL', "\\\n");
		if (!defined('RRD_MAX_FETCH_CACHE_SIZE'))
			define('RRD_MAX_FETCH_CACHE_SIZE', 5);
		if (!defined('RRD_PATH'))
			define('RRD_PATH', "/usr/bin/rrdtool");
	}
	# @return: string;
	public function escape_command($command)
 	{
		return preg_replace('/(\\\$|`)/', "", $command);
	}
	# @return: int;
	public function rrd_get_fd(&$rrd_struc, $fd_type)
 	{
		if (sizeof($rrd_struc) == 0)
	 	{
			return 0;
		}
		else
		{
			return $rrd_struc["fd"];
		} /* not sizeof */
	}
	# @return: string;
	public function rrdtool_last($filename)
 	{
		$cmd_line="last {$filename}";
		$retval = $this->rrdtool_execute($cmd_line, false, 'RRDTOOL_OUTPUT_STDOUT');
		return $retval;
	}
	# @return: array;
	public function rrdtool_get_last_value($rrdfile, $pos = 0, $rrdstep = 600)
 	{
		$start = $this->rrdtool_last($rrdfile);
		$unixtime = $start;
		if ($this->rrdtool_getversion() == "1.2")
	 	{ 
			$end = $start;
			$start = $start - $rrdstep; 
		}
		else 
		{
			$end=$start;
		} /* not $this->rrdtool_getversion() */
		$result = $this->rrdtool_function_fetch($rrdfile, $start, $end);
		# Get values from array read before and convert values in bytes
		return $result["values"][$pos-1][0];
	}
	# @return: string;
	public function rrdtool_execute($command_line, $log_to_stdout,
	 	$output_flag = 'RRDTOOL_OUTPUT_STDOUT', $rrd_struc = array(), $logopt = "WEBLOG")
 	{
		/* WIN32: before sending this command off to rrdtool, get rid
		 * of all of the '\' characters. Unix does not care; win32 does.
		 * Also make sure to replace all of the fancy \'s at the end of the line,
		 * but make sure not to get rid of the "\n"'s that are supposed to be
		 * in there (text format)
		 */
		$command_line = str_replace("\\\n", " ", $command_line);
		/* output information to the log file if appropriate 
		 * if (read_config_option("log_verbosity") >= POLLER_VERBOSITY_DEBUG) {
		 * 	cacti_log("CACTI2RRD: " . read_config_option("path_rrdtool") . " $command_line",
		 * 	$log_to_stdout, $logopt);
		 * } 
		 */
		/* if we want to see the error output from rrdtool; make sure to specify this */
		if (($output_flag == 'RRDTOOL_OUTPUT_STDERR') && (sizeof($rrd_struc) == 0))
	 	{
			$command_line .= " 2>&1";
		}
		/* use popen to eliminate the zombie issue */
		/* an empty $rrd_struc array means no fp is available */
		# echo "rrdtool=$this->rrdtool<br>";
		if (sizeof($rrd_struc) == 0)
		{
			$rrdtool = RRD_PATH;
			$fp = popen("{$rrdtool}". $this->escape_command(" {$command_line}"), "r");
		}
		else
	 	{
			fwrite($this->rrd_get_fd($rrd_struc, 'RRDTOOL_PIPE_CHILD_READ'),
			 	$this->escape_command(" {$command_line}") . "\r\n");
			fflush($this->rrd_get_fd($rrd_struc, 'RRDTOOL_PIPE_CHILD_READ'));
		} /* not sizeof */
		switch ($output_flag)
	 	{
			case 'RRDTOOL_OUTPUT_NULL':
				return; break;
			case 'RRDTOOL_OUTPUT_STDERR':
				if (isset($fp))
			 	{
					$output = fgets($fp, 1000000);
					if (substr($output, 1, 3) == "PNG")
				 	{
						return "OK";
					}
					if (substr($output, 0, 5) == "GIF87")
				 	{
						return "OK";
					}
					print $output;
				} /* isset($fp) */
				break;
			case 'RRDTOOL_OUTPUT_GRAPH_DATA':
				if (isset($fp))
			 	{
					return fpassthru($fp);
				}
				break;
			default:
				if (isset($fp))
			 	{
					$line = "";
					while (!feof($fp)) {
						$line .= fgets($fp, 4096);
					}
					return $line;
				}
				break;
		} /* switch */
	}
	# desc: rrdtool_function_fetch - given a data source, return all of its data in an array
  # $local_data_id: the data source to fetch data for;
  # $start_time: the start time to use for the data calculation. this value can
  # 						either be absolute (unix timestamp) or relative (to now)
  # $end_time: the end time to use for the data calculation. this value can
  #							either be absolute (unix timestamp) or relative (to now)
  # $resolution: the accuracy of the data measured in seconds
  # @return: array; an array containing all data in this data source broken down
	#							by each data source item.
	#					 NULL when failed;
	public function rrdtool_function_fetch($local_data_id, $start_time, $end_time, $resolution = 0)
 	{
		if (empty($local_data_id) || !file_exists($local_data_id) || !is_readable($local_data_id))
		{
			$retval = NULL;
		}
		else
	 	{
			$regexps = array();
			$fetch_array = array();
			#$data_source_path = get_data_source_path($local_data_id, true);
			$data_source_path = $local_data_id;
			/* build and run the rrdtool fetch command with all of our data */
			$cmd_line = "fetch $data_source_path AVERAGE -s $start_time -e $end_time";
			if ($resolution > 0)
		 	{
				$cmd_line .= " -r $resolution";
			}
			$output = $this->rrdtool_execute($cmd_line, false, 'RRDTOOL_OUTPUT_STDOUT');
			/* grab the first line of the output which contains a list of data sources
			 * in this .rrd file
			 */
			$line_one = substr($output, 0, strpos($output, "\n"));
			/* loop through each data source in this .rrd file ... */
			if (preg_match_all("/\s+/", $line_one, $data_source_names))
		 	{
				/* version 1.0.49 changed the output slightly */
				if (preg_match("/^timestamp/", $line_one))
			 	{
					array_shift($data_source_names[0]);
				}
				$fetch_array["data_source_names"] = $data_source_names[0];
				/* build a unique regexp to match each data source individually when
				 * passed to preg_match_all()
				 */
				for ($i = 0; $i < count($fetch_array["data_source_names"]); $i++)
			 	{
					$regexps[$i] = '/[0-9]+:\s+';
					for ($j = 0; $j < count($fetch_array["data_source_names"]); $j++)
				 	{
						/* it seems that at least some versions of the Windows RRDTool binary pads
						 * the exponent to 3 digits, rather than 2 on every Unix version that I have
						 * ever seen
						 */
						if ($j == $i)
					 	{
							$regexps[$i].= '([\-]?[0-9]{1}\.[0-9]+)e([\+-][0-9]{2,3})';
						}
						else
					 	{
							$regexps[$i].= '[\-]?[0-9]{1}\.[0-9]+e[\+-][0-9]{2,3}';
						} /* not $j == $i */
						if ($j < count($fetch_array["data_source_names"]))
					 	{
							$regexps[$i].= '\s+';
						}
					} /* for j = 0 */
					$regexps[$i].= '/';
				} /* for i = 0 */
			} /* preg_match */
			/* loop through each regexp determined above (or each data source) */
			for ($i = 0; $i < count($regexps); $i++)
		 	{
				$fetch_array["values"][$i] = array();
				/* match the regexp against the rrdtool fetch output to get a mantisa and
				 * exponent for each line
				 */
				if (preg_match_all($regexps[$i], $output, $matches))
			 	{
					for ($j = 0; $j < count($matches[1]); $j++)
				 	{
						$line = ($matches[1][$j] * (pow(10,(float)$matches[2][$j])));
						array_push($fetch_array["values"][$i], ($line * 1));
					} /* for $j = 0 */
				} /* preg_match */
			} /* for $i = 0 */
			#	echo LIST_CONTENTS($fetch_array);
			$retval = $fetch_array;
		} /* (empty($local_file... */
		return $retval;
	}
	# @return: array/NULL;
	public function get_rra_name($rrdfile, $rrapos)
 	{
		if (empty($rrdfile) || !file_exists($rrdfile) || !is_readable($rrdfile))
	 	{
			$retval = NULL;
		}
		else
		{
			# [Thu Sep 25 23:41:52 2008] [error] [client 127.0.0.1] PHP Notice:  Undefined offset:
			#   0 in /home/stybla/work/weathermap/weathermap5rrd-1.3.11/lib/rrd.php on line 263
			$fetch_array = array();
			$data_source_path = $rrdfile;
			/* build and run the rrdtool fetch command with all of our data */
			$cmd_line = "fetch {$data_source_path} AVERAGE --start=now";
			#	if ($resolution > 0) {
			#		$cmd_line .= " -r $resolution";
			#	}
			$output = $this->rrdtool_execute($cmd_line, false, 'RRDTOOL_OUTPUT_STDOUT');

			/* grab the first line of the output which contains a list of data sources
			in this .rrd file */
			$line_one = substr($output, 0, strpos($output, "\n"));
			#echo "line_one=*$line_one*<br>";
			/* loop through each data source in this .rrd file ... */
			#if (preg_match_all("/\S+/", $line_one, $data_source_names)) {
			preg_match_all("/\S+/", $line_one, $data_source_names);
			#echo "datasourcenames=".$data_source_names[0][0]."<br>";
			#echo LIST_CONTENTS($data_source_names);
			$retval = $data_source_names[0][$rrapos-1];
		} /* not empty */
		return $retval;
	}	
	# @return: image;
	public function rrdtool_graph($rrdfilein, $rranamein, $rrdfileout, $rranameout,
	 	$nodea, $nodeb, $period, $coefin, $coefout)
 	{
		$timenow = time();
		$datenow = date("d/m/Y ").date("H")."\:".date("i")."\:".date("s");
		if (!$period)
			$period="6hours";
		$cmd_line = "graph - ".
			'--imgformat=PNG  ' .
			'--start=now-'. $period .
			' --end=now ' .
			'--title="'. $nodea. ' - '. $nodeb. '"  ' .
			'--rigid  ' .
			'--base=1024  ' .
			'--height=120  ' .
			'--width=500  ' .
			'--alt-autoscale-max  ' .
			'--lower-limit=0  ' .
			'COMMENT:" "  ' .
			'COMMENT:"  \n"  ' .
			'--vertical-label="Bits per second"  ' .
			'DEF:a="' . $rrdfilein .
			'":' . $rranamein . ':AVERAGE  ' .
			'DEF:b="' . $rrdfileout .
			'":' . $rranameout . ':AVERAGE  ' .
			'CDEF:cdefa=a,' . $coefin . ',*  ' .
			'CDEF:cdefa2=cdefa,8,*  ' .
			'CDEF:cdefb=b,' . $coefout . ',*  ' .
			'CDEF:cdefb2=cdefb,8,*  ' .
			'AREA:cdefa2#00CF00:"' . $nodeb . '-->' . $nodea . '"   ' .
			'GPRINT:cdefa2:LAST:" Cur\:%8.2lf %s"   ' .
			'GPRINT:cdefa2:AVERAGE:"A/ver\:%8.2lf %s"   ' .
			'GPRINT:cdefa2:MAX:"Max\:%8.2lf %s\n"   ' .
			'LINE1:cdefb2#002A97:"' . $nodea . '-->' . $nodeb . '"   ' .
			'GPRINT:cdefb2:LAST:"Cur\:%8.2lf %s"   ' .
			'GPRINT:cdefb2:AVERAGE:"Aver\:%8.2lf %s"   ' .
			'GPRINT:cdefb2:MAX:"Max\:%8.2lf %s\n" ' .
			'COMMENT:" \n"  ' .
			'COMMENT:"\t\t\t\t\t\t\t\tTime period\: ' . $period . ' \n"  ' .
			'COMMENT:"\t\t\t\t\t\t\t\tGraph generated\: ' . $datenow . ' \n"  ';
		header("Content-type: image/png");
		$rrdtool = RRD_PATH;
		$fp = popen("{$rrdtool} {$cmd_line}","r");
		$retval = fpassthru($fp);
		pclose($fp);
		return $retval;
	}
	# @return: string;
	public function rrdtool_getversion()
	{
		$rrdtool = RRD_PATH;
		$handle = popen($rrdtool .'|grep "hide@address.com" | cut -d" " -f2 2>&1', 'r');
		$read = fread($handle, 2096);
		list($major, $majorsub, $minorsub)= explode(".", $read);
		pclose($handle);
		return ($major.".".$majorsub);
	}
	# desc: return link coeficient based uppon link units;
	# $unit: string;
	# @return: float;
	public function rrdtool_getLinkCoef($unit = null)
 	{
		switch ($unit)
	 	{
			case "Gbits":
				$retval = 10000*10000/8;
				break;
			case "Mbits":
				$retval = 1000*1000/8;
				break;
			case "Kbits":
				$retval = 1000/8;
				break;
			case "bits":
				$retval = 1/8;
				break;
			case "Mbytes":
				$retval = 1024*1024;
				break;
			case "Kbytes":
				$retval = 1024;
				break;
			case "bytes":
				$retval = 1;
				break;
			default:
				// Kbits
				$retval = 1000/8;
				break;
		} /* switch */
		return $retval;
	}
}
?>
Return current item: Weathermap5rrd