
sub parse_data {
    my $procs = shift;
    my $cmds = shift;

    while (<STDIN>) {
	if (/^(\d+)\s+(\d+)\s+\((.*?)\)\s+(.*)\s+$/) {
	    my $time = $1;
	    my $pid = $2;
	    my $exe = $3;
	    my $op = $4;
	    
	    if (/init/ && ! exists $procs->{$pid}) {
		$procs->{$pid} = {
		    start => $time,
		    end => 0,
		    sys => 0,
		    user => 0,
		};
	    }

	    if ($op =~ /exit\swith\suser\s(\d+)\ssys\s(\d+)/) {
		my $user = $1;
		my $sys = $2;
		$procs->{$pid}->{end} = $time;
		$procs->{$pid}->{sys} = $sys;
		$procs->{$pid}->{user} = $user;

		# hwclock warps system time, so adjust, pretending it takes
		# no time to execute
		if ($exe =~ /hwclock/) {
		    my $duration = $procs->{$pid}->{end} - $procs->{$pid}->{start};
		    my $tmp = $procs->{$pid};
		    $tmp->{start} += $duration;
		    while ($tmp->{parent}) {
			$tmp = $procs->{$tmp->{parent}};
			$tmp->{start} += $duration;
			if ($tmp->{end}) {
			    $tmp->{end} += $duration;
			}
		    }
		}
	    } elsif ($op =~ /forks\s(\d+)/) {
		my $kid = $1;
		
		$procs->{$kid} = {
		    start => $time,
		    end => 0,
		    parent => $pid,
		    cmd => [$exe],
		    sys => 0,
		    user => 0,
		    read => {},
		    write => {},
		    kids => {},
		};
		$procs->{$pid}->{kids}->{$kid} = 1;
		$cmds->{$exe} = {} unless $cmds->{$exe};
		$cmds->{$exe}->{$kid} = 1;
	    } elsif ($op =~ /execs\s(.*)/) {
		my $path = $1;
		my $bin = (splitpath($path))[2];
		push @{$procs->{$pid}->{cmd}}, $bin;
		$cmds->{$bin} = {} unless $cmds->{$bin};
		$cmds->{$bin}->{$pid} = 1;
	    } elsif ($op =~ /reads\s(.*)/) {
		my $file = $1;
		$procs->{$pid}->{read}->{$file} = 0 
		    unless $procs->{$pid}->{read}->{$file};
		$procs->{$pid}->{read}->{$file}++;
	    } elsif ($op =~ /writes\s(.*)/) {
		my $file = $1;
		$procs->{$pid}->{write}->{$file} = 0 
		    unless $procs->{$pid}->{write}->{$file};
		$procs->{$pid}->{write}->{$file}++;
	    }
	}
    }
}


sub accumulate_stats {
    my $procs = shift;
    my $stats = shift;
    my $pid = shift;
    
    my $proc = $procs->{$pid};

    my $nread = 0;
    my $nwrite = 0;
    foreach my $file (keys %{$proc->{read}}) {
	$nread += $proc->{read}->{$file};
    }
    foreach my $file (keys %{$proc->{write}}) {
	$nwrite += $proc->{write}->{$file};
    }

    my $cnread = $nread;
    my $cnwrite = $nwrite;
    my $csys = $proc->{sys};
    my $cuser = $proc->{user};
    
    foreach my $kid (keys %{$proc->{kids}}) {
	&accumulate_stats($procs, $stats, $kid);
	
	my $cstats = $stats->{$kid};
	
	$cnread+= $cstats->[0];
	$cnwrite+= $cstats->[1];
	$csys+= $cstats->[2];
	$cuser+= $cstats->[3];
    }
    
    $stats->{$pid} = [
		    $nread,
		    $nwrite,
		    $proc->{sys},
		    $proc->{user},
		    $cnread,
		    $cnwrite,
		    $csys,
		    $cuser
		    ];
}

