/*
This file is part of mjprof.
mjprof 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 3 of the License, or
(at your option) any later version.
mjprof 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
along with mjprof. If not, see <http://www.gnu.org/licenses/>.
*/
package com.performizeit.mjprof.parser;
import com.performizeit.mjprof.model.Profile;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static com.performizeit.mjprof.parser.ThreadInfoProps.*;
public class ThreadInfo extends Props {
public static final String LOCKED_OWNABLE_SYNCHRONIZERS = "Locked ownable synchronizers";
public static final String JAVA_LANG_THREAD_STATE = "java.lang.Thread.State";
public ThreadInfo(String stackTrace) {
BufferedReader reader = new BufferedReader(new StringReader(stackTrace));
try {
String metaLine = reader.readLine();
if (metaLine != null) {
parseMetaLine(metaLine);
String threadState = reader.readLine();
if (threadState != null) {
parseThreadState(threadState);
}
String linesOfStack = "";
String s;
while ((s = reader.readLine()) != null) {
if (s.trim().length() == 0) break;
linesOfStack += s + "\n";
}
props.put(STACK, new Profile(linesOfStack));
while ((s = reader.readLine()) != null) {
if (s.contains(LOCKED_OWNABLE_SYNCHRONIZERS)) break;
}
String linesOfLOS = "";
while ((s = reader.readLine()) != null) {
if (s.trim().length() == 0) break;
linesOfLOS += s + "\n";
}
if (linesOfLOS.trim().length() > 0)
props.put(LOS, new ThreadLockedOwnableSynchronizers(linesOfLOS));
}
} catch (IOException e) {
e.printStackTrace();
}
}
public ThreadInfo(HashMap<String, Object> mtd) {
super(mtd);
}
private void parseThreadState(String threadState) {
Pattern p = Pattern.compile("^[\\s]*" + JAVA_LANG_THREAD_STATE + ": (.*)$");
Matcher m = p.matcher(threadState);
if (m.find()) {
props.put(STATE, m.group(1));
}
}
protected String metadataProperty(String metaLine, String propertyName) {
Pattern p = Pattern.compile(".* " + propertyName + "=([0-9a-fx]*) .*");
Matcher m = p.matcher(metaLine);
if (m.find()) {
return m.group(1);
}
return null;
}
protected void metadataKeyValProperties(String metaLine) {
Pattern p = Pattern.compile("(\\S+)=(\\S+)"); // a nonspace string then = and then a non space string
Matcher m = p.matcher(metaLine);
while (m.find()) {
props.put(m.group(1), m.group(2));
}
if (props.get(TID) != null && !props.get(TID).equals("*")) {
props.put(TID + "Long", new HexaLong((String) props.get(TID)));
}
if (props.get(NID) != null && !props.get(NID).equals("*")) {
props.put(NID + "Long", new HexaLong((String) props.get(NID)));
}
}
private void parseMetaLine(String metaLine) {
Pattern p = Pattern.compile("^\"(.*)\".*");
Matcher m = p.matcher(metaLine);
if (m.find()) {
props.put(NAME, m.group(1));
}
extractStatus(metaLine);
metadataKeyValProperties(metaLine);
if (metaLine.contains("\" " + DAEMON + " ")) {
props.put(DAEMON, true);
}
}
private void extractStatus(String metaLine) {
int idx = metaLine.lastIndexOf('=');
if (idx != -1) {
String lastParam = metaLine.substring(idx);
idx = lastParam.indexOf(' ');
if (idx != -1) {
lastParam = lastParam.substring(idx + 1);
if (lastParam.length() > 0) {
props.put(STATUS, lastParam.trim());
}
}
}
}
@Override
public String toString() {
StringBuilder mdStr = new StringBuilder();
if (props.get(NAME) != null) {
mdStr.append("\"").append(props.get(NAME)).append("\"");
}
if (props.get(COUNT) != null) {
mdStr.append(" " + COUNT + "=").append(props.get(COUNT));
}
if (props.get(DAEMON) != null) {
mdStr.append(" " + DAEMON);
}
if (props.get(PRIO) != null) {
mdStr.append(" " + PRIO + "=").append(props.get(PRIO));
}
if (props.get(TID) != null) {
mdStr.append(" " + TID + "=" + props.get(TID));
}
if (props.get(NID) != null) {
mdStr.append(" " + NID + "=" + props.get(NID));
}
if (props.get(STATUS) != null) {
mdStr.append(" " + props.get(STATUS));
}
if (props.get(CPUNS) != null) {
mdStr.append(" " + CPUNS + "=").append(props.get(CPUNS));
}
if (props.get(WALL) != null) {
mdStr.append(" " + WALL + "=").append(props.get(WALL));
}
if (props.get(CPU_PREC) != null) {
mdStr.append(" " + CPU_PREC + "=").append(props.get(CPU_PREC));
}
if (props.get(STATE) != null) {
mdStr.append("\n " + JAVA_LANG_THREAD_STATE + ": ").append(props.get(STATE));
}
if (props.get(STACK) != null) {
mdStr.append("\n").append(props.get(STACK).toString());
}
mdStr.append("\n");
if (props.get(LOS) != null) {
mdStr.append("\n " + LOCKED_OWNABLE_SYNCHRONIZERS + ":\n").append(
props.get(LOS).toString());
}
return mdStr.toString();
}
}