#! /usr/bin/perl
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
#  
#  
# Licensed Materials - Property of IBM 
#  
# (C) COPYRIGHT International Business Machines Corp. 2008,2019 
# All Rights Reserved 
#  
# US Government Users Restricted Rights - Use, duplication or 
# disclosure restricted by GSA ADP Schedule Contract with IBM Corp. 
#  
# IBM_PROLOG_END_TAG 

# sccsid = "@(#)78   1.17   src/rsct/trace/trcspl/showtr.perl, trace, rsct_rady, rady2035a 11/12/15 16:32:25"
# Search on "sub help" and/or "sub usage" for script description.

use Getopt::Long;
use Fcntl ':mode';

my $local_default = '^.+\.sp$';

my $spool_dir, $from, $to, $previous, $help, $ls, $rpttr_opt_f, $rpttr_opt_b, $rpttr_opt_r, $rpttr_opt_o, $rpttr_opt_t, $rpttr_opt_s, $ctsnap, $extract, $local, $nolocal;

if (!GetOptions("spool_dir=s" => \$spool_dir, "from=s" => \$from, "to=s" => \$to, "help" => \$help, "h" => \$help, "ls" => \$ls, "f" => \$rpttr_opt_f, "b" => \$rpttr_opt_b, "r" => \$rpttr_opt_r, "o=s" => \$rpttr_opt_o, "t=s" => \$rpttr_opt_t, "s=s" => \$rpttr_opt_s, "ctsnap" => \$ctsnap, "extract" => \$extract, "local=s" => \$local, "nolocal" => \$nolocal))
{
	usage(1);
}

if (undef ne $help)
{
	help();
}

if ($nolocal) {
	if ($local) {
		printf STDERR "%s:%d: cannot specify both the --local and the --nolocal options\n", $0, __LINE__;
		usage(1);
	}
} else {
	if (!$local) {
		$local = $local_default;
	}
}

if ($extract && (! $ctsnap))
{
	printf STDERR "%s:%d: --extract option invalid without --ctsnap option\n", $0, __LINE__;
	usage(1);
}

$previous = $ARGV[0];

my $time_specification;

if ((undef ne $from) || (undef ne $to))
{
	if (undef ne $previous)
	{
		usage(1);
	}

	if (undef ne $from)
	{
		if (! ($from =~ /^\d{4}-\d{2}-\d{2}/))
		{
			usage(1);
		}
		else
		{
			$time_specification .= "--from $from ";
		}
	}
	
	if (undef ne $to)
	{
		if (! ($to =~ /^\d{4}-\d{2}-\d{2}/))
		{
			usage(1);
		}
		else
		{
			$time_specification .= "--to $to ";
		}
	}
}
else
{
	if (undef eq $previous)
	{
		$previous = 0;
	}

	if (!($previous =~ /^\d+$/)) {  # should be numbers only
		usage(1);
	}

	$time_specification = "--previous $previous";
}

if (undef eq $spool_dir)
{
	$spool_dir = $ENV{CT_TR_SPOOL_DIR};

	if (undef eq $spool_dir)
	{
		printf STDERR "%s:%d: couldn't determine spool_dir\n", $0, __LINE__;
		usage(1);
	}
}

if ($rpttr_opt_f)
{
	$rpttr_opt_f = "-f";
}

if ($rpttr_opt_b)
{
	$rpttr_opt_b = "-b";
}

if ($rpttr_opt_r)
{
	$rpttr_opt_r = "-r";
}

if ($rpttr_opt_o)
{
	$rpttr_opt_o = "-o \"$rpttr_opt_o\"";
}

if ($rpttr_opt_t)
{
	$rpttr_opt_t = "-t \"$rpttr_opt_t\"";
}

if ($rpttr_opt_s)
{
	$rpttr_opt_s = "-s \"$rpttr_opt_s\"";
}

my $pwd = `pwd`;
chomp $pwd;

my $cluster_id;

