KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > ojb > broker > locking > CommonsOJBLockManager


1 package org.apache.ojb.broker.locking;
2
3 /* Copyright 2005 The Apache Software Foundation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18 import org.apache.commons.transaction.locking.GenericLock;
19 import org.apache.commons.transaction.locking.GenericLockManager;
20 import org.apache.commons.transaction.locking.LockException;
21 import org.apache.commons.transaction.locking.MultiLevelLock;
22 import org.apache.commons.transaction.util.LoggerFacade;
23
24 /**
25  * Extension of {@link org.apache.commons.transaction.locking.GenericLockManager} to
26  * support all locking isolation level defined in OJB locking api and a provider of
27  * specific {@link org.apache.commons.transaction.locking.GenericLock} implementation classes
28  * representing the isolation levels specified in {@link org.apache.ojb.broker.locking.LockManager}, like
29  * {@link org.apache.ojb.broker.locking.LockManager#IL_READ_COMMITTED}, ... .
30  * <p/>
31  * The specific lock classes will be returned on call of
32  * {@link #createIsolationLevel(Object, Object, org.apache.commons.transaction.util.LoggerFacade)}
33  * dependend on the specified isolation level.
34  *
35  * @author <a HREF="mailto:arminw@apache.org">Armin Waibel</a>
36  * @version $Id: CommonsOJBLockManager.java,v 1.1.2.4 2005/12/21 22:25:32 tomdz Exp $
37  */

