#!/usr/bin/perl

while (<>) {
  if (/^Full thread dump/) {
    print "Found thread dump\n";
    parse_thread_dump();
  }
}
exit 0;

sub parse_thread_dump {
  my $STATE_RUNNABLE = "runnable", $STATE_WAIT_MONITOR = "monitor wait", $STATE_WAIT_OBJECT = "object wait", $UNNAMED_THREAD="unnamed thread", $TIMER_THREAD="timer thread", $IDLE_THREAD="idle thread", $RESIN_THREAD="resin thread", $VM_THREAD="vm thread", $COMPILER_THREAD="compiler thread", $GC_THREAD="gc thread";
  my %thread_state_count;
  $thread_state_count{$STATE_RUNNABLE} = 0;
  $thread_state_count{$STATE_WAIT_MONITOR} = 0;
  $thread_state_count{$STATE_WAIT_OBJECT} = 0;
  $thread_state_count{$UNNAMED_THREAD} = 0;
  $thread_state_count{$TIMER_THREAD} = 0;
  $thread_state_count{$IDLE_THREAD} = 0;
  $thread_state_count{$RESIN_THREAD} = 0;
  $thread_state_count{$VM_THREAD} = 0;
  $thread_state_count{$COMPILER_THREAD} = 0;
  $thread_state_count{$GC_THREAD} = 0;
  my $total_thread_count;
  my %runnable_method_count;
  my %monitor_method_count;
  my %object_method_count;
  my %unnamed_thread_count;
  my %timer_thread_count;
  my %idle_thread_count;
  my %resin_thread_count;
  my %vm_thread_count;
  my %compiler_thread_count;
  my %gc_thread_count;
  while (<>) {
    if (/^\"VM Periodic Task Thread/) {
#      print "found vm thread: $_";
      $total_thread_count++;
      $thread_state = $VM_THREAD;
      $vm_thread_count{"vm thread"}++;
      $thread_state_count{$thread_state}++;
      last;
    }
    elsif (/^\"Thread-/) {
#      print "found unnamed thread: $_";
      $total_thread_count++;
      $thread_state = $UNNAMED_THREAD;
      $unamed_thread_count{"unnamed thread"}++;
      $thread_state_count{$thread_state}++;
    }
    elsif (/^\"Timer-/) {
#      print "found timer thread: $_";
      $total_thread_count++;
      $thread_state = $TIMER_THREAD;
      $timer_thread_count{"timer thread"}++;
      $thread_state_count{$thread_state}++;
    }
    elsif (/^\"resin-[0-9]/) {
#      print "found idle thread: $_";
      $total_thread_count++;
      $thread_state = $IDLE_THREAD;
      $idle_thread_count{"idle thread"}++;
      $thread_state_count{$thread_state}++;
    }
    elsif (/^\"resin-[a-su-z]/) {
#      print "found resin thread: $_";
      $total_thread_count++;
      $thread_state = $RESIN_THREAD;
      $resin_thread_count{"resin thread"}++;
      $thread_state_count{$thread_state}++;
    }
    elsif (/^\"resin-thread-/) {
#      print "found resin thread: $_";
      $total_thread_count++;
      $thread_state = $RESIN_THREAD;
      $resin_thread_count{"resin thread"}++;
      $thread_state_count{$thread_state}++;
    }
    elsif (/^\"Low Memory Detector/) {
#      print "found vm thread: $_";
      $total_thread_count++;
      $thread_state = $VM_THREAD;
      $resin_thread_count{"vm thread"}++;
      $thread_state_count{$thread_state}++;
    }
    elsif (/^\"AdapterThread/) {
#      print "found resin thread: $_";
      $total_thread_count++;
      $thread_state = $RESIN_THREAD;
      $resin_thread_count{"resin thread"}++;
      $thread_state_count{$thread_state}++;
    }
    elsif (/^\"CompilerThread/) {
#      print "found compiler thread: $_";
      $total_thread_count++;
      $thread_state = $COMPILER_THREAD;
      $compiler_thread_count{"compiler thread"}++;
      $thread_state_count{$thread_state}++;
    }
    elsif (/^\"main/) {
#      print "found resin thread: $_";
      $total_thread_count++;
      $thread_state = $RESIN_THREAD;
      $resin_thread_count{"resin thread"}++;
      $thread_state_count{$thread_state}++;
    }
    elsif (/^\"Finalizer/) {
#      print "found vm thread: $_";
      $total_thread_count++;
      $thread_state = $VM_THREAD;
      $vm_thread_count{"vm thread"}++;
      $thread_state_count{$thread_state}++;
    }
    elsif (/^\"Reference Handler/) {
#      print "found vm thread: $_";
      $total_thread_count++;
      $thread_state = $VM_THREAD;
      $vm_thread_count{"vm thread"}++;
      $thread_state_count{$thread_state}++;
    }
    elsif (/^\"Signal Dispatcher/) {
#      print "found vm thread: $_";
      $total_thread_count++;
      $thread_state = $VM_THREAD;
      $vm_thread_count{"vm thread"}++;
      $thread_state_count{$thread_state}++;
    }
    elsif (/^\"VM /) {
#      print "found vm thread: $_";
      $total_thread_count++;
      $thread_state = $VM_THREAD;
      $vm_thread_count{"vm thread"}++;
      $thread_state_count{$thread_state}++;
    }
    elsif (/^\"GC /) {
#      print "found gc thread: $_";
      $total_thread_count++;
      $thread_state = $GC_THREAD;
      $gc_thread_count{"gc thread"}++;
      $thread_state_count{$thread_state}++;
    }
    elsif (/^\"resin-tcp-/) {
#      print "found thread: $_";
      $total_thread_count++;
      my $thread_state;
      # find thread state: running, waiting for monitor, or waiting for accept
      if (/in Object\.wait/) {
	$thread_state = $STATE_WAIT_OBJECT;
	while (<>) {
	  if (!/Object\.wait/ && /at (.*$)/) {
	    my $method_name = $1;
	    $object_method_count{$method_name}++;
	  }
	  elsif (! /(at|waiting)/) {
	    last;
	  }
	}
      }
      elsif (/runnable/) {
	$thread_state = $STATE_RUNNABLE;
	while (<>) {
	  if (/at (.*$)/) {
	    my $method_name = $1;
	    $runnable_method_count{$method_name}++;
	  }
	  last;
	}
      }
      elsif (/waiting for monitor entry/) {
	$thread_state = $STATE_WAIT_MONITOR;
	while (<>) {
	  if (/at (.*$)/) {
	    my $method_name = $1;
	    $monitor_method_count{$method_name}++;
	  }
	  last;
	}
      }
      else {
	# unknown state
	next;
      }
      $thread_state_count{$thread_state}++;
    }
    elsif (/^\"/) {
#      print "found unnamed thread: $_";
      $total_thread_count++;
      $thread_state = $UNNAMED_THREAD;
      $unamed_thread_count{"unnamed thread"}++;
      $thread_state_count{$thread_state}++;
    }
  }
  print "  Total threads:\t" . $total_thread_count . "\n";
  print "  Thread status:\n";
  foreach $key (keys(%thread_state_count)) {
    print "\t" . $key . "\t" . $thread_state_count{$key} . "\n";
  }
  print "  Methods blocked waiting for monitors:\n";
  print_thread_list(\%monitor_method_count);
  print "  Methods blocked in Object.wait():\n";
  print_thread_list(\%object_method_count);
  print "  Runnable methods:\n";
  print_thread_list(\%runnable_method_count);
  print "\n";
}

sub print_thread_list {
  my $map = shift;
  my %tmp_array = %$map;
  foreach $key (sort {$tmp_array{$b} <=> $tmp_array{$a}; } keys (%tmp_array)) {
    print "\t" . $map->{$key} . "\t" . $key . "\n";
  }
}
