package com.macmillan.nmeyers; import java.util.*; import java.io.*; /* * TraceBack.java: Part of the PerfAnal tool * * This class holds the data parsed from a stack trace in the * profiler output. For each trace, we store the trace number * (which is also the sort key), the trace count, and an array * of entries corresponding to the traceback. * * Author: Nathan Meyers, nmeyers@javalinux.net * $Id: TraceBack.java,v 1.11 1999/11/10 03:36:14 nathanm Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * with this program. If not, the license is available from the * GNU project, at http://www.gnu.org. */ class TraceBack { public int traceNumber; public int traceCount = 0; public LinkedList entries = new LinkedList(); public ThreadInfo thread = null; TraceBack(int t, ThreadInfo th) { traceNumber = t; thread = th; } // A TraceBack class factory that parses the traceback data from // the input file. public static TraceBack parse(String currentLine, BufferedReader reader, HashMap threads) throws IOException { // Current line is of the form "TRACE :" StringTokenizer tokenizer = new StringTokenizer(currentLine); int traceNumber = 0; ThreadInfo thread = null; try { // Extract the trace number... if (!tokenizer.nextToken().equals("TRACE")) return null; String numberToken = tokenizer.nextToken(" \t\n\r\f:"); // ... and parse it traceNumber = Integer.parseInt(numberToken); try { if (tokenizer.nextToken("=").indexOf("thread") != -1); Integer threadNum = new Integer(tokenizer.nextToken("=)")); thread = (ThreadInfo)threads.get(threadNum); } catch (NoSuchElementException e) {} catch (NumberFormatException e) {} } catch (NoSuchElementException e) { return null; } catch (NumberFormatException e) { return null; } // So far so good. Allocate an instance. TraceBack result = new TraceBack(traceNumber, thread); // Start parsing lines. We'll do this by calling the TraceBackEntry // factory. TraceBackEntry traceBackEntry; while ((traceBackEntry = TraceBackEntry.parse(reader)) != null) result.entries.add(traceBackEntry); return result; } public boolean equals(Object o) { return traceNumber == ((TraceBack)o).traceNumber; } // This class represents individual entries in the stack traceback data. // Encapsulates info on the procedure name and the line number. public static class TraceBackEntry { public String procName; public String procLineNum; private TraceBackEntry(String pN, String pLN) { procName = pN; procLineNum = pLN; } // Parse a traceback entry from the input file. public static TraceBackEntry parse(BufferedReader reader) throws IOException { // The lines we care about begin with a tab reader.mark(1); if (reader.read() != '\t') { reader.reset(); return null; } // Get the line and look for the start of the line number info String procName = reader.readLine(); int pos = procName.indexOf('('); if (pos == -1) return null; String procLineNum = procName.substring(pos); procName = procName.substring(0, pos); // We've got all of the info. Build a TraceBackEntry. return new TraceBackEntry(procName, procLineNum); } public String toString() { return "[" + procName + procLineNum + "]"; } } public String toString() { return "[traceNumber=" + traceNumber + ",traceCount=" + traceCount + ",entries=" + entries; } }