clustername = $HTTP_GET_VARS["c"] ? $HTTP_GET_VARS["c"] : null;
		$this->metricname = $HTTP_GET_VARS["m"] ? $HTTP_GET_VARS["m"] : null;
	}

	function getClusterName() {
		return $this->clustername;
	}

	function getMetricName() {
		return $this->metricname;
	}
}

class DataSource {

	var $data, $ip, $port;

	function DataSource( $ip = '127.0.0.1', $port = 8649 ) {
		$this->ip = $ip;
		$this->port = $port;
	}

	function getData() {

		$errstr;
		$errno = 0;
		$timeout = 3;

		$fp = fsockopen( $this->ip, $this->port, &$errno, &$errstr, $timeout );

		if( ! $fp ) {
			echo 'Unable to connect to '.$this->ip.':'.$this->port; // printf( 'Unable to connect to [%s:%.0f]', $this->ip, $this->port );
			return;
		}

		while ( !feof( $fp ) ) {
			
			$data .= fread( $fp, 16384 );
		}

		fclose( $fp );

		return $data;
	}
}

class DataGatherer {

	var $xmlhandler, $data, $httpvars;

	function DataGatherer() {

		$this->parser = xml_parser_create();
		$this->source = new DataSource();
		$this->httpvars = new HTTPVariables();
		$this->xmlhandler = new TorqueXMLHandler();
		xml_set_element_handler( $this->parser, array( &$this->xmlhandler, 'startElement' ), array( &$this->xmlhandler, 'stopElement' ) );
	}

	function parseXML() {

		$src = &$this->source;
		$this->data = $src->getData();

		if ( !xml_parse( &$this->parser, $this->data ) ) {
			$error = sprintf( 'XML error: %s at %d', xml_error_string( xml_get_error_code( &$this->parser ) ), xml_get_current_line_number( &$this->parser ) );
			// die( $error );
		}
	}

	function printInfo() {
		$handler = $this->xmlhandler;
		$handler->printInfo();
	}

}

class TorqueXMLHandler {

	var $clusters, $heartbeat, $nodes, $jobs;

	function TorqueXMLHandler() {
		$jobs = array();
		$clusters = array();
		$nodes = array();
		$heartbeat = array();
	}

	function gotNode( $hostname, $jobid = null, $location = 'unspecified' ) {

		$nodes = &$this->nodes;

		if( !isset( $nodes[$hostname] ) ) {

			$nodes[$hostname] = new Node( $hostname );
		}

		if( $location != 'unspecified' ) {

			$nodes[$hostname]->setLocation( $location );
		//} else {

			// Return pointer to this node if location was not set
			// Which means that this is for a jobinfo
			//$mynode = &$nodes[$hostname];
			//return $mynode;
		}

		if( $jobid ) {
			$nodes[$hostname]->addJob( $jobid );
		}
	}

	function startElement( $parser, $name, $attrs ) {

		$jobs = &$this->jobs;

		if ( $attrs[TN] ) {

			// Ignore dead metrics. Detect and mask failures.
			if ( $attrs[TN] > $attrs[TMAX] * 4 )
				return;
		}

		$jobid = null;

		// printf( '%s=%s', $attrs[NAME], $attrs[VAL] );

		if( $name == 'CLUSTER' ) {

			$clustername = $attrs[VAL];

			if( !isset( $clusters[$clustername] ) )
				$clusters[$clustername] = array();

		} else if( $name == 'HOST' ) {

			$hostname = $attrs[NAME];
			$location = $attrs[LOCATION];

			$this->gotNode( $hostname, null,$location );

		} else if( $name == 'METRIC' and strstr( $attrs[NAME], 'TOGA' ) ) {

			if( strstr( $attrs[NAME], 'TOGA-HEARTBEAT' ) ) {

				$heartbeat['time'] = $attrs[VAL];
				printf( "heartbeat %s\n", $heartbeat['time'] );

			} else if( strstr( $attrs[NAME], 'TOGA-JOB' ) ) {

				sscanf( $attrs[NAME], 'TOGA-JOB-%d', $jobid );

				printf( "jobid %s\n", $jobid );

				if( !isset( $jobs[$jobid] ) )
					$jobs[$jobid] = array();

				$fields = explode( ' ', $attrs[VAL] );

				foreach( $fields as $f ) {
					$togavalues = explode( '=', $f );

					$toganame = $togavalues[0];
					$togavalue = $togavalues[1];

					printf( "\t%s\t= %s\n", $toganame, $togavalue );

					if( $toganame == 'nodes' ) {

						if( !isset( $jobs[$toganame] ) )
							$jobs[$jobid][$toganame] = array();

						$nodes = explode( ';', $togavalue );

						foreach( $nodes as $node ) {

							// printf( "node %s\n", $node );

							$hostname = $node.'.'.$jobs[$jobid][domain];
							$jobs[$jobid][$toganame][] = $hostname;
							$this->gotNode( $hostname, $jobid );

							//$jobs[$jobid][$toganame][$hostname] = $this->gotNode( $hostname );
							// $jobs[$toganame][$node] = new Node( $node );
						}

					} else {

						$jobs[$jobid][$toganame] = $togavalue;

					}
				}
			}
		}
	}

