Subversion Repositories DevTools

Rev

Rev 271 | Rev 317 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

########################################################################
# Copyright ( C ) 2008 ERG Limited, All rights reserved
#
# Module name   : jats.sh
# Module type   : Makefile system
# Compiler(s)   : n/a
# Environment(s): jats
#
# Description   : Display Daemon Status information
#
# Usage         : See POD at end of file
#
#......................................................................#

require 5.6.1;
use strict;
use warnings;
use JatsError;
use JatsSystem;
use Getopt::Long;
use Pod::Usage;
use JatsRmApi;
use Term::ANSIColor qw(:constants);
use DBI;

my $VERSION = "1.0.0";                      # Update this
my $opt_verbose = 1;
my $opt_help = 0;
my $opt_repeat;
my $opt_short = 0;
my $opt_color;
my @opt_rtag;
my %opt_rtag;
my $opt_filter;
my $RM_DB;
my %pname;
my %rc;
my %rl;
my %rname;
my %official;
my $indefinite = 0;
my $ff_string = "\f";
my $dead_time = ( 5 * 60 ) * 2;
my %StateData = ( 1 => 'Disk Full',
                  2 => 'Paused',
                  3 => 'Active',
                  4 => 'Idle' ,
                  5 => 'Waiting',
                  6 => 'Publishing',
                  );

#-------------------------------------------------------------------------------
# Function        : Main Entry
#
# Description     :
#
# Inputs          :
#
# Returns         :
#
my $result = GetOptions (
                "help:+"        => \$opt_help,          # flag, multiple use allowed
                "manual:3"      => \$opt_help,          # flag
                "verbose:+"     => \$opt_verbose,       # flag
                "repeat=i"      => \$opt_repeat,        # Integer
                "short:+"       => \$opt_short,         # Flag
                "color"         => \$opt_color,         # Flag
                "rtag=s"        => \@opt_rtag,          # Array
                "filter"        => \$opt_filter,        # Flag
                );

#
#   Process help and manual options
#
pod2usage(-verbose => 0, -message => "Version: $VERSION")  if ($opt_help == 1  || ! $result);
pod2usage(-verbose => 1)  if ($opt_help == 2 );
pod2usage(-verbose => 2)  if ($opt_help > 2);

ErrorConfig( 'name'    =>'DSTATUS' );

#
#   Native windows doesn't handle color
#   Dispable color by default
#
unless ( $opt_color )
{
    $ENV{ANSI_COLORS_DISABLED} = 1;
    $ff_string = "\n\n\n";
}

#
#   Convert array of RTAGS into a hash for simpler usage
#

$opt_rtag{$_} = 1 foreach ( split( /[,\s]+/, "@opt_rtag"));

#
#   Attempt to prevent users from repeating every second
#   If the user specified < 10, then set it to 10
#   Exports ( with internal knowledge) can set shorter times
#
$opt_repeat = 10 if ( $opt_repeat && $opt_repeat < 10 );
$opt_repeat -= 1000 if ( $opt_repeat && $opt_repeat > 1001 );

#
#   Repeat for ever
#
while (1)
{
    getGlobal();
    GetConfigData();
    GetRunData();
    DisplayInfo();

    last unless ( $opt_repeat );
    sleep ($opt_repeat );

    #
    #   Cleanout any data from previous run
    #
    %pname = ();
    %rc = ();
    %rl = ();
    %rname = ();
    %official = ();
    
}

disconnectRM(\$RM_DB);
exit;