38 class CommonsOJBLockManager extends GenericLockManager
39 {
40     static final int COMMON_READ_LOCK = 101;
41     static final int COMMON_WRITE_LOCK = 107;
42     static final int COMMON_UPGRADE_LOCK = 113;
43
44     public CommonsOJBLockManager(LoggerFacade logger, long timeoutMSecs, long checkThreshholdMSecs)
45             throws IllegalArgumentException JavaDoc
46     {
47         super(1, logger, timeoutMSecs, checkThreshholdMSecs);
48     }
49
50     /**
51      * @see org.apache.commons.transaction.locking.GenericLockManager#tryLock(Object, Object, int, boolean)
52      */

53     public boolean tryLock(Object JavaDoc ownerId, Object JavaDoc resourceId, int targetLockLevel, boolean reentrant)
54     {
55         return tryLock(ownerId, resourceId, targetLockLevel, reentrant, null);
56     }
57
58     /**
59      * Tries to acquire a lock on a resource. <br>
60      * <br>
61      * This method does not block, but immediatly returns. If a lock is not
62      * available <code>false</code> will be returned.
63      *
64      * @param ownerId a unique id identifying the entity that wants to acquire this
65      * lock
66      * @param resourceId the resource to get the level for
67      * @param targetLockLevel the lock level to acquire
68      * @param reentrant <code>true</code> if this request shall not be influenced by
69      * other locks held by the same owner
70      * @param isolationId the isolation level identity key. See {@link CommonsOJBLockManager}.
71      * @return <code>true</code> if the lock has been acquired, <code>false</code> otherwise
72      */

73     public boolean tryLock(Object JavaDoc ownerId, Object JavaDoc resourceId, int targetLockLevel, boolean reentrant, Object JavaDoc isolationId)
74     {
75         timeoutCheck(ownerId);
76
77         OJBLock lock = atomicGetOrCreateLock(resourceId, isolationId);
78         boolean acquired = lock.tryLock(ownerId, targetLockLevel,
79                 reentrant ? GenericLock.COMPATIBILITY_REENTRANT : GenericLock.COMPATIBILITY_NONE,
80                 false);
81
82         if(acquired)
83         {
84             addOwner(ownerId, lock);
85         }
86         return acquired;
87     }
88
89     /**
90      * @see org.apache.commons.transaction.locking.GenericLockManager#lock(Object, Object, int, int, boolean, long)
91      */

92     public void lock(Object JavaDoc ownerId, Object JavaDoc resourceId, int targetLockLevel, int compatibility,
93                      boolean preferred, long timeoutMSecs) throws LockException
94     {
95         lock(ownerId, resourceId, targetLockLevel, compatibility, preferred, timeoutMSecs, null);
96     }
97
98     /**
99      * Most flexible way to acquire a lock on a resource. <br>
100      * <br>
101      * This method blocks and waits for the lock in case it is not avaiable. If
102      * there is a timeout or a deadlock or the thread is interrupted a
103      * LockException is thrown.
104      *
105      * @param ownerId a unique id identifying the entity that wants to acquire this
106      * lock
107      * @param resourceId the resource to get the level for
108      * @param targetLockLevel the lock level to acquire
109      * @param compatibility {@link GenericLock#COMPATIBILITY_NONE}if no additional compatibility is
110      * desired (same as reentrant set to false) ,
111      * {@link GenericLock#COMPATIBILITY_REENTRANT}if lock level by the same
112      * owner shall not affect compatibility (same as reentrant set to
113      * true), or {@link GenericLock#COMPATIBILITY_SUPPORT}if lock levels that
114      * are the same as the desired shall not affect compatibility, or
115      * finally {@link GenericLock#COMPATIBILITY_REENTRANT_AND_SUPPORT}which is
116      * a combination of reentrant and support
117      * @param preferred in case this lock request is incompatible with existing ones
118      * and we wait, it shall be granted before other waiting requests
119      * that are not preferred
120      * @param timeoutMSecs specifies the maximum wait time in milliseconds
121      * @param isolationId the isolation level identity key. See {@link CommonsOJBLockManager}.
122      * @throws LockException will be thrown when the lock can not be acquired
123      */

124     public void lock(Object JavaDoc ownerId, Object JavaDoc resourceId, int targetLockLevel, int compatibility,
125                      boolean preferred, long timeoutMSecs, Object JavaDoc isolationId) throws LockException
126     {
127         timeoutCheck(ownerId);
128         GenericLock lock = atomicGetOrCreateLock(resourceId, isolationId);
129         super.doLock(lock, ownerId, resourceId, targetLockLevel, compatibility, preferred, timeoutMSecs);
130     }
131
132     /**
133      * @see org.apache.commons.transaction.locking.GenericLockManager#atomicGetOrCreateLock(Object)
134      */

135     public MultiLevelLock atomicGetOrCreateLock(Object JavaDoc resourceId)
136     {
137         return atomicGetOrCreateLock(resourceId, null);
138     }
139
140     /**
141      * Either gets an existing lock on the specified resource or creates one if none exists.
142      * This methods guarantees to do this atomically.
143      *
144      * @param resourceId the resource to get or create the lock on
145      * @param isolationId the isolation level identity key. See {@link CommonsOJBLockManager}.
146      * @return the lock for the specified resource
147      */

148     public OJBLock atomicGetOrCreateLock(Object JavaDoc resourceId, Object JavaDoc isolationId)
149     {
150         synchronized(globalLocks)
151         {
152             MultiLevelLock lock = getLock(resourceId);
153             if(lock == null)
154             {
155                 lock = createLock(resourceId, isolationId);
156             }
157             return (OJBLock) lock;
158         }
159     }
160
161     /**
162      * @see org.apache.commons.transaction.locking.GenericLockManager#createLock(Object)
163      */

164     protected GenericLock createLock(Object JavaDoc resourceId)
165     {
166         return createLock(resourceId, null);
167     }
168
169     protected GenericLock createLock(Object JavaDoc resourceId, Object JavaDoc isolationId)
170     {
171         synchronized(globalLocks)
172         {
173             if(isolationId != null)
174             {
175                 GenericLock lock = createIsolationLevel(resourceId, isolationId, logger);
176                 globalLocks.put(resourceId, lock);
177                 return lock;
178             }
179             else
180             {
181                 GenericLock lock = new GenericLock(resourceId, maxLockLevel, logger);
182                 globalLocks.put(resourceId, lock);
183                 return lock;
184             }
185         }
186     }
187
188     /**
189      * Creates {@link org.apache.commons.transaction.locking.GenericLock} based
190      * {@link org.apache.commons.transaction.locking.MultiLevelLock2} instances
191      * dependend on the specified isolation identity object.
192      */

193     public OJBLock createIsolationLevel(Object JavaDoc resourceId, Object JavaDoc isolationId, LoggerFacade logger)
194     {
195         OJBLock result = null;
196         switch(((Integer JavaDoc) isolationId).intValue())
197         {
198             case LockManager.IL_READ_UNCOMMITTED:
199                 result = new ReadUncommittedLock(resourceId, logger);
200                 break;
201             case LockManager.IL_READ_COMMITTED:
202                 result = new ReadCommitedLock(resourceId, logger);
203                 break;
204             case LockManager.IL_REPEATABLE_READ:
205                 result = new RepeadableReadsLock(resourceId, logger);
206                 break;
207             case LockManager.IL_SERIALIZABLE:
208                 result = new SerializeableLock(resourceId, logger);
209                 break;
210             case LockManager.IL_OPTIMISTIC:
211                 throw new LockRuntimeException("Optimistic locking must be handled on top of this class");
212             default:
213                 throw new LockRuntimeException("Unknown lock isolation level specified");
214         }
215         return result;
216     }
217
218     /**
219      * Helper method to map the specified common lock level (e.g like
220      * {@link #COMMON_READ_LOCK}, {@link #COMMON_UPGRADE_LOCK, ...}) based
221      * on the isolation level to the internal used lock level value by the
222      * {@link org.apache.commons.transaction.locking.MultiLevelLock2} implementation.
223      *
224      * @param isolationId
225      * @param lockLevel
226      * @return
227      */

228     int mapLockLevelDependendOnIsolationLevel(Integer JavaDoc isolationId, int lockLevel)
229     {
230         int result = 0;
231         switch(isolationId.intValue())
232         {
233             case LockManager.IL_READ_UNCOMMITTED:
234                 result = ReadUncommittedLock.mapLockLevel(lockLevel);
235                 break;
236             case LockManager.IL_READ_COMMITTED:
237                 result = ReadCommitedLock.mapLockLevel(lockLevel);
238                 break;
239             case LockManager.IL_REPEATABLE_READ:
240                 result = RepeadableReadsLock.mapLockLevel(lockLevel);
241                 break;
242             case LockManager.IL_SERIALIZABLE:
243                 result = SerializeableLock.mapLockLevel(lockLevel);
244                 break;
245             case LockManager.IL_OPTIMISTIC:
246                 throw new LockRuntimeException("Optimistic locking must be handled on top of this class");
247             default:
248                 throw new LockRuntimeException("Unknown lock isolation level specified");
249         }
250         return result;
251     }
252
253
254
255     //===================================================
256
// inner class, commons-tx lock
257
//===================================================
258
/**
259      * Abstract base class to implement the different {@link org.apache.commons.transaction.locking.GenericLock}
260      * extension classes representing the OJB isolation levels (e.g. READ_COMMITTED, REPEADABLE_READ,...)
261      */

262     abstract static class OJBLock extends GenericLock
263     {
264         public OJBLock(Object JavaDoc resourceId, int maxLockLevel, LoggerFacade logger)
265         {
266             super(resourceId, maxLockLevel, logger);
267         }
268
269         /**
270          * Need to override this method to make it accessible in
271          * {@link CommonsOJBLockManager}.
272          *
273          * @see GenericLock#tryLock(Object, int, int, boolean)
274          */

275         protected boolean tryLock(Object JavaDoc ownerId, int targetLockLevel, int compatibility, boolean preferred)
276         {
277             return super.tryLock(ownerId, targetLockLevel, compatibility, preferred);
278         }
279
280         /**
281          * Convenience method.
282          */

283         abstract boolean hasRead(Object JavaDoc ownerId);
284
285         /**
286          * Convenience method.
287          */

288         abstract boolean hasWrite(Object JavaDoc ownerId);
289
290         /**
291          * Convenience method.
292          */

293         abstract boolean hasUpgrade(Object JavaDoc ownerId);
294
295         /**
296          * Convenience method.
297          */

298         abstract boolean readLock(Object JavaDoc ownerId, long timeout) throws InterruptedException JavaDoc;
299
300         /**
301          * Convenience method.
302          */

303         abstract boolean writeLock(Object JavaDoc ownerId, long timeout) throws InterruptedException JavaDoc;
304
305         /**
306          * Convenience method.
307          */

308         abstract boolean upgradeLock(Object JavaDoc ownerId, long timeout) throws InterruptedException JavaDoc;
309     }
310
311
312
313     //===================================================
314
// inner class, commons-tx lock
315
//===================================================
316
/**
317      * Implementation of isolation level {@link LockManager#IL_READ_UNCOMMITTED}.
318      */

319     static class ReadUncommittedLock extends RepeadableReadsLock
320     {
321         public ReadUncommittedLock(Object JavaDoc resourceId, LoggerFacade logger)
322         {
323             super(resourceId, logger);
324         }
325
326         protected boolean isCompatible(int targetLockLevel, int currentLockLevel)
327         {
328             if(currentLockLevel == READ_LOCK || targetLockLevel == READ_LOCK)
329             {
330                 return true;
331             }
332             else
333             {
334                 return super.isCompatible(targetLockLevel, currentLockLevel);
335             }
336         }
337     }
338
339     //===================================================
340
// inner class, commons-tx lock
341
//===================================================
342
/**
343      * Implementation of isolation level {@link LockManager#IL_READ_COMMITTED}.
344      */

345     static final class ReadCommitedLock extends RepeadableReadsLock
346     {
347         public ReadCommitedLock(Object JavaDoc resourceId, LoggerFacade logger)
348         {
349             super(resourceId, logger);
350         }
351
352         protected boolean isCompatible(int targetLockLevel, int currentLockLevel)
353         {
354             if(currentLockLevel == READ_LOCK)
355             {
356                 return true;
357             }
358             else
359             {
360                 return super.isCompatible(targetLockLevel, currentLockLevel);
361             }
362         }
363     }
364
365     //===================================================
366
// inner class, commons-tx lock
367
//===================================================
368
/**
369      * Implementation of isolation level {@link LockManager#IL_REPEATABLE_READ}.
370      */

371     static class RepeadableReadsLock extends OJBLock
372     {
373         static final int NO_LOCK = 0;
374         static final int READ_LOCK = 1;
375         static final int UPGRADE_LOCK = 2;
376         static final int WRITE_LOCK = 3;
377
378         public RepeadableReadsLock(Object JavaDoc resourceId, LoggerFacade logger)
379         {
380             super(resourceId, WRITE_LOCK, logger);
381         }
382
383         static int mapLockLevel(int commonLockLevel)
384         {
385             int result = 0;
386             switch(commonLockLevel)
387             {
388                 case COMMON_READ_LOCK:
389                     result = READ_LOCK;
390                     break;
391                 case COMMON_UPGRADE_LOCK:
392                     result = UPGRADE_LOCK;
393                     break;
394                 case COMMON_WRITE_LOCK:
395                     result = WRITE_LOCK;
396                     break;
397                 default:
398                     throw new LockRuntimeException("Unknown common lock type: " + commonLockLevel);
399             }
400             return result;
401         }
402
403         public boolean readLock(Object JavaDoc ownerId, long timeout) throws InterruptedException JavaDoc
404         {
405             return acquire(ownerId, READ_LOCK, false, GenericLock.COMPATIBILITY_REENTRANT, false, timeout);
406         }
407
408         public boolean writeLock(Object JavaDoc ownerId, long timeout) throws InterruptedException JavaDoc
409         {
410             return acquire(ownerId, WRITE_LOCK, true, GenericLock.COMPATIBILITY_REENTRANT, false, timeout);
411         }
412
413         public boolean upgradeLock(Object JavaDoc ownerId, long timeout) throws InterruptedException JavaDoc
414         {
415             return acquire(ownerId, UPGRADE_LOCK, true, GenericLock.COMPATIBILITY_REENTRANT, true, timeout);
416         }
417
418         public boolean hasRead(Object JavaDoc ownerId)
419         {
420             return has(ownerId, READ_LOCK);
421         }
422
423         public boolean hasWrite(Object JavaDoc ownerId)
424         {
425             return has(ownerId, WRITE_LOCK);
426         }
427
428         public boolean hasUpgrade(Object JavaDoc ownerId)
429         {
430             return has(ownerId, UPGRADE_LOCK);
431         }
432     }
433
434
435     //===================================================
436
// inner class, commons-tx lock
437
//===================================================
438
/**
439      * Implementation of isolation level {@link LockManager#IL_SERIALIZABLE}.
440      */

441     static final class SerializeableLock extends ReadUncommittedLock
442     {
443         public SerializeableLock(Object JavaDoc resourceId, LoggerFacade logger)
444         {
445             super(resourceId, logger);
446         }
447
448         protected boolean isCompatible(int targetLockLevel, int currentLockLevel)
449         {
450             return currentLockLevel > NO_LOCK ? false : true;
451         }
452     }
453 }
454
Popular Tags