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

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