#-------------------------------------------------------------------------------
# Function        : DisplayInfo
#
# Description     : Display collected information
#
# Inputs          : 
#
# Returns         : 
#
sub DisplayInfo
{

#DebugDumpData ("Data", \%rc);

    #
    #   Display a header
    #   Include a form feed if possible
    #
    if ( $opt_repeat )
    {
        print $ff_string, BOLD, "Build Daemon Status [" . localtime() . "]" , RESET, "\n";
    }
    if ( $opt_short && $indefinite )
    {
        print RED "*** Indefinite Pause", RESET, "\n";
    }

    #
    #  Sort by Project Name and Release Name
    #
    foreach my $pname ( sort keys %pname )
    {
        foreach my $rname ( sort keys %{$pname{$pname}} )
        {
            my $rtag_id = $pname{$pname}{$rname};
            my @orderm;
            my @orders;
            my $building = 0;
            my $dead = 0;
            my $paused = 0;
            my $in_error = 0;
            

            foreach my $rcon_id ( keys %{$rc{$rtag_id}}  )
            {
                next unless ( exists $rl{$rcon_id} );

                #
                #   Maintain alive info
                #
                if ( $rl{$rcon_id}{deltat} )
                {
                    if ( $rl{$rcon_id}{deltat} > $dead_time )
                    {
                        $dead = 1;
                    }
                }

                #
                #   Determine if any of the machines are building a package
                #
                $building = 1 if ( $rl{$rcon_id}{cpid} );

                #
                #   Sort into Master and Slaves
                #   Done so that we can print the master at the top of the list
                #
                if ($rc{$rtag_id}{$rcon_id}{hostmode} =~ m{M} )
                {
                    push @orderm, $rcon_id;
                }
                else
                {
                    push @orders, $rcon_id;
                }

                #
                #   Paused deamons don't maintain alive data
                #
                $paused += 1
                    if ( $rl{$rcon_id}{crl} == 2 );

                $dead = 0
                    if ( $paused );

                $in_error ++
                    if ( $rl{$rcon_id}{crl} == 1 );
                
            }

            if ( $in_error || $dead || $building || $opt_short < 2  )
            {
                print BOLD GREEN "[$rtag_id] $rname{$rtag_id} ($official{$rtag_id})", RESET, "\n";
            }
            
            if ( $in_error || $dead || $building || $opt_short < 1 )
            {
                foreach my $rcon_id ( @orderm, sort(@orders) )
                {
                    if ( $opt_filter )
                    {
                         printf "    %1.1s: %-20.20s %s\n",
                            $rc{$rtag_id}{$rcon_id}{hostmode},
                            $rc{$rtag_id}{$rcon_id}{hostname},
                            $rc{$rtag_id}{$rcon_id}{filter};
                    }
                    else
                    {
                             printf "    %1.1s: %-20.20s %s%10s%s(%1.1s) %-20s %-20s (%5s)\n",
                #                $rtag_id, $rcon_id,
                                $rc{$rtag_id}{$rcon_id}{hostmode},
                                $rc{$rtag_id}{$rcon_id}{hostname},
                                $indefinite ? RED : RESET,
                                $indefinite ? ('AllStop') : (getState($rl{$rcon_id}{crl})),
                                RESET,
                                defined ($rl{$rcon_id}{pause} ) ? $rl{$rcon_id}{pause} : '-',
                                $rl{$rcon_id}{cpid} || '-',
                                $rl{$rcon_id}{alive} || '-',
                                $rl{$rcon_id}{deltat} || '-',
                            ;
                    }
                }
                print "\n";
            }
        }
    }
}

#-------------------------------------------------------------------------------
# Function        : getGlobal
#
# Description     : Get global information
#
# Inputs          : 
#
# Returns         : 
#

sub getGlobal
{
    my (@row);
    $indefinite = 0;
    
    # if we are not or cannot connect then return 0 as we have not found anything
    connectRM( \$RM_DB) unless $RM_DB;

    # First get details from pv_id

    my $m_sqlstr = "SELECT SCHEDULED_PAUSE, SCHEDULED_RESUME, REPEAT, INDEFINITE_PAUSE" .
                   " FROM RELEASE_MANAGER.RUN_LEVEL_SCHEDULE";

    my $sth = $RM_DB->prepare($m_sqlstr);
    if ( defined($sth) )
    {
        if ( $sth->execute( ) )
        {
            if ( $sth->rows )
            {
                while ( @row = $sth->fetchrow_array )
                {
                    $indefinite = 1 if ( $row[3] )
#                    print "@row\n";
                }
            }
            $sth->finish();
        }
        else
        {
        Error("Execute failure" );
        }
    }
    else
    {
        Error("Prepare failure" );
    }
}

#-------------------------------------------------------------------------------
# Function        : GetConfigData
#
# Description     : Build up a list of all releases that have daemons
#                   configured
#
# Inputs          : 
#
# Returns         : 
#
sub  GetConfigData
{
    my $foundDetails = 0;
    my (@row);

    # if we are not or cannot connect then return 0 as we have not found anything
    connectRM( \$RM_DB) unless $RM_DB;

    # First get details from pv_id

    my $m_sqlstr = "SELECT rc.RCON_ID, rc.RTAG_ID, rc.GBE_ID, rc.DAEMON_HOSTNAME, " .
                          "rc.DAEMON_MODE, rc.GBE_BUILDFILTER, rt.RTAG_NAME, " .
                          "p.PROJ_NAME, rt.OFFICIAL" .
                    " FROM release_config rc, RELEASE_TAGS rt, PROJECTS p" .
                    " WHERE      rt.RTAG_ID = rc.RTAG_ID " .
                            "AND rt.PROJ_ID = p.PROJ_ID " .
                            "AND rt.OFFICIAL != 'A' " .
                            "AND rt.OFFICIAL != 'Y' "
                            ;

    my $sth = $RM_DB->prepare($m_sqlstr);
    if ( defined($sth) )
    {
        if ( $sth->execute( ) )
        {
            if ( $sth->rows )
            {
                while ( @row = $sth->fetchrow_array )
                {
                    my $rcon_id = $row[0];
                    my $rtag_id = $row[1];
                    my $gbe_id =  $row[2];
                    my $hostname = $row[3];
                    my $hostmode = $row[4];
                    my $filter = $row[5];
                    my $rname = $row[6];
                    my $pname = $row[7];
                    my $official = $row[8];

                    next unless ( $hostname );
                    if ( @opt_rtag )
                    {
                        next unless ( defined $opt_rtag{$rtag_id} );
                    }

                    my %data;
                    $data{rcon_id}  = $rcon_id;
                    $data{hostname} = $hostname;
                    $data{hostname} = $hostname;
                    $data{hostmode} = $hostmode;
                    $data{filter}   = $filter;

                    $rc{$rtag_id}{$rcon_id} = \%data;

                    $rname{$rtag_id} = "$pname: $rname";

                    $pname{$pname}{$rname} = $rtag_id;

                    $official{$rtag_id} = $official;
                    
#                    print "@row\n";
                }
            }
            $sth->finish();
        }
        else
        {
        Error("Execute failure" );
        }
    }
    else
    {
        Error("Prepare failure" );
    }
}

