#!/usr/local/sysmansw/runtime/perl/bin/perl -w

## -_- $Name: PerfGraph-2_4d $ % $Id: perfload,v 1.6.8.1 2001/01/03 15:42:09 sietse Exp $

use Pg;
use Time::Local;
use IO::Handle;
use POSIX ":sys_wait_h";

# Default database name is perfdb - changeable by defining the variable PERFDB
$PERFDB = $ENV{"PERFDB"};
$PERFDB = "perfdb" if not defined($PERFDB);

# Default directory name is ~perfgr - changeable by defining the variable PGDIR
$PGDIR = $ENV{'PGDIR'};
$PGDIR = $ENV{'HOME'} . "/perfgraph" if not defined($PGDIR);

##########################################################################
##########################################################################
##########################################################################

sub logmsg
{
    my $msg = shift @_;
    my $tm;

    chomp($tm = localtime(time));
    print "$tm: ". $msg;
}

sub logdie
{
    my $msg = shift @_;
    my $tm;

    chomp($tm = localtime(time));
    die "$tm: ". $msg;
}

##########################################################################
##########################################################################
##########################################################################

sub doq($$$)
{
    my ($db, $q, $expected) = @_;
    my ($r, $tm);

    $r = $db->exec($q);
    return $r if $r->resultStatus == $expected;

    logmsg "Error executing query:\n        " . $q . "\n        Reason: " .
           $db->errorMessage . "\n";
    return 0;
}

sub getresp($)
{
    my $prompt = shift @_;
    my $resp;

    print $prompt;
    $resp = <STDIN>;
    if (defined($resp))
    {
        chomp($resp);
        exit(0) if ($resp eq "");
        return $resp;
    }
    else
    {
        die "\nExiting $0\n\n";
    }
}

##########################################################################
##########################################################################
##########################################################################

sub loadfile($)
{
    my $f = shift @_;
    my (@parts, @dparts, @tparts, $max_sar);

    open INP, $f or die "Cannot open file $f\n";

    # Skip to first line with the date
    do
    {
        $line = <INP>;
    } while (defined($line) && $line !~ /.*\d+\/\d+\/\d+$/);

    # Check system type, and determine date
    if (defined($line) && $line =~ /.*\d+\/\d+\/\d+$/)
    {
        chomp($line);
        @parts = split(/\s+/, $line);
        $illegal = 0;
        $illegal = 1 if $systype eq "aix" && $parts[0] ne "AIX";
        $illegal = 1 if $systype eq "hpux" && $parts[0] ne "HP-UX";
        $illegal = 1 if $systype eq "solaris" && $parts[0] ne "SunOS";

        die "sar file $f is from another unix system than $systype - exiting.\n" if $illegal;

        @dparts = split("/", $parts[scalar(@parts)-1]);
    }
    else
    {
        die "No legal header found in file $f - exiting.\n";
    }

    # Skip to first line with a timestamp
    do
    {
        $line = <INP>;
    } while (defined($line) && $line !~ /^\d+:\d+:\d+/);

    close INP;

    if (defined($line) && $line =~ /^\d+:\d+:\d+/)
    {
        @parts = split(/\s+/, $line);
        @tparts = split(":", $parts[0]);
    }
    else
    {
        die "No data found in file $f - exiting.\n";
    }

    $dparts[$y_pos] += 1900 if ($dparts[$y_pos] >= 70 && $dparts[$y_pos] < 1900);
    $dparts[$y_pos] += 2000 if ($dparts[$y_pos] < 70);
    $tstamp = timegm(0, $tparts[1], $tparts[0], $dparts[$d_pos], $dparts[$m_pos] - 1, $dparts[$y_pos]);

    # Get the max_sar timestamp - not allowed to load data before this tstamp.
    $q = "select max_sar from tstamps";
    logdie "Stopping\n" unless $result = doq($conn, $q, PGRES_TUPLES_OK);
    $max_sar = $result->getvalue(0, 0);

    die "Data in sar file is older than already loaded data -exiting.\n" if $tstamp <= $max_sar;

    # No objections, load the file!
    print "Loading file $f, start date/time: " . gmtime($tstamp) . "\n";
    system("$PGDIR/perfgatherd -l $sys $f " . $dparts[$y_pos] . " " . $dparts[$m_pos] . " " . $dparts[$d_pos]);
}


