/******************************************************************************* * Copyright (c) 2007, 2010 Association for Decentralized Information Management * in Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.threadlog; import gnu.trove.TDoubleArrayList; import gnu.trove.TLongArrayList; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.DataInput; import java.io.DataInputStream; import java.io.DataOutput; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.StreamCorruptedException; import java.util.ArrayList; public class ThreadLog { private static final transient String HDR = "TLOG"; private static final transient int CURRENT_VERSION = 1; static ThreadLog defaultLog; ArrayList tasks = new ArrayList(); TDoubleArrayList times = new TDoubleArrayList(); TLongArrayList threads = new TLongArrayList(); public double[] getTimes() { return times.toNativeArray(); } public String[] getTasks() { return tasks.toArray(new String[tasks.size()]); } public long[] getThreads() { return threads.toNativeArray(); } private class TaskImpl implements Task { public String name; public long thread; public long beginTime; public TaskImpl(String name) { this.name = name; this.thread = Thread.currentThread().getId(); this.beginTime = System.nanoTime(); } @Override public void end() { long endTime = System.nanoTime(); synchronized(tasks) { tasks.add(name); times.add(beginTime*1e-9); times.add(endTime*1e-9); threads.add(thread); } } } private static enum DummyTask implements Task { INSTANCE; @Override public void end() { } } public Task begin(String name) { return new TaskImpl(name); } public static Task BEGIN(String name) { try { if(defaultLog != null) return defaultLog.begin(name); } catch(NullPointerException e) { } return DummyTask.INSTANCE; } public static ThreadLog setDefaultThreadLog(ThreadLog log) { ThreadLog currentLog = defaultLog; defaultLog = log; return currentLog; } // ------------------------------------------------------------------------ // SERIALIZATION // ------------------------------------------------------------------------ public static ThreadLog deserialize(File file) throws IOException { DataInputStream in = null; try { in = new DataInputStream(new BufferedInputStream(new FileInputStream(file))); ThreadLog log = new ThreadLog(); log.doDeserialize(in); return log; } finally { if (in != null) { in.close(); } } } public static ThreadLog deserialize(DataInput in) throws IOException { ThreadLog log = new ThreadLog(); log.doDeserialize(in); return log; } private void doDeserialize(DataInput in) throws IOException { String hdr = in.readUTF(); if (!HDR.equals(hdr)) { throw new StreamCorruptedException("invalid header '" + hdr + "', expected " + HDR); } int ver = in.readInt(); if (ver == CURRENT_VERSION) { int taskCount = in.readInt(); for (int i = 0; i < taskCount; ++i) { String task = in.readUTF(); double beginTime = in.readDouble(); double endTime = in.readDouble(); long threadId = in.readLong(); tasks.add(task); times.add(beginTime); times.add(endTime); threads.add(threadId); } } else { throw new StreamCorruptedException("unrecognized log version: " + ver); } } public void serialize(File file) throws IOException { DataOutputStream out = null; try { out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file))); serialize(out); } finally { if (out != null) { out.close(); } } } public void serialize(DataOutput out) throws IOException { out.writeUTF(HDR); out.writeInt(CURRENT_VERSION); int len = tasks.size(); out.writeInt(len); for (int i = 0; i < len; ++i) { out.writeUTF(tasks.get(i)); out.writeDouble(times.getQuick(i*2)); out.writeDouble(times.getQuick(i*2+1)); out.writeLong(threads.getQuick(i)); } } }