package com.ibm.nmon.parser.gc.state; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.TimeZone; import com.ibm.nmon.data.DataRecord; import com.ibm.nmon.parser.gc.GCParserContext; /** * The initial state for a Java 7-style garbage collection parser. */ final class Java7GC implements GCState { static final Java7GC INSTANCE = new Java7GC(); private final SimpleDateFormat datetime = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", java.util.Locale.US); private final Initialized initialized = new Initialized(this); private double timeSince; private double afInterval; private int totalCount; private int nurseryCount; private int tenuredCount; private int systemCount; @Override public GCState startElement(GCParserContext context, String elementName, String unparsedAttributes) { if ("initialized".equals(elementName)) { return initialized; } else if ("exclusive-start".equals(elementName)) { context.parseAttributes(unparsedAttributes); timeSince = context.parseDouble("intervalms") / 1000; context.setCurrentRecord(new DataRecord(parseTimestamp(context), String.format("%08x", context.getData().getRecordCount()).toString())); } else if ("sys-start".equals(elementName)) { context.parseAttributes(unparsedAttributes); context.setValue("GCSINCE", "gc_system", timeSince); context.setValue("GCCOUNT", "system_count", ++systemCount); } else if ("af-start".equals(elementName)) { context.parseAttributes(unparsedAttributes); afInterval = context.parseDouble("intervalms") / 1000; context.setValue("GCMEM", "requested", "totalBytesRequested"); } else if ("cycle-start".equals(elementName)) { context.parseAttributes(unparsedAttributes); String type = context.getAttribute("type"); if (type.startsWith("global")) { // global or 'global garbage collect' context.setValueDiv1000("GCSINCE", "gc_global", "intervalms"); if (afInterval >= 0) { context.setValue("GCSINCE", "af_tenured", afInterval); } context.setValue("GCCOUNT", "tenured_count", ++tenuredCount); } else if ("scavenge".equals(type)) { context.setValueDiv1000("GCSINCE", "gc_scavenger", "intervalms"); if (afInterval >= 0) { context.setValue("GCSINCE", "af_nursery", afInterval); } context.setValue("GCCOUNT", "nursery_count", ++nurseryCount); } context.setValue("GCCOUNT", "total_count", ++totalCount); return Java7GCCycle.INSTANCE; } else if ("response-info".equals(elementName)) { context.parseAttributes(unparsedAttributes); context.setValue("GCTIME", "exclusive_ms", "timems"); } else if ("exclusive-end".equals(elementName)) { context.parseAttributes(unparsedAttributes); context.setValue("GCTIME", "total_ms", "durationms"); } return this; } @Override public GCState endElement(GCParserContext context, String elementName) { if ("verbosegc".equals(elementName)) { context.reset(); reset(); return Start.INSTANCE; } else if ("exclusive-end".equals(elementName)) { context.saveRecord(); timeSince = 0; afInterval = -1; Java7GCCycle.INSTANCE.reset(); return this; } else { return this; } } @Override public void reset() { timeSince = 0; afInterval = -1; totalCount = 0; nurseryCount = 0; tenuredCount = 0; systemCount = 0; Java7GCCycle.INSTANCE.reset(); } void setTimeZone(TimeZone timeZone) { datetime.setTimeZone(timeZone); } private long parseTimestamp(GCParserContext context) { String value = context.getAttribute("timestamp"); if (value == null) { context.logMissingAttribute("timestamp"); return 0; } long toReturn; try { toReturn = datetime.parse(value).getTime(); } catch (ParseException pe) { context.logInvalidValue("timestamp", value); toReturn = 0; } return toReturn; } private Java7GC() { reset(); } }