sub signal_pgstart
{
    # If needed, restart perfgraphd

    chomp($thissystem = `uname`);
    if ($thissystem eq "SunOS" || $thissystem eq "HP-UX")
    {
        $pid = `ps -ef|grep $PGDIR/pgstart|grep -v grep`;
        if ($pid ne "")
        {
            @pid = split(' ', $pid);
            $pid = $pid[1];
        }
    } elsif ($thissystem eq "Linux")
    {
        $pid = `ps ax|grep $PGDIR/pgstart|grep -v grep`;
        if ($pid ne "")
        {
            @pid = split(' ', $pid);
            $pid = $pid[0];
        }
    } else
    {
        print "pgstart not restarted -- this is a unknown system type\n";
    }

    if ($pid eq "")
    {
        print "PerfGraphd is not running, use pgstart for startup of PerfGraph\n";
    }
    else
    {
        print "Signaling pgstart\n";
        kill 1, $pid;
    }
}

sub help
{
    print "Usage: $0 [-s system] [-t system type] [-n] [-f date format] [files]\n";
    print "    -s    specify system name to load data into\n";
    print "    -t    specify system type; mandatory if the system is non-existent\n";
    print "    -n    force a new database, even if the system already exists\n";
    print "    -k    keep current database, the system must already exist\n";
    print "    -f    specify date format; default is mdy. If the date in the first\n";
    print "          line of the sar file has a different format, then specify it\n";
    print "          Example: if the format is yy/mm/dd then specify '-f ymd'\n";
    print "  files   Files to load. Wild cards are allowed. Make sure the files are\n";
    print "          sequential - you cannot load a file containing data prior to\n";
    print "          data already loaded.\n";

    exit(1);
}

########################################################################################
########################################################################################
########################################################################################

$new = 0;
$keep = 0;
$fmt = "mdy";
$sys = "";
$systype = "";

while (scalar(@ARGV) > 0 && substr($ARGV[0], 0, 1) eq "-")
{
    my $switch = shift @ARGV;

    help if $switch ne "-s" && $switch ne "-n" && $switch ne "-t" && $switch ne "-f" &&
            $switch ne "-k";

    $sys = shift @ARGV if $switch eq "-s";
    $new = 1 if $switch eq "-n";
    $keep = 1 if $switch eq "-k";
    $systype = shift @ARGV if $switch eq "-t";
    $fmt = shift @ARGV if $switch eq "-f";
}

die "You cannot specify -k and -n at thesame time - exiting\n" if $keep == 1 && $new == 1;

$y_pos = $m_pos = $d_pos = 3;
die "Illegal date format $fmt, try $0 -h\n" if length($fmt) != 3;
for $f (0 .. 2)
{
    my $c = substr($fmt, $f, 1);

    die "Illegal date format $fmt, try $0 -h\n" if $c ne "y" && $c ne "m" && $c ne "d";
    $y_pos = $f if $c eq "y";
    $m_pos = $f if $c eq "m";
    $d_pos = $f if $c eq "d";
}
die "Illegal date format $fmt, try $0 -h\n" if $y_pos == 3 || $m_pos == 3 || $d_pos == 3;

$perfdb = Pg::connectdb("dbname = $PERFDB");
if ($perfdb->status == PGRES_CONNECTION_BAD)
{
    logdie "Cannot open database connection: " . $perfdb->errorMessage;
}

$q = "select distinct supptype from supp_systypes, tables " .
     "where supptype = systype and gatherfrom = 'sar'";
logdie "Stopping\n" unless $supptypes = doq($perfdb, $q, PGRES_TUPLES_OK);

$sys = getresp("System to load: ") if $sys eq "";

$q = "select * from systems where hostname = '$sys'";
logdie "Stopping\n" unless $result = doq($perfdb, $q, PGRES_TUPLES_OK);