	function stopElement( $parser, $name ) {
	}

	function printInfo() {

		$jobs = &$this->jobs;

		printf( "---jobs---\n" );

		foreach( $jobs as $jobid => $job ) {

			printf( "job %s\n", $jobid );

			if( isset( $job[nodes] ) ) {

				foreach( $job[nodes] as $node ) {

					$mynode = $this->nodes[$node];
					$hostname = $mynode->getHostname();
					$location = $mynode->getLocation();

					printf( "\t- node %s\tlocation %s\n", $hostname, $location );
					//$this->nodes[$hostname]->setLocation( "hier draait job ".$jobid );
				}
			}
		}

		printf( "---nodes---\n" );

		$nodes = &$this->nodes;

		foreach( $nodes as $node ) {

			$hostname = $node->getHostname();
			$location = $node->getLocation();
			$jobs = implode( ' ', $node->getJobs() );
			printf( "* node %s\tlocation %s\tjobs %s\n", $hostname, $location, $jobs );
		}
	}
}

class Node {

	var $img, $hostname, $location, $jobs;

	function Node( $hostname ) {

		$this->hostname = $hostname;
		$this->img = new NodeImg();
		$this->jobs = array();
	}

	function addJob( $jobid ) {
		$jobs = &$this->jobs;

		$jobs[] = $jobid;
	}

	function setLocation( $location ) {
		$this->location = $location;
	}

	function setHostname( $hostname ) {
		$this->hostname = $hostname;
	}

	function setCpus( $cpus ) {
		$this->cpus = $cpus;
	}

	function getHostname() {
		return $this->hostname;
	}

	function getLocation() {
		return $this->location;
	}

	function getCpus() {
		return $this->cpus;
	}

	function getJobs() {
		return $this->jobs;
	}
}

class NodeImg {

	var $image;

	function NodeImg( $image = null ) {

		$imageWidth = 100;
		$imageHeight = 100;

		if( !$image ) {
			$this->image = imageCreate( $imageWidth, $imageHeight );
				// or die( 'Cannot initialize new image stream: is GD installed?' );
		} else {
			$this->image = $image;
		}

		$background_color = imageColorAllocate( $this->image, 255, 255, 255 );
		$black_color = imageColorAllocate( $this->image, 0, 0, 0 );
		imageRectangle( $this->image, 0, 0, $imageWidth-1, $imageHeight-1, $black_color );
	}

	function colorHex( $color ) {
	
		$my_color = imageColorAllocate( $this->image, hexdec( substr( $color, 0, 2 )), hexdec( substr( $color, 2, 4 )), hexdec( substr( $color, 4, 6 )) );

		return $my_color;
	}

	function drawNode( $x, $y, &$queuecolor, $load, &$jobcolor ) {

		// Convert Ganglias Hexadecimal load color to a Decimal one
		$my_loadcolor = $this->colorHex( load_color($load) );

		imageFilledRectangle( $this->image, $x, $y, $x+12, $y+12, $queuecolor );
		imageFilledRectangle( $this->image, $x+2, $y+2, $x+10, $y+10, $my_loadcolor );
		//imageFilledEllipse( $this->image, ($x+9)/2, ($y+9)/2, 6, 6, $jobcolor );
	}

	function drawImage() {

		$queue_color = imageColorAllocate( $this->image, 0, 102, 304 );
		$job_color = imageColorAllocate( $this->image, 204, 204, 0 );

		$this->drawNode( 1, 1, $queue_color, 0.1, $job_color );
		header( 'Content-type: image/png' );
		imagePNG( $this->image );
		imageDestroy( $this->image );
	}
}

//$my_node = new NodeImg();
//$my_node->drawImage();

$my_data = new DataGatherer();
$my_data->parseXML();
$my_data->printInfo();
$my_data->printInfo();
?>