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
17
18
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
28
29
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 }