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 java.util.Set;
020
021/**
022 * Extended version of a lock manager that also has global knowledge or all locks and should be
023 * used as a delegate for all locking requests. This allows for things like deadlock detection.
024 * 
025 * @version $Id: LockManager2.java 493628 2007-01-07 01:42:48Z joerg $
026 * @see MultiLevelLock
027 * @see MultiLevelLock2
028 * @see LockManager
029 * @see GenericLockManager
030 * @see GenericLock
031 * @since 1.1
032 */
033public interface LockManager2 {
034
035    /**
036     * Determines if a lock is owner by an owner. <br>
037     * 
038     * @param ownerId
039     *            a unique id identifying the entity that wants to check this
040     *            lock
041     * @param resourceId
042     *            the resource to get the level for
043     * @param lockLevel
044     *            the lock level to check
045     * @return <code>true</code> if the owner has the lock, <code>false</code> otherwise
046     *  
047     */
048    public boolean hasLock(Object ownerId, Object resourceId, int lockLevel);
049
050    /**
051     * Determines if a lock <em>could</em> be acquire <em>without</em> actually acquiring it. <br>
052     * <br>
053     * This method does not block, but immediatly returns.
054     * 
055     * @param ownerId
056     *            a unique id identifying the entity that wants to check this
057     *            lock
058     * @param resourceId
059     *            the resource to get the level for
060     * @param targetLockLevel
061     *            the lock level to check
062     * @param reentrant
063     *            <code>true</code> if this request shall not be influenced by
064     *            other locks held by the same owner
065     * @return <code>true</code> if the lock could be acquired, <code>false</code> otherwise
066     *  
067     */
068    public boolean checkLock(Object ownerId, Object resourceId, int targetLockLevel, boolean reentrant);
069
070    /**
071     * Tries to acquire a lock on a resource. <br>
072     * <br>
073     * This method does not block, but immediatly returns. If a lock is not
074     * available <code>false</code> will be returned.
075     * 
076     * @param ownerId
077     *            a unique id identifying the entity that wants to acquire this
078     *            lock
079     * @param resourceId
080     *            the resource to get the level for
081     * @param targetLockLevel
082     *            the lock level to acquire
083     * @param reentrant
084     *            <code>true</code> if this request shall not be influenced by
085     *            other locks held by the same owner
086     * @return <code>true</code> if the lock has been acquired, <code>false</code> otherwise
087     *  
088     */
089    public boolean tryLock(Object ownerId, Object resourceId, int targetLockLevel, boolean reentrant);
090
091    /**
092     * Tries to acquire a lock on a resource. <br>
093     * <br>
094     * This method blocks and waits for the lock in case it is not avaiable. If
095     * there is a timeout or a deadlock or the thread is interrupted a
096     * LockException is thrown.
097     * 
098     * @param ownerId
099     *            a unique id identifying the entity that wants to acquire this
100     *            lock
101     * @param resourceId
102     *            the resource to get the level for
103     * @param targetLockLevel
104     *            the lock level to acquire
105     * @param reentrant
106     *            <code>true</code> if this request shall not be blocked by
107     *            other locks held by the same owner
108     * @throws LockException
109     *             will be thrown when the lock can not be acquired
110     */
111    public void lock(Object ownerId, Object resourceId, int targetLockLevel, boolean reentrant)
112            throws LockException;
113
114    /**
115     * Tries to acquire a 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     * @param targetLockLevel
127     *            the lock level to acquire
128     * @param reentrant
129     *            <code>true</code> if this request shall not be blocked by
130     *            other locks held by the same owner
131     * @param timeoutMSecs
132     *            specifies the maximum wait time in milliseconds
133     * @throws LockException
134     *             will be thrown when the lock can not be acquired
135     */
136    public void lock(Object ownerId, Object resourceId, int targetLockLevel, boolean reentrant,
137            long timeoutMSecs) throws LockException;
138
139    /**
140     * Most flexible way to acquire a lock on a resource. <br>
141     * <br>
142     * This method blocks and waits for the lock in case it is not avaiable. If
143     * there is a timeout or a deadlock or the thread is interrupted a
144     * LockException is thrown.
145     * 
146     * @param ownerId
147     *            a unique id identifying the entity that wants to acquire this
148     *            lock
149     * @param resourceId
150     *            the resource to get the level for
151     * @param targetLockLevel
152     *            the lock level to acquire
153     * @param compatibility
154     *            {@link GenericLock#COMPATIBILITY_NONE}if no additional compatibility is
155     *            desired (same as reentrant set to false) ,
156     *            {@link GenericLock#COMPATIBILITY_REENTRANT}if lock level by the same
157     *            owner shall not affect compatibility (same as reentrant set to
158     *            true), or {@link GenericLock#COMPATIBILITY_SUPPORT}if lock levels that
159     *            are the same as the desired shall not affect compatibility, or
160     *            finally {@link GenericLock#COMPATIBILITY_REENTRANT_AND_SUPPORT}which is
161     *            a combination of reentrant and support
162     * @param preferred
163     *            in case this lock request is incompatible with existing ones
164     *            and we wait, it shall be granted before other waiting requests
165     *            that are not preferred
166     * @param timeoutMSecs
167     *            specifies the maximum wait time in milliseconds
168     * @throws LockException
169     *             will be thrown when the lock can not be acquired
170     */
171    public void lock(Object ownerId, Object resourceId, int targetLockLevel, int compatibility,
172            boolean preferred, long timeoutMSecs) throws LockException;
173
174    /**
175     * Starts a global timeout for an owner. This is especially usefull, when the owner is a 
176     * transaction. After a global timeout occurs all of the owner's lock will be released and 
177     * the owner will not be allowed to access any
178     * locks before before calling {@link #releaseAll(Object)}.
179     * 
180     * @param ownerId
181     *            a unique id identifying the entity that wants to acquire this
182     *            lock
183     * @param timeoutMSecs
184     *            specifies the global timeout in milliseconds
185     */
186    public void startGlobalTimeout(Object ownerId, long timeoutMSecs);
187    
188    /**
189     * Gets the lock level held by certain owner on a certain resource.
190     * 
191     * @param ownerId the id of the owner of the lock
192     * @param resourceId the resource to get the level for
193     */
194    public int getLevel(Object ownerId, Object resourceId);
195
196    /**
197     * Releases all locks for a certain resource held by a certain owner.
198     * 
199     * @param ownerId the id of the owner of the lock
200     * @param resourceId the resource to releases the lock for
201     * @return <code>true</code> if the lock actually was released, <code>false</code> in case
202     * there was no lock held by the owner
203     */
204    public boolean release(Object ownerId, Object resourceId);
205
206    /**
207     * Releases all locks (partially) held by an owner.
208     * 
209     * @param ownerId the id of the owner
210     */
211    public void releaseAll(Object ownerId);
212    
213    /**
214     * Gets all locks (partially) held by an owner.
215     * 
216     * @param ownerId the id of the owner
217     * @return all locks held by ownerId
218     */
219    public Set getAll(Object ownerId);
220
221    
222    /**
223     * Gets an existing lock on the specified resource. If none exists it returns <code>null</code>. 
224     * 
225     * @param resourceId the resource to get the lock for
226     * @return the lock on the specified resource
227     * 
228     */
229    public MultiLevelLock getLock(Object resourceId);
230
231    /**
232     * Removes the specified lock from the associated resource. 
233     * 
234     * <em>Caution:</em> This does not release the lock, but only moves it out
235     * of the scope of this manager. Use {@link #release(Object, Object)} for that.
236     * 
237     * @param lock the lock to be removed
238     */
239    public void removeLock(MultiLevelLock lock);
240
241}