package com.ibm.nmon.parser; import org.slf4j.Logger; import java.util.List; import java.util.Map; import java.io.IOException; import java.io.File; import java.io.BufferedReader; import java.io.FileReader; import java.io.StringReader; import java.io.StringWriter; import java.util.TimeZone; import com.ibm.nmon.data.NMONDataSet; /** * A parser for <code>topas -a</code> output. This serves as a bridge between Topas and NMON. This class takes the * output and converts it to a string that can be parsed by {@link NMONParser}. */ public final class TopasOutParser { private static final Logger LOGGER = org.slf4j.LoggerFactory.getLogger(TopasOutParser.class); private final NMONParser nmonParser; public TopasOutParser(NMONParser nmonParser) { this.nmonParser = nmonParser; } // topas -a outputs sorted data; unsort it by looking for the header records and outputting them first // once the ZZZZ records are parsed output them then all the corresponding data records for that timestamp public NMONDataSet parse(String filename, TimeZone timeZone, boolean scaleProcessesByCPU) throws IOException { File file = new File(filename); BufferedReader in = null; StringWriter writer = null; try { in = new BufferedReader(new FileReader(file)); writer = new StringWriter((int) file.length()); // LinkedHashMap so insertion order is maintained; removes need to reparse headers later Map<String, List<String>> headersToLines = new java.util.LinkedHashMap<String, List<String>>(32); List<String> headers = new java.util.ArrayList<String>(32); List<String> timestamps = new java.util.ArrayList<String>(128); String line = null; while ((line = in.readLine()) != null) { int idx = line.indexOf(","); String header = line.substring(0, idx); if ("AAA".equals(header)) { // put all the AAA records at the top by writing them out now writer.write(line); writer.write('\n'); } else if ("ZZZZ".equals(header)) { timestamps.add(line); } else { // save all the data by header name List<String> lines = headersToLines.get(header); if (lines == null) { LOGGER.trace("found {} " + "header", header); lines = new java.util.ArrayList<String>(218); headersToLines.put(header, lines); } if (line.charAt(idx + 1) == 'T') { lines.add(line); } else { if ("LPAR".equals(header)) { // fix capitalization of LPAR data to match NMON line = "LPAR,LPAR Stats,PhysicalCPU,virtualCPUs,logicalCPUs,poolCPUs,entitled,weight,PoolIdle,usedAllCPU%,usedPoolCPU%,SharedCPU"; } headers.add(line); } } } LOGGER.debug("found {} " + "data types", headers.size()); LOGGER.debug("found {} " + "ZZZZ timestamps", timestamps.size()); LOGGER.debug("found {} " + "data types", headersToLines.size()); for (String header : headers) { writer.write(header); writer.write('\n'); } // output each timestamp, then all the data for that time // assume all arrays are the same size, i.e. there is data at each timestamp for all values for (int i = 0; i < timestamps.size(); i++) { writer.write(timestamps.get(i)); writer.write('\n'); for (List<String> lines : headersToLines.values()) { writer.write(lines.get(i)); writer.write('\n'); } } return nmonParser.parse(filename, new StringReader(writer.toString()), timeZone, scaleProcessesByCPU); } finally { if (in != null) { in.close(); } if (writer != null) { writer.close(); } } } }