KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > db > store > Lock


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Scott Ferguson
28  */

29
30 package com.caucho.db.store;
31
32 import com.caucho.log.Log;
33 import com.caucho.util.Alarm;
34 import com.caucho.util.L10N;
35
36 import java.sql.SQLException JavaDoc;
37 import java.util.logging.Level JavaDoc;
38 import java.util.logging.Logger JavaDoc;
39
40 /**
41  * Locking for tables/etc.
42  */

43 public final class Lock {
44   private final static L10N L = new L10N(Lock.class);
45   private final static Logger JavaDoc log = Log.open(Lock.class);
46
47   private final String JavaDoc _id;
48
49   // count of threads trying to upgrade from a read lock
50
private int _tryUpgradeCount;
51   // count of threads trying to get a write lock
52
private int _tryWriteCount;
53   
54   // count of threads with a read currently running
55
private int _readCount;
56   // true if a thread has a write lock
57
private boolean _isWrite;
58
59   private Thread JavaDoc _owner;
60   
61   public Lock(String JavaDoc id)
62   {
63     _id = id;
64   }
65
66   /**
67    * Returns the lock identifier.
68    */

69   public String JavaDoc getId()
70   {
71     return _id;
72   }
73
74   /**
75    * Tries to get a read lock.
76    *
77    * @param timeout how long to wait for a timeout
78    */

79   void lockRead(Transaction xa, long timeout)
80     throws LockTimeoutException
81   {
82     if (log.isLoggable(Level.FINEST)) {
83       log.finest(this + " lockRead (read:" + _readCount
84          + " write:" + _isWrite
85          + " try-write:" + _tryWriteCount + ")");
86     }
87
88     long start = Alarm.getCurrentTime();
89     long expire = start + timeout;
90
91     synchronized (this) {
92       long now;
93
94       while (true) {
95     if (! _isWrite && _tryWriteCount == 0) {
96       _readCount++;
97       return;
98     }
99
100     long delta = expire - Alarm.getCurrentTime();
101
102     if (delta < 0 || Alarm.isTest())
103       break;
104
105     try {
106       wait(delta);
107     } catch (InterruptedException JavaDoc e) {
108       throw new LockTimeoutException(e);
109     }
110       }
111
112       if (! Alarm.isTest()) {
113     printOwnerStack();
114     Thread.dumpStack();
115       }
116
117       throw new LockTimeoutException(L.l("Lock {0} timed out ({1}ms) try-writers:{2} is-write:{3}",
118                      this,
119                      Alarm.getCurrentTime() - start,
120                      _tryWriteCount,
121                      _isWrite));
122     }
123   }
124
125   /**
126    * Clears a read lock.
127    */

128   void unlockRead()
129     throws SQLException JavaDoc
130   {
131     synchronized (this) {
132       _readCount--;
133     
134       if (_readCount < 0)
135     Thread.dumpStack();
136
137       if (log.isLoggable(Level.FINEST)) {
138     log.finest(this + " unlockRead (read:" + _readCount
139            + " write:" + _isWrite
140            + " try-write:" + _tryWriteCount + ")");
141       }
142
143       notifyAll();
144     }
145   }
146
147   /**
148    * Tries to get a write lock.
149    *
150    * @param timeout how long to wait for a timeout
151    */

152   void lockReadAndWrite(Transaction xa, long timeout)
153     throws SQLException JavaDoc
154   {
155     if (log.isLoggable(Level.FINEST)) {
156       log.finest(this + " lockReadAndWrite (read:" + _readCount
157          + " write:" + _isWrite
158          + " try-write:" + _tryWriteCount + ")");
159     }
160
161     long start = Alarm.getCurrentTime();
162     long expire = start + timeout;
163     boolean isOkay = false;
164
165     synchronized (this) {
166       _tryWriteCount++;
167
168       // XXX: temp debug only
169
if (_owner == null)
170     _owner = Thread.currentThread();
171
172       try {
173     while (true) {
174       if (! _isWrite && _readCount == _tryUpgradeCount) {
175         _readCount++;
176         _isWrite = true;
177         _owner = Thread.currentThread();
178         return;
179       }
180
181       long delta = expire - Alarm.getCurrentTime();
182
183       if (delta < 0 || Alarm.isTest())
184         break;
185
186       try {
187         wait(delta);
188       } catch (InterruptedException JavaDoc e) {
189         throw new LockTimeoutException(e);
190       }
191     }
192
193     if (! Alarm.isTest()) {
194       printOwnerStack();
195       Thread.dumpStack();
196     }
197     
198     throw new LockTimeoutException(L.l("{0} lockReadAndWrite timed out ({1}ms) is-write:{2} try-writers:{3} try-upgrade:{4}",
199                        this,
200                        (Alarm.getCurrentTime() - start),
201                        _isWrite,
202                        _tryWriteCount,
203                        _tryUpgradeCount));
204       } finally {
205     _tryWriteCount--;
206
207     notifyAll();
208       }
209     }
210   }
211
212   /**
213    * Tries to get a write lock when already have a read lock.
214    *
215    * @param timeout how long to wait for a timeout
216    */

217   void lockWrite(Transaction xa, long timeout)
218     throws SQLException JavaDoc
219   {
220     if (log.isLoggable(Level.FINEST)) {
221       log.finest(this + " lockWrite (read:" + _readCount
222          + " write:" + _isWrite
223          + " try-write:" + _tryWriteCount + ")");
224     }
225
226     long start = Alarm.getCurrentTime();
227     long expire = start + timeout;
228     boolean isOkay = false;
229
230     synchronized (this) {
231       _tryWriteCount++;
232       _tryUpgradeCount++;
233
234       // XXX: temp debug only
235
if (_owner == null)
236     _owner = Thread.currentThread();
237
238       try {
239     while (true) {
240       if (! _isWrite && _readCount == _tryUpgradeCount) {
241         _isWrite = true;
242         _owner = Thread.currentThread();
243         return;
244       }
245
246       long delta = expire - Alarm.getCurrentTime();
247
248       if (delta < 0 || Alarm.isTest())
249         break;
250
251       try {
252         wait(delta);
253       } catch (InterruptedException JavaDoc e) {
254         throw new LockTimeoutException(e);
255       }
256     }
257
258     if (! Alarm.isTest()) {
259       printOwnerStack();
260       Thread.dumpStack();
261     }
262     
263     throw new LockTimeoutException(L.l("{0} lockWrite timed out ({1}ms) try-writers:{2}",
264                        this,
265                        Alarm.getCurrentTime() - start,
266                        _tryWriteCount));
267       } finally {
268     _tryWriteCount--;
269     _tryUpgradeCount--;
270
271     notifyAll();
272       }
273     }
274   }
275
276   /**
277    * Clears a write lock.
278    */

279   void unlockReadAndWrite()
280     throws SQLException JavaDoc
281   {
282     synchronized (this) {
283       _readCount--;
284       _isWrite = false;
285       _owner = null;
286
287       notifyAll();
288     }
289     
290     if (log.isLoggable(Level.FINEST)) {
291       log.finest(this + " unlockReadAndWrite (read:" + _readCount
292          + " write:" + _isWrite
293          + " try-write:" + _tryWriteCount + ")");
294     }
295   }
296
297   /**
298    * Clears a write lock.
299    */

300   void unlockWrite()
301     throws SQLException JavaDoc
302   {
303     synchronized (this) {
304       _isWrite = false;
305       _owner = null;
306
307       notifyAll();
308     }
309     
310     if (log.isLoggable(Level.FINEST)) {
311       log.finest(this + " unlockWrite (read:" + _readCount
312          + " write:" + _isWrite
313          + " try-write:" + _tryWriteCount + ")");
314     }
315   }
316
317   private void printOwnerStack()
318   {
319     Thread JavaDoc thread = _owner;
320
321     if (thread == null)
322       return;
323
324     System.out.println("Owner-stack");
325     StackTraceElement JavaDoc []stack = thread.getStackTrace();
326     for (int i = 0; i < stack.length; i++)
327       System.out.println(stack[i]);
328   }
329   
330   public String JavaDoc toString()
331   {
332     return "Lock[" + _id + "]";
333   }
334 }
335
Popular Tags