if ($ctsnap)
{
	if ($pwd =~ /^(.+)\/var\/ct\/(.+)\/log\//)
	{
		$ctsnap = "$1";
		$cluster_id = "$2";
	}
	else
	{
		printf STDERR "%s:%d: couldn't determine cluster_id\n(need to be in a subdirectory of var/ct/*/log\nin directory where ctsnap is extracted)\n", $0, __LINE__;
		usage(1);
	}
}
else
{
	if ($pwd =~ /^\/var\/ct\/(.+)\/log\//)
	{
		$cluster_id = "$1";
	}
	else
	{
		printf STDERR "%s:%d: couldn't determine cluster_id\n(need to be in a subdirectory of /var/ct/*/log)\n", $0, __LINE__;
		usage(1);
	}
}

my $daemon_name;
my $daemon_name_rc = 0;
my $daemon_name_found = 0;

if (! opendir DIR, "$pwd")
{
	printf(STDERR "Error: cannot open current working directory(%s).\n", $pwd);
	exit 2;
}

while (my $entry = readdir(DIR))
{
	if (("." ne $entry) && (".." ne $entry))
	{
		my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size, $atime, $mtime, $ctime, $blksize, $blocks) = stat("$entry");

		if (S_ISREG($mode))
		{
			$daemon_name = `rpttr -B $entry 2>/dev/null`;
			$daemon_name_rc = $?;

			if (0 == $daemon_name_rc)
			{
				$daemon_name_found = 1;
				last;
			}
		}
	}
}

close DIR;

if (0 == $daemon_name_found)
{
	print "Cannot determine daemon name because the current directory has no trace files containing in...\n";
	print "Enter daemon name (e.g. IBM.ConfigRMd): ";
	$daemon_name = <STDIN>;
}

chomp $daemon_name;

if ($daemon_name_rc || (! $daemon_name))
{
	printf STDERR "%s:%d: couldn't determine daemon_name\n", $0, __LINE__;
	usage(1);
}

my $cluster_name;

open LS, "ls -l $ctsnap/var/ct |" or die sprintf "%s:%d: trouble with ls -l $ctsnap/var/ct\n", $0, __LINE__;

while (<LS>)
{
	if (/^l.+ (.+?) -> \/var\/ct\/$cluster_id$/)
	{
		$cluster_name = "$1";
		last;
	}
}

close LS;

if (undef eq $cluster_name)
{
	printf STDERR "%s:%d: couldn't determine cluster_name\n", $0, __LINE__;
	usage(1);
}

$ENV{'PATH'} = "/usr/bin:/bin:/usr/sbin";
my $node_name = `hostname`;
chomp $node_name;

$node_name =~ s/\..*$//;

my $node_id = `/opt/rsct/bin/lsnodeid`;
chomp $node_id;

if ($ctsnap)
{
	$spool_dir = "$ctsnap/ctsnap_out/$spool_dir";

	if ($extract)
	{
	    system("cd $ctsnap/ctsnap_out; tar -xvf TRACE_SPOOL.tar");
	}
}

my $lstrsp_command = sprintf("/opt/rsct/bin/lstrsp --spool_dir %s --cluster_name %s --cluster_id %s --node_name %s --node_id %s --daemon_name %s %s", $spool_dir, $cluster_name, $cluster_id, $node_name, $node_id, $daemon_name, $time_specification);

if (undef eq $ls)
{
	my $list = `$lstrsp_command`;
	my $rc = $?;

	if ($rc)
	{
		exit $rc;
	}
	else
	{
		if ("" eq $list)
		{
			exit 0;
		}
		else
		{
			# convert newlines to spaces
			$list =~ s/\n/ /g;

			# add local files

			if ($local) {
				my @files = split /\n/, `ls`;
				
				foreach my $file (@files) {
					if ($file =~ /$local/) {
						$list .= " $file";
					}
				}
			}

			exit system("rpttr $rpttr_opt_f $rpttr_opt_b $rpttr_opt_r $rpttr_opt_o $rpttr_opt_t $rpttr_opt_s $list");
		}
	}
}
else
{
	my $rc = system($lstrsp_command);

	if ($local) {
		my @files = split /\n/, `ls`;
		
		foreach my $file (@files) {
			if ($file =~ /$local/) {
				print "$file\n";
			}
		}
	}

	exit $rc;
}

# functions

sub help
{
	usage();

	print STDERR <<HELP;

The showtr utility passes selected trace spool files corresponding
to the current working directory to rpttr. It thus must be executed
from a directory from which trace files are spooled (or the respective
directory extracted from a ctsnap if --ctsnap is specified). By default
it also includes local trace spool pages files matching the perl regex
'^.+\.sp$'. This filter can be overridden with the --local option, or
disabled altogether with the --nolocal option.


Examples:

# show ConfigRM's trace files from today
> cd /var/ct/IW/log/mc/IBM.ConfigRM
> showtr

# show ConfigRM's trace files from today and yesterday
> cd /var/ct/IW/log/mc/IBM.ConfigRM
> showtr 1

# show ConfigRM's trace files from the last week
> cd /var/ct/IW/log/mc/IBM.ConfigRM
> showtr 7

# show ConfigRM's trace files since a past date
> cd /var/ct/IW/log/mc/IBM.ConfigRM
> showtr --from 2008-03-31

# show ConfigRM's trace files from the beginning of the spool
# until a past date
> cd /var/ct/IW/log/mc/IBM.ConfigRM
> showtr --to 2008-03-31

# show ConfigRM's trace files between two dates (inclusive)
> cd /var/ct/IW/log/mc/IBM.ConfigRM
> showtr --from 2008-03-31 --to 2008-04-15.11:15:33
HELP

	exit 0;
}

sub usage
{
	print STDERR <<USAGE;

Usage:
showtr [--spool_dir <path> | first export CT_TR_SPOOL_DIR=<path>] 
       [--ls]
       [--help]
       [--ctsnap [--extract]]
       [--nolocal]
       [--local <perl regex in quotes>]
       [rpttr flags]
       [<number of days before today>] |
         [--from <yyyy-mm-dd[.hh[:mm[:ss]]]> [--to <yyyy-mm-dd[.hh[:mm[:ss]]]>]]

Notes:
- <number of days before today> defaults to 0
- the --ls option lists the spool files instead of passing them to rpttr
- showtr must be executed in a subdirectory of /var/ct/*/log
- showtr attempts to determine daemon_name from "rpttr -B" against all trace
  files the current directory until found. If it can't, it prompts for daemon_name.
- --ctsnap tells showtr caller is in var/ct/*/log of a ctsnap. It also forces the
  spool_dir path to be relative to the ctsnap's ctsnap_out directory, even if
  the spool_dir is an absolute path.
- --extract tells showtr to extract ctsnap trace spool files from their archive
  (this need be done only once)
USAGE

	if (undef ne $_[0])
	{
		exit $_[0];
	}
}