001: package com.quadcap.sql.lock;
002:
003: /* Copyright 1999 - 2003 Quadcap Software. All rights reserved.
004: *
005: * This software is distributed under the Quadcap Free Software License.
006: * This software may be used or modified for any purpose, personal or
007: * commercial. Open Source redistributions are permitted. Commercial
008: * redistribution of larger works derived from, or works which bundle
009: * this software requires a "Commercial Redistribution License"; see
010: * http://www.quadcap.com/purchase.
011: *
012: * Redistributions qualify as "Open Source" under one of the following terms:
013: *
014: * Redistributions are made at no charge beyond the reasonable cost of
015: * materials and delivery.
016: *
017: * Redistributions are accompanied by a copy of the Source Code or by an
018: * irrevocable offer to provide a copy of the Source Code for up to three
019: * years at the cost of materials and delivery. Such redistributions
020: * must allow further use, modification, and redistribution of the Source
021: * Code under substantially the same terms as this license.
022: *
023: * Redistributions of source code must retain the copyright notices as they
024: * appear in each source code file, these license terms, and the
025: * disclaimer/limitation of liability set forth as paragraph 6 below.
026: *
027: * Redistributions in binary form must reproduce this Copyright Notice,
028: * these license terms, and the disclaimer/limitation of liability set
029: * forth as paragraph 6 below, in the documentation and/or other materials
030: * provided with the distribution.
031: *
032: * The Software is provided on an "AS IS" basis. No warranty is
033: * provided that the Software is free of defects, or fit for a
034: * particular purpose.
035: *
036: * Limitation of Liability. Quadcap Software shall not be liable
037: * for any damages suffered by the Licensee or any third party resulting
038: * from use of the Software.
039: */
040:
041: import com.quadcap.util.collections.ArrayQueue;
042:
043: import com.quadcap.util.Debug;
044:
045: /**
046: * A mapped, instantiated lock object.
047: *
048: * @author Stan Bailes
049: */
050: public class Lock implements Comparable {
051: static Lock tombstone = new Lock();
052:
053: String name;
054: final int[] heldCount = new int[LockMode.MAX];
055: int refCount = 0;
056: private Lock parent = null;
057: ArrayQueue waitQueue = null;
058: Object sync = new Object();
059:
060: /**
061: * Default constructor
062: */
063: protected Lock() {
064: }
065:
066: /**
067: * Initialization/recycling
068: */
069: public void init(Lock parent, String name) {
070: this .parent = parent;
071: this .name = name;
072: }
073:
074: /**
075: * Return this lock's name
076: */
077: final String getName() {
078: return name;
079: }
080:
081: final int getHeldCount(int mode) {
082: return heldCount[mode];
083: }
084:
085: final int incrHeldCount(int mode) {
086: return ++heldCount[mode];
087: }
088:
089: final int decrHeldCount(int mode) {
090: return --heldCount[mode];
091: }
092:
093: final int getHeldCount() {
094: int sum = 0;
095: for (int i = 0; i < LockMode.MAX; i++)
096: sum += heldCount[i];
097: return sum;
098: }
099:
100: final void addWaitQueue(Transaction t) {
101: synchronized (sync) {
102: if (waitQueue == null)
103: waitQueue = new ArrayQueue(2, -1);
104: waitQueue.addBack(t);
105: }
106: }
107:
108: final boolean hasWaiters() {
109: synchronized (sync) {
110: return waitQueue == null ? false : waitQueue.size() > 0;
111: }
112: }
113:
114: final Transaction popWaitQueue() {
115: Transaction ret = null;
116: synchronized (sync) {
117: if (waitQueue != null)
118: ret = (Transaction) waitQueue.popFront();
119: }
120: return ret;
121: }
122:
123: final Transaction headWaitQueue() {
124: Transaction ret = null;
125: synchronized (sync) {
126: if (waitQueue != null)
127: ret = (Transaction) waitQueue.head();
128: }
129: return ret;
130: }
131:
132: final boolean couldLock(int mode) {
133: switch (mode) {
134: case LockMode.S:
135: return (heldCount[LockMode.X] == 0
136: && heldCount[LockMode.IX] == 0 && heldCount[LockMode.SIX] == 0);
137: case LockMode.IS:
138: return heldCount[LockMode.X] == 0;
139: case LockMode.X:
140: return (heldCount[LockMode.X] == 0
141: && heldCount[LockMode.IX] == 0
142: && heldCount[LockMode.SIX] == 0
143: && heldCount[LockMode.IS] == 0 && heldCount[LockMode.S] == 0);
144: case LockMode.IX:
145: return (heldCount[LockMode.X] == 0
146: && heldCount[LockMode.S] == 0 && heldCount[LockMode.SIX] == 0);
147: case LockMode.SIX:
148: return (heldCount[LockMode.X] == 0
149: && heldCount[LockMode.S] == 0
150: && heldCount[LockMode.IX] == 0 && heldCount[LockMode.SIX] == 0);
151: default:
152: throw new RuntimeException("Bad lock mode: " + mode);
153: }
154: }
155:
156: final boolean couldPromote(int fromMode, int toMode) {
157: int savc = heldCount[fromMode];
158: heldCount[fromMode] = 0;
159: boolean could = couldLock(toMode);
160: heldCount[fromMode] = savc;
161: return could;
162: }
163:
164: public int compareTo(Object obj) {
165: return name.compareTo(((Lock) obj).name);
166: }
167:
168: public boolean equals(Object obj) {
169: return 0 == compareTo(obj);
170: }
171:
172: public int hashCode() {
173: return name.hashCode();
174: }
175:
176: public Lock getParent() {
177: return parent;
178: }
179:
180: //#ifdef DEBUG
181: public String toString() {
182: return dump();
183: }
184:
185: public String dump() {
186: StringBuffer sb = new StringBuffer();
187: sb.append(name);
188: sb.append(": ");
189: for (int i = 0; i < LockMode.MAX; i++) {
190: if (heldCount[i] > 0) {
191: sb.append("{");
192: sb.append(LockMode.toString(i));
193: sb.append(",");
194: sb.append(Integer.toString(heldCount[i]));
195: sb.append("} ");
196: }
197: }
198: Transaction t = headWaitQueue();
199: if (t != null) {
200: sb.append("wait=T:");
201: sb.append(String.valueOf(t.getTransactionId()));
202: if (waitQueue.size() > 1) {
203: sb.append(" + ");
204: sb.append(waitQueue.size() - 1);
205: sb.append(" other");
206: if (waitQueue.size() > 2)
207: sb.append('s');
208: }
209: }
210: return sb.toString();
211: }
212: //#endif
213: }
|