#-------------------------------------------------------------------------------
# Function        : GetRunData
#
# Description     : Build up data for each daemon
#
# Inputs          : 
#
# Returns         : 
#
sub  GetRunData
{
    my $foundDetails = 0;
    my (@row);

    # if we are not or cannot connect then return 0 as we have not found anything
    connectRM( \$RM_DB) unless $RM_DB;

    # First get details from pv_id

    my $m_sqlstr = "SELECT rl.RCON_ID, rl.CURRENT_BUILD_FILES, rl.CURRENT_RUN_LEVEL, rl.PAUSE, " .
                            "rl.CURRENT_PKG_ID_BEING_BUILT, pkg.PKG_NAME, " .
                            "rl.KEEP_ALIVE, TRUNC (86400*(SYSDATE - rl.KEEP_ALIVE))" .
                    " FROM RUN_LEVEL rl, PACKAGES pkg" .
                    " WHERE pkg.PKG_ID (+)= rl.CURRENT_PKG_ID_BEING_BUILT";


    my $sth = $RM_DB->prepare($m_sqlstr);
    if ( defined($sth) )
    {
        if ( $sth->execute( ) )
        {
            if ( $sth->rows )
            {
                while ( @row = $sth->fetchrow_array )
                {
#                    print "@row\n";
                    my $rcon_id = $row[0] || '';
                    my $cbf     = $row[1] || '';
                    my $crl     = $row[2] || '-';
                    my $pause   = $row[3] || '0';
                    my $cpid    = $row[5] || '';
                    my $alive   = $row[6] || '';
                    my $deltat  = $row[7] || '0';

                    $rl{$rcon_id}{crl} = $crl;
                    $rl{$rcon_id}{pause} = $pause;
                    $rl{$rcon_id}{cpid} = $cpid;
                    $rl{$rcon_id}{alive} = $alive;
                    $rl{$rcon_id}{deltat} = $deltat;
#                    printf "%10s, %10s, %10s, %10s, %10s, %20s\n", $rcon_id, $cbf, $crl, $pause, $cpid, "$alive, $deltat";
                }
            }
            $sth->finish();
        }
        else
        {
        Error("Execute failure: GetRunData", $m_sqlstr );
        }
    }
    else
    {
        Error("Prepare failure" );
    }
}

#-------------------------------------------------------------------------------
# Function        : getState
#
# Description     : Convert number into a nice state string
#
# Inputs          : 
#
# Returns         : 
#
sub getState
{
    my ($num) = @_;
    return "Undefined" unless ( defined $num );
    if ( exists ($StateData{$num}) )
    {
        return $StateData{$num};
    }
    return "Unknown:$num";
}

#-------------------------------------------------------------------------------
#   Documentation
#

=pod

=head1 NAME

dstatus - Display Daemon Status

=head1 SYNOPSIS

  jats dstatus [options]

 Options:
    -help              - brief help message
    -help -help        - Detailed help message
    -man               - Full documentation
    -repeat=num        - Repeat display every n seconds
    -short             - Fold up inactive releases
    -short -short      - Supress inactive releases
    -color             - Pretty color display
    -rtag=num[,num]    - List of RTAG Ids to display
    -filter            - Display GBE_BUILDFILTER

=head1 OPTIONS

=over 8

=item B<-help>

Print a brief help message and exits.

=item B<-help -help>

Print a detailed help message with an explanation for each option.

=item B<-man>

Prints the manual page and exits.

=item B<-repeat=num>

This option will cause the program to re-display the status page every B<num>
seconds. The default option is to display the status once and exit.

If the user specifies a repeat time of less than 10 seconds, then it will be set
to 10 seconds - to avoid heavy loads on the Release Manager database.

This option works best with -color on a non-windows console as the screen
will be cleared before the display is refreshed.

=item B<-short>

This option will generate a short display. The body of inactive releases will
not be displayed. This option is useful in conjunction with a repeating display
to limit the display space used.

If B<-short> is used twice then the header for inactive releases will also
be supressed.

=item B<-color>

This option will enable a colored display. This will not work on Windoes.
The default is for a non-colored display.

=item B<-rtag=num[,num]>

This option will limit the display to the specified rtag Id's (Numeric Release ID).
This option can be used multiple times to specify a list, or the ID's can be comma seperated.

The default option is to display all Releases.

=item B<-filter>

This optionwill alter the display such that the GBE_BUILDFILTER for each platform
is displayed instead of the normal status information. This may result in a very
wide display.

=back

=head1 DESCRIPTION

This program will display the status of the build daemons on all daemon enabled
releases.

=cut