2424import com .hazelcast .raft .service .session .SessionAwareProxy ;
2525import com .hazelcast .spi .InternalCompletableFuture ;
2626import com .hazelcast .util .Clock ;
27- import com .hazelcast .util .UuidUtil ;
2827
2928import java .util .UUID ;
29+ import java .util .concurrent .ConcurrentHashMap ;
30+ import java .util .concurrent .ConcurrentMap ;
3031import java .util .concurrent .TimeUnit ;
3132
3233import static com .hazelcast .raft .service .lock .RaftLockService .INVALID_FENCE ;
3334import static com .hazelcast .raft .service .session .AbstractSessionManager .NO_SESSION_ID ;
3435import static com .hazelcast .util .Preconditions .checkNotNull ;
3536import static com .hazelcast .util .ThreadUtil .getThreadId ;
37+ import static com .hazelcast .util .UuidUtil .newUnsecureUUID ;
3638
3739/**
3840 * TODO: Javadoc Pending...
3941 */
4042public abstract class AbstractRaftFencedLockProxy extends SessionAwareProxy implements FencedLock {
4143
44+ // thread id -> lock state
45+ private final ConcurrentMap <Long , LockState > lockStates = new ConcurrentHashMap <Long , LockState >();
4246 protected final String name ;
4347
4448 public AbstractRaftFencedLockProxy (AbstractSessionManager sessionManager , RaftGroupId groupId , String name ) {
@@ -49,11 +53,18 @@ public AbstractRaftFencedLockProxy(AbstractSessionManager sessionManager, RaftGr
4953 @ Override
5054 public final long lock () {
5155 long threadId = getThreadId ();
52- UUID invocationUid = UuidUtil .newUnsecureUUID ();
56+ long fence = tryReentrantLock (threadId );
57+ if (fence != INVALID_FENCE ) {
58+ return fence ;
59+ }
60+
61+ UUID invocationUid = newUnsecureUUID ();
5362 for (;;) {
5463 long sessionId = acquireSession ();
5564 try {
56- return doLock (groupId , name , sessionId , threadId , invocationUid ).join ();
65+ fence = doLock (groupId , name , sessionId , threadId , invocationUid ).join ();
66+ lockStates .put (threadId , new LockState (sessionId , fence ));
67+ return fence ;
5768 } catch (SessionExpiredException e ) {
5869 invalidateSession (sessionId );
5970 }
@@ -70,15 +81,22 @@ public final long tryLock(long time, TimeUnit unit) {
7081 checkNotNull (unit );
7182
7283 long threadId = getThreadId ();
73- UUID invocationUid = UuidUtil .newUnsecureUUID ();
84+ long fence = tryReentrantLock (threadId );
85+ if (fence != INVALID_FENCE ) {
86+ return fence ;
87+ }
88+
89+ UUID invocationUid = newUnsecureUUID ();
7490 long timeoutMillis = Math .max (0 , unit .toMillis (time ));
7591 long start ;
7692 for (;;) {
7793 start = Clock .currentTimeMillis ();
7894 long sessionId = acquireSession ();
7995 try {
80- long fence = doTryLock (groupId , name , sessionId , threadId , invocationUid , timeoutMillis ).join ();
81- if (fence == INVALID_FENCE ) {
96+ fence = doTryLock (groupId , name , sessionId , threadId , invocationUid , timeoutMillis ).join ();
97+ if (fence != INVALID_FENCE ) {
98+ lockStates .put (threadId , new LockState (sessionId , fence ));
99+ } else {
82100 releaseSession (sessionId );
83101 }
84102 return fence ;
@@ -92,30 +110,62 @@ public final long tryLock(long time, TimeUnit unit) {
92110 }
93111 }
94112
113+ private long tryReentrantLock (long threadId ) {
114+ LockState lockState = lockStates .get (threadId );
115+ if (lockState != null ) {
116+ if (lockState .sessionId == getSession ()) {
117+ lockState .lockCount ++;
118+ return lockState .fence ;
119+ }
120+ lockStates .remove (threadId );
121+ throw new IllegalMonitorStateException ("Current thread is not owner of the Lock[" + name + "] because Session["
122+ + lockState .sessionId + "] is closed by server!" );
123+ }
124+ return INVALID_FENCE ;
125+ }
126+
95127 @ Override
96128 public final void unlock () {
97129 long sessionId = getSession ();
98130 if (sessionId == NO_SESSION_ID ) {
99131 throw new IllegalMonitorStateException ("Current thread is not owner of the Lock[" + name
100132 + "] because session not found!" );
101133 }
102- UUID invocationUid = UuidUtil .newUnsecureUUID ();
134+ long threadId = getThreadId ();
135+ LockState lockState = lockStates .get (threadId );
136+ if (lockState == null ) {
137+ throw new IllegalMonitorStateException ("Current thread is not owner of the Lock[" + name + "]" );
138+ }
139+ if (lockState .sessionId != sessionId ) {
140+ lockStates .remove (threadId );
141+ throw new IllegalMonitorStateException ("Current thread is not owner of the Lock[" + name + "] because Session["
142+ + lockState .sessionId + "] is closed by server!" );
143+ }
144+ if (lockState .lockCount > 1 ) {
145+ lockState .lockCount --;
146+ return ;
147+ }
148+
103149 try {
104- doUnlock (groupId , name , sessionId , getThreadId (), invocationUid ).join ();
150+ doUnlock (groupId , name , sessionId , threadId , newUnsecureUUID () ).join ();
105151 } catch (SessionExpiredException e ) {
106152 invalidateSession (sessionId );
107153 throw new IllegalMonitorStateException ("Current thread is not owner of the Lock[" + name + "] because Session["
108154 + sessionId + "] is closed by server!" );
109155 } finally {
156+ lockStates .remove (threadId );
110157 releaseSession (sessionId );
111158 }
112159 }
113160
114161 @ Override
115162 public final void forceUnlock () {
116- long fence = doGetLockFence (groupId , name , NO_SESSION_ID , 0 ).join ();
117- UUID invocationUid = UuidUtil .newUnsecureUUID ();
118- doForceUnlock (groupId , name , fence , invocationUid ).join ();
163+ try {
164+ long fence = doGetLockFence (groupId , name , NO_SESSION_ID , 0 ).join ();
165+ doForceUnlock (groupId , name , fence , newUnsecureUUID ()).join ();
166+ } finally {
167+ lockStates .remove (getThreadId ());
168+ }
119169 }
120170
121171 @ Override
@@ -125,7 +175,12 @@ public final long getFence() {
125175 throw new IllegalMonitorStateException ();
126176 }
127177
128- return doGetLockFence (groupId , name , sessionId , getThreadId ()).join ();
178+ LockState lockState = lockStates .get (getThreadId ());
179+ if (lockState == null ) {
180+ throw new IllegalMonitorStateException ();
181+ }
182+
183+ return lockState .fence ;
129184 }
130185
131186 @ Override
@@ -135,16 +190,17 @@ public final boolean isLocked() {
135190
136191 @ Override
137192 public final boolean isLockedByCurrentThread () {
138- long sessionId = getSession ();
139- if (sessionId == NO_SESSION_ID ) {
140- return false ;
141- }
142-
143- return doGetLockCount (groupId , name , sessionId , getThreadId ()).join () > 0 ;
193+ LockState lockState = lockStates .get (getThreadId ());
194+ return (lockState != null && lockState .sessionId == getSession ());
144195 }
145196
146197 @ Override
147198 public final int getLockCount () {
199+ LockState lockState = lockStates .get (getThreadId ());
200+ if (lockState != null && lockState .sessionId == getSession ()) {
201+ return lockState .lockCount ;
202+ }
203+
148204 return doGetLockCount (groupId , name , NO_SESSION_ID , 0 ).join ();
149205 }
150206
@@ -181,4 +237,15 @@ protected abstract InternalCompletableFuture<Long> doGetLockFence(RaftGroupId gr
181237 protected abstract InternalCompletableFuture <Integer > doGetLockCount (RaftGroupId groupId , String name , long sessionId ,
182238 long threadId );
183239
240+ private static class LockState {
241+ final long sessionId ;
242+ final long fence ;
243+ int lockCount ;
244+
245+ LockState (long sessionId , long fence ) {
246+ this .sessionId = sessionId ;
247+ this .fence = fence ;
248+ this .lockCount = 1 ;
249+ }
250+ }
184251}
0 commit comments