View Javadoc

1   package org.sourceforge.jemm.database.components;
2   
3   import java.util.Set;
4   
5   import org.sourceforge.jemm.database.ClientId;
6   import org.sourceforge.jemm.database.ClientThreadId;
7   import org.sourceforge.jemm.database.LockAcquiredListener;
8   import org.sourceforge.jemm.database.ObjectAccessor;
9   import org.sourceforge.jemm.database.components.interfaces.DBUserLockHandler;
10  import org.sourceforge.jemm.database.components.se.StorageEngineUserLockIF;
11  import org.sourceforge.jemm.database.components.userlock.InternalLockListenerNotifier;
12  import org.sourceforge.jemm.types.ID;
13  import org.sourceforge.jemm.util.LockManager;
14  
15  /**
16   * Default lock handler for database implementations
17   * 
18   * @author Rory Graves
19   */
20  public class DefaultDBUserLockHandler implements DBUserLockHandler {
21  	
22      private final ObjectAccessor objectAccessor;
23      private final InternalLockListenerNotifier lockListenerNotifier = new InternalLockListenerNotifier();
24      private final StorageEngineUserLockIF userLockIF;
25      private final LockManager<ID> locks = new LockManager<ID>();
26      
27      /** Create a DefaultDBUserLockHandler instance
28       * @param storageEngine The underlying storage engine.
29       * @param objectAccessor The object accessor to use.
30       */
31      public DefaultDBUserLockHandler(StorageEngine storageEngine,ObjectAccessor objectAccessor) {
32      	this.userLockIF = storageEngine.getUserLockIF();
33          this.objectAccessor = objectAccessor;
34          userLockIF.clearAll();
35      }
36      
37      @Override
38      public void removeClientListener(ClientId clientId) {
39          lockListenerNotifier.removeListener(clientId);
40      }
41  
42      @Override
43      public void release(ClientThreadId threadId, ID objectId) {
44      	ClientThreadId acquiringThreadId = null;
45      	try {
46      		locks.acquire(objectId);
47      		UserLockInfo lockInfo = userLockIF.getLockInfo(objectId);
48      		acquiringThreadId = lockInfo.releaseLock(threadId);
49      		userLockIF.saveLockInfo(lockInfo);
50      		userLockIF.removeClientLockReference(threadId, objectId);
51      	} finally {
52      		locks.release(objectId);
53      	}    	
54      	
55  		if(acquiringThreadId != null)
56          	lockListenerNotifier.notifyLockAcquired(acquiringThreadId, objectId);
57      }
58  
59      @Override
60      public void setClientListener(ClientId clientId, LockAcquiredListener listener) {
61          lockListenerNotifier.setListener(clientId,listener);
62      }
63  
64      @Override
65      public void acquire(ClientThreadId threadId, ID objectId) {
66      	if(!objectAccessor.checkExists(objectId))
67      		throw new IllegalStateException("Unable to lock on " + objectId + " object does not exist");
68  
69      	boolean acquired = false;
70      	try {
71      		locks.acquire(objectId);
72      		userLockIF.addClientLockReference(threadId, objectId);
73      		UserLockInfo lockInfo = userLockIF.getLockInfo(objectId);
74      		acquired = lockInfo.acquireLock(threadId);
75      		userLockIF.saveLockInfo(lockInfo);
76      	} finally {
77      		locks.release(objectId);
78      	}
79  
80      	if(acquired)
81          	lockListenerNotifier.notifyLockAcquired(threadId, objectId);
82      }
83      
84      public void shutdown() {
85      	lockListenerNotifier.shutdown();
86      }
87  
88  	@Override
89  	public void clientDisconnect(ClientId clientId) {
90  		Set<ClientThreadIdRef> activeLocks = userLockIF.getClientLockSet(clientId);
91  		if(activeLocks.size() == 0)
92  			return;
93  		
94  		for (ClientThreadIdRef threadIdRef : activeLocks) {
95  			ClientThreadId newLockOwner = null;
96  			ClientThreadId clientThreadId = threadIdRef.getClientThread();
97  			ID objectId = threadIdRef.getID();
98  	    	try {
99  	    		locks.acquire(objectId);
100 	    		UserLockInfo lockInfo = userLockIF.getLockInfo(objectId);	    		
101 	    		newLockOwner = lockInfo.releaseOrClearFromQueue(clientThreadId);	    		
102 	    	}finally {
103 	    		locks.release(objectId);
104 	    	}		
105 	    	
106 	    	if(newLockOwner != null)
107 	        	lockListenerNotifier.notifyLockAcquired(newLockOwner, objectId);
108 		}
109 	}
110 }