Quadcap Embeddable Database

com/quadcap/sql/lock/Lock.java

Go to the documentation of this file.
00001 package com.quadcap.sql.lock; 00002 00003 /* Copyright 1999 - 2003 Quadcap Software. All rights reserved. 00004 * 00005 * This software is distributed under the Quadcap Free Software License. 00006 * This software may be used or modified for any purpose, personal or 00007 * commercial. Open Source redistributions are permitted. Commercial 00008 * redistribution of larger works derived from, or works which bundle 00009 * this software requires a "Commercial Redistribution License"; see 00010 * http://www.quadcap.com/purchase. 00011 * 00012 * Redistributions qualify as "Open Source" under one of the following terms: 00013 * 00014 * Redistributions are made at no charge beyond the reasonable cost of 00015 * materials and delivery. 00016 * 00017 * Redistributions are accompanied by a copy of the Source Code or by an 00018 * irrevocable offer to provide a copy of the Source Code for up to three 00019 * years at the cost of materials and delivery. Such redistributions 00020 * must allow further use, modification, and redistribution of the Source 00021 * Code under substantially the same terms as this license. 00022 * 00023 * Redistributions of source code must retain the copyright notices as they 00024 * appear in each source code file, these license terms, and the 00025 * disclaimer/limitation of liability set forth as paragraph 6 below. 00026 * 00027 * Redistributions in binary form must reproduce this Copyright Notice, 00028 * these license terms, and the disclaimer/limitation of liability set 00029 * forth as paragraph 6 below, in the documentation and/or other materials 00030 * provided with the distribution. 00031 * 00032 * The Software is provided on an "AS IS" basis. No warranty is 00033 * provided that the Software is free of defects, or fit for a 00034 * particular purpose. 00035 * 00036 * Limitation of Liability. Quadcap Software shall not be liable 00037 * for any damages suffered by the Licensee or any third party resulting 00038 * from use of the Software. 00039 */ 00040 00041 import com.quadcap.util.collections.ArrayQueue; 00042 00043 import com.quadcap.util.Debug; 00044 00045 /** 00046 * A mapped, instantiated lock object. 00047 * 00048 * @author Stan Bailes 00049 */ 00050 public class Lock implements Comparable { 00051 static Lock tombstone = new Lock(); 00052 00053 String name; 00054 final int[] heldCount = new int[LockMode.MAX]; 00055 int refCount = 0; 00056 private Lock parent = null; 00057 ArrayQueue waitQueue = null; 00058 Object sync = new Object(); 00059 00060 /** 00061 * Default constructor 00062 */ 00063 protected Lock() {} 00064 00065 /** 00066 * Initialization/recycling 00067 */ 00068 public void init(Lock parent, String name) { 00069 this.parent = parent; 00070 this.name = name; 00071 } 00072 00073 /** 00074 * Return this lock's name 00075 */ 00076 final String getName() { return name; } 00077 00078 final int getHeldCount(int mode) { 00079 return heldCount[mode]; 00080 } 00081 00082 final int incrHeldCount(int mode) { 00083 return ++heldCount[mode]; 00084 } 00085 final int decrHeldCount(int mode) { 00086 return --heldCount[mode]; 00087 } 00088 00089 final int getHeldCount() { 00090 int sum = 0; 00091 for (int i = 0; i < LockMode.MAX; i++) sum += heldCount[i]; 00092 return sum; 00093 } 00094 00095 final void addWaitQueue(Transaction t) { 00096 synchronized (sync) { 00097 if (waitQueue == null) waitQueue = new ArrayQueue(2, -1); 00098 waitQueue.addBack(t); 00099 } 00100 } 00101 00102 final boolean hasWaiters() { 00103 synchronized (sync) { 00104 return waitQueue == null ? false : waitQueue.size() > 0; 00105 } 00106 } 00107 00108 final Transaction popWaitQueue() { 00109 Transaction ret = null; 00110 synchronized (sync) { 00111 if (waitQueue != null) ret = (Transaction)waitQueue.popFront(); 00112 } 00113 return ret; 00114 } 00115 00116 final Transaction headWaitQueue() { 00117 Transaction ret = null; 00118 synchronized (sync) { 00119 if (waitQueue != null) ret = (Transaction)waitQueue.head(); 00120 } 00121 return ret; 00122 } 00123 00124 final boolean couldLock(int mode) { 00125 switch (mode) { 00126 case LockMode.S: 00127 return (heldCount[LockMode.X] == 0 && 00128 heldCount[LockMode.IX] == 0 && 00129 heldCount[LockMode.SIX] == 0); 00130 case LockMode.IS: 00131 return heldCount[LockMode.X] == 0; 00132 case LockMode.X: 00133 return (heldCount[LockMode.X] == 0 && 00134 heldCount[LockMode.IX] == 0 && 00135 heldCount[LockMode.SIX] == 0 && 00136 heldCount[LockMode.IS] == 0 && 00137 heldCount[LockMode.S] == 0); 00138 case LockMode.IX: 00139 return (heldCount[LockMode.X] == 0 && 00140 heldCount[LockMode.S] == 0 && 00141 heldCount[LockMode.SIX] == 0); 00142 case LockMode.SIX: 00143 return (heldCount[LockMode.X] == 0 && 00144 heldCount[LockMode.S] == 0 && 00145 heldCount[LockMode.IX] == 0 && 00146 heldCount[LockMode.SIX] == 0); 00147 default: 00148 throw new RuntimeException("Bad lock mode: " + mode); 00149 } 00150 } 00151 00152 final boolean couldPromote(int fromMode, int toMode) { 00153 int savc = heldCount[fromMode]; 00154 heldCount[fromMode] = 0; 00155 boolean could = couldLock(toMode); 00156 heldCount[fromMode] = savc; 00157 return could; 00158 } 00159 00160 public int compareTo(Object obj) { 00161 return name.compareTo(((Lock)obj).name); 00162 } 00163 00164 public boolean equals(Object obj) { 00165 return 0 == compareTo(obj); 00166 } 00167 00168 public int hashCode() { 00169 return name.hashCode(); 00170 } 00171 00172 public Lock getParent() { return parent; } 00173 00174 //#ifdef DEBUG 00175 public String toString() { 00176 return dump(); 00177 } 00178 00179 public String dump() { 00180 StringBuffer sb = new StringBuffer(); 00181 sb.append(name); 00182 sb.append(": "); 00183 for (int i = 0; i < LockMode.MAX; i++) { 00184 if (heldCount[i] > 0) { 00185 sb.append("{"); 00186 sb.append(LockMode.toString(i)); 00187 sb.append(","); 00188 sb.append(Integer.toString(heldCount[i])); 00189 sb.append("} "); 00190 } 00191 } 00192 Transaction t = headWaitQueue(); 00193 if (t != null) { 00194 sb.append("wait=T:"); 00195 sb.append(String.valueOf(t.getTransactionId())); 00196 if (waitQueue.size() > 1) { 00197 sb.append(" + "); 00198 sb.append(waitQueue.size() - 1); 00199 sb.append(" other"); 00200 if (waitQueue.size() > 2) sb.append('s'); 00201 } 00202 } 00203 return sb.toString(); 00204 } 00205 //#endif 00206 }