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