source: branches/0.4/web/addons/job_monarch/libtoga.php @ 809

Last change on this file since 809 was 809, checked in by ramonb, 11 years ago
  • cast timestamp to int for operator
  • Property svn:keywords set to Id
File size: 73.7 KB
RevLine 
[102]1<?php
[225]2/*
3 *
4 * This file is part of Jobmonarch
5 *
[713]6 * Copyright (C) 2006-2013  Ramon Bastiaans
[225]7 *
8 * Jobmonarch is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * Jobmonarch is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21 *
[231]22 * SVN $Id: libtoga.php 809 2013-04-08 19:20:13Z ramonb $
23 *
[225]24 */
25
26
[519]27class HTTPVariables
28{
[721]29    var $clustername, $metricname;
30    var $restvars, $httpvars;
[103]31
[721]32    function HTTPVariables( $httpvars, $getvars )
33    {
34        $this->restvars        = array();
[103]35
[721]36        $this->clustername    = isset( $httpvars["c"] ) ? $httpvars["c"] : $getvars["c"];
37        $this->metricname    = isset( $httpvars["m"] ) ? $httpvars["m"] : $getvars["m"];
[110]38
[721]39        if( count( $httpvars ) > 0 )
40        {
41            foreach( $httpvars as $httpvar => $httpval )
42            {
43                if( $httpval )
44                {
45                    $this->restvars[$httpvar] = $httpval;
46                }
47            }
48        }
[117]49
[721]50        if( count( $getvars ) > 0 )
51        {
52            foreach( $getvars as $getvar => $getval )
53            {
54                if( $getval )
55                {
56                    $this->restvars[$getvar] = $getval;
57                }
58            }
59        }
60    }
[103]61
[721]62    function getClusterName()
63    {
64        return $this->clustername;
65    }
[103]66
[721]67    function getMetricName()
68    {
69        return $this->metricname;
70    }
[110]71
[721]72    function getHttpVar( $var )
73    {
74        if( isset( $this->restvars[$var] ) )
75        {
76            return $this->restvars[$var];
77        }
78        else
79        {
80            return null;
81        }
82    }
[103]83}
84
[721]85$CLUSTER_CONFS    = array();
[337]86
[686]87ini_set("memory_limit","500M");
[652]88set_time_limit(0);
89
[519]90// Monarch's conf
[112]91//
92include_once "./conf.php";
[195]93include_once "./version.php";
[112]94
[117]95global $GANGLIA_PATH;
[206]96global $RRDTOOL;
97global $JOB_ARCHIVE_DIR;
[207]98global $JOB_ARCHIVE_DBASE;
[778]99global $JOB_ARCHIVE_SQL_USER;
100global $JOB_ARCHIVE_SQL_PASSWORD;
[329]101global $skan_str;
102global $x_first, $y_first;
[337]103global $CLUSTER_CONFS;
[112]104
[117]105$my_dir = getcwd();
[112]106
[117]107// Load Ganglia's PHP
108chdir( $GANGLIA_PATH );
[112]109
[686]110include_once "./eval_conf.php";
[117]111include_once "./functions.php";
[145]112include_once "./get_context.php";
[519]113
[751]114global $GLOBALS, $conf, $metrics, $version, $rrdtool_version, $context;
115
116// ganglia start
117$metrics = array();
118$version = array();
119
120$version["webfrontend"] = $GLOBALS["ganglia_version"];
121
122# Get rrdtool version
123$rrdtool_version = array();
124exec($conf['rrdtool'], $rrdtool_version);
125$rrdtool_version = explode(" ", $rrdtool_version[0]);
126$rrdtool_version = $rrdtool_version[1];
127$version["rrdtool"] = "$rrdtool_version";
128
129// ganglia end
130
[145]131$context = 'cluster';
[117]132
133// Back to our PHP
134chdir( $my_dir );
135
136global $SMALL_CLUSTERIMAGE_MAXWIDTH, $SMALL_CLUSTERIMAGE_NODEWIDTH, $DATA_SOURCE, $HTTP_GET_VARS, $_GET;
137$httpvars = new HTTPVariables( $HTTP_GET_VARS, $_GET );
138
[112]139// Set cluster context so that Ganglia will
140// provide us with the correct metrics array
141//
[126]142global $context, $clustername, $reports;
[129]143
[126]144global $default_metric;
145
[112]146// Ganglia's array of host metrics
147//
[751]148global $hosts_up;
[738]149global $start;
[112]150
[246]151global $DATETIME_FORMAT;
152
[519]153function makeDate( $time )
154{
[721]155    global $DATETIME_FORMAT;
156    return strftime( $DATETIME_FORMAT, $time );
[246]157}
158
[514]159
[519]160class TarchDbase
161{
[721]162    var $ip, $dbase, $conn;
[130]163
[778]164    function TarchDbase( $ip = null, $dbase = null, $user =null, $password=null )
[721]165    {
166        global $CLUSTER_CONFS, $clustername;
167        global $JOB_ARCHIVE_DBASE;
[207]168
[721]169        // Import cluster specific settings
170        //
171        foreach( $CLUSTER_CONFS as $confcluster => $conffile )
172        {
173            if( strtolower( trim($this->clustername) ) == strtolower(trim($confcluster)) )
174            {
175                include_once $conffile;
176            }
177        }
[454]178
[721]179        $db_fields = explode( '/', $JOB_ARCHIVE_DBASE );
[207]180
[721]181        $this->ip    = $db_fields[0];
182        $this->dbase    = $db_fields[1];
183        $this->conn    = null;
184    }
[130]185
[721]186    function connect()
187    {
[778]188        global $JOB_ARCHIVE_SQL_USER, $JOB_ARCHIVE_SQL_PASSWORD;
189
190        $connect_args ='';
[721]191        if( $this->ip == null )
[778]192        {
193            $connect_args .= "dbname=".$this->dbase;
194        }
[721]195        else
[778]196        {
197            $connect_args .= "host=".$this->ip." dbname=".$this->dbase;
198        }
199        if( isset($JOB_ARCHIVE_SQL_USER) )
200        {
201            $connect_args .= " user=".$JOB_ARCHIVE_SQL_USER;
202        }
203        if( isset($JOB_ARCHIVE_SQL_PASSWORD) )
204        {
205            $connect_args .= " password=".$JOB_ARCHIVE_SQL_PASSWORD;
206        }
207
208
209        $this->conn = pg_connect( $connect_args );
210
[721]211    }
[138]212
[721]213    function searchDbase( $id = null, $queue = null, $owner = null, $name = null, $start_from_time = null, $start_to_time = null, $end_from_time = null, $end_to_time = null )
214    {
215        global $SEARCH_RESULT_LIMIT;
[248]216
[721]217        if( $id )
218        {
219            $select_query = "SELECT job_id FROM jobs WHERE job_id = '$id' AND job_status = 'F'";
220            $this->resultcount = 1;
221        }
222        else
223        {
224            $query_args = array();
225           
226            if( $queue )
227            {
228                $query_args[] = "job_queue ='$queue'";
229            }
230            if( $owner )
231            {
232                $query_args[] = "job_owner ='$owner'";
233            }
234            if( $name )
235            {
236                $query_args[] = "job_name = '$name'";
237            }
238            if( $start_from_time )
239            {
[809]240                $query_args[] = "CAST(job_start_timestamp as INT) >= $start_from_time";
[721]241            }
242            if( $start_to_time )
243            {
[809]244                $query_args[] = "CAST(job_start_timestamp as INT) <= $start_to_time";
[721]245            }
246            if( $end_from_time )
247            {
[809]248                $query_args[] = "CAST(job_stop_timestamp as INT) >= $end_from_time";
[721]249            }
250            if( $end_to_time )
251            {
[809]252                $query_args[] = "CAST(job_stop_timestamp as INT) <= $end_to_time";
[721]253            }
[138]254
[721]255            $query = "FROM jobs WHERE job_status = 'F' AND ";
256            $extra_query_args = '';
[138]257
[721]258            foreach( $query_args as $myquery )
259            {
260                if( $extra_query_args == '' )
261                {
262                    $extra_query_args = $myquery;
263                }
264                else
265                {
266                    $extra_query_args .= " AND ".$myquery;
267                }
268            }
269            $query .= $extra_query_args;
[138]270
[721]271            $count_result_idname = "COUNT(job_id)";
272            $select_result_idname = "job_id";
[140]273
[721]274            $count_query = "SELECT " . $count_result_idname . " " . $query;
[248]275
[721]276            $count_result = $this->queryDbase( $count_query );
277            $this->resultcount = (int) $count_result[0]['count'];
[248]278
[721]279            $select_query = "SELECT " . $select_result_idname . " " . $query . " ORDER BY job_id DESC LIMIT " . $SEARCH_RESULT_LIMIT;
280        }
[251]281
[721]282        $ids = $this->queryDbase( $select_query );
[248]283
[778]284        //print_r( $ids );
285
[721]286        $ret = array();
[140]287
[721]288        foreach( $ids as $crow)
289        {
290            $ret[] = $crow['job_id'];
291        }
[140]292
[721]293        return $ret;
294    }
[138]295
[721]296    function getNodesForJob( $jobid )
297    {
298        $result = $this->queryDbase( "SELECT node_id FROM job_nodes WHERE job_id = '$jobid'" );
[138]299
[721]300        $nodes = array();
[138]301
[721]302        foreach( $result as $result_row ) 
303        {
304            $nodes[] = $this->getNodeArray( $result_row['node_id'] );
305        }
[138]306
[721]307        return $nodes;
308    }
[138]309
[721]310    function getJobsForNode( $nodeid )
311    {
312        $result = $this->queryDbase( "SELECT job_id FROM job_nodes WHERE node_id = '$nodeid'" );
[138]313
[721]314        $jobs = array();
[138]315
[721]316        foreach( $result as $result_row )
317        {
318            $jobs[] = $this->getJobArray( $result_row['job_id'] );
319        }
320        return $jobs;
321    }
[138]322
[721]323    function getJobArray( $id )
324    {
325        $result = $this->queryDbase( "SELECT * FROM jobs WHERE job_id = '$id'" );
[138]326
[721]327        return ( $this->makeArray( $result[0] ) );
328    }
[138]329
[721]330    function getNodeArray( $id )
331    {
332        $result = $this->queryDbase( "SELECT * FROM nodes WHERE node_id = '$id'" );
[138]333
[721]334        return ( $this->makeArray( $result[0] ) );
335    }
[138]336
[721]337    function makeArray( $result_row )
338    {
339        $myar = array();
[138]340
[721]341        foreach( $result_row as $mykey => $myval )
342        {
343            $map_key = explode( '_', $mykey );
[138]344
[721]345            $rmap_key = array_reverse( $map_key );
346            array_pop( $rmap_key );
347            $map_key = array_reverse( $rmap_key );
348           
349            $newkey = implode( '_', $map_key );
350           
351            $myar[$newkey] = $result_row[$mykey];
352        }
[138]353
[721]354        return $myar;
355    }
[138]356
[721]357    function queryDbase( $query )
358    {
359        $result_rows = array();
[778]360   
361        if( $this->conn == null )
[721]362        {
363            $this->connect();
364        }
[138]365
[778]366        if( $this->conn == null )
367        {
368            printf(" no connection!\n");
369        }
[721]370        $result = pg_query( $this->conn, $query );
[138]371
[721]372        while ($row = pg_fetch_assoc($result))
373        {
[778]374            //print_r( $row );
[721]375            $result_rows[] = $row;
376        }
[138]377
[721]378        return $result_rows;
379    }
[130]380}
381
[519]382class TarchRrdGraph
383{
[721]384    var $rrdbin, $rrdvalues, $clustername, $hostname, $tempdir, $tarchdir, $metrics;
[130]385
[721]386    function TarchRrdGraph( $clustername, $hostname )
387    {
[725]388        global $conf;
[721]389        global $JOB_ARCHIVE_DIR;
[206]390
[779]391        $this->rrdbin      = $conf['rrdtool'];
392        $this->rrdvalues   = array();
393        $this->tarchdir    = $JOB_ARCHIVE_DIR;
394        $this->clustername = $clustername;
395        $this->hostname    = $hostname;
[721]396    }
[130]397
[721]398    function doCmd( $command )
399    {
400        $pipe = popen( $command . ' 2>&1', 'r' );
[130]401
[721]402        if (!$pipe)
403        {
404            print "pipe failed.";
405            return "";
406        }
[130]407
[721]408        $output = '';
[519]409
[721]410        while(!feof($pipe))
411        {
412            $output .= fread($pipe, 1024);
413        }
[130]414
[721]415        pclose($pipe);
[130]416
[721]417        $output = explode( "\n", $output );
[519]418
[721]419        return $output;
420    }
[130]421
[721]422    function dirList( $dir )
423    {
424        $dirlist = array();
[130]425
[721]426        if ($handle = opendir( $dir ))
427        {
428            while (false !== ($file = readdir($handle)))
429            {
430                if ($file != "." && $file != "..")
431                {
432                    $dirlist[] = $file;
433                }
434            }
435            closedir($handle);
436        }
[130]437
[721]438        return $dirlist;
439    }
[130]440
[721]441    function getTimePeriods( $start, $end )
442    {
443        $times = array();
444        $dirlist = $this->dirList( $this->tarchdir . '/' . $this->clustername . '/' . $this->hostname );
[145]445
[721]446        $first = 0;
447        $last = 9999999999999;
[130]448
[721]449        foreach( $dirlist as $dir )
450        {
451            if( $dir > $first and $dir <= $start )
452            {
453                $first = $dir;
454            }
455            if( $dir < $last and $dir >= $end )
456            {
457                $last = $dir;
458            }
459        }
[130]460
[721]461        foreach( $dirlist as $dir )
462        {
463            if( $dir >= $first and $dir <= $last and !array_key_exists( $dir, $times ) )
464            {
465                $times[] = $dir;
466            }
467        }
[130]468
[721]469        sort( $times );
[130]470
[721]471        return $times;
472    }
[130]473
[721]474    function getRrdDirs( $start, $stop )
475    {
476        $timess = $this->getTimePeriods( $start, $stop );
[145]477
[721]478        $rrd_files = array();
[145]479
[721]480        foreach( $timess as $time )
481        {
482            $rrd_files[] = $this->tarchdir . '/' . $this->clustername . '/' . $this->hostname. '/'.$time;
483        }
[145]484
[721]485        return $rrd_files;
486    }
[145]487
[721]488    function getRrdFiles( $metric, $start, $stop )
489    {
490        $times = $this->getTimePeriods( $start, $stop );
[145]491
[721]492        $rrd_files = array();
[145]493
[721]494        foreach( $times as $time )
495        {
496            $rrd_files[] = $this->tarchdir . '/' . $this->clustername . '/' . $this->hostname . '/' .$time. '/' . $metric. '.rrd';
497        }
[145]498
[721]499        return $rrd_files;
500    }
[130]501}
502
[519]503class DataSource
504{
[721]505    var $data, $ip, $port;
[103]506
[721]507    function DataSource()
508    {
[742]509        global $DATA_SOURCE, $clustername;
[326]510
[721]511        $ds_fields     = explode( ':', $DATA_SOURCE );
[326]512
[721]513        $ds_ip         = $ds_fields[0];
[742]514        $ds_port       = $ds_fields[1];
[326]515
[742]516        $this->ip       = $ds_ip;
[721]517        $this->port     = $ds_port;
[742]518        $this->clustername = $clustername;
[721]519    }
[103]520
[721]521    function getData()
522    {
523        $errstr        = '';
[742]524        $errno         = 0;
525        $timeout       = 3;
[103]526
[721]527        $fp = fsockopen( $this->ip, $this->port, $errno, $errstr, $timeout );
[103]528
[721]529        if( !$fp )
530        {
531            echo 'Unable to connect to '.$this->ip.':'.$this->port;
532            return;
533        }
[103]534
[742]535        if( $this->port == '8652' )
536        {
[745]537            $request = "/" . $this->clustername . "\n";
[742]538            $rc = fputs($fp, $request);
539            if (!$rc)
540            {
541                $error = "Could not sent request to gmetad: $errstr";
542                if ($debug) print "<br/>DEBUG: $error\n";
543                   return FALSE;
544            }
545        }
546
[721]547        stream_set_timeout( $fp, 30 );
[177]548
[721]549        while ( !feof( $fp ) )
550        {
551            $data .= fread( $fp, 16384 );
552        }
[103]553
[721]554        fclose( $fp );
[103]555
[721]556        return $data;
557    }
[103]558}
559
[519]560class DataGatherer
561{
[721]562    var $xmlhandler, $data, $httpvars;
[103]563
[721]564    function DataGatherer( $cluster )
565    {
566        $this->cluster    = $cluster;
567        $this->httpvars = $httpvars;
568    }
[103]569
[721]570    function parseXML( $data )
571    {
[745]572
[721]573        $this->parser         = xml_parser_create();
574        $this->xmlhandler     = new TorqueXMLHandler( $this->cluster );
[326]575
[750]576        xml_parser_set_option( $this->parser, XML_OPTION_CASE_FOLDING, 0 );
[721]577        xml_set_element_handler( $this->parser, array( &$this->xmlhandler, 'startElement' ), array( &$this->xmlhandler, 'stopElement' ) );
[519]578
[721]579        if ( !xml_parse( $this->parser, $data ) )
580        {
581            $error = sprintf( 'XML error: %s at %d', xml_error_string( xml_get_error_code( $this->parser ) ), xml_get_current_line_number( $this->parser ) );
582        }
[748]583        $handler = &$this->xmlhandler;
584        $handler->finishUp();
[721]585    }
[103]586
[721]587    function printInfo()
588    {
589        $handler = $this->xmlhandler;
590        $handler->printInfo();
591    }
[105]592
[721]593    function getUsingFQDN()
594    {
595        $handler = $this->xmlhandler;
596        return $handler->getUsingFQDN();
597    }
[463]598
[751]599    function getMetrics()
600    {
601        $handler = $this->xmlhandler;
602        return $handler->getMetrics();
603    }
[721]604    function getNodes()
605    {
606        $handler = $this->xmlhandler;
607        return $handler->getNodes();
608    }
[106]609
[721]610    function getNode( $node )
611    {
612        $handler = $this->xmlhandler;
613        return $handler->getNode( $node );
614    }
[303]615
[721]616    function getCpus()
617    {
618        $handler = $this->xmlhandler;
619        return $handler->getCpus();
620    }
[124]621
[721]622    function getJobs()
623    {
624        $handler = $this->xmlhandler;
625        return $handler->getJobs();
626    }
[106]627
[721]628    function getJob( $job )
629    {
630        $handler = $this->xmlhandler;
631        return $handler->getJob( $job );
632    }
[303]633
[721]634    function getHeartbeat()
635    {
636        $handler = $this->xmlhandler;
637        return $handler->getHeartbeat();
638    }
[298]639
[721]640    function isJobmonRunning()
641    {
642        $handler = $this->xmlhandler;
643        return $handler->isJobmonRunning();
644    }
[103]645}
646
[519]647class TorqueXMLHandler
648{
[721]649    var $clusters, $heartbeat, $nodes, $jobs, $clustername, $proc_cluster;
[104]650
[721]651    function TorqueXMLHandler( $clustername )
652    {
653        $this->jobs        = array();
654        $this->clusters     = array();
655        $this->nodes         = array();
[751]656        $this->metrics      = array();
[721]657        $this->heartbeat     = array();
658        $this->down_nodes    = array();
659        $this->offline_nodes    = array();
660        $this->clustername    = $clustername;
[749]661        $this->proc_cluster = null;
[751]662        $this->proc_hostname = null;
[721]663        $this->fqdn        = 1;
664    }
[103]665
[721]666    function getUsingFQDN()
667    {
668        return $this->fqdn;
669    }
[463]670
[721]671    function getCpus()
672    {
673        $cpus = 0;
[124]674
[721]675        if( isset( $this->jobs ) && count( $this->jobs ) > 0 )
676        {
677            foreach( $this->jobs as $jobid=>$jobattrs )
678            {
679                $nodes    = count( $jobattrs['nodes'] );
680                $ppn    = (int) $jobattrs['ppn'] ? $jobattrs['ppn'] : 1;
681                $mycpus    = $nodes * $ppn;
[124]682
[721]683                $cpus    = $cpus + $mycpus;
684            }
685        }
686    }
[124]687
[721]688    function isJobmonRunning()
689    {
690        if (isset( $this->heartbeat['time'] ))
691        {
692            return 1;
693        }
694        else
695        {
696            return 0;
697        }
698    }
[298]699
[721]700    function makeHostname( $thostname, $tdomain=null )
701    {
702        // Should hostname be FQDN or short w/o domain
703        //
704        $nodes = &$this->nodes;
[514]705
[721]706        $fqdn = 1;
[514]707
[721]708        //$tdomain = explode( '.', $thostname );
709        //
710        // TODO?: extract domain from hostname or something?
[514]711
[721]712        if( $tdomain )
713        {
714            $domain_len    = 0 - strlen( $tdomain );
[514]715
[721]716            // Let's see if Ganglia use's FQDN or short hostnames
717            //
718            foreach( $nodes as $hostname => $nimage )
719            {
[747]720                if( strpos( $hostname, $tomdain ) !== false )
[721]721                {
722                    $fqdn    = 0;
723                }
724            }
725        }
726        else
727        {
728            $fqdn    = 0;
729        }
730   
731        if( $tdomain && $fqdn )
732        {
[747]733            if( strpos( $thostname, $tdomain ) !== false )
[721]734            {
735                $thostname = $thostname . '.'.$tdomain;
736            } 
737            else
738            {
739                $thostname = $thostname;
740            }
741        }
[514]742
[721]743        return $thostname;
744    }
[514]745
[721]746    function startElement( $parser, $name, $attrs )
747    {
[767]748        global $cluster, $metrics, $self, $grid;
[105]749
[721]750        $jobid = null;
[103]751
[767]752        if( $name == 'GRID' )
753        {
754            $self = $attrs['NAME'];
755            $grid = $attrs;
756
757            return null;
758        }
759
[721]760        if( $name == 'CLUSTER' )
761        {
[751]762            // ganglia start
763            $cluster = $attrs;
764            // ganglia end
765
[721]766            $this->proc_cluster = $attrs['NAME'];
[749]767            //printf("set proc cluster to %s\n", $attrs['NAME'] );
768            return null;
[721]769        }
[749]770        if( $this->proc_cluster != $this->clustername )
[721]771        {
[749]772            //printf("cluster does not match: %s\n", $this->clustername );
773            return null;
774        }
775
776        if( $name == 'HOST' )
777        {
[751]778            // ganglia start
[721]779            $hostname = $attrs['NAME'];
[751]780            $this->proc_hostname = $hostname;
[459]781
[751]782            # Pseudo metrics - add useful HOST attributes like gmond_started & last_reported to the metrics list:
783            $metrics[$hostname]['gmond_started']['NAME'] = "GMOND_STARTED";
784            $metrics[$hostname]['gmond_started']['VAL'] = $attrs['GMOND_STARTED'];
785            $metrics[$hostname]['gmond_started']['TYPE'] = "timestamp";
786            $metrics[$hostname]['last_reported']['NAME'] = "REPORTED";
[752]787            $metrics[$hostname]['last_reported']['VAL'] = $attrs['REPORTED'];
[751]788            $metrics[$hostname]['last_reported']['TYPE'] = "string";
789            $metrics[$hostname]['ip_address']['NAME'] = "IP";
790            $metrics[$hostname]['ip_address']['VAL'] = $attrs['IP'];
791            $metrics[$hostname]['ip_address']['TYPE'] = "string";
792            $metrics[$hostname]['location']['NAME'] = "LOCATION";
793            $metrics[$hostname]['location']['VAL'] = $attrs['LOCATION'];
794            $metrics[$hostname]['location']['TYPE'] = "string";
795            // ganglia end
796
[749]797            //printf( "host %s\n", $hostname );
798            //$location = $attrs['LOCATION'];
[105]799
[749]800            if( !isset( $this->nodes[$hostname] ) )
[721]801            {
[749]802                $this->nodes[$hostname] = new NodeImage( $this->proc_cluster, $hostname );
[721]803            }
[749]804            return null;
[721]805        }
[751]806
807        if( $name == 'METRIC' )
[721]808        {
[751]809            $hostname = $this->proc_hostname;
810
811            // ganglia start
812            $metricname = rawurlencode($attrs['NAME']);
813            $metrics[$hostname][$metricname] = $attrs;
814            // ganglia end
815
816            if ( strpos( $attrs['NAME'], 'zplugin_monarch' ) === false )
817            {
818                return null;
819            }
820
[747]821            if( strpos( $attrs['NAME'], 'zplugin_monarch_heartbeat' ) !== false )
[721]822            {
823                $this->heartbeat['time'] = $attrs['VAL'];
[749]824                return;
[721]825            }
[747]826            else if( strpos( $attrs['NAME'], 'zplugin_monarch_down' ) !== false )
[721]827            {
828                $fields        = explode( ' ', $attrs['VAL'] );
[104]829
[721]830                $nodes_down    = array();
831                $down_domain    = null;
[514]832
[721]833                foreach( $fields as $f )
834                {
835                    $togavalues    = explode( '=', $f );
[514]836
[721]837                    $toganame    = $togavalues[0];
838                    $togavalue    = $togavalues[1];
[514]839
[721]840                    if( $toganame == 'nodes' )
841                    {
842                        $mynodes = explode( ';', $togavalue );
[514]843
[721]844                        foreach( $mynodes as $node )
845                        {
846                            $nodes_down[] = $node;
847                        }
848                    }
849                    else if( $toganame == 'domain' )
850                    {
851                        $down_domain = $togavalue;
852                    }
853                    else if( $toganame == 'reported' )
854                    {
855                        if( !isset( $this->down_nodes['heartbeat'] ) )
856                        {
857                            $this->down_nodes[$togavalue]    = array( $nodes_down, $down_domain );
858                        }
859                    }
860                }
[749]861                return;
[721]862            }
[747]863            else if( strpos( $attrs['NAME'], 'zplugin_monarch_offline' ) !== false )
[721]864            {
865                $fields        = explode( ' ', $attrs['VAL'] );
[514]866
[721]867                $nodes_offline    = array();
868                $offline_domain    = null;
[514]869
[721]870                foreach( $fields as $f )
871                {
872                    $togavalues    = explode( '=', $f );
[514]873
[721]874                    $toganame    = $togavalues[0];
875                    $togavalue    = $togavalues[1];
[514]876
[721]877                    if( $toganame == 'nodes' )
878                    {
879                        $mynodes = explode( ';', $togavalue );
[514]880
[721]881                        foreach( $mynodes as $node )
882                        {
883                            $nodes_offline[] = $node;
884                        }
885                    }
886                    else if( $toganame == 'domain' )
887                    {
888                        $offline_domain = $togavalue;
889                    }
890                    else if( $toganame == 'reported' )
891                    {
892                        if( !isset( $this->offline_nodes['heartbeat'] ) )
893                        {
894                            $this->offline_nodes[$togavalue] = array( $nodes_offline, $offline_domain );
895                        }
896                    }
897                }
[749]898                return;
[721]899            }
[747]900            else if( strpos( $attrs['NAME'], 'zplugin_monarch_job' ) !== false )
[721]901            {
[726]902                sscanf( $attrs['NAME'], 'zplugin_monarch_job_%d_%s$', $monincr, $jobid );
[104]903
[749]904                if( !isset( $this->jobs[$jobid] ) )
[721]905                {
[749]906                    $this->jobs[$jobid] = array();
[721]907                }
[104]908
[721]909                $fields = explode( ' ', $attrs['VAL'] );
[104]910
[721]911                foreach( $fields as $f )
912                {
913                    $togavalues = explode( '=', $f );
[104]914
[721]915                    $toganame = $togavalues[0];
916                    $togavalue = $togavalues[1];
[104]917
[721]918                    if( $toganame == 'nodes' )
919                    {
[749]920                        if( $this->jobs[$jobid]['status'] == 'R' )
[721]921                        {
[749]922                            if( !isset( $this->jobs[$jobid][$toganame] ) )
[721]923                            {
[749]924                                $this->jobs[$jobid][$toganame] = array();
[721]925                            }
[104]926
[721]927                            $mynodes = explode( ';', $togavalue );
[103]928
[721]929                            foreach( $mynodes as $node )
930                            {
[749]931                                if( !in_array( $node, $this->jobs[$jobid][$toganame] ) )
[721]932                                {
[749]933                                    array_push( $this->jobs[$jobid][$toganame], $node );
[721]934                                }
935                            }
[135]936
[721]937                        }
[749]938                        else if( $this->jobs[$jobid]['status'] == 'Q' )
[721]939                        {
[749]940                            $this->jobs[$jobid][$toganame] = $togavalue;
[721]941                        }
942                    }
943                    else
944                    {
[749]945                        $this->jobs[$jobid][$toganame] = $togavalue;
[721]946                    }
947                }
[111]948
[749]949                if( isset( $this->jobs[$jobid]['nodes'] ) )
[721]950                {
[749]951                    $nr_nodes = count( $this->jobs[$jobid]['nodes'] );
[721]952       
[749]953                    if( $this->jobs[$jobid]['status'] == 'R' )
[721]954                    {
[111]955
[749]956                        if( isset( $this->jobs[$jobid]['domain'] ) )
[721]957                        {
[749]958                            $domain        = $this->jobs[$jobid]['domain'];
[721]959                            $domain_len    = 0 - strlen( $domain );
[461]960
[752]961                            $first_host    = key( array_slice($this->nodes, 0, 1, true) );
[746]962
[721]963                            // Let's see if Ganglia use's FQDN or short hostnames
964                            //
[747]965                            if( strpos( $first_host, $domain ) === false )
[721]966                            {
[746]967                                $this->fqdn    = 0;
[721]968                            }
969                        }
970                        else
971                        {
972                            $this->fqdn    = 0;
973                        }
[459]974
[749]975                        foreach( $this->jobs[$jobid]['nodes'] as $node )
[721]976                        {
[200]977
[721]978                            // Only add domain name to the hostname if Ganglia is doing that too
979                            //
[749]980                            if( $this->fqdn && isset( $this->jobs[$jobid]['domain'] ) )
[721]981                            {
[747]982                                if( strpos( $node, $domain ) === false )
[721]983                                {
984                                    $host = $node. '.'.$domain;
985                                } else
986                                {
987                                    $host = $node;
988                                }
989                            }
990                            else
991                            {
992                                $host    = $node;
993                            }
[300]994
[749]995                            if( !isset( $this->nodes[$host] ) )
[721]996                            {
997                                $my_node = new NodeImage( $this->proc_cluster, $host );
998                            }
999                            else
1000                            {
[749]1001                                $my_node = $this->nodes[$host];
[721]1002                            }
[111]1003
[721]1004                            if( !$my_node->hasJob( $jobid ) )
1005                            {
1006                                if( isset( $jobs[$jobid]['ppn'] ) )
1007                                {
1008                                    $my_node->addJob( $jobid, ((int) $jobs[$jobid]['ppn']) );
1009                                }
1010                                else
1011                                {
1012                                    $my_node->addJob( $jobid, 1 );
1013                                }
1014                            }
[111]1015
[749]1016                            $this->nodes[$host] = $my_node;
[721]1017                        }
1018                    }
1019                }
1020            }
[749]1021            return;
[721]1022        }
1023    }
[103]1024
[748]1025    function finishUp( )
[721]1026    {
1027        $nodes    = $this->nodes;
[514]1028
[748]1029        if( sizeof( $this->down_nodes ) > 0 )
[721]1030        {
[748]1031            foreach( $this->down_nodes as $reported => $dnodes )
[721]1032            {
[748]1033                if( $reported == $this->heartbeat['time'] )
[721]1034                {
[748]1035                    $domain = $dnodes[1];
1036
1037                    foreach( $dnodes[0] as $downhost )
[721]1038                    {
[748]1039                        $downhost = $this->makeHostname( $downhost, $domain );
[514]1040
[748]1041                        if( isset( $nodes[$downhost] ) )
[721]1042                        {
[748]1043                            // OMG PHP4 is fking stupid!
1044                            // $nodes[$downhost]->setDown( 1 ) won't work here..
1045                            //
1046                            $mynode = $nodes[$downhost];
1047                            $mynode->setDown( 1 );
1048                            $nodes[$downhost] = $mynode;
[721]1049                        }
1050                    }
1051                }
1052            }
[748]1053        }
[514]1054
[748]1055        if( sizeof( $this->offline_nodes ) > 0 )
1056        {
1057            foreach( $this->offline_nodes as $reported => $onodes )
[721]1058            {
[748]1059                if( $reported == $this->heartbeat['time'] )
[721]1060                {
[748]1061                    $domain = $onodes[1];
1062
1063                    foreach( $onodes[0] as $offlinehost )
[721]1064                    {
[748]1065                        $offlinehost = $this->makeHostname( $offlinehost, $domain );
[514]1066
[748]1067                        if( isset( $nodes[$offlinehost] ) )
[721]1068                        {
[748]1069                            // OMG PHP4 is fking stupid!
1070                            // $nodes[$offlinehost]->setDown( 1 ) won't work here..
1071                            //
1072                            $mynode = $nodes[$offlinehost];
1073                            $mynode->setOffline( 1 );
1074                            $nodes[$offlinehost] = $mynode;
[721]1075                        }
1076                    }
1077                }
1078            }
1079        }
[514]1080
[721]1081        $this->nodes = $nodes;
1082    }
[105]1083
[748]1084    function stopElement( $parser, $name )
1085    {
1086    }
1087
[721]1088    function printInfo()
1089    {
1090        $jobs = &$this->jobs;
[105]1091
[721]1092        printf( "---jobs---\n" );
[105]1093
[721]1094        foreach( $jobs as $jobid => $job )
1095        {
1096            printf( "job %s\n", $jobid );
[105]1097
[721]1098            if( isset( $job['nodes'] ) )
1099            {
1100                foreach( $job['nodes'] as $node )
1101                {
1102                    $mynode = $this->nodes[$node];
1103                    $hostname = $mynode->getHostname();
1104                    $location = $mynode->getLocation();
[105]1105
[721]1106                    printf( "\t- node %s\tlocation %s\n", $hostname, $location );
1107                }
1108            }
1109        }
[105]1110
[721]1111        printf( "---nodes---\n" );
[105]1112
[721]1113        $nodes = &$this->nodes;
[105]1114
[721]1115        foreach( $nodes as $node )
1116        {
1117            $hostname = $node->getHostname();
1118            $location = $node->getLocation();
1119            $jobs = implode( ' ', $node->getJobs() );
1120            printf( "* node %s\tlocation %s\tjobs %s\n", $hostname, $location, $jobs );
1121        }
1122    }
[106]1123
[721]1124    function getNodes()
1125    {
1126        return $this->nodes;
1127    }
[106]1128
[721]1129    function getNode( $node )
1130    {
1131        $nodes = &$this->nodes;
[303]1132
[721]1133        if( isset( $nodes[$node] ) )
1134        {
1135            return $nodes[$node];
1136        }
1137        else
1138        {
1139            return NULL;
1140        }
1141    }
[303]1142
[721]1143    function getJobs()
1144    {
1145        return $this->jobs;
1146    }
[114]1147
[721]1148    function getJob( $job )
1149    {
1150        $jobs = &$this->jobs;
[303]1151
[721]1152        if( isset( $jobs[$job] ) )
1153        {
1154            return $jobs[$job];
1155        }
1156        else
1157        {
1158            return NULL;
1159        }
1160    }
[303]1161
[721]1162    function getHeartbeat()
1163    {
1164        return $this->heartbeat['time'];
1165    }
[103]1166}
1167
[519]1168class NodeImage
1169{
[721]1170    var $image, $x, $y, $hostname, $jobs, $tasks, $showinfo;
[102]1171
[721]1172    function NodeImage( $cluster, $hostname )
1173    {
1174        global $SMALL_CLUSTERIMAGE_NODEWIDTH;
[305]1175
[721]1176        $this->jobs        = array();
1177        $this->tasks        = 0;
1178        $this->hostname        = $hostname;
1179        $this->clustername    = $cluster;
1180        $this->showinfo        = 1;
1181        $this->size        = $SMALL_CLUSTERIMAGE_NODEWIDTH;
1182        $this->down        = 0;
1183        $this->offline        = 0;
1184    }
[102]1185
[721]1186    function addJob( $jobid, $cpus )
1187    {
1188        $jobs        = &$this->jobs;
1189        $jobs[]        = $jobid;
1190        $this->jobs    = $jobs;
[111]1191
[721]1192        $this->addTask( $cpus );
1193    }
[111]1194
[721]1195    function hasJob( $jobid )
1196    {
1197        $jobfound = 0;
[111]1198
[721]1199        if( count( $this->jobs ) > 0 )
1200        {
1201            foreach( $this->jobs as $job )
1202            {
1203                if( $job == $jobid )
1204                {
1205                    $jobfound = 1;
1206                }
1207            }
1208        }
[111]1209
[721]1210        return $jobfound;
1211    }
[111]1212
[721]1213    function addTask( $cpus )
1214    {
1215        $this->tasks = $this->tasks + $cpus;
1216    }
1217    function setDown( $down )
1218    {
1219        $this->down = $down;
1220    }
1221    function isDown()
1222    {
1223        return $this->down;
1224    }
1225    function setOffline( $offline )
1226    {
1227        $this->offline = $offline;
1228    }
1229    function isOffline()
1230    {
1231        return $this->offline;
1232    }
1233    function setImage( $image )
1234    {
1235        $this->image = $image;
1236    }
1237    function setCoords( $x, $y )
1238    {
1239        $this->x = $x;
1240        $this->y = $y;
1241    }
1242    function getX()
1243    {
1244        return $this->x;
1245    }
1246    function getY()
1247    {
1248        return $this->y;
1249    }
[106]1250
[721]1251    function getImagemapArea()
1252    {
1253        $area_topleft        = $this->x . "," . $this->y;
1254        $area_bottomright    = ($this->x + $this->size) . "," . ($this->y + $this->size);
1255        $area_coords        = $area_topleft . "," . $area_bottomright;
[326]1256
[721]1257        $area_href        = "./?c=" . $this->clustername . "&h=" . $this->hostname;
[326]1258
[721]1259        $area_tooltip        = $this->hostname;
[514]1260
[721]1261        if( $this->down)
1262        {
1263            $area_tooltip        = $area_tooltip . ": DOWN";
1264        }
1265        else if( $this->offline )
1266        {
1267            $area_tooltip        = $area_tooltip . ": OFFLINE";
1268        }
[514]1269
[721]1270        $area_tooltip        = $area_tooltip . ": " . implode( " ", $this->jobs );
[514]1271
[721]1272        $tag_href        = "HREF=\"" . $area_href . "\"";
1273        $tag_coords        = "COORDS=\"" . $area_coords . "\"";
1274        $tag_tooltip1        = "ALT=\"" . $area_tooltip . "\"";
1275        $tag_tooltip2        = "TITLE=\"" . $area_tooltip . "\"";
[326]1276
[721]1277        return ("<AREA SHAPE=\"RECT\" " . $tag_coords . " " . $tag_href . " " . $tag_tooltip1 . " " . $tag_tooltip2 . ">");
1278    }
[326]1279
[721]1280    function colorHex( $color )
1281    {
1282        $my_color = imageColorAllocate( $this->image, hexdec( substr( $color, 0, 2 )), hexdec( substr( $color, 2, 2 )), hexdec( substr( $color, 4, 2 )) );
[102]1283
[721]1284        return $my_color;
1285    }
[102]1286
[721]1287    function setLoad( $load )
1288    {
1289        $this->load = $load;
1290    }
[106]1291
[721]1292    function setHostname( $hostname )
1293    {
1294        $this->hostname = $hostname;
1295    }
[108]1296
[721]1297    function getHostname()
1298    {
1299        return $this->hostname;
1300    }
[122]1301
[721]1302    function getJobs()
1303    {
1304        return $this->jobs;
1305    }
[114]1306
[721]1307    function setShowinfo( $showinfo )
1308    {
1309        $this->showinfo = $showinfo;
1310    }
[122]1311
[721]1312    function drawSmall()
1313    {
1314        global $SMALL_CLUSTERIMAGE_NODEWIDTH;
[305]1315
[721]1316        $this->size    = $SMALL_CLUSTERIMAGE_NODEWIDTH;
[305]1317
[721]1318        $this->draw();
1319    }
[110]1320
[721]1321    function drawBig()
1322    {
1323        global $BIG_CLUSTERIMAGE_NODEWIDTH;
[305]1324
[721]1325        $this->size    = $BIG_CLUSTERIMAGE_NODEWIDTH;
[305]1326
[766]1327        $this->drawShadow();
[721]1328        $this->draw();
1329    }
[106]1330
[766]1331    function drawShadow()
1332    {
1333        // offset of drop shadow from top left
1334        //
1335        $ds_offset  = 5;
1336
1337        // number of steps from black to background color
1338        //
1339        $ds_steps   = 15;
1340
1341        // distance between steps
1342        //
1343        $ds_spread = 1;
1344
1345        // define the background color
1346        //
1347        $background = array("r" => 255, "g" => 255, "b" => 255);
1348
1349        // create a new canvas.  New canvas dimensions should be larger than the original's
1350        //
1351        $width  = $this->size + $ds_offset;
1352        $height = $this->size + $ds_offset;
1353
1354        // determine the offset between colors
1355        //
1356        $step_offset = array("r" => ($background['r'] / $ds_steps), "g" => ($background['g'] / $ds_steps), "b" => ($background['b'] / $ds_steps));
1357
1358        // calculate and allocate the needed colors
1359        //
1360        $current_color = $background;
1361
1362        for ($i = 0; $i <= $ds_steps ; $i++)
1363        {
1364            $colors[$i] = imagecolorallocate($this->image, round($current_color['r']), round($current_color['g']), round($current_color['b']));
1365
1366            $current_color['r'] -= $step_offset['r'];
1367            $current_color['g'] -= $step_offset['g'];
1368            $current_color['b'] -= $step_offset['b'];
1369        }
1370
1371        // draw overlapping rectangles to create a drop shadow effect
1372        //
1373        for ($i = 3; $i < count($colors); $i++)
1374        {
1375            imagefilledrectangle( $this->image, ($this->x + $ds_offset), ($this->y + $ds_offset), ($this->x + $width), ($this->y + $height), $colors[$i] );
1376            $width -= $ds_spread;
1377            $height -= $ds_spread;
1378        }
1379    }
1380
[721]1381    function draw()
1382    {
1383        global $JOB_NODE_MARKING, $NODE_DOWN_MARKING, $NODE_OFFLINE_MARKING;
[102]1384
[721]1385        $black_color = imageColorAllocate( $this->image, 0, 0, 0 );
1386        $size = $this->size;
[107]1387
[721]1388        imageFilledRectangle( $this->image, $this->x, $this->y, $this->x+($size), $this->y+($size), $black_color );
[110]1389
[721]1390        if( $this->showinfo)
1391        {
1392            $this->load = $this->determineLoad();
[111]1393
[721]1394            if( !isset( $this->image ) or !isset( $this->x ) or !isset( $this->y ) )
1395            {
1396                printf( "aborting\n" );
1397                printf( "x %d y %d load %f\n", $this->x, $this->y, $load );
1398                return;
1399            }
[111]1400
[721]1401            // Convert Ganglias Hexadecimal load color to a Decimal one
1402            //
1403            $load = $this->determineLoad();   
1404            $usecolor = $this->colorHex( load_color($load) );
1405            imageFilledRectangle( $this->image, $this->x+1, $this->y+1, $this->x+($size-1), $this->y+($size-1), $usecolor );
1406            if( $this->down )
1407            {
1408                imageString( $this->image, 1, $this->x+(($size/2)-1), $this->y+(($size/2)-4), $NODE_DOWN_MARKING, $black_color );
1409            }
1410            else if( $this->offline )
1411            {
1412                imageString( $this->image, 1, $this->x+(($size/2)-1), $this->y+(($size/2)-4), $NODE_OFFLINE_MARKING, $black_color );
1413            }
1414            else if( count( $this->jobs ) > 0 )
1415            {
1416                imageString( $this->image, 1, $this->x+(($size/2)-1), $this->y+(($size/2)-4), $JOB_NODE_MARKING, $black_color );
1417            }
1418        }
1419        else
1420        {
1421            // White
1422            $usecolor = imageColorAllocate( $this->image, 255, 255, 255 );
1423            imageFilledRectangle( $this->image, $this->x+1, $this->y+1, $this->x+($size-1), $this->y+($size-1), $usecolor );
1424        }
1425    }
[102]1426
[742]1427    function determineLoad()
[721]1428    {
1429        global $metrics;
[108]1430
[721]1431        $cpus = $metrics[$this->hostname]['cpu_num']['VAL'];
1432        if (!$cpus)
1433        {
1434            $cpus=1;
1435        }
[519]1436
[721]1437        $load_one    = $metrics[$this->hostname]['load_one']['VAL'];
[742]1438        $load        = ((float) $load_one)/$cpus;
[102]1439
[721]1440        return $load;
1441    }
[106]1442}
1443
[519]1444class ClusterImage
1445{
[721]1446    var $dataget, $image, $clustername;
1447    var $filtername, $filters;
[106]1448
[721]1449    function ClusterImage( $data, $clustername )
1450    {
[765]1451        $this->dataget      = new DataGatherer( $clustername );
1452        $this->data         = $data;
1453        $this->clustername  = $clustername;
1454        $this->filters      = array();
1455        $this->size         = 's';
[721]1456        $this->width        = 0;
[765]1457        $this->height       = 0;
1458        $this->output       = 1;
[743]1459        $this->jobs         = null;
1460        $this->nodes        = null;
[765]1461        $this->parsed       = false;
[721]1462    }
[106]1463
[721]1464    function getWidth()
1465    {
1466        return $this->width;
1467    }
1468    function getHeight()
1469    {
1470        return $this->height;
1471    }
1472    function setSmall()
1473    {
1474        $this->size    = 's';
1475    }
1476    function setBig()
1477    {
1478        $this->size    = 'b';
1479    }
1480    function setNoimage()
1481    {
1482        $this->output    = 0;
1483    }
[765]1484    function checkParse()
1485    {
1486        if( $this->parsed == false )
1487        {
1488            $this->dataget->parseXML( $this->data );
1489            $this->parsed = true;
1490        }
1491    }
[743]1492    function getJobs()
1493    {
1494        if( $this->jobs == null )
1495        {
[765]1496            $this->checkParse();
[743]1497            $mydatag = $this->dataget;
1498            $this->jobs = $mydatag->getJobs();
1499        }
1500
1501        return $this->jobs;
1502    }
[764]1503    function setJobs($jobs)
1504    {
1505        $this->jobs   = &$jobs;
1506    }
[743]1507    function getNodes()
1508    {
1509        if( $this->nodes== null )
1510        {
[765]1511            $this->checkParse();
[743]1512            $mydatag = $this->dataget;
1513            $this->nodes = $mydatag->getNodes();
1514        }
1515
1516        return $this->nodes;
1517    }
1518    function setNodes($nodes)
1519    {
1520        $this->nodes    = &$nodes;
1521    }
[721]1522    function isSmall()
1523    {
1524        return ($this->size == 's');
1525    }
1526    function isBig()
1527    {
1528        return ($this->size == 'b');
1529    }
1530    function setFilter( $filtername, $filtervalue )
1531    {
1532        $this->filters[$filtername] = $filtervalue;
1533    }
[122]1534
[721]1535    function filterNodes( $jobs, $nodes )
1536    {
1537        $filtered_nodes = array();
[122]1538
[743]1539        //print_r( $nodes );
1540
[721]1541        foreach( $nodes as $node )
1542        {
1543            $hostname = $node->getHostname();
[122]1544
[721]1545            $addhost = 1;
[122]1546
[721]1547            if( count( $this->filters ) > 0 )
1548            {
1549                $mynjobs = $node->getJobs();
[124]1550
[721]1551                if( count( $mynjobs ) > 0 )
1552                {
1553                    foreach( $mynjobs as $myjob )
1554                    {
1555                        foreach( $this->filters as $filtername => $filtervalue )
1556                        {
1557                            if( $filtername!=null && $filtername!='' )
1558                            {
1559                                if( $filtername == 'jobid' && !$node->hasJob( $filtervalue) )
1560                                {
1561                                    $addhost = 0;
1562                                }
1563                                else if( $filtername != 'jobid' )
1564                                {
1565                                    if( $jobs[$myjob][$filtername] != $filtervalue )
1566                                    {
1567                                        $addhost = 0;
1568                                    }
1569                                }
1570                            }
1571                        }
1572                    }
1573                }
1574                else
1575                {
1576                    $addhost = 0;
1577                }
1578            }
[124]1579
[721]1580            if( $addhost )
1581            {
1582                $filtered_nodes[] = $hostname;
1583            }
1584        }
[122]1585
[721]1586        return $filtered_nodes;
1587    }
[122]1588
[721]1589    function draw()
1590    {
1591        global $SMALL_CLUSTERIMAGE_MAXWIDTH, $SMALL_CLUSTERIMAGE_NODEWIDTH;
1592        global $BIG_CLUSTERIMAGE_MAXWIDTH, $BIG_CLUSTERIMAGE_NODEWIDTH;
1593        global $CLUSTER_CONFS, $confcluster, $SHOW_EMPTY_COLUMN, $SHOW_EMPTY_ROW;
[329]1594
[721]1595        global $SORTBY_HOSTNAME, $SORT_ORDER, $skan_str;
1596        global $x_first, $y_first;
[331]1597
[721]1598        foreach( $CLUSTER_CONFS as $confcluster => $conffile )
1599        {
1600            if( strtolower( trim($this->clustername) ) == strtolower(trim($confcluster)) )
1601            {
1602                include_once $conffile;
1603            }
1604        }
[337]1605
[721]1606        if( $this->isSmall() )
1607        {
1608            $max_width    = $SMALL_CLUSTERIMAGE_MAXWIDTH;
1609            $node_width    = $SMALL_CLUSTERIMAGE_NODEWIDTH;
1610        }
1611        else if( $this->isBig() )
1612        {
1613            $max_width    = $BIG_CLUSTERIMAGE_MAXWIDTH;
1614            $node_width    = $BIG_CLUSTERIMAGE_NODEWIDTH;
1615        }
[106]1616
[743]1617        $nodes        = $this->getNodes();
[721]1618        $nodes_hosts    = array_keys( $nodes );
[106]1619
[721]1620        $nodes_nr    = count( $nodes );
[106]1621
[721]1622        $nodes_size    = $nodes_nr*$node_width;
1623        $node_rows    = 0;
[106]1624
[721]1625        if( $nodes_size > $max_width )
1626        {
1627            $nodes_per_row = ( (int) ($max_width/$node_width) );
1628        }
1629        else
1630        {
1631            $nodes_per_row = $nodes_size;
1632            $node_rows = 1;
1633        }
[106]1634
[721]1635        if( $nodes_per_row < $nodes_nr )
1636        {
1637            $node_rows = ( (int) ($nodes_nr/$nodes_per_row) );
1638            $node_rest = fmod( $nodes_nr, $nodes_per_row );
[519]1639
[721]1640            if( $node_rest > 0 )
1641            {
1642                $node_rows++;
1643            }
1644        }
[106]1645
[721]1646        $y_offset    = 0;
1647        $font         = 2;
1648        $fontwidth    = ImageFontWidth( $font );
1649        $fontheight    = ImageFontHeight( $font );
1650        $fontspaceing    = 2;
1651        $y_offset    = $fontheight + (2 * $fontspaceing);
[306]1652
[721]1653        $this->width    = $max_width;
1654        $this->height    = ($y_offset + (($node_rows*$node_width)+1) );
[326]1655
[743]1656        $jobs = $this->getJobs();
[721]1657        $filtered_nodes = $this->filterNodes( $jobs, $nodes );
[122]1658
[721]1659        if( $SORTBY_HOSTNAME != "" )
1660        {
1661                $sorted     = array();
[329]1662
[721]1663            $x_first    = 0;
1664            $y_first    = 0;
[329]1665
[721]1666            $skan_str    = $SORTBY_HOSTNAME;
[329]1667
[721]1668            global $x_present, $y_present;
1669            $x_present    = false;
1670            $y_present    = false;
[339]1671
[721]1672            // Should we scan by X, Y or both
1673            //
1674            if(strpos( $SORTBY_HOSTNAME, "{x}" ) != false )
1675            {
1676                $x_str        = "{x}";
1677                $x_present    = true;
1678            }
1679            else if(strpos( $SORTBY_HOSTNAME, "{X}" ) != false )
1680            {
1681                $x_str        = "{X}";
1682                $x_present    = true;
1683            }
1684            if(strpos( $SORTBY_HOSTNAME, "{y}" ) != false )
1685            {
1686                $y_str        = "{y}";
1687                $y_present    = true;
1688            }
1689            else if(strpos( $SORTBY_HOSTNAME, "{Y}" ) != false )
1690            {
1691                $y_str        = "{Y}";
1692                $y_present    = true;
1693            }
[339]1694
[721]1695            // If we should scan for both X and Y: see which one is first
1696            //
1697            if(( strpos( $SORTBY_HOSTNAME, $x_str ) < strpos( $SORTBY_HOSTNAME, $y_str ) ) && ( $x_present && $y_present ))
1698            {
1699                $x_first    = 1;
1700            }
1701            else if(( strpos( $SORTBY_HOSTNAME, $x_str ) > strpos( $SORTBY_HOSTNAME, $y_str ) ) && ( $x_present && $y_present ))
1702            {
1703                $y_first    = 1;
1704       
1705            }
1706            else if( $x_present )
1707            {
1708                $x_first    = 1;
1709            }
1710            else if( $y_present )
1711            {
1712                $y_first    = 1;
1713            }
[329]1714
[721]1715            // Now replace our {x} and {y} with %d for sscanf parsing
1716            //
1717            if(( $x_first ) && ( $x_present && $y_present ) )
1718            {
1719                $skan_str    = str_replace( $x_str, "%d", $skan_str );
1720                $skan_str    = str_replace( $y_str, "%d", $skan_str );
1721            } 
1722            else if( $x_present)
1723            {
1724                $skan_str    = str_replace( $x_str, "%d", $skan_str );
1725            }
1726            else if( $y_present)
1727            {
1728                $skan_str    = str_replace( $y_str, "%d", $skan_str );
1729            }
[329]1730
[721]1731            $x_min        = null;
1732            $x_max        = null;
1733            $y_min        = null;
1734            $y_max        = null;
[329]1735
[721]1736            $x_columns    = array();
1737            $y_rows        = array();
[522]1738
[721]1739            // Now let's walk through all our nodes and see which one are valid for our scan pattern
1740            //
1741            foreach( $nodes as $hostname => $node )
1742            {
1743                $x    = null;
1744                $y    = null;
[339]1745
[721]1746                if( $x_present && $y_present )
1747                {
1748                    if( $x_first )
1749                    {
1750                        $n = sscanf( $hostname, $skan_str, $x, $y );
1751                    }
1752                    else if( $y_first )
1753                    {
1754                        $n = sscanf( $hostname, $skan_str, $y, $x );
1755                    }
[463]1756
[721]1757                    // Remove nodes that don't match
1758                    //
1759                    if( $n < 2 )
1760                    {
1761                        // This node hostname has no match for: {x} and {y}
1762                        //
1763                        unset( $nodes[$hostname] );
1764                    }
1765                }
1766                else if( $x_present && !$y_present )
1767                {
1768                    $n = sscanf( $hostname, $skan_str, $x );
[463]1769
[721]1770                    // Remove nodes that don't match
1771                    //
1772                    if( $n < 1 )
1773                    {
1774                        // This node hostname has no match for: {x}
1775                        //
1776                        unset( $nodes[$hostname] );
1777                    }
1778                    $y    = 1;
1779                }
1780                else if( $y_present && !$x_present )
1781                {
1782                    $n = sscanf( $hostname, $skan_str, $y );
[463]1783
[721]1784                    // Remove nodes that don't match
1785                    //
1786                    if( $n < 1 )
1787                    {
1788                        // This node hostname has no match for: {y}
1789                        //
1790                        unset( $nodes[$hostname] );
1791                    }
1792                    $x    = 1;
1793                }
[329]1794
[721]1795                // Determine the lowest value of {x} that exists in all node hostnames
1796                //
1797                if( !$x_min && $x != null )
1798                {
1799                    $x_min    = $x;
1800                }
1801                else if( $x < $x_min && $x != null )
1802                {
1803                    $x_min    = $x;
1804                }
[463]1805
[721]1806                // Determine the highest value of {x} that exists in all node hostnames
1807                //
1808                if( !$x_max && $x != null )
1809                {
1810                    $x_max    = $x;
1811                }
1812                else if( $x > $x_max && $x != null )
1813                {
1814                    $x_max    = $x;
1815                }
[463]1816
[721]1817                // Determine the lowest value of {y} that exists in all node hostnames
1818                //
1819                if( !$y_min && $y != null )
1820                {
1821                    $y_min    = $y;
1822                }
1823                else if( $y < $y_min && $y != null )
1824                {
1825                    $y_min    = $y;
1826                }
[463]1827
[721]1828                // Determine the highest value of {y} that exists in all node hostnames
1829                //
1830                if( !$y_max && $y != null )
1831                {
1832                    $y_max    = $y;
1833                }
1834                else if( $y > $y_max && $y != null )
1835                {
1836                    $y_max    = $y;
1837                }
[522]1838
[721]1839                // Store which non-empty columns and rows we found
1840                //
1841                if( !in_array( $x, $x_columns ) )
1842                {
1843                    $x_columns[] = $x;
1844                }
1845                if( !in_array( $y, $y_rows ) )
1846                {
1847                    $y_rows[] = $y;
1848                }
1849            }
[329]1850
[721]1851            // Sort all the nodes (alpha and numerically)
1852            // 1: gb-r1n1, 2: gb-r1n2, 3: gb-r2n1, etc
1853            //
1854            $sorted_nodes    = usort( $nodes, "cmp" );
[329]1855
[721]1856            //print_r( $x_columns ) ;
[522]1857
[721]1858            $cur_node    = 0;
[329]1859
[721]1860            $x_offset    = 0;
1861            $y_offset    = 0;
1862            $font         = 2;
1863            $fontwidth    = ImageFontWidth( $font );
1864            $fontheight    = ImageFontHeight( $font );
1865            $fontspaceing    = 2;
[331]1866
[721]1867            if( $this->isSmall() ) 
1868            {
1869                $y_offset    = $y_offset + (2 * $fontspaceing) + $fontheight;
1870            }
[333]1871
[721]1872            if( $this->isBig() ) 
1873            {
1874                $y_offset    = ($fontheight * (1 + strlen( $x_max) ) ) + ((2 + strlen( $x_max)) * $fontspaceing);
1875                $x_offset    = ($fontwidth * (1 + strlen( $y_max) ) ) + ((2 + strlen( $y_max)) * $fontspaceing);
1876            }
[331]1877
[721]1878            $image_width    = $x_offset + ($node_width * ($x_max-$x_min+2));
[428]1879
[721]1880            if( $this->isSmall() ) 
1881            {
1882                $image_width    = $max_width;
1883            }
1884            else if( $this->isBig() ) 
1885            {
1886                $image_width    = ($image_width < $max_width) ? $image_width : $max_width;
1887            }
1888            $image_height    = $y_offset + ($node_width * ($y_max-$y_min+2));
[330]1889
[721]1890            $this->width    = $image_width;
1891            $this->heigth    = $image_heigth;
[330]1892
[721]1893            $image        = imageCreateTrueColor( $image_width, $image_height );
1894            $colorwhite    = imageColorAllocate( $image, 255, 255, 255 );
[329]1895
[721]1896            imageFill( $image, 0, 0, $colorwhite );
[329]1897
[721]1898            if( $this->isSmall() )
1899            {
1900                // Draw a fancy little header text to explain what it is
1901                //
1902                $colorblue    = imageColorAllocate( $image, 0, 0, 255 );
[333]1903
[721]1904                imageString( $image, $font, 2, 2, "Monarch Joblist - cluster: ".$this->clustername, $colorblue );
1905            }
[333]1906
[721]1907            if( $this->isBig() && ( isset( $SORT_XLABEL ) || isset( $SORT_YLABEL ) ) )
1908            {
1909                $colorblue    = imageColorAllocate( $image, 0, 0, 255 );
[329]1910
[721]1911                if( isset( $SORT_XLABEL ) )
1912                {
1913                    // Print the {x} label: rack
1914                    //
1915                    imageString( $image, $font, $x_offset, $fontspaceing, $SORT_XLABEL, $colorblue );
1916                }
[329]1917
[721]1918                if( isset( $SORT_YLABEL ) )
1919                {
1920                    // Stupid php without imageStringDown function... we'll make one ourself
1921                    //
[463]1922
[721]1923                    // Print the {y} label: node
1924                    //
1925                    imageStringDown( $image, $font, $fontspaceing, $y_offset, $SORT_YLABEL, $colorblue );
1926                }
1927            }
[329]1928
[721]1929            $previous_n    = 0;
1930            $previous_m    = 0;
1931            $x_empty_count    = 0;
1932            $y_empty_count    = 0;
[522]1933
[721]1934            // Let's start assigning x,y coordinates now
1935            //
1936            for( $n = $x_min; $n <= $x_max; $n++ )
1937            {
1938                for( $m = $y_min; $m <= $y_max; $m++ )
1939                {
1940                    if( $x_min > 0 )
1941                    {
1942                        $x    = $x_offset + ( ($n-$x_min) * $node_width ) - ($x_empty_count * $node_width);
1943                    }
1944                    if( $y_min > 0 )
1945                    {
1946                        $y    = $y_offset + ( ($m-$y_min) * $node_width ) - ($y_empty_count * $node_width);
1947                    }
[329]1948
[721]1949                    // Don't show empty rows/columns if option enabled
1950                    //
1951                    if( !in_array( $n, $x_columns ) && !$SHOW_EMPTY_COLUMN )
1952                    {
1953                        // Skip to next iteration: we don't want a empty column
1954                        //
1955                        if( $n > $previous_n )
1956                        {
1957                            $previous_n = $n;
1958                            $x_empty_count++;
1959                        }
1960                        continue;
1961                    }
1962                    if( !in_array( $m, $y_rows ) && !$SHOW_EMPTY_ROW )
[522]1963
[721]1964                    {
1965                        // Skip to next iteration: we don't want a empty column
1966                        //
1967                        if( $m > $previous_m )
1968                        {
1969                            $previous_m = $m;
1970                            $y_empty_count++;
1971                        }
1972                        continue;
1973                    }
[522]1974
[721]1975                    if( $this->isBig() ) 
1976                    {
1977                        // Draw y(node) column number header
1978                        //
1979                        if(( $n == $x_min ) && ( isset($SORT_YLABEL) ) )
1980                        {
1981                            $mfontspacing    = 1;
[463]1982
[721]1983                            $ylabel_x    = $x - ( $fontwidth * strlen( $y_max ) ) - $mfontspacing;
1984                            $ylabel_y    = $y;
[463]1985
[721]1986                            imageString( $image, $font, $ylabel_x, $ylabel_y, strval( $m ), $colorblue );
[463]1987
[721]1988                            $xmin_hit[$n]    = true;
1989                        }
[463]1990
[721]1991                        // Draw x(rack) column number header
1992                        //
1993                        if(( $m == $y_min ) && ( isset($SORT_XLABEL) ) )
1994                        {
1995                            $mfontspacing    = 2;
1996                            $xlabel_y    = $y - ( $fontheight * strlen( $x_max ) );
1997                            $xlabel_x    = $x + $mfontspacing; 
[463]1998
[721]1999                            imageStringDown( $image, $font, $xlabel_x, $xlabel_y, strval( $n ), $colorblue );
2000                        }
2001                    }
[463]2002
[721]2003                    if( isset( $nodes[$cur_node] ) ) 
2004                    {
2005                        $host    = $nodes[$cur_node]->getHostname();
[329]2006
[721]2007                        if( $x_present && $y_present )
2008                        {
2009                            if( $x_first )
2010                            {
2011                                $nn = sscanf( $host, $skan_str, $rx, $ry );
2012                            }
2013                            else if( $y_first )
2014                            {
2015                                $nn = sscanf( $host, $skan_str, $ry, $rx );
2016                            }
2017                            if ( $nn < 2 )
2018                            {
2019                                //printf( "skipping node %s - y present & x present + <2 x,y matchs\n", $host);
2020                                continue;
2021                            }
2022                            if( intval( $rx ) > $n )
2023                            {
2024                                // If x(rack) is higher than current x, skip to next x(rack)
2025                                //
2026                                $m        = $y_max + 1;
[463]2027
[721]2028                                continue;
2029                            }
2030                            if( intval( $ry ) > $m )
2031                            {
2032                                // If y(node) is higher than current y, skip to next y(node)
2033                                //
2034                                continue;
2035                            }
2036                        }
2037                        else if( $x_present )
2038                        {
2039                            $nn = sscanf( $host, $skan_str, $rx );
2040                        }
2041                        else if( $y_present )
2042                        {
2043                            $nn = sscanf( $host, $skan_str, $ry );
2044                        }
[329]2045
[721]2046                        if( !in_array( $host, $filtered_nodes ) )
2047                        {
2048                            // This node has been filtered out: we only want to see certain nodes
2049                            //
2050                            $nodes[$cur_node]->setShowinfo( 0 );
2051                        }
[329]2052
[721]2053                        $nodes[$cur_node]->setCoords( $x, $y );
2054                        $nodes[$cur_node]->setImage( $image );
[329]2055
[721]2056                        if( $this->isSmall() )
2057                        {
2058                            $nodes[$cur_node]->drawSmall();
2059                        }
2060                        else if( $this->isBig() )
2061                        {
2062                            $nodes[$cur_node]->drawBig();
2063                        }
[404]2064
[721]2065                        $cur_node++;
2066                    }
2067                }
2068            }
[329]2069
[721]2070        }
2071        else
2072        {
2073            if( $this->isSmall() )
2074            {
2075                $image        = imageCreateTrueColor( $max_width, ($y_offset + (($node_rows*$node_width)+1) ) );
2076            }
2077            else if( $this->isBig() )
2078            {
2079                $image_width    = ($node_width * $nodes_nr) + 2;
2080                $image_width    = ($image_width < $max_width) ? $image_width : $max_width;
2081                $image        = imageCreateTrueColor( $image_width, ($y_offset + (($node_rows*$node_width)+1) ) );
2082            }
2083            $colorwhite    = imageColorAllocate( $image, 255, 255, 255 );
[329]2084
[721]2085            imageFill( $image, 0, 0, $colorwhite );
[329]2086
[721]2087            if( $this->isSmall() )
2088            {
2089                $colorblue    = imageColorAllocate( $image, 0, 0, 255 );
[329]2090
[721]2091                imageString( $image, $font, 2, 2, "Monarch Joblist - cluster: ".$this->clustername, $colorblue );
2092            }
[329]2093
[721]2094            for( $n = 0; $n < $node_rows; $n++ )
2095            {
2096                for( $m = 0; $m < $nodes_per_row; $m++ )
2097                {
2098                    $x = ($m * $node_width);
2099                    $y = $y_offset + ($n * $node_width);
[107]2100
[721]2101                    $cur_node = ($n * $nodes_per_row) + ($m);
2102                    $host = isset( $nodes_hosts[$cur_node] ) ? $nodes_hosts[$cur_node] : '';
[107]2103
[721]2104                    if( isset( $nodes[$host] ) )
2105                    {
2106                        $nodes[$host]->setCoords( $x, $y );
2107                        $nodes[$host]->setImage( $image );
[122]2108
[721]2109                        if( !in_array( $host, $filtered_nodes ) )
2110                        {
2111                            $nodes[$host]->setShowinfo( 0 );
2112                        }
[122]2113
[721]2114                        if( $this->isSmall() )
2115                        {
2116                            $nodes[$host]->drawSmall();
2117                        }
2118                        else if( $this->isBig() )
2119                        {
2120                            $nodes[$host]->drawBig();
2121                        }
2122                    }
2123                }
2124            }
2125        }
2126   
2127        $this->nodes    = &$nodes;
[326]2128
[721]2129        if ($this->output)
2130        {
2131            header( 'Content-type: image/png' );
2132            imagePNG( $image );
2133            imageDestroy( $image );
2134        }
2135    }
[326]2136
[721]2137    function getImagemapArea()
2138    {
2139        $clusterimage_map    = "";
[326]2140
[764]2141        $nodes = &$this->getNodes();
2142
2143        foreach( $nodes as $node )
[721]2144        {
[764]2145            $node_map          = $node->getImagemapArea();
2146            $clusterimage_map .= $node_map;
[721]2147        }
[326]2148
[721]2149        return $clusterimage_map;
2150    }
[102]2151}
2152
[519]2153class EmptyImage
2154{
[721]2155    function draw()
2156    {
2157        $image        = imageCreateTrueColor( 1, 1 );
2158        $colorwhite    = imageColorAllocate( $image, 255, 255, 255 );
2159        imageFill( $image, 0, 0, $colorwhite );                         
[298]2160
[721]2161        header( 'Content-type: image/png' );
2162        imagePNG( $image );
2163        imageDestroy( $image );
2164    }
[298]2165}
2166
[519]2167class HostImage
2168{
[721]2169    var $data_gather, $cluster, $host, $node, $image;
2170    var $headerstrlen;
[303]2171
[721]2172    function HostImage( $data_gather, $cluster, $host )
2173    {
2174        $this->data_gather     = $data_gather;
2175        $this->cluster        = $cluster;
2176        $this->host        = $host;
2177        $this->y_offset        = 0;
2178        $this->font        = 2;
2179        $this->fontspaceing    = 2;
2180        $this->headerstrlen    = array();
[303]2181
[721]2182        $this->fontheight    = ImageFontHeight( $this->font );
2183        $this->fontwidth    = ImageFontWidth( $this->font );
[303]2184
[721]2185        $dg            = &$this->data_gather;
2186        $this->node        = &$dg->getNode( $this->host );
2187        $n            = &$this->node;
2188        $this->njobs        = $n->getJobs();
2189    }
[303]2190
[721]2191    function drawJobs()
2192    {
2193        $dg                     = &$this->data_gather;
2194        $colorblack        = imageColorAllocate( $this->image, 0, 0, 0 );
[303]2195
[721]2196        for( $n = 0; $n < count( $this->njobs ); $n++ )
2197        {
2198            $jobid            = $this->njobs[$n];
2199            $jobinfo        = $dg->getJob( $jobid );
[303]2200
[721]2201            $xoffset        = 5;
2202            imageString( $this->image, $this->font, $xoffset, $this->y_offset, strval( $jobid ), $colorblack );
[303]2203
[721]2204            foreach( $this->headerstrlen as $headername => $headerlen )
2205            {
2206                if( $headername == 'nodes' )
2207                {
2208                    $attrval    = strval( count( $jobinfo['nodes'] ) );
2209                }
2210                else if( $headername == 'cpus' )
2211                {
2212                    if( !isset( $jobinfo['ppn'] ) )
2213                    {
2214                        $jobinfo['ppn'] = 1;
2215                    }
[303]2216
[721]2217                    $attrval    = strval( count( $jobinfo['nodes'] ) * intval( $jobinfo['ppn'] ) );
2218                }
2219                else if( $headername == 'runningtime' )
2220                {
2221                    $attrval    = makeTime( intval( $jobinfo['reported'] ) - intval( $jobinfo['start_timestamp'] ) );
2222                }
2223                else
2224                {
2225                    $attrval    = strval( $jobinfo[$headername] );
2226                }
[303]2227
[721]2228                imageString( $this->image, $this->font, $xoffset, $this->y_offset, $attrval, $colorblack );
2229       
2230                $xoffset    = $xoffset + ($this->fontwidth * ( $headerlen + 1 ) );
2231            }
2232           
2233            $this->newLineOffset();
2234        }
2235    }
[303]2236
[721]2237    function drawHeader()
2238    {
2239        $dg                     = &$this->data_gather;
[303]2240
[721]2241        for( $n = 0; $n < count( $this->njobs ); $n++ )
2242        {
2243            $jobid            = $this->njobs[$n];
2244            $jobinfo        = $dg->getJob( $jobid );
[303]2245
[721]2246            if( !isset( $this->headerstrlen['id'] ) )
2247            {
2248                $this->headerstrlen['id']    = strlen( strval( $jobid ) );
2249            }
2250            else if( strlen( strval( $jobid ) ) > $this->headerstrlen['id'] )
2251            {
2252                $this->headerstrlen['id']    = strlen( strval( $jobid ) );
2253            }
[303]2254
[721]2255            if( !isset( $this->headerstrlen['owner'] ) )
2256            {
2257                $this->headerstrlen['owner']    = strlen( strval( $jobinfo['owner'] ) );
2258            }
2259            else if( strlen( strval( $jobinfo['owner'] ) ) > $this->headerstrlen['owner'] )
2260            {
2261                $this->headerstrlen['owner']    = strlen( strval( $jobinfo['owner'] ) );
2262            }
[303]2263
[721]2264            if( !isset( $this->headerstrlen['queue'] ) )
2265            {
2266                $this->headerstrlen['queue']    = strlen( strval( $jobinfo['queue'] ) );
2267            }
2268            else if( strlen( strval( $jobinfo['queue'] ) ) > $this->headerstrlen['queue'] )
2269            {
2270                $this->headerstrlen['queue']    = strlen( strval( $jobinfo['queue'] ) );
2271            }
[303]2272
[721]2273            if( !isset( $jobinfo['ppn'] ) )
2274            {
2275                $jobinfo['ppn'] = 1;
2276            }
[303]2277
[721]2278            $cpus            = count( $jobinfo['nodes'] ) * intval( $jobinfo['ppn'] );
[303]2279
[721]2280            if( !isset( $this->headerstrlen['cpus'] ) )
2281            {
2282                $this->headerstrlen['cpus']    = strlen( strval( $cpus ) );
2283            }
2284            else if( strlen( strval( $cpus ) ) > $this->headerstrlen['cpus'] )
2285            {
2286                $this->headerstrlen['cpus']    = strlen( strval( $cpus ) );
2287            }
[303]2288
[721]2289            $nodes            = count( $jobinfo['nodes'] );
[303]2290
[721]2291            if( !isset( $this->headerstrlen['nodes'] ) )
2292            {
2293                $this->headerstrlen['nodes']    = strlen( strval( $nodes ) );
2294            }
2295            else if( strlen( strval( $nodes) ) > $this->headerstrlen['nodes'] )
2296            {
2297                $this->headerstrlen['nodes']    = strlen( strval( $nodes ) );
2298            }
[303]2299
[721]2300            $runningtime        = makeTime( intval( $jobinfo[reported] ) - intval( $jobinfo['start_timestamp'] ) );
[303]2301
[721]2302            if( !isset( $this->headerstrlen['runningtime'] ) )
2303            {
2304                $this->headerstrlen['runningtime']    = strlen( strval( $runningtime) );
2305            }
2306            else if( strlen( strval( $runningtime) ) > $this->headerstrlen['runningtime'] )
2307            {
2308                $this->headerstrlen['runningtime']    = strlen( strval( $runningtime) );
2309            }
[303]2310
[721]2311            if( !isset( $this->headerstrlen['name'] ) )
2312            {
2313                $this->headerstrlen['name']    = strlen( strval( $jobinfo['name'] ) );
2314            }
2315            else if( strlen( strval( $jobinfo['name'] ) ) > $this->headerstrlen['name'] )
2316            {
2317                $this->headerstrlen['name']    = strlen( strval( $jobinfo['name'] ) );
2318            }
2319        }
[303]2320
[721]2321        $xoffset    = 5;
[303]2322
[721]2323        foreach( $this->headerstrlen as $headername => $headerlen )
2324        {
2325            $colorgreen    = imageColorAllocate( $this->image, 0, 200, 0 );
[303]2326
[721]2327            if( $headerlen < strlen( $headername ) )
2328            {
2329                $this->headerstrlen[$headername]    = strlen( $headername );
2330            }
[303]2331
[721]2332            imageString( $this->image, $this->font, $xoffset, $this->y_offset, ucfirst( $headername ), $colorgreen );
[303]2333
[721]2334            $xoffset    = $xoffset + ($this->fontwidth * ( $this->headerstrlen[$headername] + 1 ) );
2335        }
2336        $this->newLineOffset();
2337    }
[303]2338
[721]2339    function newLineOffset()
2340    {
2341        $this->y_offset        = $this->y_offset + $this->fontheight + $this->fontspaceing;
2342    }
[303]2343
[721]2344    function draw()
2345    {
2346        $xlen        = 450;
2347        $ylen        = ( count( $this->njobs ) * ( $this->fontheight + $this->fontspaceing ) ) + (3 * $this->fontheight);
[303]2348
[721]2349        $this->image    = imageCreateTrueColor( $xlen, $ylen );
2350        $colorwhite    = imageColorAllocate( $this->image, 255, 255, 255 );
2351        imageFill( $this->image, 0, 0, $colorwhite );                         
[303]2352
[721]2353        $colorblue    = imageColorAllocate( $this->image, 0, 0, 255 );
[303]2354
[721]2355        imageString( $this->image, $this->font, 1, $this->y_offset, "Monarch Joblist - host: ".$this->host, $colorblue );
2356        $this->newLineOffset();
[303]2357
[721]2358        $this->drawHeader();
2359        $this->drawJobs();
[303]2360
[721]2361        header( 'Content-type: image/png' );
2362        imagePNG( $this->image );
2363        imageDestroy( $this->image );
2364    }
[303]2365}
2366
[331]2367function imageStringDown( &$image, $font, $x, $y, &$s, &$col )
2368{
[721]2369    $fw    = imagefontwidth( $font);
2370    $fh    = imagefontheight( $font);
2371   
2372    $fontspacing = 0;
[331]2373
[721]2374    $fx    = $x;
2375    $fy    = $y;
[331]2376
[721]2377    for( $n=0; $n<strlen( $s ); $n++ )
2378    {
2379        $myc    = $s{$n};
[331]2380
[721]2381        imagestring( $image, $font, $fx, $fy, $myc, $col );
[331]2382
[721]2383        $fy    += ($fontspacing + $fh );
2384    }
[331]2385}
2386
[329]2387function array_rem( $val, &$arr )
2388{
[721]2389    // Delete val from arr
2390    //
2391    $i    = array_search( $val, $arr );
[329]2392
[721]2393    if( $i == false ) return false;
[329]2394
[721]2395    $arr    = array_merge( array_slice( $arr, 0, $i ), array_slice( $arr, $i+1, count( $arr ) ) );
[329]2396
[721]2397    return true;
[329]2398}
2399
2400function cmp( $a, $b ) 
2401{
[721]2402    global $SORT_ORDER;
2403    global $skan_str;
2404    global $x_first, $y_first;
2405    global $x_present, $y_present;
[329]2406
[721]2407    $a_node        = $a;
2408    $b_node        = $b;
2409    $a        = $a_node->getHostname();
2410    $b        = $b_node->getHostname();
[329]2411
[721]2412    if( $a == $b ) return 0;
[329]2413
[721]2414    $a_x        = 0;
2415    $b_x        = 0;
2416    $a_y        = 0;
2417    $b_y        = 0;
[339]2418
[721]2419    if( $x_present && $y_present )
2420    {
2421        if( $x_first )
2422        {
2423            $n = sscanf( $a, $skan_str, $a_x, $a_y );
2424            $n = sscanf( $b, $skan_str, $b_x, $b_y );
2425        }
2426        else if( $y_first )
2427        {
2428            $n = sscanf( $a, $skan_str, $a_y, $a_x );
2429            $n = sscanf( $b, $skan_str, $b_y, $b_x );
2430        }
2431    } 
2432    else if( $x_present && !$y_present )
2433    {
2434        $n = sscanf( $a, $skan_str, $a_x );
2435        $n = sscanf( $b, $skan_str, $b_x );
2436    }
2437    else if( $y_present && !$x_present )
2438    {
2439        $n = sscanf( $a, $skan_str, $a_y );
2440        $n = sscanf( $b, $skan_str, $b_y );
2441    }
[329]2442
[721]2443    if ( $SORT_ORDER=="desc" )
2444    {
[329]2445
[721]2446        if( $x_present && $y_present )
2447        {
2448            // 1  = a < b
2449            // -1 = a > b
2450            //
2451            if ($a_x == $b_x)
2452            {
2453                if ($a_y < $b_y)
2454                {
2455                    return 1;
2456                }
2457                else if ($a_y > $b_y)
2458                {
2459                    return -1;
2460                }
2461            }
2462            else if ($a_x < $b_x)
2463            {
2464                return 1;
2465            }
2466            else if ($a_x > $b_x)
2467            {
2468                return -1;
2469            }
2470        } 
2471        else if( $x_present && !$y_present )
2472        {
2473            if ($a_x < $b_x)
2474            {
2475                return 1;
2476            }
2477            else if ($a_x > $b_x)
2478            {
2479                return -1;
2480            }
2481        }
2482        else if( $y_present && !$x_present )
2483        {
2484            if ($a_y < $b_y)
2485            {
2486                return 1;
2487            }
2488            else if ($a_y > $b_y)
2489            {
2490                return -1;
2491            }
2492        }
2493    }
2494    else if ( $SORT_ORDER == "asc" )
2495    {
[329]2496
[721]2497        if( $x_present && $y_present )
2498        {
2499            // 1  = a > b
2500            // -1 = a < b
2501            //
2502            if ($a_x == $b_x)
2503            {
2504                if ($a_y > $b_y)
2505                {
2506                    return 1;
2507                }
2508                else if ($a_y < $b_y)
2509                {
2510                    return -1;
2511                }
2512            }
2513            else if ($a_x > $b_x)
2514            {
2515                return 1;
2516            }
2517            else if ($a_x < $b_x)
2518            {
2519                return -1;
2520            }
2521        }
2522        else if( $x_present && !$y_present )
2523        {
2524            if ($a_x > $b_x)
2525            {
2526                return 1;
2527            }
2528            else if ($a_x < $b_x)
2529            {
2530                return -1;
2531            }
2532        }
2533        else if( $y_present && !$x_present )
2534        {
2535            if ($a_y > $b_y)
2536            {
2537                return 1;
2538            }
2539            else if ($a_y < $b_y)
2540            {
2541                return -1;
2542            }
2543        }
2544    }
[329]2545}
[519]2546function makeTime( $time )
2547{
[303]2548        $days = intval( $time / 86400 );
2549        $time = ($days>0) ? $time % ($days * 86400) : $time;
2550
2551        $date_str = '';
2552        $day_str = '';
2553
[519]2554        if( $days > 0 )
[721]2555        {
2556            if( $days > 1 )
2557            {
2558                $day_str .= $days . ' days';
2559            }
2560            else
2561            {
2562                $day_str .= $days . ' day';
2563            }
[303]2564        }
2565
2566        $hours = intval( $time / 3600 );
2567        $time = $hours ? $time % ($hours * 3600) : $time;
2568
[519]2569        if( $hours > 0 )
[721]2570        {
2571             $date_str .= $hours . ':';
2572             $date_unit = 'hours'; 
[303]2573        }
2574
2575        $minutes = intval( $time / 60 );
2576        $seconds = $minutes ? $time % ($minutes * 60) : $time;
2577
[519]2578        if( $minutes > 0 )
[721]2579        {
2580            if( $minutes >= 10 )
2581            {
2582                $date_str .= $minutes . ':';
2583            }
2584            else
2585            {
2586                $date_str .= '0' . $minutes . ':';
2587            }
[303]2588                $date_unit = (!isset($date_unit)) ? 'minutes' : $date_unit;
[519]2589        }
[721]2590        else
2591        {
2592            if($hours > 0 )
2593            {
2594                $date_str .= '00:';
2595                $date_unit = (!isset($date_unit)) ? 'minutes' : $date_unit;
2596            }
[303]2597        }
2598
2599        $date_unit = (!isset($date_unit)) ? 'seconds' : $date_unit;
2600
[519]2601        if( $seconds > 0 )
[721]2602        {
2603            if( $seconds >= 10 )
2604            {
2605                $date_str .= $seconds . ' ' . $date_unit;
2606            }
2607            else
2608            {
2609                $date_str .= '0' . $seconds . ' ' . $date_unit;
2610            }
[519]2611        }
[721]2612        else if ( $hours > 0 or $minutes > 0 )
2613        {
2614            $date_str .= '00 ' . $date_unit;
2615        }
[303]2616
[519]2617        if( $days > 0)
[721]2618        {
2619            if( $hours > 0 or $minutes > 0 or $seconds > 0 )
2620            {
2621                $date_str = $day_str . ' - ' . $date_str;
2622            }
2623            else
2624            {
2625                $date_str = $day_str;
2626            }
[303]2627        }
2628        return $date_str;
2629}
[102]2630?>
Note: See TracBrowser for help on using the repository browser.