use of com.ibm.jvm.trace.format.api.TraceContext in project openj9 by eclipse.
the class ProgramOption method main.
/**
* @param args
*/
public static void main(String[] args) throws Exception {
/* Add the option parsers we want to provide */
ProgramOption.addOption(InputFile.class);
ProgramOption.addOption(OutputFile.class);
ProgramOption.addOption(MessageFile.class);
ProgramOption.addOption(FormatTimestamp.class);
ProgramOption.addOption(Indent.class);
ProgramOption.addOption(Summary.class);
ProgramOption.addOption(Threads.class);
ProgramOption.addOption(Timezone.class);
ProgramOption.addOption(Verbose.class);
ProgramOption.addOption(Debug.class);
ProgramOption.addOption(Statistics.class);
/* The trace context holds the configuration and state for the parsing */
TraceContext context;
/* Process the command line options and populate any unspecified options with default values */
try {
for (int i = 0; i < args.length; i++) {
ProgramOption.addArgument(args[i]);
}
ProgramOption.applyDefaults();
} catch (IllegalArgumentException e) {
System.err.println(e.getMessage());
return;
}
/*
* At this point we have valid data for all command line options so get on with the parsing
*/
/* Get the input files to process */
List inputFiles = (List) ProgramOption.getValue("input_file");
List messageFiles = (List) ProgramOption.getValue("datfile");
List threads = (List) ProgramOption.getValue("threads");
Integer timezone = (Integer) ProgramOption.getValue("timezone");
Boolean formatTime = (Boolean) ProgramOption.getValue("format_time");
Boolean indenting = (Boolean) ProgramOption.getValue("indent");
Boolean summary = (Boolean) ProgramOption.getValue("summary");
Boolean verbose = (Boolean) ProgramOption.getValue("verbose");
Integer debugLevel = (Integer) ProgramOption.getValue("debug");
Boolean statistics = (Boolean) ProgramOption.getValue("statistics");
/* Parse the header on the first file */
int blockSize = 4000;
PrintStream error = null;
PrintStream warning = null;
PrintStream debug = null;
if (debugLevel.intValue() > 0) {
debug = System.err;
}
try {
while (true) {
try {
ByteBuffer data;
data = ((RandomAccessFile) inputFiles.get(0)).getChannel().map(FileChannel.MapMode.READ_ONLY, 0, blockSize);
context = TraceContext.getContext(data, (File) messageFiles.get(0), System.out, warning, error, debug);
break;
} catch (BufferUnderflowException e) {
blockSize *= 2;
}
}
} catch (IOException e) {
/* could be many things, one is a file shorter than blockSize so try a different method */
try {
long length = ((RandomAccessFile) inputFiles.get(0)).length();
if (length > 0) {
byte[] header = new byte[(int) length];
((RandomAccessFile) inputFiles.get(0)).seek(0);
int i = ((RandomAccessFile) inputFiles.get(0)).read(header);
if (i == length && length < blockSize) {
context = TraceContext.getContext(header, header.length, (File) messageFiles.get(0), System.out, warning, error, debug);
} else {
throw new Exception("received premature end of file: " + e.getMessage());
}
} else {
throw new Exception("empty trace file");
}
} catch (Exception f) {
/* this wasn't due to filesize < blocksize so print the exception message and exit */
System.err.println("Unable to read trace header from file: " + f.getMessage());
System.err.println("Please check that the input file is a binary trace file");
return;
}
} catch (IllegalArgumentException e) {
System.err.println("Problem reading the trace file header: " + e.getMessage());
System.err.println("Please check that that the input file is a binary trace file");
return;
}
if (verbose.booleanValue() || debugLevel.intValue() > 0) {
/* we don't set these in the constructor otherwise we see error messages during the retry logic if the block
* size estimate is too small */
context.setErrorStream(System.err);
context.setWarningStream(System.err);
}
context.setDebugLevel(debugLevel.intValue());
/* set up the thread filters */
Iterator itr = threads.iterator();
while (itr.hasNext()) {
Long id = (Long) itr.next();
context.addThreadToFilter(id);
}
context.setTimeZoneOffset(timezone.intValue());
/* add any remaining dat files */
for (int i = 1; i < messageFiles.size(); i++) {
File file = (File) messageFiles.get(i);
try {
context.addMessageData(file);
} catch (IOException e) {
// Problem reading one of the trace format .dat files, issue message and exit
System.err.println("Unable to process trace format data file: " + file.getAbsolutePath() + " (" + e.getMessage() + ")");
return;
}
}
/* Set the output file */
PrintWriter output = (PrintWriter) ProgramOption.getValue("output_file");
/* read in the blocks from the various files and sort them */
long recordsInData = 0;
long lostCountByException = 0;
long start = System.currentTimeMillis();
long end = 0;
long startBlock = start;
long recordsProcessed = 0;
long totalBytes = 0;
/* loop over the generational files and add the blocks to the context */
for (int i = 0; i < inputFiles.size(); i++) {
long offset = context.getHeaderSize();
long recordSize = context.getRecordSize();
RandomAccessFile traceFile = (RandomAccessFile) inputFiles.get(i);
long length = traceFile.length();
if ((length - context.getHeaderSize()) % recordSize != 0) {
context.warning(context, "The body of the trace file is not a multiple of the record size, file either truncated or corrupt");
}
while (offset < length) {
try {
TraceThread thread = context.addData(traceFile, offset);
indentMap.put(thread, "");
} catch (IllegalArgumentException e) {
context.error(context, "Bad block of trace data in input file at offset " + offset + ": " + e.getMessage());
}
offset += recordSize;
totalBytes += recordSize;
recordsInData++;
}
}
/* output the summary information */
output.println(context.summary());
if (summary.booleanValue() && !statistics.booleanValue()) {
/* we've requested only the summary so exit here */
output.close();
return;
}
if (!summary.booleanValue()) {
/* output the section header line and the column headings for the trace point data section */
output.println(" Trace Formatted Data " + System.getProperty("line.separator"));
String columnHeader;
if (timezone.intValue() == 0) {
columnHeader = "Time (UTC) ";
} else {
/* user specified a timezone offset, show that in the timestamp column header */
if (timezone.intValue() > 0) {
columnHeader = "Time (UTC +";
} else {
columnHeader = "Time (UTC -";
}
columnHeader += Math.abs(timezone.intValue() / 60) + ":" + Math.abs(timezone.intValue() % 60) + ") ";
}
if (context.getPointerSize() == 4) {
columnHeader += "Thread ID ";
} else {
columnHeader += "Thread ID ";
}
columnHeader += " Tracepoint ID Type Tracepoint Data";
output.println(columnHeader);
}
/* start reading tracepoints */
itr = context.getTracepoints();
String totalMbytes = (float) totalBytes / (float) (1024 * 1024) + "Mb";
context.message(context, "Processing " + totalMbytes + " of binary trace data");
TraceThread thread = null;
String indent = "";
while (itr.hasNext()) {
TracePointImpl tracepoint;
try {
tracepoint = (TracePointImpl) itr.next();
} catch (MissingDataException e) {
lostCountByException += e.getMissingBytes() / context.getRecordSize();
continue;
}
/* If we've only been asked for the summary we don't format the trace */
if (!summary.booleanValue()) {
TraceThread current = tracepoint.getThread();
String component = tracepoint.getComponentName();
int tpID = tracepoint.getID();
String container = tracepoint.getContainerComponent();
String parameters = "";
try {
parameters = tracepoint.getFormattedParameters();
if (parameters == null || parameters.length() == 0) {
context.error(context, "null parameter data for trace point " + component + "." + tpID);
}
} catch (BufferUnderflowException e) {
/* This may be thrown, but there's essentially nothing we can do about it at this level so
* just report it
*/
context.error(context, "Underflow accessing parameter data for trace point " + component + "." + tpID);
}
StringBuilder formatted = new StringBuilder();
if (formatTime.booleanValue()) {
formatted.append(tracepoint.getFormattedTime());
} else {
formatted.append(tracepoint.getRawTime());
}
/* append thread id */
formatted.append(" ").append((current != thread ? "*" : " "));
formatted.append(context.formatPointer(current.getThreadID()));
formatted.append(" ");
/* append component and padding - add container if this is a sub component.
* e.g j9codertvm(j9jit).91 vs j9jit.18 */
String fullTracepointID = String.format((container != null ? "%s(%s).%d" : "%1$s.%3$d"), component, container, tpID);
/* Left justify but include a space in the formatting as a column separator in case of very long component id's. */
formatted.append(String.format("%-19s ", fullTracepointID));
formatted.append(tracepoint.getType());
if (indenting.booleanValue()) {
indent = indentMap.get(current).toString();
/* we remove the indent before appending for exit */
if (tracepoint.getTypeAsInt() == TracePoint.EXIT_TYPE || tracepoint.getTypeAsInt() == TracePoint.EXIT_EXCPT_TYPE) {
try {
indent = indent.substring(2);
indentMap.put(current, indent);
} catch (IndexOutOfBoundsException e) {
indent = "";
indentMap.put(current, "");
}
}
formatted.append(indent);
}
formatted.append(parameters.length() > 0 ? ((parameters.charAt(0) == '*' ? " " : "") + parameters) : "");
if (indenting.booleanValue()) {
/* juggle the indent for the thread */
if (tracepoint.getTypeAsInt() == TracePoint.ENTRY_TYPE || tracepoint.getTypeAsInt() == TracePoint.ENTRY_EXCPT_TYPE) {
indent = indent + " ";
indentMap.put(current, indent);
}
}
if (debugLevel > 0) {
formatted.append(" [" + ((TracePointImpl) tracepoint).getDebugInfo() + "]");
}
thread = current;
output.println(formatted.toString());
}
/* print percentage */
if (context.getTotalRecords() != recordsProcessed) {
recordsProcessed = context.getTotalRecords();
float processedMbytes = ((float) (context.getTotalRecords() * context.getRecordSize())) / (1024 * 1024);
if (processedMbytes % 10 == 0) {
int percent = (int) ((processedMbytes * 100) / (totalBytes / (1024 * 1024)));
if (verbose.booleanValue()) {
end = System.currentTimeMillis();
float MbpsBlock = (float) 10.0 / (float) ((end - startBlock) / 1000.0);
float Mbps = (float) (processedMbytes) / (float) (((float) (end - start) / 1000.0));
startBlock = System.currentTimeMillis();
context.message(context, "Processed " + processedMbytes + "Mb (" + percent + "%), burst speed: " + MbpsBlock + "Mb/s, average: " + Mbps + "Mb/s");
} else {
context.message(context, "Processed " + processedMbytes + "Mb (" + percent + "%)");
}
}
}
}
if (lostCountByException > 0) {
context.warning(context, lostCountByException + " records were discarded during trace generation");
}
output.close();
context.message(context, "Completed processing of " + context.getTotalTracePoints() + " tracepoints with " + context.getWarningCount() + " warnings and " + context.getErrorCount() + " errors");
if (verbose.booleanValue()) {
end = System.currentTimeMillis();
float Mbps = (float) (recordsInData * context.getRecordSize()) / (float) (((float) (end - start) / 1000) * (1024 * 1024));
context.message(context, "Total processing time " + (end - start) + "ms (" + Mbps + "Mb/s)");
}
if (statistics) {
context.message(context, context.statistics());
}
}
Aggregations