2828import java .util .ArrayList ;
2929import java .util .Collection ;
3030import java .util .Collections ;
31+ import java .util .HashMap ;
3132import java .util .Iterator ;
3233import java .util .List ;
34+ import java .util .Map ;
3335import java .util .UUID ;
3436
3537import static com .hazelcast .raft .service .lock .RaftLockService .INVALID_FENCE ;
@@ -42,37 +44,41 @@ class RaftLock extends BlockingResource<LockInvocationKey> implements Identified
4244
4345 private LockInvocationKey owner ;
4446 private int lockCount ;
45- private UUID releaseRefUid ;
47+ private Map < LockEndpoint , UUID > invocationRefUids = new HashMap < LockEndpoint , UUID >() ;
4648
47- public RaftLock () {
49+ RaftLock () {
4850 }
4951
5052 RaftLock (RaftGroupId groupId , String name ) {
5153 super (groupId , name );
5254 }
5355
5456 @ Override
55- public Collection <Long > getOwnerSessionIds () {
57+ public Collection <Long > getActiveSessions () {
5658 return owner != null ? Collections .singleton (owner .sessionId ()) : Collections .<Long >emptyList ();
5759 }
5860
5961 AcquireResult acquire (LockEndpoint endpoint , long commitIndex , UUID invocationUid , boolean wait ) {
6062 // if acquire() is being retried
61- if (owner != null && owner .invocationUid ().equals (invocationUid )) {
63+ if (invocationUid .equals (invocationRefUids .get (endpoint ))
64+ || (owner != null && owner .invocationUid ().equals (invocationUid ))) {
6265 return AcquireResult .successful (owner .commitIndex ());
6366 }
6467
68+ invocationRefUids .remove (endpoint );
69+
6570 LockInvocationKey key = new LockInvocationKey (name , endpoint , commitIndex , invocationUid );
6671 if (owner == null ) {
6772 owner = key ;
6873 }
6974
7075 if (endpoint .equals (owner .endpoint ())) {
76+ invocationRefUids .put (endpoint , invocationUid );
7177 lockCount ++;
7278 return AcquireResult .successful (owner .commitIndex ());
7379 }
7480
75- Collection <LockInvocationKey > cancelledWaitKeys = cancelWaitKeys (endpoint , invocationUid );
81+ Collection <LockInvocationKey > cancelledWaitKeys = cancelWaitKeys (endpoint );
7682
7783 if (wait ) {
7884 waitKeys .add (key );
@@ -81,12 +87,12 @@ AcquireResult acquire(LockEndpoint endpoint, long commitIndex, UUID invocationUi
8187 return AcquireResult .failed (cancelledWaitKeys );
8288 }
8389
84- private Collection <LockInvocationKey > cancelWaitKeys (LockEndpoint endpoint , UUID invocationUid ) {
90+ private Collection <LockInvocationKey > cancelWaitKeys (LockEndpoint endpoint ) {
8591 List <LockInvocationKey > cancelled = new ArrayList <LockInvocationKey >(0 );
8692 Iterator <LockInvocationKey > it = waitKeys .iterator ();
8793 while (it .hasNext ()) {
8894 LockInvocationKey waitKey = it .next ();
89- if (waitKey .endpoint ().equals (endpoint ) && ! waitKey . invocationUid (). equals ( invocationUid ) ) {
95+ if (waitKey .endpoint ().equals (endpoint )) {
9096 cancelled .add (waitKey );
9197 it .remove ();
9298 }
@@ -101,12 +107,12 @@ ReleaseResult release(LockEndpoint endpoint, UUID invocationUuid) {
101107
102108 private ReleaseResult release (LockEndpoint endpoint , int releaseCount , UUID invocationUid ) {
103109 // if release() is being retried
104- if (invocationUid .equals (releaseRefUid )) {
110+ if (invocationUid .equals (invocationRefUids . get ( endpoint ) )) {
105111 return ReleaseResult .SUCCESSFUL ;
106112 }
107113
108114 if (owner != null && endpoint .equals (owner .endpoint ())) {
109- releaseRefUid = invocationUid ;
115+ invocationRefUids . put ( endpoint , invocationUid ) ;
110116
111117 lockCount -= Math .min (releaseCount , lockCount );
112118 if (lockCount > 0 ) {
@@ -115,39 +121,21 @@ private ReleaseResult release(LockEndpoint endpoint, int releaseCount, UUID invo
115121
116122 LockInvocationKey newOwner = waitKeys .poll ();
117123 if (newOwner != null ) {
118- List <LockInvocationKey > keys = new ArrayList <LockInvocationKey >();
119- keys .add (newOwner );
120-
121- Iterator <LockInvocationKey > iter = waitKeys .iterator ();
122- while (iter .hasNext ()) {
123- LockInvocationKey key = iter .next ();
124- if (newOwner .invocationUid ().equals (key .invocationUid ())) {
125- assert newOwner .endpoint ().equals (key .endpoint ());
126- keys .add (key );
127- iter .remove ();
128- }
129- }
130-
131124 owner = newOwner ;
132125 lockCount = 1 ;
133126
134- return ReleaseResult .successful (keys );
127+ return ReleaseResult .successful (Collections . singleton ( newOwner ) );
135128 } else {
136129 owner = null ;
137130 }
138131
139132 return ReleaseResult .SUCCESSFUL ;
140133 }
141134
142- return ReleaseResult .failed (cancelWaitKeys (endpoint , invocationUid ));
135+ return ReleaseResult .failed (cancelWaitKeys (endpoint ));
143136 }
144137
145138 ReleaseResult forceRelease (long expectedFence , UUID invocationUid ) {
146- // if forceRelease() is being retried
147- if (invocationUid .equals (releaseRefUid )) {
148- return ReleaseResult .SUCCESSFUL ;
149- }
150-
151139 if (owner == null ) {
152140 return ReleaseResult .FAILED ;
153141 }
@@ -170,6 +158,13 @@ LockInvocationKey owner() {
170158 @ Override
171159 protected void onInvalidateSession (long sessionId , Long2ObjectHashMap <Object > responses ) {
172160 if (owner != null && sessionId == owner .endpoint ().sessionId ()) {
161+ Iterator <LockEndpoint > it = invocationRefUids .keySet ().iterator ();
162+ while (it .hasNext ()) {
163+ if (it .next ().sessionId () == sessionId ) {
164+ it .remove ();
165+ }
166+ }
167+
173168 ReleaseResult result = release (owner .endpoint (), Integer .MAX_VALUE , UuidUtil .newUnsecureUUID ());
174169
175170 if (!result .success ) {
@@ -207,11 +202,12 @@ public void writeData(ObjectDataOutput out)
207202 out .writeObject (owner );
208203 }
209204 out .writeInt (lockCount );
210- boolean hasRefUid = (releaseRefUid != null );
211- out .writeBoolean (hasRefUid );
212- if (hasRefUid ) {
213- out .writeLong (releaseRefUid .getLeastSignificantBits ());
214- out .writeLong (releaseRefUid .getMostSignificantBits ());
205+ out .writeInt (invocationRefUids .size ());
206+ for (Map .Entry <LockEndpoint , UUID > e : invocationRefUids .entrySet ()) {
207+ out .writeObject (e .getKey ());
208+ UUID releaseUid = e .getValue ();
209+ out .writeLong (releaseUid .getLeastSignificantBits ());
210+ out .writeLong (releaseUid .getMostSignificantBits ());
215211 }
216212 }
217213
@@ -224,18 +220,19 @@ public void readData(ObjectDataInput in)
224220 owner = in .readObject ();
225221 }
226222 lockCount = in .readInt ();
227- boolean hasRefUid = in .readBoolean ();
228- if (hasRefUid ) {
223+ int releaseRefUidCount = in .readInt ();
224+ for (int i = 0 ; i < releaseRefUidCount ; i ++) {
225+ LockEndpoint endpoint = in .readObject ();
229226 long least = in .readLong ();
230227 long most = in .readLong ();
231- releaseRefUid = new UUID (most , least );
228+ invocationRefUids . put ( endpoint , new UUID (most , least ) );
232229 }
233230 }
234231
235232 @ Override
236233 public String toString () {
237234 return "RaftLock{" + "groupId=" + groupId + ", name='" + name + '\'' + ", owner=" + owner + ", lockCount=" + lockCount
238- + ", releaseRefUid =" + releaseRefUid + ", waitKeys=" + waitKeys + '}' ;
235+ + ", invocationRefUids =" + invocationRefUids + ", waitKeys=" + waitKeys + '}' ;
239236 }
240237
241238 static class AcquireResult {
0 commit comments