KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > jalisto > se > impl > lock > Lock


1 /*
2  * Jalisto - JAva LIght STOrage
3  * Copyright (C) 2000-2005 Xcalia http://www.xcalia.com
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
18  *
19  * Xcalia
20  * 71, rue Desnouettes
21  * 75014 Paris - France
22  * http://www.xcalia.com
23  */

24 package org.objectweb.jalisto.se.impl.lock;
25
26 import org.objectweb.jalisto.se.api.internal.DataWrapper;
27 import org.objectweb.jalisto.se.api.internal.multi.SessionMulti;
28 import org.objectweb.jalisto.se.exception.multi.LockException;
29 import org.objectweb.jalisto.se.exception.multi.SleepingException;
30 import org.objectweb.jalisto.se.JalistoFactory;
31
32 import java.io.Serializable JavaDoc;
33 import java.util.*;
34
35 public class Lock implements Serializable JavaDoc {
36
37     private Lock() {
38         currentLock = NO_LOCK;
39         writeSession = "";
40         transactionnalStates = new HashMap();
41         readSessions = new LinkedList();
42         sleepingSessions = new LinkedList();
43     }
44
45     public void release() {
46         instances.add(this);
47     }
48
49     public synchronized int getCurrentAction(Object JavaDoc sessionId) {
50         int result = ObjectTransactionnalState.NO_ACTION;
51         if (transactionnalStates.containsKey(sessionId)) {
52             result = ((ObjectTransactionnalState) transactionnalStates.get(sessionId)).getCurrentAction();
53         }
54         return result;
55     }
56
57     public synchronized DataWrapper getModifiedValue(Object JavaDoc sessionId) {
58         ObjectTransactionnalState image = (ObjectTransactionnalState) transactionnalStates.get(sessionId);
59         if (image != null) {
60             return image.getCurrentValue();
61         }
62         return null;
63     }
64
65     public synchronized short getUpdate(Object JavaDoc sessionId) {
66         ObjectTransactionnalState image = (ObjectTransactionnalState) transactionnalStates.get(sessionId);
67         if (image != null) {
68             return image.getUpdate();
69         }
70         return (short) -1;
71     }
72
73     public void update(Object JavaDoc sessionId) {
74         ((ObjectTransactionnalState) transactionnalStates.get(sessionId)).update();
75     }
76
77
78     public synchronized void addTransactionnalValue(Object JavaDoc sessionId, DataWrapper value,
79                                                     int action, short update) {
80         // a read value can not be put over a write value
81
ObjectTransactionnalState image = (ObjectTransactionnalState) transactionnalStates.get(sessionId);
82         if (image == null) {
83             image = new ObjectTransactionnalState(action, value, update);
84             transactionnalStates.put(sessionId, image);
85         } else {
86             image.setValue(action, value);
87             image.setUpdate(update);
88         }
89     }
90
91     public synchronized void updateTransactionnalValue(Object JavaDoc sessionId, DataWrapper value, short update) {
92         // a read value can not be put over a write value
93
ObjectTransactionnalState image = (ObjectTransactionnalState) transactionnalStates.get(sessionId);
94         if (image != null) {
95             image.setValue(image.getCurrentAction(), value);
96             image.setUpdate(update);
97         }
98     }
99
100     public synchronized boolean addSleepingSession(Object JavaDoc sessionId) {
101         if (currentLock == NO_LOCK) {
102             return false;
103         }
104         if (sleepingSessions.contains(sessionId)) { // TODO : cette exception n'est pas gérée
105
throw new LockException("dead lock : sessionId = " + String.valueOf(sessionId));
106         }
107         DeadLockToken asleepingSession = DeadLockToken.getToken(sessionId);
108         if (sleepingSessions.isEmpty()) {
109             if (currentLock == READ_LOCK) {
110                 for (int i = 0; i < readSessions.size(); i++) {
111                     asleepingSession.waitFor(DeadLockToken.getToken(readSessions.get(i)));
112                 }
113             } else if (currentLock == WRITE_LOCK) {
114                 asleepingSession.waitFor(DeadLockToken.getToken(writeSession));
115             }
116         } else {
117             asleepingSession.waitFor(DeadLockToken.getToken(sleepingSessions.getLast()));
118         }
119         sleepingSessions.addLast(sessionId);
120         return true;
121     }
122
123     private void wakeUpASession(Object JavaDoc releasingSessionId) {
124         if (!sleepingSessions.isEmpty()) {
125             Object JavaDoc awakingId = sleepingSessions.getFirst();
126             DeadLockToken releasingSessionToken = DeadLockToken.getToken(releasingSessionId);
127             DeadLockToken awakingSessionToken = DeadLockToken.getToken(awakingId);
128             synchronized (awakingSessionToken) {
129                 awakingSessionToken.noMoreWaitFor(releasingSessionToken);
130                 if (awakingSessionToken.couldWakeUp()) {
131                     sleepingSessions.remove(awakingId);
132                     ((SessionMulti) JalistoFactory.getInternalFactory().getSessionById(awakingId)).wakeUp();
133                 }
134             }
135         }
136     }
137
138     public synchronized void resolveTimeOut(Object JavaDoc sessionId) {
139         DeadLockToken timeOutToken = DeadLockToken.getToken(sessionId);
140         if (sleepingSessions.contains(sessionId)) { // wake other sessions waiting for sessionId
141
int index = sleepingSessions.indexOf(sessionId);
142             if ((index + 1) < sleepingSessions.size()) {
143                 DeadLockToken tokenWhoWaitForTimeOutToken =
144                         DeadLockToken.getToken(sleepingSessions.get(index + 1));
145                 timeOutToken.timeOutWakeUp(tokenWhoWaitForTimeOutToken);
146             } else {
147                 timeOutToken.timeOutWakeUp(null);
148             }
149             sleepingSessions.remove(sessionId);
150         } else {
151             // dans quels cas ?????
152
DeadLockToken tokenWhoWaitForTimeOutToken = null;
153             try {
154                 tokenWhoWaitForTimeOutToken = DeadLockToken.getToken(sleepingSessions.getFirst());
155             } catch (NoSuchElementException e) {
156             }
157             timeOutToken.timeOutWakeUp(tokenWhoWaitForTimeOutToken);
158         }
159     }
160
161     /**
162      * ******************************* LOCK MANAGEMENT *****************************************
163      */

164
165     public synchronized void takeReadLock(Object JavaDoc sessionId) {
166         // 1 : cas pas de lock et pas de sleeping -> ajouter RL avec sessionId
167
// 2 : cas pas de lock et sleepings et le premier sleeping attends la session courante -> add RL
168
// 3 : cas pas de lock et sleepings et le premier sleeping n'attends pas la session courante -> sleep
169
if (currentLock == NO_LOCK) {
170             if (sleepingSessions.isEmpty()) { // 1
171
currentLock = READ_LOCK;
172             } else {
173                 DeadLockToken awakingToken = DeadLockToken.getToken(sleepingSessions.getFirst());
174                 if (awakingToken.isWaitingFor(DeadLockToken.getToken(sessionId))) { // 2
175
currentLock = READ_LOCK;
176                 } else { // 3
177
throw new SleepingException("takeReadLock case 3", this);
178                 }
179             }
180             // 4 : cas read session avec sessionId et eventuellement d'autre -> ne fée rien
181
// 5 : cas read session avec autre exclusivement que sessionId et pas sleeping -> ajouter sessionId readSessions
182
// 6 : cas read session avec autre exclusivement que sessionId et sleeping -> sleep
183
} else if (currentLock == READ_LOCK) {
184             if (!readSessions.contains(sessionId)) {
185                 if (!sleepingSessions.isEmpty()) {
186                     throw new SleepingException("takeReadLock case 6", this); // 6
187
} // else : 5
188
} // else : 4
189
// 7 : cas write session avec sessionId -> rien à faire
190
// 8 : cas write session avec autre -> sleep
191
} else if (currentLock == WRITE_LOCK) {
192             if (!writeSession.equals(sessionId)) { // 8
193
throw new SleepingException("takeReadLock case 8", this);
194             } // else : 7
195
}
196         if (!readSessions.contains(sessionId)) {
197             readSessions.addLast(sessionId);
198         }
199     }
200
201     public synchronized void takeWriteLock(Object JavaDoc sessionId) {
202         // 1 : cas pas de lock et pas sleepings -> ajouter WL avec sessionId
203
// 2 : cas pas de lock et sleepings et premier sleeping attends sessionId -> sessionId pose WL
204
// 3 : cas pas de lock et sleepings et premier sleeping n'attends pas sessionId -> sleep
205
if (currentLock == NO_LOCK) {
206             if (sleepingSessions.isEmpty()) { // 1
207
currentLock = WRITE_LOCK;
208             } else {
209                 DeadLockToken awakingToken = DeadLockToken.getToken(sleepingSessions.getFirst());
210                 if (awakingToken.isWaitingFor(DeadLockToken.getToken(sessionId))) { // 2
211
currentLock = WRITE_LOCK;
212                 } else { // 3
213
throw new SleepingException(this);
214                 }
215             }
216             // 4 : cas read session avec seulement sessionId -> transforme RL en WL
217
// 5 : cas read session avec autre exclusivement que sessionId -> sleep
218
// 6 : cas read session avec autre que sessionId ET sessionId -> sleep
219
} else if (currentLock == READ_LOCK) {
220             if (readSessions.contains(sessionId)) {
221                 if (readSessions.size() > 1) { // 6
222
wakeUpASession(sessionId);
223                     throw new SleepingException(this);
224                 } else { // 4
225
currentLock = WRITE_LOCK;
226                 }
227             } else { // 5
228
throw new SleepingException(this);
229             }
230             // 7 : cas WL session avec sessionId -> ne fait rien
231
// 8 : cas WL session avec autre -> sleep
232
} else { // currentLock == WL
233
if (writeSession.equals(sessionId)) { // 7
234
return;
235             } else { // 8
236
throw new SleepingException(this);
237             }
238         }
239         writeSession = sessionId;
240     }
241
242     public synchronized void releaseReadLock(Object JavaDoc sessionId) {
243         if (currentLock == WRITE_LOCK) {
244             if (writeSession.equals(sessionId)) {
245                 readSessions.remove(sessionId);
246             } else {
247                 throw new LockException();
248             }
249         } else {
250             readSessions.remove(sessionId);
251             if (readSessions.isEmpty()) {
252                 currentLock = NO_LOCK;
253             }
254             wakeUpASession(sessionId);
255         }
256     }
257
258     public synchronized void releaseWriteLock(Object JavaDoc sessionId) {
259         if ((currentLock == WRITE_LOCK) && (writeSession.equals(sessionId))) {
260             readSessions.remove(sessionId);
261             currentLock = NO_LOCK;
262             writeSession = "";
263             wakeUpASession(sessionId);
264         } else {
265             throw new LockException();
266         }
267     }
268
269     public synchronized void releaseAllLock(Object JavaDoc sessionId) {
270         if ((currentLock == WRITE_LOCK) && (writeSession.equals(sessionId))) {
271             writeSession = "";
272             currentLock = NO_LOCK;
273         } else if ((currentLock == READ_LOCK) && (readSessions.contains(sessionId))) {
274             currentLock = NO_LOCK;
275         }
276         readSessions.remove(sessionId);
277         transactionnalStates.remove(sessionId);
278         wakeUpASession(sessionId);
279     }
280
281
282     /**
283      * ************************* TESTS ******************************************
284      */

285
286     public synchronized boolean canBeDeleted() {
287         return ((currentLock == NO_LOCK) &&
288                 transactionnalStates.isEmpty() &&
289                 sleepingSessions.isEmpty());
290     }
291
292     public synchronized boolean hasModifiedValueWith(Object JavaDoc sessionId) {
293         return (transactionnalStates.get(sessionId) != null);
294     }
295
296     public synchronized boolean hasReadLockWith(Object JavaDoc sessionId) {
297         return readSessions.contains(sessionId);
298     }
299
300     public synchronized boolean mustTakeWriteLock(Object JavaDoc sessionId) {
301         ObjectTransactionnalState itm = (ObjectTransactionnalState) transactionnalStates.get(sessionId);
302         return ((itm.getCurrentAction() != ObjectTransactionnalState.READ_ACTION) &&
303                 (itm.getCurrentAction() != ObjectTransactionnalState.NO_ACTION));
304     }
305
306     public synchronized boolean hasWriteLockWith(Object JavaDoc sessionId) {
307         return writeSession.equals(sessionId);
308     }
309
310     public synchronized boolean hasToBeRemoveForExtentWith(Object JavaDoc sessionId) {
311         if (transactionnalStates.containsKey(sessionId)) {
312             ObjectTransactionnalState itm = (ObjectTransactionnalState) transactionnalStates.get(sessionId);
313             return (itm.getCurrentAction() == ObjectTransactionnalState.DELETE_ACTION);
314         }
315         return false;
316     }
317
318     /**
319      * **********************************************************************************************
320      */

321
322     private String JavaDoc getLockAsString(int lock) {
323         if (lock == NO_LOCK) {
324             return "no_lock";
325         } else if (lock == READ_LOCK) {
326             return "r_lock";
327         } else {
328             return "w_lock";
329         }
330     }
331
332
333     public String JavaDoc toString() {
334         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
335         sb.append(getLockAsString(currentLock)).append(" ").append(super.toString()).append("\n");
336         sb.append("\tRead Locks : ").append(readSessions).append("\n");
337         sb.append("\tWrite Lock : ").append(writeSession).append("\n");
338         sb.append("\tActions : \n");
339         sb.append("\tSleeping session : ").append(sleepingSessions).append("\n");
340         Iterator sessions = transactionnalStates.keySet().iterator();
341         if (!sessions.hasNext()) {
342             sb.append("CurrentStates is empty");
343         }
344         while (sessions.hasNext()) {
345             Object JavaDoc key = sessions.next();
346             ObjectTransactionnalState image = (ObjectTransactionnalState) transactionnalStates.get(key);
347             sb.append(" ").append(image);
348         }
349         sb.append("\n");
350         return sb.toString();
351     }
352
353
354     private HashMap transactionnalStates;
355     private LinkedList readSessions;
356     private LinkedList sleepingSessions;
357
358     private Object JavaDoc writeSession; // utiliser "" pour signifier null
359
private int currentLock;
360
361
362     static final long serialVersionUID = -7589377087694761459L;
363
364
365     public static final int NO_LOCK = 0;
366     public static final int READ_LOCK = 1;
367     public static final int WRITE_LOCK = 2;
368
369     private static ArrayList instances = new ArrayList();
370
371     public static Lock newInstance() {
372         if (instances.isEmpty()) {
373             return new Lock();
374         } else {
375             return (Lock) instances.remove(0);
376         }
377     }
378 }
379
Popular Tags