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, long timeoutMSecs) {
053 super(ReadWriteUpgradeLock.WRITE_LOCK, logger, timeoutMSecs);
054 }
055
056 /**
057 * Tries to acquire a reentrant upgrade lock on a resource. <br>
058 * <br>
059 * This method does not block, but immediatly returns. If a lock is not
060 * available <code>false</code> will be returned.
061 *
062 * @param ownerId
063 * a unique id identifying the entity that wants to acquire this
064 * lock
065 * @param resourceId
066 * the resource to get the lock for
067 * @return <code>true</code> if the lock has been acquired, <code>false</code> otherwise
068 */
069 public boolean tryUpgradeLock(Object ownerId, Object resourceId) {
070 return tryLock(ownerId, resourceId, ReadWriteUpgradeLock.UPGRADE_LOCK, true);
071 }
072
073 /**
074 * Tries to acquire an exclusive, reentrant write lock on a resource. <br>
075 * <br>
076 * This method does not block, but immediatly returns. If a lock is not
077 * available <code>false</code> will be returned.
078 *
079 * @param ownerId
080 * a unique id identifying the entity that wants to acquire this
081 * lock
082 * @param resourceId
083 * the resource to get the lock for
084 * @return <code>true</code> if the lock has been acquired, <code>false</code> otherwise
085 */
086 public boolean tryWriteLock(Object ownerId, Object resourceId) {
087 return tryLock(ownerId, resourceId, ReadWriteUpgradeLock.WRITE_LOCK, true);
088 }
089
090 /**
091 * Tries to acquire a reentrant upgrade lock on a resource. <br>
092 * <br>
093 * This method blocks and waits for the lock in case it is not avaiable. If
094 * there is a timeout or a deadlock or the thread is interrupted a
095 * LockException is thrown.
096 *
097 * @param ownerId
098 * a unique id identifying the entity that wants to acquire this
099 * lock
100 * @param resourceId
101 * the resource to get the level for
102 * @throws LockException
103 * will be thrown when the lock can not be acquired
104 */
105 public void upgradeLock(Object ownerId, Object resourceId) throws LockException {
106 super.lock(ownerId, resourceId, ReadWriteUpgradeLock.UPGRADE_LOCK, true);
107 }
108
109 /**
110 * Tries to acquire an exclusive, reentrant write lock on a resource. <br>
111 * <br>
112 * This method blocks and waits for the lock in case it is not avaiable. If
113 * there is a timeout or a deadlock or the thread is interrupted a
114 * LockException is thrown.
115 *
116 * @param ownerId
117 * a unique id identifying the entity that wants to acquire this
118 * lock
119 * @param resourceId
120 * the resource to get the level for
121 * @throws LockException
122 * will be thrown when the lock can not be acquired
123 */
124 public void writeLock(Object ownerId, Object resourceId) throws LockException {
125 super.lock(ownerId, resourceId, ReadWriteUpgradeLock.WRITE_LOCK, true);
126 }
127
128 protected GenericLock createLock(Object resourceId) {
129 synchronized (globalLocks) {
130 GenericLock lock = new ReadWriteUpgradeLock(resourceId, logger);
131 globalLocks.put(resourceId, lock);
132 return lock;
133 }
134 }
135
136 }