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

Last change on this file since 749 was 749, checked in by ramonb, 11 years ago
  • more speedup attempts
  • Property svn:keywords set to Id
File size: 69.3 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 749 2013-03-25 17:49:23Z 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 $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 $conf;
346        global $JOB_ARCHIVE_DIR;
347
348        $this->rrdbin        = $conf['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, $clustername;
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        $this->clustername = $clustername;
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        if( $this->port == '8652' )
493        {
494            $request = "/" . $this->clustername . "\n";
495            $rc = fputs($fp, $request);
496            if (!$rc)
497            {
498                $error = "Could not sent request to gmetad: $errstr";
499                if ($debug) print "<br/>DEBUG: $error\n";
500                   return FALSE;
501            }
502        }
503
504        stream_set_timeout( $fp, 30 );
505
506        while ( !feof( $fp ) )
507        {
508            $data .= fread( $fp, 16384 );
509        }
510
511        fclose( $fp );
512
513        return $data;
514    }
515}
516
517class DataGatherer
518{
519    var $xmlhandler, $data, $httpvars;
520
521    function DataGatherer( $cluster )
522    {
523        $this->cluster    = $cluster;
524        $this->httpvars = $httpvars;
525    }
526
527    function parseXML( $data )
528    {
529
530        $this->parser         = xml_parser_create();
531        $this->xmlhandler     = new TorqueXMLHandler( $this->cluster );
532
533        xml_set_element_handler( $this->parser, array( &$this->xmlhandler, 'startElement' ), array( &$this->xmlhandler, 'stopElement' ) );
534
535        if ( !xml_parse( $this->parser, $data ) )
536        {
537            $error = sprintf( 'XML error: %s at %d', xml_error_string( xml_get_error_code( $this->parser ) ), xml_get_current_line_number( $this->parser ) );
538        }
539        $handler = &$this->xmlhandler;
540        $handler->finishUp();
541    }
542
543    function printInfo()
544    {
545        $handler = $this->xmlhandler;
546        $handler->printInfo();
547    }
548
549    function getUsingFQDN()
550    {
551        $handler = $this->xmlhandler;
552        return $handler->getUsingFQDN();
553    }
554
555    function getNodes()
556    {
557        $handler = $this->xmlhandler;
558        return $handler->getNodes();
559    }
560
561    function getNode( $node )
562    {
563        $handler = $this->xmlhandler;
564        return $handler->getNode( $node );
565    }
566
567    function getCpus()
568    {
569        $handler = $this->xmlhandler;
570        return $handler->getCpus();
571    }
572
573    function getJobs()
574    {
575        $handler = $this->xmlhandler;
576        return $handler->getJobs();
577    }
578
579    function getJob( $job )
580    {
581        $handler = $this->xmlhandler;
582        return $handler->getJob( $job );
583    }
584
585    function getHeartbeat()
586    {
587        $handler = $this->xmlhandler;
588        return $handler->getHeartbeat();
589    }
590
591    function isJobmonRunning()
592    {
593        $handler = $this->xmlhandler;
594        return $handler->isJobmonRunning();
595    }
596}
597
598class TorqueXMLHandler
599{
600    var $clusters, $heartbeat, $nodes, $jobs, $clustername, $proc_cluster;
601
602    function TorqueXMLHandler( $clustername )
603    {
604        $this->jobs        = array();
605        $this->clusters     = array();
606        $this->nodes         = array();
607        $this->heartbeat     = array();
608        $this->down_nodes    = array();
609        $this->offline_nodes    = array();
610        $this->clustername    = $clustername;
611        $this->proc_cluster = null;
612        $this->fqdn        = 1;
613    }
614
615    function getUsingFQDN()
616    {
617        return $this->fqdn;
618    }
619
620    function getCpus()
621    {
622        $cpus = 0;
623
624        if( isset( $this->jobs ) && count( $this->jobs ) > 0 )
625        {
626            foreach( $this->jobs as $jobid=>$jobattrs )
627            {
628                $nodes    = count( $jobattrs['nodes'] );
629                $ppn    = (int) $jobattrs['ppn'] ? $jobattrs['ppn'] : 1;
630                $mycpus    = $nodes * $ppn;
631
632                $cpus    = $cpus + $mycpus;
633            }
634        }
635    }
636
637    function isJobmonRunning()
638    {
639        if (isset( $this->heartbeat['time'] ))
640        {
641            return 1;
642        }
643        else
644        {
645            return 0;
646        }
647    }
648
649    function makeHostname( $thostname, $tdomain=null )
650    {
651        // Should hostname be FQDN or short w/o domain
652        //
653        $nodes = &$this->nodes;
654
655        $fqdn = 1;
656
657        //$tdomain = explode( '.', $thostname );
658        //
659        // TODO?: extract domain from hostname or something?
660
661        if( $tdomain )
662        {
663            $domain_len    = 0 - strlen( $tdomain );
664
665            // Let's see if Ganglia use's FQDN or short hostnames
666            //
667            foreach( $nodes as $hostname => $nimage )
668            {
669                if( strpos( $hostname, $tomdain ) !== false )
670                {
671                    $fqdn    = 0;
672                }
673            }
674        }
675        else
676        {
677            $fqdn    = 0;
678        }
679   
680        if( $tdomain && $fqdn )
681        {
682            if( strpos( $thostname, $tdomain ) !== false )
683            {
684                $thostname = $thostname . '.'.$tdomain;
685            } 
686            else
687            {
688                $thostname = $thostname;
689            }
690        }
691
692        return $thostname;
693    }
694
695    function startElement( $parser, $name, $attrs )
696    {
697
698        if( isset( $attrs['TN'] ) )
699        {
700            if ( $attrs['TN'] )
701            {
702                // Ignore dead metrics. Detect and mask failures.
703                if ( $attrs['TN'] > $attrs['TMAX'] * 4 )
704                {
705                    return null;
706                }
707            }
708        }
709
710        $jobid = null;
711
712        if( $name == 'CLUSTER' )
713        {
714            $this->proc_cluster = $attrs['NAME'];
715            //printf("set proc cluster to %s\n", $attrs['NAME'] );
716            return null;
717        }
718        if( $this->proc_cluster != $this->clustername )
719        {
720            //printf("cluster does not match: %s\n", $this->clustername );
721            return null;
722        }
723
724        if( $name == 'HOST' )
725        {
726            $hostname = $attrs['NAME'];
727
728            //printf( "host %s\n", $hostname );
729            //$location = $attrs['LOCATION'];
730
731            if( !isset( $this->nodes[$hostname] ) )
732            {
733                $this->nodes[$hostname] = new NodeImage( $this->proc_cluster, $hostname );
734            }
735            return null;
736        }
737        if( $name == 'METRIC' and ( strpos( $attrs['NAME'], 'zplugin_monarch' ) !== false ) )
738        {
739            if( strpos( $attrs['NAME'], 'zplugin_monarch_heartbeat' ) !== false )
740            {
741                $this->heartbeat['time'] = $attrs['VAL'];
742                return;
743            }
744            else if( strpos( $attrs['NAME'], 'zplugin_monarch_down' ) !== false )
745            {
746                $fields        = explode( ' ', $attrs['VAL'] );
747
748                $nodes_down    = array();
749                $down_domain    = null;
750
751                foreach( $fields as $f )
752                {
753                    $togavalues    = explode( '=', $f );
754
755                    $toganame    = $togavalues[0];
756                    $togavalue    = $togavalues[1];
757
758                    if( $toganame == 'nodes' )
759                    {
760                        $mynodes = explode( ';', $togavalue );
761
762                        foreach( $mynodes as $node )
763                        {
764                            $nodes_down[] = $node;
765                        }
766                    }
767                    else if( $toganame == 'domain' )
768                    {
769                        $down_domain = $togavalue;
770                    }
771                    else if( $toganame == 'reported' )
772                    {
773                        if( !isset( $this->down_nodes['heartbeat'] ) )
774                        {
775                            $this->down_nodes[$togavalue]    = array( $nodes_down, $down_domain );
776                        }
777                    }
778                }
779                return;
780            }
781            else if( strpos( $attrs['NAME'], 'zplugin_monarch_offline' ) !== false )
782            {
783                $fields        = explode( ' ', $attrs['VAL'] );
784
785                $nodes_offline    = array();
786                $offline_domain    = null;
787
788                foreach( $fields as $f )
789                {
790                    $togavalues    = explode( '=', $f );
791
792                    $toganame    = $togavalues[0];
793                    $togavalue    = $togavalues[1];
794
795                    if( $toganame == 'nodes' )
796                    {
797                        $mynodes = explode( ';', $togavalue );
798
799                        foreach( $mynodes as $node )
800                        {
801                            $nodes_offline[] = $node;
802                        }
803                    }
804                    else if( $toganame == 'domain' )
805                    {
806                        $offline_domain = $togavalue;
807                    }
808                    else if( $toganame == 'reported' )
809                    {
810                        if( !isset( $this->offline_nodes['heartbeat'] ) )
811                        {
812                            $this->offline_nodes[$togavalue] = array( $nodes_offline, $offline_domain );
813                        }
814                    }
815                }
816                return;
817            }
818            else if( strpos( $attrs['NAME'], 'zplugin_monarch_job' ) !== false )
819            {
820                sscanf( $attrs['NAME'], 'zplugin_monarch_job_%d_%s$', $monincr, $jobid );
821
822                if( !isset( $this->jobs[$jobid] ) )
823                {
824                    $this->jobs[$jobid] = array();
825                }
826
827                $fields = explode( ' ', $attrs['VAL'] );
828
829                foreach( $fields as $f )
830                {
831                    $togavalues = explode( '=', $f );
832
833                    $toganame = $togavalues[0];
834                    $togavalue = $togavalues[1];
835
836                    if( $toganame == 'nodes' )
837                    {
838                        if( $this->jobs[$jobid]['status'] == 'R' )
839                        {
840                            if( !isset( $this->jobs[$jobid][$toganame] ) )
841                            {
842                                $this->jobs[$jobid][$toganame] = array();
843                            }
844
845                            $mynodes = explode( ';', $togavalue );
846
847                            foreach( $mynodes as $node )
848                            {
849                                if( !in_array( $node, $this->jobs[$jobid][$toganame] ) )
850                                {
851                                    array_push( $this->jobs[$jobid][$toganame], $node );
852                                }
853                            }
854
855                        }
856                        else if( $this->jobs[$jobid]['status'] == 'Q' )
857                        {
858                            $this->jobs[$jobid][$toganame] = $togavalue;
859                        }
860                    }
861                    else
862                    {
863                        $this->jobs[$jobid][$toganame] = $togavalue;
864                    }
865                }
866
867                if( isset( $this->jobs[$jobid]['nodes'] ) )
868                {
869                    $nr_nodes = count( $this->jobs[$jobid]['nodes'] );
870       
871                    if( $this->jobs[$jobid]['status'] == 'R' )
872                    {
873
874                        if( isset( $this->jobs[$jobid]['domain'] ) )
875                        {
876                            $domain        = $this->jobs[$jobid]['domain'];
877                            $domain_len    = 0 - strlen( $domain );
878
879                            $nodekeys     = array_keys( $this->nodes );
880
881                            $first_host    = $nodekeys[0];
882                            // Let's see if Ganglia use's FQDN or short hostnames
883                            //
884                            if( strpos( $first_host, $domain ) === false )
885                            {
886                                $this->fqdn    = 0;
887                            }
888                        }
889                        else
890                        {
891                            $this->fqdn    = 0;
892                        }
893
894                        foreach( $this->jobs[$jobid]['nodes'] as $node )
895                        {
896
897                            // Only add domain name to the hostname if Ganglia is doing that too
898                            //
899                            if( $this->fqdn && isset( $this->jobs[$jobid]['domain'] ) )
900                            {
901                                if( strpos( $node, $domain ) === false )
902                                {
903                                    $host = $node. '.'.$domain;
904                                } else
905                                {
906                                    $host = $node;
907                                }
908                            }
909                            else
910                            {
911                                $host    = $node;
912                            }
913
914                            if( !isset( $this->nodes[$host] ) )
915                            {
916                                $my_node = new NodeImage( $this->proc_cluster, $host );
917                            }
918                            else
919                            {
920                                $my_node = $this->nodes[$host];
921                            }
922
923                            if( !$my_node->hasJob( $jobid ) )
924                            {
925                                if( isset( $jobs[$jobid]['ppn'] ) )
926                                {
927                                    $my_node->addJob( $jobid, ((int) $jobs[$jobid]['ppn']) );
928                                }
929                                else
930                                {
931                                    $my_node->addJob( $jobid, 1 );
932                                }
933                            }
934
935                            $this->nodes[$host] = $my_node;
936                        }
937                    }
938                }
939            }
940            return;
941        }
942    }
943
944    function finishUp( )
945    {
946        $nodes    = $this->nodes;
947
948        if( sizeof( $this->down_nodes ) > 0 )
949        {
950            foreach( $this->down_nodes as $reported => $dnodes )
951            {
952                if( $reported == $this->heartbeat['time'] )
953                {
954                    $domain = $dnodes[1];
955
956                    foreach( $dnodes[0] as $downhost )
957                    {
958                        $downhost = $this->makeHostname( $downhost, $domain );
959
960                        if( isset( $nodes[$downhost] ) )
961                        {
962                            // OMG PHP4 is fking stupid!
963                            // $nodes[$downhost]->setDown( 1 ) won't work here..
964                            //
965                            $mynode = $nodes[$downhost];
966                            $mynode->setDown( 1 );
967                            $nodes[$downhost] = $mynode;
968                        }
969                    }
970                }
971            }
972        }
973
974        if( sizeof( $this->offline_nodes ) > 0 )
975        {
976            foreach( $this->offline_nodes as $reported => $onodes )
977            {
978                if( $reported == $this->heartbeat['time'] )
979                {
980                    $domain = $onodes[1];
981
982                    foreach( $onodes[0] as $offlinehost )
983                    {
984                        $offlinehost = $this->makeHostname( $offlinehost, $domain );
985
986                        if( isset( $nodes[$offlinehost] ) )
987                        {
988                            // OMG PHP4 is fking stupid!
989                            // $nodes[$offlinehost]->setDown( 1 ) won't work here..
990                            //
991                            $mynode = $nodes[$offlinehost];
992                            $mynode->setOffline( 1 );
993                            $nodes[$offlinehost] = $mynode;
994                        }
995                    }
996                }
997            }
998        }
999
1000        $this->nodes = $nodes;
1001    }
1002
1003    function stopElement( $parser, $name )
1004    {
1005    }
1006
1007    function printInfo()
1008    {
1009        $jobs = &$this->jobs;
1010
1011        printf( "---jobs---\n" );
1012
1013        foreach( $jobs as $jobid => $job )
1014        {
1015            printf( "job %s\n", $jobid );
1016
1017            if( isset( $job['nodes'] ) )
1018            {
1019                foreach( $job['nodes'] as $node )
1020                {
1021                    $mynode = $this->nodes[$node];
1022                    $hostname = $mynode->getHostname();
1023                    $location = $mynode->getLocation();
1024
1025                    printf( "\t- node %s\tlocation %s\n", $hostname, $location );
1026                }
1027            }
1028        }
1029
1030        printf( "---nodes---\n" );
1031
1032        $nodes = &$this->nodes;
1033
1034        foreach( $nodes as $node )
1035        {
1036            $hostname = $node->getHostname();
1037            $location = $node->getLocation();
1038            $jobs = implode( ' ', $node->getJobs() );
1039            printf( "* node %s\tlocation %s\tjobs %s\n", $hostname, $location, $jobs );
1040        }
1041    }
1042
1043    function getNodes()
1044    {
1045        return $this->nodes;
1046    }
1047
1048    function getNode( $node )
1049    {
1050        $nodes = &$this->nodes;
1051
1052        if( isset( $nodes[$node] ) )
1053        {
1054            return $nodes[$node];
1055        }
1056        else
1057        {
1058            return NULL;
1059        }
1060    }
1061
1062    function getJobs()
1063    {
1064        return $this->jobs;
1065    }
1066
1067    function getJob( $job )
1068    {
1069        $jobs = &$this->jobs;
1070
1071        if( isset( $jobs[$job] ) )
1072        {
1073            return $jobs[$job];
1074        }
1075        else
1076        {
1077            return NULL;
1078        }
1079    }
1080
1081    function getHeartbeat()
1082    {
1083        return $this->heartbeat['time'];
1084    }
1085}
1086
1087class NodeImage
1088{
1089    var $image, $x, $y, $hostname, $jobs, $tasks, $showinfo;
1090
1091    function NodeImage( $cluster, $hostname )
1092    {
1093        global $SMALL_CLUSTERIMAGE_NODEWIDTH;
1094
1095        $this->jobs        = array();
1096        $this->tasks        = 0;
1097        $this->hostname        = $hostname;
1098        $this->clustername    = $cluster;
1099        $this->showinfo        = 1;
1100        $this->size        = $SMALL_CLUSTERIMAGE_NODEWIDTH;
1101        $this->down        = 0;
1102        $this->offline        = 0;
1103    }
1104
1105    function addJob( $jobid, $cpus )
1106    {
1107        $jobs        = &$this->jobs;
1108        $jobs[]        = $jobid;
1109        $this->jobs    = $jobs;
1110
1111        $this->addTask( $cpus );
1112    }
1113
1114    function hasJob( $jobid )
1115    {
1116        $jobfound = 0;
1117
1118        if( count( $this->jobs ) > 0 )
1119        {
1120            foreach( $this->jobs as $job )
1121            {
1122                if( $job == $jobid )
1123                {
1124                    $jobfound = 1;
1125                }
1126            }
1127        }
1128
1129        return $jobfound;
1130    }
1131
1132    function addTask( $cpus )
1133    {
1134        $this->tasks = $this->tasks + $cpus;
1135    }
1136    function setDown( $down )
1137    {
1138        $this->down = $down;
1139    }
1140    function isDown()
1141    {
1142        return $this->down;
1143    }
1144    function setOffline( $offline )
1145    {
1146        $this->offline = $offline;
1147    }
1148    function isOffline()
1149    {
1150        return $this->offline;
1151    }
1152    function setImage( $image )
1153    {
1154        $this->image = $image;
1155    }
1156    function setCoords( $x, $y )
1157    {
1158        $this->x = $x;
1159        $this->y = $y;
1160    }
1161    function getX()
1162    {
1163        return $this->x;
1164    }
1165    function getY()
1166    {
1167        return $this->y;
1168    }
1169
1170    function getImagemapArea()
1171    {
1172        $area_topleft        = $this->x . "," . $this->y;
1173        $area_bottomright    = ($this->x + $this->size) . "," . ($this->y + $this->size);
1174        $area_coords        = $area_topleft . "," . $area_bottomright;
1175
1176        $area_href        = "./?c=" . $this->clustername . "&h=" . $this->hostname;
1177
1178        $area_tooltip        = $this->hostname;
1179
1180        if( $this->down)
1181        {
1182            $area_tooltip        = $area_tooltip . ": DOWN";
1183        }
1184        else if( $this->offline )
1185        {
1186            $area_tooltip        = $area_tooltip . ": OFFLINE";
1187        }
1188
1189        $area_tooltip        = $area_tooltip . ": " . implode( " ", $this->jobs );
1190
1191        $tag_href        = "HREF=\"" . $area_href . "\"";
1192        $tag_coords        = "COORDS=\"" . $area_coords . "\"";
1193        $tag_tooltip1        = "ALT=\"" . $area_tooltip . "\"";
1194        $tag_tooltip2        = "TITLE=\"" . $area_tooltip . "\"";
1195
1196        return ("<AREA SHAPE=\"RECT\" " . $tag_coords . " " . $tag_href . " " . $tag_tooltip1 . " " . $tag_tooltip2 . ">");
1197    }
1198
1199    function colorHex( $color )
1200    {
1201        $my_color = imageColorAllocate( $this->image, hexdec( substr( $color, 0, 2 )), hexdec( substr( $color, 2, 2 )), hexdec( substr( $color, 4, 2 )) );
1202
1203        return $my_color;
1204    }
1205
1206    function setLoad( $load )
1207    {
1208        $this->load = $load;
1209    }
1210
1211    function setHostname( $hostname )
1212    {
1213        $this->hostname = $hostname;
1214    }
1215
1216    function getHostname()
1217    {
1218        return $this->hostname;
1219    }
1220
1221    function getJobs()
1222    {
1223        return $this->jobs;
1224    }
1225
1226    function setShowinfo( $showinfo )
1227    {
1228        $this->showinfo = $showinfo;
1229    }
1230
1231    function drawSmall()
1232    {
1233        global $SMALL_CLUSTERIMAGE_NODEWIDTH;
1234
1235        $this->size    = $SMALL_CLUSTERIMAGE_NODEWIDTH;
1236
1237        $this->draw();
1238    }
1239
1240    function drawBig()
1241    {
1242        global $BIG_CLUSTERIMAGE_NODEWIDTH;
1243
1244        $this->size    = $BIG_CLUSTERIMAGE_NODEWIDTH;
1245
1246        $this->draw();
1247    }
1248
1249    function draw()
1250    {
1251        global $JOB_NODE_MARKING, $NODE_DOWN_MARKING, $NODE_OFFLINE_MARKING;
1252
1253        $black_color = imageColorAllocate( $this->image, 0, 0, 0 );
1254        $size = $this->size;
1255
1256        imageFilledRectangle( $this->image, $this->x, $this->y, $this->x+($size), $this->y+($size), $black_color );
1257
1258        if( $this->showinfo)
1259        {
1260            $this->load = $this->determineLoad();
1261
1262            if( !isset( $this->image ) or !isset( $this->x ) or !isset( $this->y ) )
1263            {
1264                printf( "aborting\n" );
1265                printf( "x %d y %d load %f\n", $this->x, $this->y, $load );
1266                return;
1267            }
1268
1269            // Convert Ganglias Hexadecimal load color to a Decimal one
1270            //
1271            $load = $this->determineLoad();   
1272            $usecolor = $this->colorHex( load_color($load) );
1273            imageFilledRectangle( $this->image, $this->x+1, $this->y+1, $this->x+($size-1), $this->y+($size-1), $usecolor );
1274            if( $this->down )
1275            {
1276                imageString( $this->image, 1, $this->x+(($size/2)-1), $this->y+(($size/2)-4), $NODE_DOWN_MARKING, $black_color );
1277            }
1278            else if( $this->offline )
1279            {
1280                imageString( $this->image, 1, $this->x+(($size/2)-1), $this->y+(($size/2)-4), $NODE_OFFLINE_MARKING, $black_color );
1281            }
1282            else if( count( $this->jobs ) > 0 )
1283            {
1284                imageString( $this->image, 1, $this->x+(($size/2)-1), $this->y+(($size/2)-4), $JOB_NODE_MARKING, $black_color );
1285            }
1286        }
1287        else
1288        {
1289            // White
1290            $usecolor = imageColorAllocate( $this->image, 255, 255, 255 );
1291            imageFilledRectangle( $this->image, $this->x+1, $this->y+1, $this->x+($size-1), $this->y+($size-1), $usecolor );
1292        }
1293    }
1294
1295    function determineLoad()
1296    {
1297        global $metrics;
1298
1299        $cpus = $metrics[$this->hostname]['cpu_num']['VAL'];
1300        if (!$cpus)
1301        {
1302            $cpus=1;
1303        }
1304
1305        $load_one    = $metrics[$this->hostname]['load_one']['VAL'];
1306        $load        = ((float) $load_one)/$cpus;
1307
1308        return $load;
1309    }
1310}
1311
1312class ClusterImage
1313{
1314    var $dataget, $image, $clustername;
1315    var $filtername, $filters;
1316
1317    function ClusterImage( $data, $clustername )
1318    {
1319        $this->dataget        = new DataGatherer( $clustername );
1320        $this->data        = $data;
1321        $this->clustername    = $clustername;
1322        $this->filters        = array();
1323        $this->size        = 's';
1324        $this->width        = 0;
1325        $this->height        = 0;
1326        $this->output        = 1;
1327        $this->jobs         = null;
1328        $this->nodes        = null;
1329    }
1330
1331    function getWidth()
1332    {
1333        return $this->width;
1334    }
1335    function getHeight()
1336    {
1337        return $this->height;
1338    }
1339    function setSmall()
1340    {
1341        $this->size    = 's';
1342    }
1343    function setBig()
1344    {
1345        $this->size    = 'b';
1346    }
1347    function setNoimage()
1348    {
1349        $this->output    = 0;
1350    }
1351    function setJobs($jobs )
1352    {
1353        $this->jobs     = &$jobs;
1354    }
1355    function getJobs()
1356    {
1357        if( $this->jobs == null )
1358        {
1359            $mydatag = $this->dataget;
1360            $mydatag->parseXML( $this->data );
1361            $this->jobs = $mydatag->getJobs();
1362        }
1363
1364        return $this->jobs;
1365    }
1366    function getNodes()
1367    {
1368        if( $this->nodes== null )
1369        {
1370            $mydatag = $this->dataget;
1371            $mydatag->parseXML( $this->data );
1372            $this->nodes = $mydatag->getNodes();
1373        }
1374
1375        return $this->nodes;
1376    }
1377    function setNodes($nodes)
1378    {
1379        $this->nodes    = &$nodes;
1380    }
1381    function isSmall()
1382    {
1383        return ($this->size == 's');
1384    }
1385    function isBig()
1386    {
1387        return ($this->size == 'b');
1388    }
1389    function setFilter( $filtername, $filtervalue )
1390    {
1391        $this->filters[$filtername] = $filtervalue;
1392    }
1393
1394    function filterNodes( $jobs, $nodes )
1395    {
1396        $filtered_nodes = array();
1397
1398        //print_r( $nodes );
1399
1400        foreach( $nodes as $node )
1401        {
1402            $hostname = $node->getHostname();
1403
1404            $addhost = 1;
1405
1406            if( count( $this->filters ) > 0 )
1407            {
1408                $mynjobs = $node->getJobs();
1409
1410                if( count( $mynjobs ) > 0 )
1411                {
1412                    foreach( $mynjobs as $myjob )
1413                    {
1414                        foreach( $this->filters as $filtername => $filtervalue )
1415                        {
1416                            if( $filtername!=null && $filtername!='' )
1417                            {
1418                                if( $filtername == 'jobid' && !$node->hasJob( $filtervalue) )
1419                                {
1420                                    $addhost = 0;
1421                                }
1422                                else if( $filtername != 'jobid' )
1423                                {
1424                                    if( $jobs[$myjob][$filtername] != $filtervalue )
1425                                    {
1426                                        $addhost = 0;
1427                                    }
1428                                }
1429                            }
1430                        }
1431                    }
1432                }
1433                else
1434                {
1435                    $addhost = 0;
1436                }
1437            }
1438
1439            if( $addhost )
1440            {
1441                $filtered_nodes[] = $hostname;
1442            }
1443        }
1444
1445        return $filtered_nodes;
1446    }
1447
1448    function draw()
1449    {
1450        global $SMALL_CLUSTERIMAGE_MAXWIDTH, $SMALL_CLUSTERIMAGE_NODEWIDTH;
1451        global $BIG_CLUSTERIMAGE_MAXWIDTH, $BIG_CLUSTERIMAGE_NODEWIDTH;
1452        global $CLUSTER_CONFS, $confcluster, $SHOW_EMPTY_COLUMN, $SHOW_EMPTY_ROW;
1453
1454        global $SORTBY_HOSTNAME, $SORT_ORDER, $skan_str;
1455        global $x_first, $y_first;
1456
1457        foreach( $CLUSTER_CONFS as $confcluster => $conffile )
1458        {
1459            if( strtolower( trim($this->clustername) ) == strtolower(trim($confcluster)) )
1460            {
1461                include_once $conffile;
1462            }
1463        }
1464
1465        if( $this->isSmall() )
1466        {
1467            $max_width    = $SMALL_CLUSTERIMAGE_MAXWIDTH;
1468            $node_width    = $SMALL_CLUSTERIMAGE_NODEWIDTH;
1469        }
1470        else if( $this->isBig() )
1471        {
1472            $max_width    = $BIG_CLUSTERIMAGE_MAXWIDTH;
1473            $node_width    = $BIG_CLUSTERIMAGE_NODEWIDTH;
1474        }
1475
1476        $nodes        = $this->getNodes();
1477        $nodes_hosts    = array_keys( $nodes );
1478
1479        $nodes_nr    = count( $nodes );
1480
1481        $nodes_size    = $nodes_nr*$node_width;
1482        $node_rows    = 0;
1483
1484        if( $nodes_size > $max_width )
1485        {
1486            $nodes_per_row = ( (int) ($max_width/$node_width) );
1487        }
1488        else
1489        {
1490            $nodes_per_row = $nodes_size;
1491            $node_rows = 1;
1492        }
1493
1494        if( $nodes_per_row < $nodes_nr )
1495        {
1496            $node_rows = ( (int) ($nodes_nr/$nodes_per_row) );
1497            $node_rest = fmod( $nodes_nr, $nodes_per_row );
1498
1499            if( $node_rest > 0 )
1500            {
1501                $node_rows++;
1502            }
1503        }
1504
1505        $y_offset    = 0;
1506        $font         = 2;
1507        $fontwidth    = ImageFontWidth( $font );
1508        $fontheight    = ImageFontHeight( $font );
1509        $fontspaceing    = 2;
1510        $y_offset    = $fontheight + (2 * $fontspaceing);
1511
1512        $this->width    = $max_width;
1513        $this->height    = ($y_offset + (($node_rows*$node_width)+1) );
1514
1515        $jobs = $this->getJobs();
1516        $filtered_nodes = $this->filterNodes( $jobs, $nodes );
1517
1518        if( $SORTBY_HOSTNAME != "" )
1519        {
1520                $sorted     = array();
1521
1522            $x_first    = 0;
1523            $y_first    = 0;
1524
1525            $skan_str    = $SORTBY_HOSTNAME;
1526
1527            global $x_present, $y_present;
1528            $x_present    = false;
1529            $y_present    = false;
1530
1531            // Should we scan by X, Y or both
1532            //
1533            if(strpos( $SORTBY_HOSTNAME, "{x}" ) != false )
1534            {
1535                $x_str        = "{x}";
1536                $x_present    = true;
1537            }
1538            else if(strpos( $SORTBY_HOSTNAME, "{X}" ) != false )
1539            {
1540                $x_str        = "{X}";
1541                $x_present    = true;
1542            }
1543            if(strpos( $SORTBY_HOSTNAME, "{y}" ) != false )
1544            {
1545                $y_str        = "{y}";
1546                $y_present    = true;
1547            }
1548            else if(strpos( $SORTBY_HOSTNAME, "{Y}" ) != false )
1549            {
1550                $y_str        = "{Y}";
1551                $y_present    = true;
1552            }
1553
1554            // If we should scan for both X and Y: see which one is first
1555            //
1556            if(( strpos( $SORTBY_HOSTNAME, $x_str ) < strpos( $SORTBY_HOSTNAME, $y_str ) ) && ( $x_present && $y_present ))
1557            {
1558                $x_first    = 1;
1559            }
1560            else if(( strpos( $SORTBY_HOSTNAME, $x_str ) > strpos( $SORTBY_HOSTNAME, $y_str ) ) && ( $x_present && $y_present ))
1561            {
1562                $y_first    = 1;
1563       
1564            }
1565            else if( $x_present )
1566            {
1567                $x_first    = 1;
1568            }
1569            else if( $y_present )
1570            {
1571                $y_first    = 1;
1572            }
1573
1574            // Now replace our {x} and {y} with %d for sscanf parsing
1575            //
1576            if(( $x_first ) && ( $x_present && $y_present ) )
1577            {
1578                $skan_str    = str_replace( $x_str, "%d", $skan_str );
1579                $skan_str    = str_replace( $y_str, "%d", $skan_str );
1580            } 
1581            else if( $x_present)
1582            {
1583                $skan_str    = str_replace( $x_str, "%d", $skan_str );
1584            }
1585            else if( $y_present)
1586            {
1587                $skan_str    = str_replace( $y_str, "%d", $skan_str );
1588            }
1589
1590            $x_min        = null;
1591            $x_max        = null;
1592            $y_min        = null;
1593            $y_max        = null;
1594
1595            $x_columns    = array();
1596            $y_rows        = array();
1597
1598            // Now let's walk through all our nodes and see which one are valid for our scan pattern
1599            //
1600            foreach( $nodes as $hostname => $node )
1601            {
1602                $x    = null;
1603                $y    = null;
1604
1605                if( $x_present && $y_present )
1606                {
1607                    if( $x_first )
1608                    {
1609                        $n = sscanf( $hostname, $skan_str, $x, $y );
1610                    }
1611                    else if( $y_first )
1612                    {
1613                        $n = sscanf( $hostname, $skan_str, $y, $x );
1614                    }
1615
1616                    // Remove nodes that don't match
1617                    //
1618                    if( $n < 2 )
1619                    {
1620                        // This node hostname has no match for: {x} and {y}
1621                        //
1622                        unset( $nodes[$hostname] );
1623                    }
1624                }
1625                else if( $x_present && !$y_present )
1626                {
1627                    $n = sscanf( $hostname, $skan_str, $x );
1628
1629                    // Remove nodes that don't match
1630                    //
1631                    if( $n < 1 )
1632                    {
1633                        // This node hostname has no match for: {x}
1634                        //
1635                        unset( $nodes[$hostname] );
1636                    }
1637                    $y    = 1;
1638                }
1639                else if( $y_present && !$x_present )
1640                {
1641                    $n = sscanf( $hostname, $skan_str, $y );
1642
1643                    // Remove nodes that don't match
1644                    //
1645                    if( $n < 1 )
1646                    {
1647                        // This node hostname has no match for: {y}
1648                        //
1649                        unset( $nodes[$hostname] );
1650                    }
1651                    $x    = 1;
1652                }
1653
1654                // Determine the lowest value of {x} that exists in all node hostnames
1655                //
1656                if( !$x_min && $x != null )
1657                {
1658                    $x_min    = $x;
1659                }
1660                else if( $x < $x_min && $x != null )
1661                {
1662                    $x_min    = $x;
1663                }
1664
1665                // Determine the highest value of {x} that exists in all node hostnames
1666                //
1667                if( !$x_max && $x != null )
1668                {
1669                    $x_max    = $x;
1670                }
1671                else if( $x > $x_max && $x != null )
1672                {
1673                    $x_max    = $x;
1674                }
1675
1676                // Determine the lowest value of {y} that exists in all node hostnames
1677                //
1678                if( !$y_min && $y != null )
1679                {
1680                    $y_min    = $y;
1681                }
1682                else if( $y < $y_min && $y != null )
1683                {
1684                    $y_min    = $y;
1685                }
1686
1687                // Determine the highest value of {y} that exists in all node hostnames
1688                //
1689                if( !$y_max && $y != null )
1690                {
1691                    $y_max    = $y;
1692                }
1693                else if( $y > $y_max && $y != null )
1694                {
1695                    $y_max    = $y;
1696                }
1697
1698                // Store which non-empty columns and rows we found
1699                //
1700                if( !in_array( $x, $x_columns ) )
1701                {
1702                    $x_columns[] = $x;
1703                }
1704                if( !in_array( $y, $y_rows ) )
1705                {
1706                    $y_rows[] = $y;
1707                }
1708            }
1709
1710            // Sort all the nodes (alpha and numerically)
1711            // 1: gb-r1n1, 2: gb-r1n2, 3: gb-r2n1, etc
1712            //
1713            $sorted_nodes    = usort( $nodes, "cmp" );
1714
1715            //print_r( $x_columns ) ;
1716
1717            $cur_node    = 0;
1718
1719            $x_offset    = 0;
1720            $y_offset    = 0;
1721            $font         = 2;
1722            $fontwidth    = ImageFontWidth( $font );
1723            $fontheight    = ImageFontHeight( $font );
1724            $fontspaceing    = 2;
1725
1726            if( $this->isSmall() ) 
1727            {
1728                $y_offset    = $y_offset + (2 * $fontspaceing) + $fontheight;
1729            }
1730
1731            if( $this->isBig() ) 
1732            {
1733                $y_offset    = ($fontheight * (1 + strlen( $x_max) ) ) + ((2 + strlen( $x_max)) * $fontspaceing);
1734                $x_offset    = ($fontwidth * (1 + strlen( $y_max) ) ) + ((2 + strlen( $y_max)) * $fontspaceing);
1735            }
1736
1737            $image_width    = $x_offset + ($node_width * ($x_max-$x_min+2));
1738
1739            if( $this->isSmall() ) 
1740            {
1741                $image_width    = $max_width;
1742            }
1743            else if( $this->isBig() ) 
1744            {
1745                $image_width    = ($image_width < $max_width) ? $image_width : $max_width;
1746            }
1747            $image_height    = $y_offset + ($node_width * ($y_max-$y_min+2));
1748
1749            $this->width    = $image_width;
1750            $this->heigth    = $image_heigth;
1751
1752            $image        = imageCreateTrueColor( $image_width, $image_height );
1753            $colorwhite    = imageColorAllocate( $image, 255, 255, 255 );
1754
1755            imageFill( $image, 0, 0, $colorwhite );
1756
1757            if( $this->isSmall() )
1758            {
1759                // Draw a fancy little header text to explain what it is
1760                //
1761                $colorblue    = imageColorAllocate( $image, 0, 0, 255 );
1762
1763                imageString( $image, $font, 2, 2, "Monarch Joblist - cluster: ".$this->clustername, $colorblue );
1764            }
1765
1766            if( $this->isBig() && ( isset( $SORT_XLABEL ) || isset( $SORT_YLABEL ) ) )
1767            {
1768                $colorblue    = imageColorAllocate( $image, 0, 0, 255 );
1769
1770                if( isset( $SORT_XLABEL ) )
1771                {
1772                    // Print the {x} label: rack
1773                    //
1774                    imageString( $image, $font, $x_offset, $fontspaceing, $SORT_XLABEL, $colorblue );
1775                }
1776
1777                if( isset( $SORT_YLABEL ) )
1778                {
1779                    // Stupid php without imageStringDown function... we'll make one ourself
1780                    //
1781
1782                    // Print the {y} label: node
1783                    //
1784                    imageStringDown( $image, $font, $fontspaceing, $y_offset, $SORT_YLABEL, $colorblue );
1785                }
1786            }
1787
1788            $previous_n    = 0;
1789            $previous_m    = 0;
1790            $x_empty_count    = 0;
1791            $y_empty_count    = 0;
1792
1793            // Let's start assigning x,y coordinates now
1794            //
1795            for( $n = $x_min; $n <= $x_max; $n++ )
1796            {
1797                for( $m = $y_min; $m <= $y_max; $m++ )
1798                {
1799                    if( $x_min > 0 )
1800                    {
1801                        $x    = $x_offset + ( ($n-$x_min) * $node_width ) - ($x_empty_count * $node_width);
1802                    }
1803                    if( $y_min > 0 )
1804                    {
1805                        $y    = $y_offset + ( ($m-$y_min) * $node_width ) - ($y_empty_count * $node_width);
1806                    }
1807
1808                    // Don't show empty rows/columns if option enabled
1809                    //
1810                    if( !in_array( $n, $x_columns ) && !$SHOW_EMPTY_COLUMN )
1811                    {
1812                        // Skip to next iteration: we don't want a empty column
1813                        //
1814                        if( $n > $previous_n )
1815                        {
1816                            $previous_n = $n;
1817                            $x_empty_count++;
1818                        }
1819                        continue;
1820                    }
1821                    if( !in_array( $m, $y_rows ) && !$SHOW_EMPTY_ROW )
1822
1823                    {
1824                        // Skip to next iteration: we don't want a empty column
1825                        //
1826                        if( $m > $previous_m )
1827                        {
1828                            $previous_m = $m;
1829                            $y_empty_count++;
1830                        }
1831                        continue;
1832                    }
1833
1834                    if( $this->isBig() ) 
1835                    {
1836                        // Draw y(node) column number header
1837                        //
1838                        if(( $n == $x_min ) && ( isset($SORT_YLABEL) ) )
1839                        {
1840                            $mfontspacing    = 1;
1841
1842                            $ylabel_x    = $x - ( $fontwidth * strlen( $y_max ) ) - $mfontspacing;
1843                            $ylabel_y    = $y;
1844
1845                            imageString( $image, $font, $ylabel_x, $ylabel_y, strval( $m ), $colorblue );
1846
1847                            $xmin_hit[$n]    = true;
1848                        }
1849
1850                        // Draw x(rack) column number header
1851                        //
1852                        if(( $m == $y_min ) && ( isset($SORT_XLABEL) ) )
1853                        {
1854                            $mfontspacing    = 2;
1855                            $xlabel_y    = $y - ( $fontheight * strlen( $x_max ) );
1856                            $xlabel_x    = $x + $mfontspacing; 
1857
1858                            imageStringDown( $image, $font, $xlabel_x, $xlabel_y, strval( $n ), $colorblue );
1859                        }
1860                    }
1861
1862                    if( isset( $nodes[$cur_node] ) ) 
1863                    {
1864                        $host    = $nodes[$cur_node]->getHostname();
1865
1866                        if( $x_present && $y_present )
1867                        {
1868                            if( $x_first )
1869                            {
1870                                $nn = sscanf( $host, $skan_str, $rx, $ry );
1871                            }
1872                            else if( $y_first )
1873                            {
1874                                $nn = sscanf( $host, $skan_str, $ry, $rx );
1875                            }
1876                            if ( $nn < 2 )
1877                            {
1878                                //printf( "skipping node %s - y present & x present + <2 x,y matchs\n", $host);
1879                                continue;
1880                            }
1881                            if( intval( $rx ) > $n )
1882                            {
1883                                // If x(rack) is higher than current x, skip to next x(rack)
1884                                //
1885                                $m        = $y_max + 1;
1886
1887                                continue;
1888                            }
1889                            if( intval( $ry ) > $m )
1890                            {
1891                                // If y(node) is higher than current y, skip to next y(node)
1892                                //
1893                                continue;
1894                            }
1895                        }
1896                        else if( $x_present )
1897                        {
1898                            $nn = sscanf( $host, $skan_str, $rx );
1899                        }
1900                        else if( $y_present )
1901                        {
1902                            $nn = sscanf( $host, $skan_str, $ry );
1903                        }
1904
1905                        if( !in_array( $host, $filtered_nodes ) )
1906                        {
1907                            // This node has been filtered out: we only want to see certain nodes
1908                            //
1909                            $nodes[$cur_node]->setShowinfo( 0 );
1910                        }
1911
1912                        $nodes[$cur_node]->setCoords( $x, $y );
1913                        $nodes[$cur_node]->setImage( $image );
1914
1915                        if( $this->isSmall() )
1916                        {
1917                            $nodes[$cur_node]->drawSmall();
1918                        }
1919                        else if( $this->isBig() )
1920                        {
1921                            $nodes[$cur_node]->drawBig();
1922                        }
1923
1924                        $cur_node++;
1925                    }
1926                }
1927            }
1928
1929        }
1930        else
1931        {
1932            if( $this->isSmall() )
1933            {
1934                $image        = imageCreateTrueColor( $max_width, ($y_offset + (($node_rows*$node_width)+1) ) );
1935            }
1936            else if( $this->isBig() )
1937            {
1938                $image_width    = ($node_width * $nodes_nr) + 2;
1939                $image_width    = ($image_width < $max_width) ? $image_width : $max_width;
1940                $image        = imageCreateTrueColor( $image_width, ($y_offset + (($node_rows*$node_width)+1) ) );
1941            }
1942            $colorwhite    = imageColorAllocate( $image, 255, 255, 255 );
1943
1944            imageFill( $image, 0, 0, $colorwhite );
1945
1946            if( $this->isSmall() )
1947            {
1948                $colorblue    = imageColorAllocate( $image, 0, 0, 255 );
1949
1950                imageString( $image, $font, 2, 2, "Monarch Joblist - cluster: ".$this->clustername, $colorblue );
1951            }
1952
1953            for( $n = 0; $n < $node_rows; $n++ )
1954            {
1955                for( $m = 0; $m < $nodes_per_row; $m++ )
1956                {
1957                    $x = ($m * $node_width);
1958                    $y = $y_offset + ($n * $node_width);
1959
1960                    $cur_node = ($n * $nodes_per_row) + ($m);
1961                    $host = isset( $nodes_hosts[$cur_node] ) ? $nodes_hosts[$cur_node] : '';
1962
1963                    if( isset( $nodes[$host] ) )
1964                    {
1965                        $nodes[$host]->setCoords( $x, $y );
1966                        $nodes[$host]->setImage( $image );
1967
1968                        if( !in_array( $host, $filtered_nodes ) )
1969                        {
1970                            $nodes[$host]->setShowinfo( 0 );
1971                        }
1972
1973                        if( $this->isSmall() )
1974                        {
1975                            $nodes[$host]->drawSmall();
1976                        }
1977                        else if( $this->isBig() )
1978                        {
1979                            $nodes[$host]->drawBig();
1980                        }
1981                    }
1982                }
1983            }
1984        }
1985   
1986        $this->nodes    = &$nodes;
1987
1988        if ($this->output)
1989        {
1990            header( 'Content-type: image/png' );
1991            imagePNG( $image );
1992            imageDestroy( $image );
1993        }
1994    }
1995
1996    function getImagemapArea()
1997    {
1998        $clusterimage_map    = "";
1999
2000        foreach( $this->nodes as $hostname => $node )
2001        {
2002            $node_map        = $node->getImagemapArea();
2003            $clusterimage_map    .= $node_map;
2004        }
2005
2006        return $clusterimage_map;
2007    }
2008}
2009
2010class EmptyImage
2011{
2012    function draw()
2013    {
2014        $image        = imageCreateTrueColor( 1, 1 );
2015        $colorwhite    = imageColorAllocate( $image, 255, 255, 255 );
2016        imageFill( $image, 0, 0, $colorwhite );                         
2017
2018        header( 'Content-type: image/png' );
2019        imagePNG( $image );
2020        imageDestroy( $image );
2021    }
2022}
2023
2024class HostImage
2025{
2026    var $data_gather, $cluster, $host, $node, $image;
2027    var $headerstrlen;
2028
2029    function HostImage( $data_gather, $cluster, $host )
2030    {
2031        $this->data_gather     = $data_gather;
2032        $this->cluster        = $cluster;
2033        $this->host        = $host;
2034        $this->y_offset        = 0;
2035        $this->font        = 2;
2036        $this->fontspaceing    = 2;
2037        $this->headerstrlen    = array();
2038
2039        $this->fontheight    = ImageFontHeight( $this->font );
2040        $this->fontwidth    = ImageFontWidth( $this->font );
2041
2042        $dg            = &$this->data_gather;
2043        $this->node        = &$dg->getNode( $this->host );
2044        $n            = &$this->node;
2045        $this->njobs        = $n->getJobs();
2046    }
2047
2048    function drawJobs()
2049    {
2050        $dg                     = &$this->data_gather;
2051        $colorblack        = imageColorAllocate( $this->image, 0, 0, 0 );
2052
2053        for( $n = 0; $n < count( $this->njobs ); $n++ )
2054        {
2055            $jobid            = $this->njobs[$n];
2056            $jobinfo        = $dg->getJob( $jobid );
2057
2058            $xoffset        = 5;
2059            imageString( $this->image, $this->font, $xoffset, $this->y_offset, strval( $jobid ), $colorblack );
2060
2061            foreach( $this->headerstrlen as $headername => $headerlen )
2062            {
2063                if( $headername == 'nodes' )
2064                {
2065                    $attrval    = strval( count( $jobinfo['nodes'] ) );
2066                }
2067                else if( $headername == 'cpus' )
2068                {
2069                    if( !isset( $jobinfo['ppn'] ) )
2070                    {
2071                        $jobinfo['ppn'] = 1;
2072                    }
2073
2074                    $attrval    = strval( count( $jobinfo['nodes'] ) * intval( $jobinfo['ppn'] ) );
2075                }
2076                else if( $headername == 'runningtime' )
2077                {
2078                    $attrval    = makeTime( intval( $jobinfo['reported'] ) - intval( $jobinfo['start_timestamp'] ) );
2079                }
2080                else
2081                {
2082                    $attrval    = strval( $jobinfo[$headername] );
2083                }
2084
2085                imageString( $this->image, $this->font, $xoffset, $this->y_offset, $attrval, $colorblack );
2086       
2087                $xoffset    = $xoffset + ($this->fontwidth * ( $headerlen + 1 ) );
2088            }
2089           
2090            $this->newLineOffset();
2091        }
2092    }
2093
2094    function drawHeader()
2095    {
2096        $dg                     = &$this->data_gather;
2097
2098        for( $n = 0; $n < count( $this->njobs ); $n++ )
2099        {
2100            $jobid            = $this->njobs[$n];
2101            $jobinfo        = $dg->getJob( $jobid );
2102
2103            if( !isset( $this->headerstrlen['id'] ) )
2104            {
2105                $this->headerstrlen['id']    = strlen( strval( $jobid ) );
2106            }
2107            else if( strlen( strval( $jobid ) ) > $this->headerstrlen['id'] )
2108            {
2109                $this->headerstrlen['id']    = strlen( strval( $jobid ) );
2110            }
2111
2112            if( !isset( $this->headerstrlen['owner'] ) )
2113            {
2114                $this->headerstrlen['owner']    = strlen( strval( $jobinfo['owner'] ) );
2115            }
2116            else if( strlen( strval( $jobinfo['owner'] ) ) > $this->headerstrlen['owner'] )
2117            {
2118                $this->headerstrlen['owner']    = strlen( strval( $jobinfo['owner'] ) );
2119            }
2120
2121            if( !isset( $this->headerstrlen['queue'] ) )
2122            {
2123                $this->headerstrlen['queue']    = strlen( strval( $jobinfo['queue'] ) );
2124            }
2125            else if( strlen( strval( $jobinfo['queue'] ) ) > $this->headerstrlen['queue'] )
2126            {
2127                $this->headerstrlen['queue']    = strlen( strval( $jobinfo['queue'] ) );
2128            }
2129
2130            if( !isset( $jobinfo['ppn'] ) )
2131            {
2132                $jobinfo['ppn'] = 1;
2133            }
2134
2135            $cpus            = count( $jobinfo['nodes'] ) * intval( $jobinfo['ppn'] );
2136
2137            if( !isset( $this->headerstrlen['cpus'] ) )
2138            {
2139                $this->headerstrlen['cpus']    = strlen( strval( $cpus ) );
2140            }
2141            else if( strlen( strval( $cpus ) ) > $this->headerstrlen['cpus'] )
2142            {
2143                $this->headerstrlen['cpus']    = strlen( strval( $cpus ) );
2144            }
2145
2146            $nodes            = count( $jobinfo['nodes'] );
2147
2148            if( !isset( $this->headerstrlen['nodes'] ) )
2149            {
2150                $this->headerstrlen['nodes']    = strlen( strval( $nodes ) );
2151            }
2152            else if( strlen( strval( $nodes) ) > $this->headerstrlen['nodes'] )
2153            {
2154                $this->headerstrlen['nodes']    = strlen( strval( $nodes ) );
2155            }
2156
2157            $runningtime        = makeTime( intval( $jobinfo[reported] ) - intval( $jobinfo['start_timestamp'] ) );
2158
2159            if( !isset( $this->headerstrlen['runningtime'] ) )
2160            {
2161                $this->headerstrlen['runningtime']    = strlen( strval( $runningtime) );
2162            }
2163            else if( strlen( strval( $runningtime) ) > $this->headerstrlen['runningtime'] )
2164            {
2165                $this->headerstrlen['runningtime']    = strlen( strval( $runningtime) );
2166            }
2167
2168            if( !isset( $this->headerstrlen['name'] ) )
2169            {
2170                $this->headerstrlen['name']    = strlen( strval( $jobinfo['name'] ) );
2171            }
2172            else if( strlen( strval( $jobinfo['name'] ) ) > $this->headerstrlen['name'] )
2173            {
2174                $this->headerstrlen['name']    = strlen( strval( $jobinfo['name'] ) );
2175            }
2176        }
2177
2178        $xoffset    = 5;
2179
2180        foreach( $this->headerstrlen as $headername => $headerlen )
2181        {
2182            $colorgreen    = imageColorAllocate( $this->image, 0, 200, 0 );
2183
2184            if( $headerlen < strlen( $headername ) )
2185            {
2186                $this->headerstrlen[$headername]    = strlen( $headername );
2187            }
2188
2189            imageString( $this->image, $this->font, $xoffset, $this->y_offset, ucfirst( $headername ), $colorgreen );
2190
2191            $xoffset    = $xoffset + ($this->fontwidth * ( $this->headerstrlen[$headername] + 1 ) );
2192        }
2193        $this->newLineOffset();
2194    }
2195
2196    function newLineOffset()
2197    {
2198        $this->y_offset        = $this->y_offset + $this->fontheight + $this->fontspaceing;
2199    }
2200
2201    function draw()
2202    {
2203        $xlen        = 450;
2204        $ylen        = ( count( $this->njobs ) * ( $this->fontheight + $this->fontspaceing ) ) + (3 * $this->fontheight);
2205
2206        $this->image    = imageCreateTrueColor( $xlen, $ylen );
2207        $colorwhite    = imageColorAllocate( $this->image, 255, 255, 255 );
2208        imageFill( $this->image, 0, 0, $colorwhite );                         
2209
2210        $colorblue    = imageColorAllocate( $this->image, 0, 0, 255 );
2211
2212        imageString( $this->image, $this->font, 1, $this->y_offset, "Monarch Joblist - host: ".$this->host, $colorblue );
2213        $this->newLineOffset();
2214
2215        $this->drawHeader();
2216        $this->drawJobs();
2217
2218        header( 'Content-type: image/png' );
2219        imagePNG( $this->image );
2220        imageDestroy( $this->image );
2221    }
2222}
2223
2224function imageStringDown( &$image, $font, $x, $y, &$s, &$col )
2225{
2226    $fw    = imagefontwidth( $font);
2227    $fh    = imagefontheight( $font);
2228   
2229    $fontspacing = 0;
2230
2231    $fx    = $x;
2232    $fy    = $y;
2233
2234    for( $n=0; $n<strlen( $s ); $n++ )
2235    {
2236        $myc    = $s{$n};
2237
2238        imagestring( $image, $font, $fx, $fy, $myc, $col );
2239
2240        $fy    += ($fontspacing + $fh );
2241    }
2242}
2243
2244function array_rem( $val, &$arr )
2245{
2246    // Delete val from arr
2247    //
2248    $i    = array_search( $val, $arr );
2249
2250    if( $i == false ) return false;
2251
2252    $arr    = array_merge( array_slice( $arr, 0, $i ), array_slice( $arr, $i+1, count( $arr ) ) );
2253
2254    return true;
2255}
2256
2257function cmp( $a, $b ) 
2258{
2259    global $SORT_ORDER;
2260    global $skan_str;
2261    global $x_first, $y_first;
2262    global $x_present, $y_present;
2263
2264    $a_node        = $a;
2265    $b_node        = $b;
2266    $a        = $a_node->getHostname();
2267    $b        = $b_node->getHostname();
2268
2269    if( $a == $b ) return 0;
2270
2271    $a_x        = 0;
2272    $b_x        = 0;
2273    $a_y        = 0;
2274    $b_y        = 0;
2275
2276    if( $x_present && $y_present )
2277    {
2278        if( $x_first )
2279        {
2280            $n = sscanf( $a, $skan_str, $a_x, $a_y );
2281            $n = sscanf( $b, $skan_str, $b_x, $b_y );
2282        }
2283        else if( $y_first )
2284        {
2285            $n = sscanf( $a, $skan_str, $a_y, $a_x );
2286            $n = sscanf( $b, $skan_str, $b_y, $b_x );
2287        }
2288    } 
2289    else if( $x_present && !$y_present )
2290    {
2291        $n = sscanf( $a, $skan_str, $a_x );
2292        $n = sscanf( $b, $skan_str, $b_x );
2293    }
2294    else if( $y_present && !$x_present )
2295    {
2296        $n = sscanf( $a, $skan_str, $a_y );
2297        $n = sscanf( $b, $skan_str, $b_y );
2298    }
2299
2300    if ( $SORT_ORDER=="desc" )
2301    {
2302
2303        if( $x_present && $y_present )
2304        {
2305            // 1  = a < b
2306            // -1 = a > b
2307            //
2308            if ($a_x == $b_x)
2309            {
2310                if ($a_y < $b_y)
2311                {
2312                    return 1;
2313                }
2314                else if ($a_y > $b_y)
2315                {
2316                    return -1;
2317                }
2318            }
2319            else if ($a_x < $b_x)
2320            {
2321                return 1;
2322            }
2323            else if ($a_x > $b_x)
2324            {
2325                return -1;
2326            }
2327        } 
2328        else if( $x_present && !$y_present )
2329        {
2330            if ($a_x < $b_x)
2331            {
2332                return 1;
2333            }
2334            else if ($a_x > $b_x)
2335            {
2336                return -1;
2337            }
2338        }
2339        else if( $y_present && !$x_present )
2340        {
2341            if ($a_y < $b_y)
2342            {
2343                return 1;
2344            }
2345            else if ($a_y > $b_y)
2346            {
2347                return -1;
2348            }
2349        }
2350    }
2351    else if ( $SORT_ORDER == "asc" )
2352    {
2353
2354        if( $x_present && $y_present )
2355        {
2356            // 1  = a > b
2357            // -1 = a < b
2358            //
2359            if ($a_x == $b_x)
2360            {
2361                if ($a_y > $b_y)
2362                {
2363                    return 1;
2364                }
2365                else if ($a_y < $b_y)
2366                {
2367                    return -1;
2368                }
2369            }
2370            else if ($a_x > $b_x)
2371            {
2372                return 1;
2373            }
2374            else if ($a_x < $b_x)
2375            {
2376                return -1;
2377            }
2378        }
2379        else if( $x_present && !$y_present )
2380        {
2381            if ($a_x > $b_x)
2382            {
2383                return 1;
2384            }
2385            else if ($a_x < $b_x)
2386            {
2387                return -1;
2388            }
2389        }
2390        else if( $y_present && !$x_present )
2391        {
2392            if ($a_y > $b_y)
2393            {
2394                return 1;
2395            }
2396            else if ($a_y < $b_y)
2397            {
2398                return -1;
2399            }
2400        }
2401    }
2402}
2403function makeTime( $time )
2404{
2405        $days = intval( $time / 86400 );
2406        $time = ($days>0) ? $time % ($days * 86400) : $time;
2407
2408        $date_str = '';
2409        $day_str = '';
2410
2411        if( $days > 0 )
2412        {
2413            if( $days > 1 )
2414            {
2415                $day_str .= $days . ' days';
2416            }
2417            else
2418            {
2419                $day_str .= $days . ' day';
2420            }
2421        }
2422
2423        $hours = intval( $time / 3600 );
2424        $time = $hours ? $time % ($hours * 3600) : $time;
2425
2426        if( $hours > 0 )
2427        {
2428             $date_str .= $hours . ':';
2429             $date_unit = 'hours'; 
2430        }
2431
2432        $minutes = intval( $time / 60 );
2433        $seconds = $minutes ? $time % ($minutes * 60) : $time;
2434
2435        if( $minutes > 0 )
2436        {
2437            if( $minutes >= 10 )
2438            {
2439                $date_str .= $minutes . ':';
2440            }
2441            else
2442            {
2443                $date_str .= '0' . $minutes . ':';
2444            }
2445                $date_unit = (!isset($date_unit)) ? 'minutes' : $date_unit;
2446        }
2447        else
2448        {
2449            if($hours > 0 )
2450            {
2451                $date_str .= '00:';
2452                $date_unit = (!isset($date_unit)) ? 'minutes' : $date_unit;
2453            }
2454        }
2455
2456        $date_unit = (!isset($date_unit)) ? 'seconds' : $date_unit;
2457
2458        if( $seconds > 0 )
2459        {
2460            if( $seconds >= 10 )
2461            {
2462                $date_str .= $seconds . ' ' . $date_unit;
2463            }
2464            else
2465            {
2466                $date_str .= '0' . $seconds . ' ' . $date_unit;
2467            }
2468        }
2469        else if ( $hours > 0 or $minutes > 0 )
2470        {
2471            $date_str .= '00 ' . $date_unit;
2472        }
2473
2474        if( $days > 0)
2475        {
2476            if( $hours > 0 or $minutes > 0 or $seconds > 0 )
2477            {
2478                $date_str = $day_str . ' - ' . $date_str;
2479            }
2480            else
2481            {
2482                $date_str = $day_str;
2483            }
2484        }
2485        return $date_str;
2486}
2487?>
Note: See TracBrowser for help on using the repository browser.