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

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