public String readLine() throws IOException {
StringBuilder sb = new StringBuilder(); char lineSeparator = '\n'; char c = (char) dataStream.readUnsignedByte(); while (c != lineSeparator) {
sb.append(c);
c = (char) dataStream.readUnsignedByte();
} return sb.toString();
}
publicint readNumber(int numBytes) throws IOException { int number = 0; for (int i = 0; i < numBytes; i++) {
number += dataStream.readUnsignedByte() << (i * 8);
} return number;
}
publicvoid validateTraceHeader(int expectedVersion) throws Exception { // Read 4-byte magicNumber. int magicNumber = readNumber(4); if (magicNumber != MAGIC_NUMBER) { thrownew Exception("Magic number doesn't match. Expected "
+ Integer.toHexString(MAGIC_NUMBER) + " Got "
+ Integer.toHexString(magicNumber));
} // Read 2-byte version. int version = readNumber(2); if (version != expectedVersion) { thrownew Exception("Unexpected version. Expected " + expectedVersion + " Got "
+ version);
}
traceFormatVersion = version & 0xF; // Read 2-byte headerLength length. int headerLength = readNumber(2); // Read 8-byte starting time - Ignore timestamps since they are not deterministic.
dataStream.skipBytes(8); // 4 byte magicNumber + 2 byte version + 2 byte offset + 8 byte timestamp. int numBytesRead = 16; if (version >= DUAL_CLOCK_VERSION) { // Read 2-byte record size. // TODO(mythria): Check why this is needed. We can derive recordSize from version. Not // sure why this is needed.
recordSize = readNumber(2);
numBytesRead += 2;
} // Skip any padding. if (headerLength > numBytesRead) {
dataStream.skipBytes(headerLength - numBytesRead);
}
}
publicint GetThreadID() throws IOException { // Read 2-byte thread-id. On host thread-ids can be greater than 16-bit but it is truncated // to 16-bits in the trace. int threadId = readNumber(2); return threadId;
}
publicvoid ProcessMethodInfoEntry() throws IOException { // Read 2-byte method info size int headerLength = readNumber(2); // Read header size data.
String methodInfo = readString(headerLength);
String[] tokens = methodInfo.split("\t", 2); // Get methodId and record methodId -> methodName map. int methodId = Integer.decode(tokens[0]);
String methodLine = tokens[1].replace('\t', ' ');
methodLine = methodLine.substring(0, methodLine.length() - 1);
methodIdMap.put(methodId, methodLine);
}
publicvoid ProcessThreadInfoEntry() throws IOException { // Read 2-byte thread id int threadId = readNumber(2); // Read 2-byte thread info size int headerLength = readNumber(2); // Read header size data.
String threadInfo = readString(headerLength);
threadIdMap.put(threadId, threadInfo);
}
publicboolean ShouldCheckThread(int threadId, String threadName) throws Exception { if (!threadIdMap.containsKey(threadId)) {
System.out.println("no threadId -> name mapping for thread " + threadId); // TODO(b/279547877): Ideally we should throw here, since it isn't expected. Just // continuing to get more logs from the bots to see what's happening here. The // test will fail anyway because the expected output will be different. returntrue;
}
publicvoid CheckTimestamp(int timestamp, int threadId,
HashMap<Integer, Integer> threadTimestampMap) throws Exception { if (threadTimestampMap.containsKey(threadId)) { int oldTimestamp = threadTimestampMap.get(threadId); if (timestamp < oldTimestamp) { thrownew Exception("timestamps are not increasing current: " + timestamp
+ " earlier: " + oldTimestamp);
}
}
threadTimestampMap.put(threadId, timestamp);
}
public String ProcessEventEntry(int threadId, String methodNameFilter) throws IOException, Exception { // Read 4-byte method value int methodAndEvent = readNumber(4); int methodId = methodAndEvent & ~0x3; int eventType = methodAndEvent & 0x3;
// Depending on the version skip either one or two timestamps. int timestamp1 = readNumber(4);
CheckTimestamp(timestamp1, threadId, threadTimestamp1Map); if (traceFormatVersion != 2) { // Read second timestamp int timestamp2 = readNumber(4);
CheckTimestamp(timestamp2, threadId, threadTimestamp2Map);
}
int currNestingLevel = 0; if (nestingLevelMap.containsKey(threadId)) {
currNestingLevel = nestingLevelMap.get(threadId);
} boolean recordMethodEvent = true; if (!ignoredMethodNestingLevelMap.containsKey(threadId)) { if (ignoredMethods.contains(methodName)) { // This should be an entry event. if (eventType != 0) { thrownew Exception("Seeing an exit for an ignored event without an entry");
}
ignoredMethodNestingLevelMap.put(threadId, currNestingLevel);
recordMethodEvent = false;
}
} else { // We need to ignore all calls until the ignored method exits. int ignoredMethodDepth = ignoredMethodNestingLevelMap.get(threadId); // If this is a method exit and we are at the right depth remove the entry so we start // recording from the next event. if (ignoredMethodDepth == currNestingLevel - 1 && eventType != 0) {
ignoredMethodNestingLevelMap.remove(threadId); if (!ignoredMethods.contains(methodName)) { thrownew Exception( "Unexpected method on exit. Mismatch on method entry and exit");
}
}
recordMethodEvent = false;
}
String str = eventTypeToString(eventType, threadId) + " " + threadIdMap.get(threadId) + " "
+ methodName; return recordMethodEvent ? str : null;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.