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

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