#!/usr/bin/perl

my %data;
$| = 1;
my $timeout = (shift || 1);
my $firsttime = 1;
my %lines;
my %ops;
my %idle;
my %vfscache;

sub GetVFSName {
    my ($vfsid) = @_;

    if (!exists($vfscache{$vfsid})){
	open(VF, "vldbTest localhost rec_lookup -vfsid $vfsid|");
	while (<VF>){
	    next unless /^RES/ && /vfsname\s+\'([^\']+)\'/;
	    $vfscache{$vfsid} = $1;
	}
	close(VF);
    }

    $vfscache{$vfsid};
}

while (1){
    my $printed = 0;
    my $ignore;
    if ($firsttime){
	$firsttime = 0;
    } else {
	select undef, undef, undef, $timeout;
    }
    open(IF, "/proc/spin/spindblade.d/rnums");
    my @data = <IF>;
    close(IF);
    my $rnc = 0;
    my %hist;

    sub ByValue {
	return $hist{$a} <=> $hist{$b};
    }

    if (@data){
	
	my $curtime = time();
	my @keys;
	foreach my $line (@data){
	    chomp $line;
	    if ($line =~ /Rnum (0x[0-9a-f]+) in use,\s+\S+\s+op=(\S+)\s+delta=(\S+)\s*/){
		my $rnum = $1;
		my $op = $2;
		my $delta = $3;
		if (($op == 30) || ($op == 31) || ($op == 32) || ($delta < 1000000)){
		    $ignore = 1;
		    next;
		}
		if (defined($ops{$rnum}) && ($ops{$rnum} ne $op)){	
		    print "Got mismatched op $ops{$rnum}, $op\n";
		    delete $data{$rnum};
		}
		$ops{$rnum} = $op;
		$lines{$rnum} = $line;
		$idle{$rnum} = $delta;
	    } elsif ($line =~ /Rnum (0x[0-9a-f]+) in use:/){
		my $rnum = $1;
		if ($ignore){
		    $ignore = 0;
		    next;
		}
		$lines{$rnum} .= " $line";

		push @keys, $rnum;
		if ($data{$rnum}){
		    my $delta = $curtime - $data{$rnum};
		    my $idle = int($idle{$rnum}/1000000);

		    if ($delta){
			if ($lines{$rnum} =~ /vfs=([0-9a-f]+)/){
			    my $dvfsid = hex("0x" . $1);
			    if (!exists($vfscache{$dvfsid})){
				open(VF, "vldbTest localhost rec_lookup -vfsid $dvfsid|");
				while (<VF>){
				    next unless /^RES/ && /vfsname\s+\'([^\']+)\'/;
				    $vfscache{$dvfsid} = $1;
				}
				close(VF);
			    }
			    print GetVFSName($dvfsid) . "($dvfsid) - ";
			    $hist{$dvfsid}++;
			}

			print "Rnum $rnum around for $delta sec(idle $idle): $lines{$rnum}\n";
			$printed = 1;
		    }
                    $rnc++;
		} else {
		    $data{$rnum} = $curtime;
		}
	    } else {
	    }
	}
	my @dkeys;
	foreach my $key (keys %data){
	    if (!grep(/^$key$/, @keys)){
		delete $data{$key}; 
		delete $ops{$key}; 
		push @dkeys, $key;
	    }
	}
    } else {
	undef %data;
    }

    if (keys %hist){
	foreach my $key (reverse sort ByValue keys %hist){
	    print "  " . GetVFSName($key) . ":$hist{$key}";
	}
	print "\n";
    }
    print "================ " . (scalar localtime) . " - $rnc ================\n" if $printed;
}
