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 */ 017package org.apache.commons.transaction.locking; 018 019import 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 */ 044public 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}