1 /*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 2002, 2014 Oracle and/or its affiliates. All rights reserved. 5 * 6 */ 7 8 package com.sleepycat.je.txn; 9 10 import java.util.Collections; 11 import java.util.Map; 12 import java.util.WeakHashMap; 13 14 import com.sleepycat.je.utilint.LoggerUtils; 15 16 /** 17 * LockInfo is a class that embodies information about a lock instance. The 18 * holding thread and the locktype are all contained in the object. 19 * 20 * This class is public for unit tests. 21 */ 22 public class LockInfo implements Cloneable { 23 protected Locker locker; 24 protected LockType lockType; 25 26 private static boolean deadlockStackTrace = false; 27 private static Map<LockInfo, StackTraceAtLockTime> traceExceptionMap = 28 Collections.synchronizedMap(new WeakHashMap<LockInfo, 29 StackTraceAtLockTime>()); 30 @SuppressWarnings("serial") 31 private static class StackTraceAtLockTime extends Exception {} 32 33 /** 34 * Called when the je.txn.deadlockStackTrace property is changed. 35 */ setDeadlockStackTrace(boolean enable)36 static void setDeadlockStackTrace(boolean enable) { 37 deadlockStackTrace = enable; 38 } 39 40 /** 41 * For unit testing only. 42 */ getDeadlockStackTrace()43 public static boolean getDeadlockStackTrace() { 44 return deadlockStackTrace; 45 } 46 47 /** 48 * Construct a new LockInfo. public for Sizeof program. 49 */ LockInfo(Locker locker, LockType lockType)50 public LockInfo(Locker locker, LockType lockType) { 51 this.locker = locker; 52 this.lockType = lockType; 53 54 if (deadlockStackTrace) { 55 traceExceptionMap.put(this, new StackTraceAtLockTime()); 56 } 57 } 58 59 /** 60 * Clone from given LockInfo. Use this constructor when copying a LockInfo 61 * and its identity should be copied (e.g., when mutating a thin lock to a 62 * thick lock) to ensure that debugging info is retained. 63 */ LockInfo(LockInfo other)64 LockInfo(LockInfo other) { 65 this.locker = other.locker; 66 this.lockType = other.lockType; 67 68 if (deadlockStackTrace) { 69 traceExceptionMap.put(this, traceExceptionMap.get(other)); 70 } 71 } 72 73 /** 74 * Change this lockInfo over to the prescribed locker. 75 */ setLocker(Locker locker)76 void setLocker(Locker locker) { 77 this.locker = locker; 78 } 79 80 /** 81 * @return The transaction associated with this Lock. 82 */ getLocker()83 public Locker getLocker() { 84 return locker; 85 } 86 87 /** 88 * @return The LockType associated with this Lock. 89 */ setLockType(LockType lockType)90 void setLockType(LockType lockType) { 91 this.lockType = lockType; 92 } 93 94 /** 95 * @return The LockType associated with this Lock. 96 */ getLockType()97 LockType getLockType() { 98 return lockType; 99 } 100 101 @Override clone()102 public Object clone() 103 throws CloneNotSupportedException { 104 105 return super.clone(); 106 } 107 108 /** 109 * Debugging 110 */ dump()111 public void dump() { 112 System.out.println(this); 113 } 114 115 @Override toString()116 public String toString() { 117 StringBuilder buf = new StringBuilder(500); 118 119 buf.append("<LockInfo locker=\""); 120 buf.append(locker); 121 buf.append("\" type=\""); 122 buf.append(lockType); 123 buf.append("\"/>"); 124 125 if (deadlockStackTrace) { 126 Exception traceException = traceExceptionMap.get(this); 127 if (traceException != null) { 128 buf.append(" lock taken at: "); 129 buf.append(LoggerUtils.getStackTrace(traceException)); 130 } 131 } 132 133 return buf.toString(); 134 } 135 } 136