View Javadoc

1   package org.sourceforge.jemm.database.components;
2   
3   import java.util.LinkedList;
4   
5   import org.sourceforge.jemm.database.ClientThreadId;
6   import org.sourceforge.jemm.types.ID;
7   
8   public class UserLockInfo {
9   	private final ID id;
10  	
11  	private ClientThreadId lockHolder;
12  	private LinkedList<ClientThreadId> waitingQueue;
13  
14  	public UserLockInfo(ID id) {
15  		this(id,null,null);
16  	}
17  	
18      public UserLockInfo(ID id,ClientThreadId lockHolder,LinkedList<ClientThreadId> lockQueue) {
19      	this.id = id;
20      	this.lockHolder = lockHolder;
21      	this.waitingQueue = lockQueue;
22  	}
23  
24  	/**
25       * Attempts to acquire the lock.  Returns true if the lock is acquired, otherwise
26       * returns false and the requestor is added to the lock waiting queue.
27       * @param clientThreadId The client thread attempted to acquire the lock.
28       * @return True if the requesting thread acquired the lock, false if it is waiting.
29       * @throws LockInfoDeadException If the lock is dead and a new one should be created
30       */
31      public boolean acquireLock(ClientThreadId clientThreadId) {
32      	if(lockHolder == null) {
33      		lockHolder = clientThreadId;
34      		return true;
35      	}
36      	
37      	if(waitingQueue == null)
38      		waitingQueue = new LinkedList<ClientThreadId>();
39      	
40      	waitingQueue.add(clientThreadId);
41      	return false;
42      }
43      
44      /**
45       * Release the lock on this object. This must be performed by the current lock holder.
46       * If there is any waiters on the lock the first will immediately acquire the lock.  
47       * The new lock owner is returned by the method and it is the responsibility of the caller 
48       * to notify the new owner.  
49       * @param releasingThreadId The current lock holder.
50       * @return The ClientThreadId who now holds the lock, or null if none.
51       */
52      public ClientThreadId releaseLock(ClientThreadId releasingThreadId) {
53      	if(lockHolder == null || !lockHolder.equals(releasingThreadId))
54              throw new IllegalStateException("Releasing thread does not hold lock on " + getId());
55          
56          if(waitingQueue == null || waitingQueue.isEmpty())
57              lockHolder = null;
58          else
59          	lockHolder = waitingQueue.remove();
60          
61          return lockHolder;
62      }
63  
64      /**
65       * Release the lock on this object if it is held by this thread, or removed the thread
66       * from the waiting queue.
67       * If the owner had changed it will be returned by this method and it is the responsibility 
68       * of the caller 
69       * to notify the new owner.  
70       * @param clientThreadId The thread being cleared.
71       * @return The ClientThreadId of the new lock holder (if the lock holder has changed)
72       */
73      public ClientThreadId releaseOrClearFromQueue(ClientThreadId clientThreadId) {
74      	if(lockHolder == clientThreadId)
75      		return releaseLock(clientThreadId);
76      	else {
77      		if(waitingQueue != null)
78      			waitingQueue.remove(clientThreadId);
79      		return null;
80      	}
81      }
82  
83      
84  	public boolean isUnused() {
85  		return lockHolder == null;
86  	}
87  
88  	public LinkedList<ClientThreadId> getLockQueue() {
89  		return waitingQueue;
90  	}
91  
92  	public ClientThreadId getHolder() {
93  		return lockHolder;
94  	}
95  	
96  	@Override
97  	public int hashCode() {
98  		return getId().hashCode();
99  	}
100 
101 	@Override
102 	public boolean equals(Object obj) {
103 		if (this == obj)
104 			return true;
105 		if (obj == null)
106 			return false;
107 		if (getClass() != obj.getClass())
108 			return false;
109 		UserLockInfo other = (UserLockInfo) obj;
110 		return getId().equals(other.getId());
111 	}
112 
113 	public ID getId() {
114 		return id;
115 	}
116 }