if ($result->ntuples == 0)
{
    if ($systype eq "")
    {
        print "Supported system types:\n";

        do
        {
            foreach $i (0 .. $supptypes->ntuples - 1)
            {
                print "    " . ($i + 1) . ". " . $supptypes->getvalue($i, 0) . "\n";
            }
            $systype = getresp("Select system type number (press return to go quit): ");
            if ($systype !~ /\d/ || $systype > $supptypes->ntuples)
            {
                print "Illegal input, give a number\n";
            }
        } while ($systype !~ /\d/ || $systype > $supptypes->ntuples);
    }
    else
    {
        my $found = 0;
        foreach $st (0 .. $supptypes->ntuples - 1)
        {
            $found = 1 if $supptypes->getvalue($st, 0) eq $systype;
        }
        die "Illegal system type $systype - exiting\n" if $found == 0;
    }

    print "Creating system $sys...\n";
    $systype = $supptypes->getvalue($systype - 1, 0);
    system("$PGDIR/pgadmin -c $sys $systype");
    print "Done\n";
}
else
{
    $q = "select systype from systems where hostname = '" . $sys . "'";
    logdie "Stopping\n" unless $result = doq($perfdb, $q, PGRES_TUPLES_OK);
    $systype = $result->getvalue(0, 0) if $systype eq "";
    $found = 0;
    foreach $st (0 .. $supptypes->ntuples - 1)
    {
        $found = 1 if $supptypes->getvalue($st, 0) eq $systype;
    }
    die "Illegal system type $systype - exiting\n" if $found == 0;

    $q = "select hostname from systems, tables " .
         "where systems.systype = tables.systype " .
         "  and gatherfrom = 'sar'" . 
         "  and hostname = '$sys'";
    logdie "Stopping\n" unless $result = doq($perfdb, $q, PGRES_TUPLES_OK);
    die "System type $systype does not support sar.\n" if $result->ntuples == 0;

    if ($new == 1)
    {

        print "Removing system $sys...\n";
        system("$PGDIR/pgadmin -r $sys");
        print "Creating system $sys...\n";
        system("$PGDIR/pgadmin -c $sys $systype");
    }
    else
    {
        if ($keep == 0)
        {
            print "System $sys already exists.\n";

            do
            {
                print "Do you want to\n";
                print "    1. keep data of system $sys;\n";
                print "    2. remove the data for system $sys before loading.\n";
                $resp = getresp("Select action (press return to go quit): ");
                if ($resp ne "1" && $resp ne "2")
                {
                    print "Illegal response, try again.\n";
                }
            } while ($resp ne "1" && $resp ne "2");

            if ($resp eq "2")
            {
                print "Removing system $sys...\n";
                system("$PGDIR/pgadmin -r $sys");
                print "Creating system $sys...\n";
                system("$PGDIR/pgadmin -c $sys $systype");
            }
        }
    }
}

if (scalar(@ARGV) == 0)
{
    $resp = getresp("File(s) to load (return to quit): ");
    @files = split(/\s+/, `ksh -c "echo $resp"`);
}
else
{
    @files = @ARGV;
}

$conn = Pg::connectdb("dbname = $sys");
if ($conn->status == PGRES_CONNECTION_BAD)
{
    logdie "Cannot open database connection: " . $conn->errorMessage;
}

foreach $f (@files)
{
    loadfile($f);
}

print "Aggregating...\n";
system("$PGDIR/perfgatherd -a $sys");

# Now set deldays to something before the first entry...
print "Adjusting cleanup parameters...\n";
$q = "select min(tstamp) from sar_cpu";
logdie "Stopping\n" unless $result = doq($conn, $q, PGRES_TUPLES_OK);
$mindays = int((time() - $result->getvalue(0, 0)) / (24 * 60 * 60)) + 1;
$q = "select * from deldays";
logdie "Stopping\n" unless $result = doq($conn, $q, PGRES_TUPLES_OK);
$q = "update deldays set hour = ";
$q .= ($mindays > $result->getvalue(0, 0)) ? $mindays : $result->getvalue(0, 0);
$q .= ", day = ";
$q .= ($mindays > $result->getvalue(0, 1)) ? $mindays : $result->getvalue(0, 1);
$q .= ", week = ";
$q .= ($mindays > $result->getvalue(0, 2)) ? $mindays : $result->getvalue(0, 2);
$q .= ", mon = ";
$q .= ($mindays > $result->getvalue(0, 3)) ? $mindays : $result->getvalue(0, 3);
$q .= ", year = ";
$q .= ($mindays > $result->getvalue(0, 4)) ? $mindays : $result->getvalue(0, 4);
logdie "Stopping\n" unless $result = doq($conn, $q, PGRES_COMMAND_OK);

signal_pgstart;

print "Done!\n";

exit(0);
