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

Last change on this file since 723 was 723, checked in by ramonb, 9 years ago

libtoga.php,
overview.php,
graph.php:

  • renamed MONARCH-metrics to zplugin-monarch-metrics

version.php:

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