#!/usr/bin/perl

###############################################################################
###############################################################################
##
##  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
##  Copyright (C) 2004 Red Hat, Inc.  All rights reserved.
##
##  This copyrighted material is made available to anyone wishing to use,
##  modify, copy, or redistribute it subject to the terms and conditions
##  of the GNU General Public License v.2.
##
###############################################################################
###############################################################################


&do_input(@ARGV);

print 'Entries:  ', scalar(@gl), "\n";
print 'Glocks:  ', scalar(keys(%gl)), "\n";
print 'PIDs:  ', scalar(keys(%pid)), "\n";
print "\n";

for ($x = 0; $x < @gl; $x++)
{
    if (!$done[$x])
    {
	@chain = &find_chain($x);
	$req = 0;

	print scalar(@chain), " chain:\n";

	foreach $y (@chain)
	{
	    print $gl[$y];
	    $req++ if ($gl[$y] =~ /request/i);
	    $done[$y]++;
	}
	
	print "$req requests\n";
	print "\n";

	$chains++;
    }
}

for ($x = 0; $x < @gl; $x++)
{
    die "parse_lockdump: something is hosed\n" unless ($done[$x] == 1);
}

print "Chains:  $chains\n";





sub do_input
{
    my(@host) = @_;
    my($host);
    local(*FILE);
    my($line);
    my($gl);

    foreach $host (@host)
    {
	open(FILE, "< $host") || die;

	while ($line = <FILE>)
	{
	    if ($line eq "\n")
	    {
		&file($host, $gl);
		$gl = '';
	    }
	    else
	    {
		$gl .= $line;
	    }
	}

	if ($gl ne '')
	{
	    &file($host, $gl);
	    $gl = '';
	}

	close(FILE);
    }
}


#  Builds:
#
#  @gl:      A list of all the glock sections read in
#  @name:    Contains the name of the glock of each member of @gl
#  @pid:     Contains the pids contained in each member of @gl
#  %gl:      Maps a lockname to the members of @gl that coorespond to that name
#  %pid:     Maps a pid to the members of @gl that correspond to that pid

sub file
{
    my($host, $gl) = @_;
    my($x);
    my($name, $pid);

    ($name) = $gl =~ /^Glock (\(.*\))/;

    push(@gl, "$host $gl");
    $x = @gl - 1;
    push(@name, $name);

    $gl{$name} .= "$x ";

    foreach (split("\n", $gl))
    {
	if (/owner = (\d+)/)
	{
	    $pid = "$host:$1";

	    if (!&is_in($pid, split(' ', $pid[$x])))
	    {
		$pid[$x] .= "$pid ";
		$pid{$pid} .= "$x ";
	    }
	}
    }
}


sub find_chain
{
    my($x, @chain) = @_;
    my($y, $z);
    my($name, $pid);

    $name = $name[$x];

    foreach $y (split(' ', $gl{$name}))
    {
	push(@chain, $y);
    }

    foreach $y (split(' ', $gl{$name}))
    {
	foreach $pid (split(' ', $pid[$y]))
	{
	    foreach $z (split(' ', $pid{$pid}))
	    {
		@chain = &find_chain($z, @chain) unless (&is_in($z, @chain));
	    }
	}
    }

    return @chain;
}


sub is_in
{
    my($val, @list) = @_;

    foreach (@list)
    {
        return 1 if ($_ eq $val);
    }

    return 0;
}


