package edu.washington.cs.oneswarm.f2f; import java.util.Collection; import java.util.LinkedList; import java.util.List; import java.util.concurrent.locks.ReentrantLock; import java.util.logging.Level; import java.util.logging.Logger; import org.gudy.azureus2.core3.util.Debug; public class BigFatLock extends ReentrantLock { private static final long serialVersionUID = 1L; private static Logger logger = Logger.getLogger(BigFatLock.class.getName()); private long mMostRecentAcquire; /** * These are for debugging. */ public LinkedList<Long> recentRuntimes = new LinkedList<Long>(); public LinkedList<Long> recentAcquireTimes = new LinkedList<Long>(); public long longestRunTime = 0; public long longestWaitTime = 0; public long waits[][] = new long[][] { { 0, 10 }, { 0, 20 }, { 0, 50 }, { 0, 100 } }; private StackTraceElement[] lockedBy; public static final long mCreated = System.currentTimeMillis(); private final static BigFatLock instance = new BigFatLock(); public static BigFatLock getInstance(boolean isAEMonitor) { /* * if checkloglevel and the log level is <FINE, return null */ if (isAEMonitor) { if (logger.isLoggable(Level.FINE)) { return instance; } else { return null; } } return instance; } protected BigFatLock() { } public String getLockedTrace(){ if(this.isLocked() && lockedBy != null){ return getStackTraceAsString(lockedBy); } return ""; } public void lock() { if (logger.isLoggable(Level.FINEST)) { logger.finest("trying to lock: " + Thread.currentThread().getName() + " count=" + super.getHoldCount()); } if (logger.isLoggable(Level.FINE)) { lockedBy = new Exception().getStackTrace(); if (this.isLocked() && this.isHeldByCurrentThread()) { new Exception("Lock called byt thread already owner").printStackTrace(); } } long start = System.currentTimeMillis(); super.lock(); long time = (System.currentTimeMillis() - start); if (mCreated + 10000 < System.currentTimeMillis()) { if (time > longestWaitTime) { longestWaitTime = time; } } if (logger.isLoggable(Level.FINE)) { synchronized (recentAcquireTimes) { recentAcquireTimes.add(time); if (recentAcquireTimes.size() > 1000) { recentAcquireTimes.removeFirst(); } for (long[] w : waits) { if (time > w[1]) { w[0]++; } } } } mMostRecentAcquire = System.currentTimeMillis(); if (logger.isLoggable(Level.FINEST)) { logger.finer("lock: " + Thread.currentThread().getName() + " count=" + super.getHoldCount()); } } public void unlock() { super.unlock(); long time = System.currentTimeMillis() - mMostRecentAcquire; if (mCreated + 10000 < System.currentTimeMillis()) { if (time > longestRunTime) { longestRunTime = time; } } if (logger.isLoggable(Level.FINE)) { synchronized (recentRuntimes) { recentRuntimes.add(time); if (recentRuntimes.size() > 1000) { recentRuntimes.removeFirst(); } } } if (logger.isLoggable(Level.FINEST)) { logger.finest("unlock: " + Thread.currentThread().getName() + " count=" + super.getHoldCount()); } } public String getLockDebug() { StringBuilder b = new StringBuilder(); final Thread owner = getOwner(); boolean skip = false; if (owner == null) { b.append("owner: null\n"); b.append(" count=" + super.getHoldCount() + "\n"); skip = true; } if (!skip) { b.append("owner: " + owner.getName() + "\n"); b.append(" count=" + super.getHoldCount() + "\n"); b.append(getStackTraceAsString(owner.getStackTrace()) + "\n\n"); b.append("waiting threads:\n"); final Collection<Thread> queuedThreads = getQueuedThreads(); for (Thread thread : queuedThreads) { b.append("name=" + thread.getName() + "\n"); b.append("status=" + thread.getState().name() + "\n"); b.append(getStackTraceAsString(thread.getStackTrace()) + "\n\n"); } b.append("\n\nall other threads:\n"); for (Thread thread : Thread.getAllStackTraces().keySet()) { b.append("name=" + thread.getName() + "\n"); b.append("status=" + thread.getState().name() + "\n"); b.append(getStackTraceAsString(thread.getStackTrace()) + "\n\n"); } } b.append("\nlongest runtime: " + longestRunTime + " longest wait: " + longestWaitTime + "\n"); for (long[] w : waits) { b.append("waits > " + w[1] + " " + w[0] + "\n"); } synchronized (recentAcquireTimes) { b.append("\n\nwaits (" + recentAcquireTimes.size() + "):"); for (Long l : recentAcquireTimes) { b.append(l + "\n"); } } synchronized (recentRuntimes) { b.append("\n\nrun:"); for (Long l : recentRuntimes) { b.append(l + "\n"); } } return b.toString(); } private String getStackTraceAsString(final StackTraceElement[] trace) { StringBuilder b = new StringBuilder(); for (int i = 0; i < trace.length; i++) { b.append(("\tat " + trace[i] + "\n")); } return b.toString(); } }