Skip to content

Commit a0985c6

Browse files
metanetmdogan
authored andcommitted
Revert fenced lock proxy to local re-entrancy
1 parent bd2eb6d commit a0985c6

2 files changed

Lines changed: 87 additions & 22 deletions

File tree

hazelcast-raft-dataservices/src/main/java/com/hazelcast/raft/service/lock/proxy/AbstractRaftFencedLockProxy.java

Lines changed: 85 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,21 +24,25 @@
2424
import com.hazelcast.raft.service.session.SessionAwareProxy;
2525
import com.hazelcast.spi.InternalCompletableFuture;
2626
import com.hazelcast.util.Clock;
27-
import com.hazelcast.util.UuidUtil;
2827

2928
import java.util.UUID;
29+
import java.util.concurrent.ConcurrentHashMap;
30+
import java.util.concurrent.ConcurrentMap;
3031
import java.util.concurrent.TimeUnit;
3132

3233
import static com.hazelcast.raft.service.lock.RaftLockService.INVALID_FENCE;
3334
import static com.hazelcast.raft.service.session.AbstractSessionManager.NO_SESSION_ID;
3435
import static com.hazelcast.util.Preconditions.checkNotNull;
3536
import static com.hazelcast.util.ThreadUtil.getThreadId;
37+
import static com.hazelcast.util.UuidUtil.newUnsecureUUID;
3638

3739
/**
3840
* TODO: Javadoc Pending...
3941
*/
4042
public 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
}

hazelcast-raft-dataservices/src/test/java/com/hazelcast/raft/service/lock/RaftFencedLockBasicTest.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,6 @@ public void run() {
206206
}
207207
});
208208

209-
sleepSeconds(3);
210209
lock.unlock();
211210

212211
assertTrueEventually(new AssertTask() {
@@ -449,11 +448,10 @@ public void run() {
449448
}
450449
}).get();
451450

452-
long fence2 = lock.lock();
451+
lock.lock();
453452

454-
assertTrue(fence2 > fence1);
455453
assertTrue(lock.isLockedByCurrentThread());
456-
assertEquals(1, lock.getLockCount());
454+
assertEquals(2, lock.getLockCount());
457455
}
458456

459457
@Test(timeout = 60000)

0 commit comments

Comments
 (0)