source: branches/1.0/web/addons/job_monarch/libtoga.php @ 825

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