001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.commons.transaction.locking;
018:
019: import org.apache.commons.transaction.util.LoggerFacade;
020:
021: /**
022: * Manager for
023: * {@link org.apache.commons.transaction.locking.ReadWriteUpgradeLock}s on
024: * resources. <br>
025: * <br>
026: * <p>
027: * The idea (as explained by Jim LoVerde) is that only one owner can hold an
028: * upgrade lock, but while that is held, it is possible for read locks to exist
029: * and/or be obtained, and when the request is made to upgrade to a write lock
030: * by the same owner, the lock manager prevents additional read locks until the
031: * write lock can be aquired.
032: * </p>
033: * <p>
034: * In this sense the write lock becomes preferred over all other locks when it gets upgraded from
035: * a upgrate lock. Preferred means that if it has to wait and others wait as well it will be
036: * served before all other none preferred locking requests.
037: * </p>
038: *
039: * @version $Id: ReadWriteUpgradeLockManager.java 493628 2007-01-07 01:42:48Z joerg $
040: *
041: * @see ReadWriteUpgradeLock
042: * @since 1.1
043: */
044: public class ReadWriteUpgradeLockManager extends ReadWriteLockManager {
045:
046: /**
047: * Creates a new read/write/upgrade lock manager.
048: *
049: * @param logger generic logger used for all kind of debug logging
050: * @param timeoutMSecs specifies the maximum time to wait for a lock in milliseconds
051: */
052: public ReadWriteUpgradeLockManager(LoggerFacade logger,
053: long timeoutMSecs) {
054: super (ReadWriteUpgradeLock.WRITE_LOCK, logger, timeoutMSecs);
055: }
056:
057: /**
058: * Tries to acquire a reentrant upgrade lock on a resource. <br>
059: * <br>
060: * This method does not block, but immediatly returns. If a lock is not
061: * available <code>false</code> will be returned.
062: *
063: * @param ownerId
064: * a unique id identifying the entity that wants to acquire this
065: * lock
066: * @param resourceId
067: * the resource to get the lock for
068: * @return <code>true</code> if the lock has been acquired, <code>false</code> otherwise
069: */
070: public boolean tryUpgradeLock(Object ownerId, Object resourceId) {
071: return tryLock(ownerId, resourceId,
072: ReadWriteUpgradeLock.UPGRADE_LOCK, true);
073: }
074:
075: /**
076: * Tries to acquire an exclusive, reentrant write lock on a resource. <br>
077: * <br>
078: * This method does not block, but immediatly returns. If a lock is not
079: * available <code>false</code> will be returned.
080: *
081: * @param ownerId
082: * a unique id identifying the entity that wants to acquire this
083: * lock
084: * @param resourceId
085: * the resource to get the lock for
086: * @return <code>true</code> if the lock has been acquired, <code>false</code> otherwise
087: */
088: public boolean tryWriteLock(Object ownerId, Object resourceId) {
089: return tryLock(ownerId, resourceId,
090: ReadWriteUpgradeLock.WRITE_LOCK, true);
091: }
092:
093: /**
094: * Tries to acquire a reentrant upgrade lock on a resource. <br>
095: * <br>
096: * This method blocks and waits for the lock in case it is not avaiable. If
097: * there is a timeout or a deadlock or the thread is interrupted a
098: * LockException is thrown.
099: *
100: * @param ownerId
101: * a unique id identifying the entity that wants to acquire this
102: * lock
103: * @param resourceId
104: * the resource to get the level for
105: * @throws LockException
106: * will be thrown when the lock can not be acquired
107: */
108: public void upgradeLock(Object ownerId, Object resourceId)
109: throws LockException {
110: super .lock(ownerId, resourceId,
111: ReadWriteUpgradeLock.UPGRADE_LOCK, true);
112: }
113:
114: /**
115: * Tries to acquire an exclusive, reentrant write lock on a resource. <br>
116: * <br>
117: * This method blocks and waits for the lock in case it is not avaiable. If
118: * there is a timeout or a deadlock or the thread is interrupted a
119: * LockException is thrown.
120: *
121: * @param ownerId
122: * a unique id identifying the entity that wants to acquire this
123: * lock
124: * @param resourceId
125: * the resource to get the level for
126: * @throws LockException
127: * will be thrown when the lock can not be acquired
128: */
129: public void writeLock(Object ownerId, Object resourceId)
130: throws LockException {
131: super .lock(ownerId, resourceId,
132: ReadWriteUpgradeLock.WRITE_LOCK, true);
133: }
134:
135: protected GenericLock createLock(Object resourceId) {
136: synchronized (globalLocks) {
137: GenericLock lock = new ReadWriteUpgradeLock(resourceId,
138: logger);
139: globalLocks.put(resourceId, lock);
140: return lock;
141: }
142: }
143:
144: }
|